/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Business Objects nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* LECCProgram.java
* Created: Nov 24, 2003 5:55:26 PM
* By: RCypher
*/
package org.openquark.cal.internal.machine.lecc;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.openquark.cal.compiler.ModuleName;
import org.openquark.cal.machine.Module;
import org.openquark.cal.machine.Program;
import org.openquark.cal.machine.ProgramResourceRepository;
import org.openquark.cal.module.Cal.Core.CAL_Prelude;
import org.openquark.cal.runtime.ExecutionContext;
/**
* The lecc machine specific version of the Program class.
*
* @author rcypher
*/
final class LECCProgram extends Program {
private final ProgramResourceRepository resourceRepository;
/**
* Constructor for a LECCProgram.
* @param resourceRepository the finder for resources generated by this program.
*/
LECCProgram(ProgramResourceRepository resourceRepository) {
this.resourceRepository = resourceRepository;
}
/**
* {@inheritDoc}
*/
@Override
synchronized public void resetCachedResults(ExecutionContext context) {
resetCachedResults (CAL_Prelude.MODULE_NAME, context);
}
/**
* {@inheritDoc}
*/
@Override
synchronized public void resetCachedResults (ModuleName moduleName, ExecutionContext context) {
resetCachedResultsHelper (moduleName, context, new HashSet<ModuleName>());
// run the cleanup hooks when the CAFs are released.
context.cleanup();
}
synchronized private void resetCachedResultsHelper(ModuleName moduleName, ExecutionContext context, Set<ModuleName> resetModules) {
if (resetModules.contains (moduleName)) {
return;
}
LECCModule m = (LECCModule)getModule(moduleName);
if (m == null) {
return;
}
m.resetCachedResults(context);
resetModules.add (moduleName);
for (final Module m2 : getModules()) {
if (m2.dependsOn(moduleName)) {
resetCachedResultsHelper(m2.getName(), context, resetModules);
}
}
}
/**
* {@inheritDoc}
*/
@Override
synchronized public void resetMachineState(ExecutionContext context) {
resetMachineState(CAL_Prelude.MODULE_NAME, context);
}
/**
* {@inheritDoc}
*/
@Override
synchronized public void resetMachineState (ModuleName moduleName, ExecutionContext context) {
resetMachineStateHelper(moduleName, context, new HashSet<ModuleName>());
// run the cleanup hooks when the CAFs are released.
context.cleanup();
}
/**
* Helper method for resetting the machine state for a given module.
* @param moduleName the module whose associated machine state is to be reset.
* @param context the context with which the machine state is associated.
* @param resetModules the modules that have already had their machine state reset.
*/
synchronized private void resetMachineStateHelper(ModuleName moduleName, ExecutionContext context, Set/*ModuleName*/<ModuleName> resetModules) {
if (resetModules.contains (moduleName)) {
return;
}
LECCModule m = (LECCModule)getModule(moduleName);
if (m == null) {
return;
}
m.resetMachineState(context);
resetModules.add (moduleName);
for (final Module m2 : getModules()) {
if (m2.dependsOn(moduleName)) {
resetMachineStateHelper(m2.getName(), context, resetModules);
}
}
}
/**
* @return the machine statistics associated with this program.
*/
synchronized public LECCMachineStatistics getMachineStatistics() {
int totalNRegularClassesLoaded = 0;
int totalNAdjunctClassesLoaded = 0;
int totalNRegularBytesLoaded = 0;
int totalNAdjunctBytesLoaded = 0;
long totalGenerateRegularClassDataTimeMS = 0;
long totalGenerateAdjunctClassDataTimeMS = 0;
long totalLookupRegularClassDataTimeMS = 0;
long totalLookupAdjunctClassDataTimeMS = 0;
long totalRegularFindClassTimeMS = 0;
long totalAdjunctFindClassTimeMS = 0;
for (final Module moduleBase : getModules()) {
LECCModule module = (LECCModule)moduleBase;
totalNRegularClassesLoaded += module.getNClassesLoaded(false);
totalNAdjunctClassesLoaded += module.getNClassesLoaded(true);
totalNRegularBytesLoaded += module.getNClassBytesLoaded(false);
totalNAdjunctBytesLoaded += module.getNClassBytesLoaded(true);
totalGenerateRegularClassDataTimeMS += module.getGenerateClassDataTimeMS(false);
totalGenerateAdjunctClassDataTimeMS += module.getGenerateClassDataTimeMS(true);
totalLookupRegularClassDataTimeMS += module.getLookupClassDataTimeMS(false);
totalLookupAdjunctClassDataTimeMS += module.getLookupClassDataTimeMS(true);
totalRegularFindClassTimeMS += module.getFindClassTimeMS(false);
totalAdjunctFindClassTimeMS += module.getFindClassTimeMS(true);
}
return new LECCMachineStatistics(
totalNRegularClassesLoaded, totalNAdjunctClassesLoaded,
totalNRegularBytesLoaded, totalNAdjunctBytesLoaded,
CALClassLoader.PERFORM_TIMING,
totalGenerateRegularClassDataTimeMS, totalGenerateAdjunctClassDataTimeMS,
totalLookupRegularClassDataTimeMS, totalLookupAdjunctClassDataTimeMS,
totalRegularFindClassTimeMS, totalAdjunctFindClassTimeMS);
}
/**
* @param moduleName
* @return the machine statistics associated with the given module.
*/
synchronized public LECCMachineStatistics getMachineStatisticsForModule(ModuleName moduleName) {
LECCModule module = (LECCModule)getModule(moduleName);
if (module == null) {
return new LECCMachineStatistics(0, 0, 0, 0, false, 0, 0, 0, 0, 0, 0);
}
int totalNRegularClassesLoaded = module.getNClassesLoaded(false);
int totalNAdjunctClassesLoaded = module.getNClassesLoaded(true);
int totalNRegularBytesLoaded = module.getNClassBytesLoaded(false);
int totalNAdjunctBytesLoaded = module.getNClassBytesLoaded(true);
long totalGenerateRegularClassDataTimeMS = module.getGenerateClassDataTimeMS(false);
long totalGenerateAdjunctClassDataTimeMS = module.getGenerateClassDataTimeMS(true);
long totalLookupRegularClassDataTimeMS = module.getLookupClassDataTimeMS(false);
long totalLookupAdjunctClassDataTimeMS = module.getLookupClassDataTimeMS(true);
long totalRegularFindClassTimeMS = module.getFindClassTimeMS(false);
long totalAdjunctFindClassTimeMS = module.getFindClassTimeMS(true);
return new LECCMachineStatistics(
totalNRegularClassesLoaded, totalNAdjunctClassesLoaded,
totalNRegularBytesLoaded, totalNAdjunctBytesLoaded,
CALClassLoader.PERFORM_TIMING,
totalGenerateRegularClassDataTimeMS, totalGenerateAdjunctClassDataTimeMS,
totalLookupRegularClassDataTimeMS, totalLookupAdjunctClassDataTimeMS,
totalRegularFindClassTimeMS, totalAdjunctFindClassTimeMS);
}
/**
* Add a module to this program.
* Normally called by a Loader.
* Derived Program classes create a type-specific module object and then call addModule (Module)
* Creation date: (3/17/00 4:11:18 PM)
* @param moduleName
* @param foreignClassLoader the classloader to use to resolve foreign classes for the module.
* @return the newly created Module
*/
@Override
synchronized public Module addModule(ModuleName moduleName, ClassLoader foreignClassLoader) {
Module module = new LECCModule(moduleName, foreignClassLoader, resourceRepository);
addModule (module);
return module;
}
/**
* Add the given module to this program.
* @param module
*/
@Override
synchronized public void addModule (Module module) {
super.addModule (module);
// Deserialization code does not set the repository.
LECCModule leccModule = (LECCModule)module;
if (!leccModule.hasRepository()) {
leccModule.setRepository(resourceRepository);
}
}
@Override
public String toString () {
StringBuilder sb = new StringBuilder();
sb.append ("Program: ");
List<Module> modules = getModules();
for (int i = 0, n = modules.size(); i < n; ++i) {
sb.append((modules.get(i)).getName());
if (i < n-1) {
sb.append(", ");
}
}
return sb.toString();
}
}