rubah.runtime.state.ComputingUpdateMetadata.java Source code

Java tutorial

Introduction

Here is the source code for rubah.runtime.state.ComputingUpdateMetadata.java

Source

/*******************************************************************************
 *     Copyright 2014,
 *        Luis Pina <luis@luispina.me>,
 *        Michael Hicks <mwh@cs.umd.edu>
 *     
 *     This file is part of Rubah.
 *
 *     Rubah 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.
 *
 *     Rubah 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 Rubah.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package rubah.runtime.state;

import java.io.File;
import java.util.LinkedList;
import java.util.Set;

import org.objectweb.asm.Opcodes;

import rubah.Rubah;
import rubah.framework.Clazz;
import rubah.runtime.Version;
import rubah.runtime.VersionManager;
import rubah.runtime.classloader.RubahClassloader;
import rubah.runtime.state.migrator.UnsafeUtils;

public class ComputingUpdateMetadata extends RubahState implements Opcodes {
    private static final String UPDATE_PACKAGE_DUMP_FILE_PROPERTY = "dumpUpdatePackage";
    private static final File UPDATE_PACKAGE_DUMP_FILE;

    static {
        String fileName = System.getProperty(UPDATE_PACKAGE_DUMP_FILE_PROPERTY);
        if (fileName != null)
            UPDATE_PACKAGE_DUMP_FILE = new File(fileName);
        else
            UPDATE_PACKAGE_DUMP_FILE = null;
    }

    public ComputingUpdateMetadata(UpdateState state) {
        super(state);
    }

    @Override
    public void doStart() {
        long time = System.currentTimeMillis();
        Version v1 = VersionManager.getInstance().getLatestVersion();

        LinkedList<Class<?>> loadedClasses = null;
        synchronized (RubahClassloader.class) {
            loadedClasses = new LinkedList<Class<?>>(RubahClassloader.getLoadedClasses());
        }

        //      Map<String, ClassRedefinition> redefinitions = null;
        //      File updatePackage = this.state.getOptions().getUpdatePackage();
        //      ObjectInputStream ois = null;
        //
        //      try {
        //         if (updatePackage != null) {
        //            ois = new ObjectInputStream(new FileInputStream(updatePackage));
        //            redefinitions = (Map<String, ClassRedefinition>) ois.readObject();
        //         }
        //      } catch (FileNotFoundException e) {
        //         throw new Error(e);
        //      } catch (IOException e) {
        //         throw new Error(e);
        //      } catch (ClassNotFoundException e) {
        //         throw new Error(e);
        //      } finally {
        //         try {
        //            if (ois != null)
        //               ois.close();
        //         } catch (IOException e) {
        //            // Don't care
        //         }
        //      }

        //      if (redefinitions == null) {
        //         ObjectOutputStream oos = null;
        //         try {
        //            redefinitions = computeBytecode(v1, loadedClasses);
        //
        //            if (UPDATE_PACKAGE_DUMP_FILE != null) {
        //               oos = new ObjectOutputStream(new FileOutputStream(UPDATE_PACKAGE_DUMP_FILE));
        //               oos.writeObject(redefinitions);
        //            }
        //
        //         } catch (IOException e) {
        //            throw new Error(e);
        //         } finally {
        //            if (oos != null)
        //               try {
        //                  oos.close();
        //               } catch (IOException e) {
        //                  // Don't care
        //               }
        //         }
        //      }
        //
        //      state.setRedefinitions(redefinitions);

        for (Class<?> c0 : loadedClasses) {
            String originalName = v1.getOriginalName(c0.getName());

            if (originalName == null)
                continue;

            Class<?> c1;
            try {
                c1 = Class.forName(v1.getUpdatableName(originalName), false, Rubah.getLoader());
            } catch (ClassNotFoundException e) {
                throw new Error(e);
            }

            UnsafeUtils.getInstance().setOffsets(c0);
            UnsafeUtils.getInstance().setOffsets(c1);
        }

        time = System.currentTimeMillis() - time;
        System.out.println("Time spent computing update metadata " + time + "ms");
    }

    @Override
    public void update(String updatePoint) {
        /* Empty */
    }

    @Override
    public boolean isUpdating() {
        return false;
    }

    @Override
    public boolean isUpdateRequested() {
        return false;
    }

    private static void computeInterestingAndFailfastClasses(Set<String> interestingClassNames,
            Set<String> failfastClassNames, Version version) {
        for (Clazz c1 : version.getNamespace().getDefinedClasses()) {

            for (Version v = version; v != null; v = v.getPrevious()) {
                Clazz c0 = v.getUpdate().getV0(c1);

                if (c0 == null) {
                    // Class introduced in version v
                    interestingClassNames.add(v.getUpdatableName(c1.getFqn()));
                    break;
                }

                if (v == version && v.getUpdate().isUpdated(c0)) {
                    failfastClassNames.add(v.getPrevious().getUpdatableName(c1.getFqn()));
                    interestingClassNames.add(v.getUpdatableName(c1.getFqn()));
                    break;
                }

                if (v.getPrevious() == null) {
                    interestingClassNames.add(v.getUpdatableName(c1.getFqn()));
                    break;
                }
            }
        }
    }

    //   public Map<String, ClassRedefinition> computeBytecode(Version version, Collection<Class<?>> loadedClasses) throws IOException {
    //      Set<String> interestingClassNames = new HashSet<String>();
    //      Set<String> failfastClassNames = new HashSet<String>();
    //
    //      computeInterestingAndFailfastClasses(interestingClassNames, failfastClassNames, version);
    //
    //      Map<String, ClassRedefinition> redefinitions = new HashMap<String, ClassRedefinition>();
    //
    //      for (Class<?> loadedClass : loadedClasses) {
    //         String className = loadedClass.getName();
    //         byte[] scaffoldedBytecodes = null;
    //         byte[] newBytecodes = null;
    //         boolean classChanged = false;
    //         boolean isFailfast = false;
    //
    //         if (!AddTraverseMethod.isAllowed(className) || loadedClass.equals(Object.class))
    //            continue;
    //
    //         if (className.startsWith("org.apache.commons.io")) {
    //            // Loaded by Rubah and bypassed bytecode processing, disregard
    //            continue;
    //         }
    //
    //         String originalName = version.getOriginalName(className);
    //
    //         if (originalName == null) {
    //            // Non-updatable, update refs to old code
    //
    //            GetMostRecentUsedFactory f = this.getMostRecentUsedFactory();
    //            scaffoldedBytecodes = UpdateManager.getInstance().getClassBytes(className, version, f);
    //
    //            classChanged = (f.mostRecentVersionUsed == UpdateManager.getInstance().getLatestVersion());
    //            if (classChanged)
    //               newBytecodes = UpdateManager.getInstance().getClassBytes(className, version);
    //
    //         } else if (failfastClassNames.contains(className)) {
    //               // TODO: Compute failfast bytecode
    //               classChanged = true;
    //               isFailfast = true;
    //         }
    //
    //         ClassRedefinition bytecode = new ClassRedefinition(scaffoldedBytecodes, newBytecodes, isFailfast, classChanged);
    //         redefinitions.put(className, bytecode);
    //      }
    //
    //      for (String className : interestingClassNames) {
    //         GetMostRecentUsedFactory f = this.getMostRecentUsedFactory();
    //         byte[] scaffoldedBytecodes = UpdateManager.getInstance().getClassBytes(className, version, f);
    //         boolean classChanged = (f.mostRecentVersionUsed == UpdateManager.getInstance().getLatestVersion());
    //         byte[] newBytecodes = UpdateManager.getInstance().getClassBytes(className, version);
    //         ClassRedefinition bytecode = new ClassRedefinition(scaffoldedBytecodes, newBytecodes, false, classChanged);
    //         redefinitions.put(className, bytecode);
    //      }
    //
    //      return redefinitions;
    //   }
    //
    //   protected GetMostRecentUsedFactory getMostRecentUsedFactory() {
    //      return new GetMostRecentUsedFactory();
    //   }
    //
    //   protected class GetMostRecentUsedFactory extends TransformerFactory {
    //      protected Version mostRecentVersionUsed;
    //
    //      @Override
    //      public ClassVisitor getUpdatableClassRenamer(
    //            HashMap<String, Object> objectsMap,
    //            Version version,
    //            Namespace namespace,
    //            ClassVisitor visitor) {
    //         return new UpdatableClassRenamerVersionGetter(version, objectsMap, namespace, visitor);
    //      }
    //
    //      protected void registerVersion(Type type) {
    //         Version v = UpdateManager.getInstance().getIntroducedVersion(type.getClassName());
    //
    //         if (this.mostRecentVersionUsed == null || v.getNumber() > this.mostRecentVersionUsed.getNumber()) {
    //            this.mostRecentVersionUsed = v;
    //         }
    //      }
    //
    //      protected class UpdatableClassRenamerVersionGetter extends UpdatableClassRenamer {
    //         public UpdatableClassRenamerVersionGetter(Version version,
    //               HashMap<String, Object> objectsMap, Namespace namespace,
    //               ClassVisitor cv) {
    //            super(version, objectsMap, namespace, cv);
    //         }
    //
    //         @Override
    //         protected Type renameIfUpdatable(Type type) {
    //            Type ret = super.renameIfUpdatable(type);
    //
    //            if (ret != type)
    //               registerVersion(ret);
    //
    //            return ret;
    //         }
    //      }
    //   }
}