Changeset 13631


Ignore:
Timestamp:
Oct 1, 2019 3:03:38 PM (2 months ago)
Author:
Jonathan Kämpe
Message:

#5837 Moved some classes

Location:
branches/dev-cw-evaluator/Compiler
Files:
7 added
5 edited

Legend:

Unmodified
Added
Removed
  • branches/dev-cw-evaluator/Compiler/ModelicaFlatTree/src/jastadd/ConstantEvaluation/ExternalConstantEvaluation.jrag

    r13629 r13631  
    2626import java.util.TimerTask;
    2727
     28import org.jmodelica.common.evaluation.Compiler;
    2829import org.jmodelica.common.evaluation.ExternalFunction;
    2930import org.jmodelica.common.evaluation.ExternalProcessCache;
    3031import org.jmodelica.common.evaluation.ExternalProcessCacheImpl;
    3132import org.jmodelica.common.evaluation.ExternalProcessMultiCache;
     33import org.jmodelica.common.evaluation.FailedExternalFunction;
    3234import org.jmodelica.common.evaluation.ProcessCommunicator;
    3335
     
    4951    class ModelicaCompiler {}
    5052   
    51     ModelicaCompiler   implements ExternalProcessMultiCache.Compiler<ExternalArgument, FExternalStmt>;
     53    ModelicaCompiler   implements Compiler<ExternalArgument, FExternalStmt>;
    5254    FExternalStmt      implements ExternalProcessMultiCache.External<ExternalArgument>;
    5355    ExternalArgument   extends    ExternalProcessMultiCache.Variable<CValue,FType>;
     
    172174        ExternalFunctionCache efc = root().getUtilInterface().getExternalFunctionCache();
    173175        if (efc == null) {
    174             return new ExternalProcessCacheImpl<>(root().getUtilInterface().getModelicaCompiler())
    175                 .failedEval(this, "external function cache unavailable", false);
     176            return FailedExternalFunction.<ExternalArgument, CValue, FType, FExternalStmt>failedEval(
     177                    root().getUtilInterface().getModelicaCompiler(),
     178                    this, "external function cache unavailable", false);
    176179        }
    177180        return efc.getExternalProcessCache(getLibTopPackagePath()).getExternalFunction(this);
     
    208211       
    209212        if (error != null) {
    210             throw new ConstantEvaluationException(null, ExternalProcessCacheImpl.failedEvalMsg(getName(), error));
     213            throw new ConstantEvaluationException(null, FailedExternalFunction.failedEvalMsg(getName(), error));
    211214        }
    212215       
  • branches/dev-cw-evaluator/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/common/evaluation/ExternalProcessCache.java

    r10910 r13631  
    2424
    2525    protected abstract void tearDown();
    26 
    27     public abstract ExternalFunction<K, V> failedEval(External<?> ext, String msg, boolean log);
    2826   
    2927
  • branches/dev-cw-evaluator/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/common/evaluation/ExternalProcessCacheImpl.java

    r13629 r13631  
    33import java.io.File;
    44import java.io.FileNotFoundException;
    5 import java.io.IOException;
    65import java.io.PrintStream;
    76import java.util.ArrayList;
     
    1211import java.util.Set;
    1312
    14 import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Compiler;
    1513import org.jmodelica.common.evaluation.ExternalProcessMultiCache.External;
    1614import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Type;
     
    2220import org.jmodelica.util.exceptions.CcodeCompilationException;
    2321import org.jmodelica.util.logging.ModelicaLogger;
    24 import org.jmodelica.util.values.ConstantEvaluationException;
    2522
    2623public class ExternalProcessCacheImpl<K extends Variable<V, T>, V extends Value, T extends Type<V>, E extends External<K>> extends ExternalProcessCache<K, V, T, E> {
     
    140137        if (ef == null) {
    141138            if (mc == null) {
    142                 return failedEval(ext, "Missing ModelicaCompiler", false);
     139                return FailedExternalFunction.<K,V,T,E>failedEval(mc, ext, "Missing ModelicaCompiler", false);
    143140            }
    144141            try {
     
    169166               
    170167                if (ext.processLimit() > 0) {
    171                     ef = new MappedExternalFunction(ext, extFunctionExecutable);
     168                    ef = new MappedExternalFunction<K,V,T,E>(mc, ext, extFunctionExecutable, livingCachedExternals);
    172169                } else {
    173                     ef = new CompiledExternalFunction(ext, extFunctionExecutable);
     170                    ef = new CompiledExternalFunction<K,V,T,E>(mc, ext, extFunctionExecutable);
    174171                }
    175172                time = System.currentTimeMillis() - time;
    176173                mc.log().debug(debugMsg +", time: " + time + "ms");
    177174            } catch (FileNotFoundException e) {
    178                 ef = failedEval(ext, "c-code generation failed '" + e.getMessage() + "'", true);
     175                ef = FailedExternalFunction.<K,V,T,E>failedEval(mc, ext, "c-code generation failed '" + e.getMessage() + "'", true);
    179176                mc.log().debug(ef.getMessage());
    180177            } catch (CcodeCompilationException e) {
    181                 ef = failedEval(ext, "c-code compilation failed '" + e.getMessage() + "'", true);
     178                ef = FailedExternalFunction.<K,V,T,E>failedEval(mc, ext, "c-code compilation failed '" + e.getMessage() + "'", true);
    182179                mc.log().debug(ef.getMessage());
    183180                e.printStackTrace(new PrintStream(mc.log().debugStream()));
     
    209206    }
    210207
    211     @Override
    212     public ExternalFunction<K, V> failedEval(External<?> ext, String msg, boolean log) {
    213         return new FailedExternalFunction(failedEvalMsg(ext.getName(), msg), log);
    214     }
    215 
    216     public static String failedEvalMsg(String name, String msg) {
    217         return "Failed to evaluate external function '" + name + "', " + msg;
    218     }
    219    
    220     private abstract class ExternalFunctionExecutable {
    221        
    222         public abstract ProcessBuilder createProcessBuilder();
    223        
    224         public abstract void remove();
    225     }
    226    
    227     private class CompiledExternalFunctionExecutable extends ExternalFunctionExecutable {
    228         protected String executable;
    229        
    230         public CompiledExternalFunctionExecutable(String executable) {
    231             this.executable = executable;
    232         }
    233        
    234         @Override
    235         public ProcessBuilder createProcessBuilder() {
    236             return new ProcessBuilder(executable);
    237         }
    238        
    239         @Override
    240         public void remove() {
    241             new File(executable).delete();
    242         }
    243     }
    244    
    245    
    246     private class DynamicExternalFunctionExecutable extends ExternalFunctionExecutable {
    247         protected ArrayList<String> executable;
    248        
    249         public DynamicExternalFunctionExecutable(ArrayList<String> executable) {
    250             this.executable = executable;
    251         }
    252        
    253         @Override
    254         public ProcessBuilder createProcessBuilder() {
    255             return new ProcessBuilder(executable);
    256         }
    257         @Override
    258         public void remove() {
    259             // Do not remove the dynamic executable
    260         }
    261     }
    262 
    263     private class FailedExternalFunction implements ExternalFunction<K, V> {
    264         private String msg;
    265         private boolean log;
    266 
    267         public FailedExternalFunction(String msg, boolean log) {
    268             this.msg = msg;
    269             this.log = log;
    270         }
    271 
    272         @Override
    273         public String getMessage() {
    274             return msg;
    275         }
    276 
    277         @Override
    278         public int evaluate(External<K> ext, Map<K, V> values, int timeout) throws IOException {
    279             if (log) {
    280                 log().debug("Evaluating failed external function: " + ext.getName());
    281             }
    282             throw new ConstantEvaluationException(null, getMessage());
    283         }
    284 
    285         @Override
    286         public void destroyProcess() {
    287             // Do nothing
    288         }
    289 
    290         @Override
    291         public void remove() {
    292             // Do nothing
    293         }
    294     }
    295 
    296     /**
    297      * Represents an external function that has been compiled successfully.
    298      */
    299     private class CompiledExternalFunction implements ExternalFunction<K, V> {
    300         protected ExternalFunctionExecutable extFunctionExecutable;
    301         protected ProcessBuilder processBuilder;
    302         private String msg;
    303 
    304         public CompiledExternalFunction(External<K> ext, ExternalFunctionExecutable extFunctionExecutable) {
    305             this.extFunctionExecutable = extFunctionExecutable;
    306             this.processBuilder = createProcessBuilder(ext);
    307             this.msg = "Succesfully compiled external function '" + ext.getName() + "'";
    308         }
    309 
    310         @Override
    311         public String getMessage() {
    312             return msg;
    313         }
    314 
    315         protected ProcessCommunicator<V, T> createProcessCommunicator() throws IOException {
    316             return new ProcessCommunicator<V, T>(mc, processBuilder.start());
    317         }
    318 
    319         @Override
    320         public int evaluate(External<K> ext, Map<K, V> values, int timeout) throws IOException {
    321             log().debug("Evaluating compiled external function: " + ext.getName());
    322             ProcessCommunicator<V, T> com = null;
    323             try {
    324                 com = createProcessCommunicator();
    325                 setup(ext, values, timeout, com);
    326                 evaluate(ext, values, timeout, com);
    327                 return teardown(timeout, com);
    328             } finally {
    329                 if (com != null) {
    330                     com.destroy();
    331                 }
    332             }
    333         }
    334 
    335         public void setup(External<K> ext, Map<K, V> values, int timeout, ProcessCommunicator<V, T> com)
    336                 throws IOException {
    337             com.startTimer(timeout);
    338             com.accept("START");
    339             for (K eo : ext.externalObjectsToSerialize()) {
    340                 com.put(values.containsKey(eo) ? values.get(eo) : eo.ceval(), eo.type());
    341             }
    342             com.accept("READY");
    343             com.cancelTimer();
    344         }
    345 
    346         public void evaluate(External<K> ext, Map<K, V> values, int timeout, ProcessCommunicator<V, T> com)
    347                 throws IOException {
    348             com.startTimer(timeout);
    349             com.check("EVAL");
    350 
    351             for (K arg : ext.functionArgsToSerialize()) {
    352                 com.put(values.containsKey(arg) ? values.get(arg) : arg.ceval(), arg.type());
    353             }
    354             com.accept("CALC");
    355             com.accept("DONE");
    356             for (K cvd : ext.varsToDeserialize()) {
    357                 values.put(cvd, com.get(cvd.type()));
    358             }
    359             com.accept("READY");
    360             com.cancelTimer();
    361         }
    362 
    363         public int teardown(int timeout, ProcessCommunicator<V, T> com) throws IOException {
    364             com.startTimer(timeout);
    365             com.check("EXIT");
    366             com.accept("END");
    367             int result = com.end();
    368             com.cancelTimer();
    369             // log().debug("SUCCESS TEARDOWN");
    370             return result;
    371         }
    372 
    373         @Override
    374         public void destroyProcess() {
    375             // Do nothing
    376         }
    377 
    378         @Override
    379         public void remove() {
    380             extFunctionExecutable.remove();
    381         }
    382 
    383         private ProcessBuilder createProcessBuilder(External<K> ext) {
    384             ProcessBuilder pb = extFunctionExecutable.createProcessBuilder();
    385             Map<String, String> env = pb.environment();
    386             if (env.keySet().contains("Path")) {
    387                 env.put("PATH", env.get("Path"));
    388                 env.remove("Path");
    389             }
    390             pb.redirectErrorStream(true);
    391             if (ext.libraryDirectory() != null) {
    392                 // Update environment in case of shared library
    393                 String platform = CCompilerDelegator.reduceBits(EnvironmentUtils.getJavaPlatform(),
    394                         mc.getCCompiler().getTargetPlatforms());
    395                 File f = new File(ext.libraryDirectory(), platform);
    396                 String libLoc = f.isDirectory() ? f.getPath() : ext.libraryDirectory();
    397                 appendPath(env, libLoc, platform);
    398             }
    399             return pb;
    400         }
    401 
    402         /**
    403          * Append a library location <code>libLoc</code> to the path variable in
    404          * environment <code>env</code>.
    405          */
    406         private void appendPath(Map<String, String> env, String libLoc, String platform) {
    407             String sep = platform.startsWith("win") ? ";" : ":";
    408             String var = platform.startsWith("win") ? "PATH" : "LD_LIBRARY_PATH";
    409             String res = env.get(var);
    410             if (res == null) {
    411                 res = libLoc;
    412             } else {
    413                 res = res + sep + libLoc;
    414             }
    415             env.put(var, res);
    416         }
    417     }
    418 
    419     /**
    420      * A CompiledExternalFunction which can cache several processes with external
    421      * object constructor only called once.
    422      */
    423     private class MappedExternalFunction extends CompiledExternalFunction {
    424 
    425         private Map<String, ExternalFunction<K, V>> lives = new HashMap<>();
    426 
    427         private final int externalConstantEvaluationMaxProc;
    428 
    429         public MappedExternalFunction(External<K> ext, ExternalFunctionExecutable extFunctionExecutable) {
    430             super(ext, extFunctionExecutable);
    431             externalConstantEvaluationMaxProc = ext.processLimit();
    432         }
    433 
    434         /**
    435          * Find a LiveExternalFunction based on the external object of this external
    436          * function. Start a new process if not up already. Failure to set up (call
    437          * constructor) will cache and return a Failed external function.
    438          */
    439         private ExternalFunction<K, V> getActual(External<K> ext, Map<K, V> values, int timeout) {
    440             Variable<V, T> cvd = ext.cachedExternalObject();
    441             String name = cvd == null ? "" : cvd.ceval().getMarkedExternalObject();
    442             ExternalFunction<K, V> ef = lives.get(name);
    443             if (ef == null) {
    444                 LiveExternalFunction lef = new LiveExternalFunction();
    445                 try {
    446                     lef.ready(ext, values, timeout);
    447                     ef = lef;
    448                 } catch (IOException e) {
    449                     lef.destroyProcess();
    450                     ef = failedEval(ext, " error starting process '" + e.getMessage() + "'", true);
    451                 } catch (ConstantEvaluationException e) {
    452                     lef.destroyProcess();
    453                     ef = failedEval(ext, " error starting process '" + e.getMessage() + "'", true);
    454                 }
    455                 lives.put(name, ef);
    456             }
    457             return ef;
    458         }
    459 
    460         @Override
    461         public int evaluate(External<K> ext, Map<K, V> values, int timeout) throws IOException {
    462             return getActual(ext, values, timeout).evaluate(ext, values, timeout);
    463         }
    464 
    465         @Override
    466         public void destroyProcess() {
    467             for (ExternalFunction<K, V> ef : lives.values()) {
    468                 ef.destroyProcess();
    469             }
    470             lives.clear();
    471         }
    472 
    473         /**
    474          * Represents a (possible) living external function process.
    475          */
    476         private class LiveExternalFunction implements ExternalFunction<K, V> {
    477 
    478             protected ProcessCommunicator<V, T> com;
    479 
    480             public LiveExternalFunction() {
    481                 super();
    482             }
    483 
    484             @Override
    485             public String getMessage() {
    486                 return MappedExternalFunction.this.getMessage();
    487             }
    488 
    489             @Override
    490             public int evaluate(External<K> ext, Map<K, V> values, int timeout) throws IOException {
    491                 log().debug("Evaluating live external function: " + ext.getName());
    492                 try {
    493                     ready(ext, values, timeout);
    494                     long time = System.currentTimeMillis();
    495                     MappedExternalFunction.this.evaluate(ext, values, timeout, com);
    496                     time = System.currentTimeMillis() - time;
    497                     log().debug("Finished evaluating live external function, time: " + time + "ms");
    498                 } catch (ProcessCommunicator.AbortConstantEvaluationException e) {
    499 
    500                 } catch (ConstantEvaluationException e) {
    501                     destroyProcess();
    502                     throw e;
    503                 } catch (IOException e) {
    504                     destroyProcess();
    505                     throw e;
    506                 }
    507                 return 0;
    508             }
    509 
    510             /**
    511              * Make sure process is ready for evaluation call.
    512              */
    513             protected void ready(External<K> ext, Map<K, V> values, int timeout) throws IOException {
    514                 if (com == null) {
    515                     long time1 = System.currentTimeMillis();
    516                     // Start process if not live.
    517                     com = createProcessCommunicator();
    518                     long time2 = System.currentTimeMillis();
    519                     // Send external object constructor inputs
    520                     MappedExternalFunction.this.setup(ext, values, timeout, com);
    521                     long time3 = System.currentTimeMillis();
    522                     log().debug("Setup live external function: " + ext.getName()
    523                               + ", createProcessCommunicator() time: " + (time2 - time1)
    524                               + "ms, setup time: " + (time3 - time2) + "ms");
    525                 }
    526 
    527                 // Mark as most recently used
    528                 livingCachedExternals.remove(this);
    529                 livingCachedExternals.add(this);
    530 
    531                 // If we are over the allowed number of cached processes
    532                 // we kill the least recently used.
    533                 if (livingCachedExternals.size() > externalConstantEvaluationMaxProc) {
    534                     livingCachedExternals.iterator().next().destroyProcess();
    535                 }
    536             }
    537 
    538             @Override
    539             public void destroyProcess() {
    540                 if (com != null) {
    541                     livingCachedExternals.remove(this);
    542                     com.destroy();
    543                     com = null;
    544                 }
    545             }
    546 
    547             @Override
    548             public void remove() {
    549                 // Removing this executable is handled by surrounding MappedExternalFunction
    550                 throw new UnsupportedOperationException();
    551             }
    552         }
    553     }
    554208}
  • branches/dev-cw-evaluator/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/common/evaluation/ExternalProcessMultiCache.java

    r13629 r13631  
    22
    33import java.io.BufferedWriter;
    4 import java.io.FileNotFoundException;
    54import java.io.IOException;
    65import java.util.LinkedHashMap;
    76import java.util.Map;
    87
    9 import org.jmodelica.common.LogContainer;
    108import org.jmodelica.common.options.AbstractOptionRegistry;
    11 import org.jmodelica.util.ccompiler.CCompilerDelegator;
    12 import org.jmodelica.util.exceptions.CcodeCompilationException;
    139
    1410public class ExternalProcessMultiCache<K extends ExternalProcessMultiCache.Variable<V, T>, V extends ExternalProcessMultiCache.Value, T extends ExternalProcessMultiCache.Type<V>, E extends ExternalProcessMultiCache.External<K>> {
    15 
    16     public interface Compiler<K, E extends External<K>> extends LogContainer {
    17         public String compileExternal(E ext) throws FileNotFoundException, CcodeCompilationException;
    18 
    19         public CCompilerDelegator getCCompiler();
    20     }
    2111
    2212    public interface External<K> {
  • branches/dev-cw-evaluator/Compiler/ModelicaFrontEnd/test/junit/org/jmodelica/test/common/ExternalProcessCacheTest.java

    r13629 r13631  
    99import java.io.IOException;
    1010
     11import org.jmodelica.common.evaluation.Compiler;
    1112import org.jmodelica.common.evaluation.ExternalFunction;
    1213import org.jmodelica.common.evaluation.ExternalProcessCache;
     
    108109        }
    109110
    110         @Override
    111         public ExternalFunction<K,V> failedEval(External<?> ext, String msg, boolean log) {
    112             // TODO Auto-generated method stub
    113             return null;
    114         }
    115        
    116     }
    117 
    118     class CompilerMock implements ExternalProcessMultiCache.Compiler<VariableMock, ExternalMock> {
     111    }
     112
     113    class CompilerMock implements Compiler<VariableMock, ExternalMock> {
    119114
    120115        @Override
Note: See TracChangeset for help on using the changeset viewer.