Package org.iosgi.impl.engine

Source Code of org.iosgi.impl.engine.IsolationEngineImpl$CellVisitor

/* 
* i-OSGi - Tunable Bundle Isolation for OSGi
* Copyright (C) 2011  Sven Schulz
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.iosgi.impl.engine;

import java.net.URI;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
import org.iosgi.IsolationConstraint;
import org.iosgi.IsolationConstraintRegistry;
import org.iosgi.engine.IsolationEngine;
import org.iosgi.engine.Operation;
import org.iosgi.impl.BundleOperation;
import org.iosgi.impl.EnvironmentIDs;
import org.iosgi.impl.IsolationEnvironmentOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import algorithms.graphColorer.Colorer;
import algorithms.graphColorer.reoptimizer.IteratedGreedyColorer;
import dataStructures.graph.Edge;
import dataStructures.graph.ExtendedSimpleGraphAjazenzList;
import dataStructures.graph.ExtendedUndirectedGraph;
import dataStructures.graph.GraphColoring;

/**
* @author Sven Schulz
*/
@Component(immediate = true)
@Provides(specifications = IsolationEngine.class)
public class IsolationEngineImpl implements IsolationEngine {

  private static final Logger LOGGER = LoggerFactory
      .getLogger(IsolationEngineImpl.class);

  public enum OptimizationMode {
    NONE, ITERATED_GREEDY, PSEUDO_BOOLEAN
  }

  @Requires
  private IsolationConstraintRegistry constraintRegistry;

  private Cell root;
  private int depth;
  private OptimizationMode optimizationMode;

  public IsolationEngineImpl() {
    this(null, 2, OptimizationMode.PSEUDO_BOOLEAN);
  }

  IsolationEngineImpl(final IsolationConstraintRegistry registry, int depth,
      OptimizationMode optimizationMode) {
    this.constraintRegistry = registry;
    this.depth = depth;
    this.optimizationMode = optimizationMode;
    root = new Cell();
  }

  @Override
  public List<Operation> install(String location) throws Exception {
    List<Operation> ops = new LinkedList<Operation>();
    root.add(location, ops);
    optimize(ops);
    return ops;
  }

  @Override
  public List<Operation> uninstall(String location) throws Exception {
    List<Operation> ops = new LinkedList<Operation>();
    root.remove(location, ops);
    optimize(ops);
    return ops;
  }

  void optimize(List<Operation> ops) {
    Set<Operation> subsumed = new HashSet<Operation>();
    for (int i = 0; i < ops.size(); i++) {
      Operation op = ops.get(i);
      for (int j = 0; j < i; j++) {
        Operation c = ops.get(j);
        if (!subsumed.contains(c) && op.subsumes(c))
          subsumed.add(c);
      }
    }
    int sc = 0;
    for (Iterator<Operation> it = ops.iterator(); it.hasNext();) {
      Operation op = it.next();
      if (subsumed.contains(op)) {
        it.remove();
        sc++;
      }
    }
    if (sc > 0) {
      LOGGER.debug("{} operations subsumed", sc);
    }
  }

  @Override
  public String toString() {
    return root.toString();
  }

  int[] calc() {
    int[] counts = new int[depth + 1];
    LinkedList<Cell> open = new LinkedList<Cell>();
    open.add(root);
    while (!open.isEmpty()) {
      Cell c = open.pop();
      open.addAll(c.children);
      counts[c.getLevel()]++;
    }
    return counts;
  }

  class Cell {

    private int childSn;
    private Set<String> bundles;
    private Cell parent;
    private List<Cell> children;
    private String target;

    Cell() {
      this(null);
    }

    Cell(final Cell parent) {
      this.childSn = 0;
      this.parent = parent;
      bundles = new HashSet<String>();
      children = new LinkedList<Cell>();
      if (parent != null)
        parent.children.add(this);
      target = (parent != null ? (parent.target + "/") + parent.childSn++
          : "");
    }

    void verify() {
      for (String a : bundles) {
        for (String b : bundles) {
          int lvl = constraintRegistry.getIsolationLevel(a, b);
          if (lvl < this.getLevel()) {
            throw new RuntimeException("verification failed");
          }
        }
      }
    }

    void add(final String location, List<Operation> ops) {
      bundles.add(location);
      if (this.getLevel() < depth) {
        boolean added = false;
        for (Cell c : children) {
          if (c.isCompatible(location)) {
            c.add(location, ops);
            added = true;
            break;
          }
        }
        if (!added) {
          Cell c = new Cell(this);
          ops.add(new IsolationEnvironmentOperation(
              IsolationEnvironmentOperation.Type.CREATE, c
                  .getTarget()));
          c.add(location, ops);
          if (optimizationMode != OptimizationMode.NONE)
            optimize(ops);
        }
      } else {
        ops.add(new BundleOperation(BundleOperation.Type.INSTALL, this
            .getTarget(), location));
      }
      verify();
    }

    void remove(final String location, List<Operation> ops) {
      bundles.remove(location);
      if (this.getLevel() < depth) {
        for (Iterator<Cell> it = children.iterator(); it.hasNext();) {
          Cell c = it.next();
          if (c.getBundles().contains(location)) {
            c.remove(location, ops);
            if (this.getLevel() > 0 && c.isEmpty()) {
              it.remove();
              if (EnvironmentIDs.isDestructible(URI.create(this
                  .getTarget()))) {
                ops.add(new IsolationEnvironmentOperation(
                    IsolationEnvironmentOperation.Type.DESTROY,
                    this.getTarget()));
              }
            }
            break;
          }
        }
      } else {
        ops.add(new BundleOperation(BundleOperation.Type.UNINSTALL,
            this.getTarget(), location));
      }
    }

    public Cell getParent() {
      return parent;
    }

    public List<Cell> getChildren() {
      return children;
    }

    String getTarget() {
      return target;
    }

    int getLevel() {
      Cell p = this.getParent();
      return p != null ? p.getLevel() + 1 : 0;
    }

    boolean isCompatible(final String location) {
      for (String b : bundles) {
        int lvl = constraintRegistry.getIsolationLevel(location, b);
        if (lvl < this.getLevel()) {
          return false;
        }
      }
      return true;
    }

    Set<String> getBundles() {
      return bundles;
    }

    boolean isEmpty() {
      return this.getBundles().isEmpty();
    }

    @Override
    public String toString() {
      StringBuilder b = new StringBuilder();
      for (int i = 0; i < this.getLevel(); i++) {
        b.append('\t');
      }
      b.append("[ ");
      for (String location : bundles) {
        b.append(location).append(' ');
      }
      b.append(']');
      for (Cell c : children) {
        b.append('\n');
        b.append(c);
      }
      return b.toString();
    }

    void optimize(List<Operation> ops) {

      if (this.getLevel() == depth) {
        return;
      }

      ExtendedUndirectedGraph<String, Edge<String>> g = new ExtendedSimpleGraphAjazenzList<String>();
      for (String b : bundles) {
        g.addVertex(b);
      }
      for (String b : bundles) {
        for (IsolationConstraint c : constraintRegistry
            .getConstraints(b)) {
          if (c.getLevel() <= this.getLevel()) {
            String[] cp = c.getBundles();
            if (g.containsVertex(cp[0]) && g.containsVertex(cp[1])) {
              g.addEdge(cp[0], cp[1]);
            }
          }
        }
      }
      GraphColoring<String, Edge<String>> base = new GraphColoring<String, Edge<String>>(
          g);
      int color = 1;
      for (Cell c : this.getChildren()) {
        for (String b : c.getBundles()) {
          base.setColor(b, color);
        }
        color++;
      }

      Colorer<String, Edge<String>> colorer = null;
      switch (optimizationMode) {
      case ITERATED_GREEDY: {
        colorer = new IteratedGreedyColorer<String, Edge<String>>(g,
            1000, base);
        break;
      }
      case PSEUDO_BOOLEAN: {
        colorer = new PseudoBooleanColorer<String, Edge<String>>(g);
        break;
      }
      }

      long ref = System.currentTimeMillis();
      GraphColoring<String, Edge<String>> optimized = colorer
          .getColoring();
      long elapsed = System.currentTimeMillis() - ref;
      LOGGER.debug(
          "level: {}, new: {}, old: {}, elapsed: {} ms",
          new Object[] { this.getLevel(),
              optimized.getNumberOfColors(),
              base.getNumberOfColors(), elapsed });
      if (optimized.getNumberOfColors() == base.getNumberOfColors()) {
        return;
      }

      /* Find least cost match. */
      List<Set<String>> a = new LinkedList<Set<String>>(), b = new LinkedList<Set<String>>();
      for (Cell c : children) {
        Set<String> s = new HashSet<String>(c.getBundles());
        a.add(s);
      }
      b = new LinkedList<Set<String>>(optimized.getColorVertexMapping()
          .values());
      while (b.size() < a.size())
        b.add(new HashSet<String>());

      ref = System.currentTimeMillis();
      Map<Integer, Integer> matching = SetMatching.findBestMatch(a, b);
      LOGGER.debug("matching took {} ms", System.currentTimeMillis()
          - ref);
      for (Map.Entry<Integer, Integer> e : matching.entrySet()) {
        Integer cellIdx = e.getKey();
        Set<String> s1 = a.get(cellIdx), s2 = b.get(e.getValue());
        Cell c = children.get(cellIdx);
        boolean dirty = false;
        for (String r : s1) {
          if (!s2.contains(r)) {
            c.remove(r, ops);
            dirty = true;
          }
        }
        for (String r : s2) {
          if (!s1.contains(r)) {
            c.add(r, ops);
            dirty = true;
          }
        }
        if (dirty && !c.isEmpty()) {
          c.optimize(ops);
        }
      }
      for (Iterator<Cell> it = children.iterator(); it.hasNext();) {
        Cell c = it.next();
        if (c.isEmpty())
          it.remove();
      }
    }
  }

  interface CellVisitor {
    void visit(Cell c);
  }

}
TOP

Related Classes of org.iosgi.impl.engine.IsolationEngineImpl$CellVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.