import org.simantics.db.procedure.AsyncProcedure;
public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result> {
+<<<<<<< Upstream, based on branch 'private/antti_threads' of ssh://villberg@gerrit.simantics.org:29418/simantics/platform.git
final private Object key;
final private ReadGraphImpl graph;
public Result getResult() {
return result;
+=======
+
+ final private static Object NO_RESULT = new Object();
+
+ final private Object key;
+ final private ReadGraphImpl graph;
+ final private AsyncProcedure<Result> procedure;
+
+ private Object result = NO_RESULT;
+ private Throwable exception = null;
+
+ public BlockingAsyncProcedure(ReadGraphImpl graph, AsyncProcedure<Result> procedure, Object key) {
+ this.procedure = procedure;
+ this.key = key;
+ this.graph = ReadGraphImpl.newAsync(graph);
+ this.graph.asyncBarrier.inc();
+ }
+
+ @Override
+ public void execute(AsyncReadGraph graph, Result result) {
+ this.result = result;
+ this.graph.asyncBarrier.dec();
+ try {
+ if(procedure != null) procedure.execute(graph, result);
+ } catch (Throwable throwable) {
+ Logger.defaultLogError("AsyncProcedure.execute threw for " + procedure, throwable);
+ }
+ }
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable t) {
+ this.exception = t;
+ try {
+ if(procedure != null) procedure.exception(graph, t);
+ } catch (Throwable throwable) {
+ Logger.defaultLogError("AsyncProcedure.exception threw for " + procedure, throwable);
+ } finally {
+ }
+ this.graph.asyncBarrier.dec();
+ }
+
+ public Result get() throws DatabaseException {
+
+ graph.asyncBarrier.waitBarrier(key, graph);
+
+ if(exception != null) {
+ if(exception instanceof DatabaseException) throw (DatabaseException)exception;
+ throw new DatabaseException(exception);
+ } else {
+ return (Result)result;
+ }
+
+ }
+
+ public Result getResult() {
+ return (Result)result;
+>>>>>>> 82fa68e Generate parts of db client query code
}
public Throwable getException() {
String[] signatureChildMap = { "int r", "r", "keyR", "long", "InternalProcedure<ObjectResourceIdMap<String>>", "entry.id" };
String[] signatureRead = { "Read<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
String[] signatureAsyncRead = { "AsyncRead<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
+<<<<<<< Upstream, based on branch 'private/antti_threads' of ssh://villberg@gerrit.simantics.org:29418/simantics/platform.git
String[] signatureMultiRead = { "MultiRead<?> r", "r", "id", "long", "AsyncMultiProcedure", "entry.request" };
String[] signatureAsyncMultiRead = { "AsyncMultiRead<?> r", "r", "id", "long", "AsyncMultiProcedure", "entry.request" };
String[] signatureExternalRead = { "ExternalRead<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
content.append("import org.simantics.db.request.Read;\n");
content.append("\n");
content.append("import gnu.trove.map.hash.TObjectIntHashMap;\n");
+=======
+ String[] signatureMultiRead = { "MultiRead<?> r", "r", "id", "long", "SyncMultiProcedure", "entry.request" };
+ String[] signatureAsyncMultiRead = { "AsyncMultiRead<?> r", "r", "id", "long", "AsyncMultiProcedure", "entry.request" };
+ String[] signatureExternalRead = { "ExternalRead<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
+
+ private void line(StringBuilder content, String line) {
+ for(int i=0;i<indent;i++)
+ content.append(" ");
+ content.append(line);
+ content.append("\n");
+ }
+
+ public void generateQuery(StringBuilder content, String clazz, String[] signature, boolean runnerShortcut, boolean genAsync) {
+ generateGetOrCreate(content, clazz, signature, genAsync);
+ generateRemove(content, clazz, signature);
+ generateRunner(content, clazz, signature, runnerShortcut, genAsync);
+ }
+
+ public void generateRunner(StringBuilder content, String clazz, String[] signature, boolean shortcut, boolean genAsync) {
+
+ line(content, "public static void runner" + clazz + "(ReadGraphImpl graph, " + signature[0] + ", CacheEntry parent, ListenerBase listener, final " + signature[4] + " procedure" + (genAsync ? ", boolean isSync" : "") + ") throws DatabaseException {");
+ line(content, " QueryCache cache = graph.processor.cache;");
+ if(shortcut) {
+ line(content, " if(parent == null && listener == null && !cache.shouldCache(graph.processor, " + signature[1] + ")) {");
+ line(content, " " + clazz + ".computeForEach(graph, " + signature[1] + ", null, procedure);");
+ line(content, " return;");
+ line(content, " }");
+ }
+ line(content, " " + clazz + " entry = (" + clazz + ")cache.getOrCreate" + clazz + "(graph.processor, " + signature[1] + (genAsync ? ", isSync" : "") + ");");
+ if(genAsync) {
+ line(content, " if(entry == null) {");
+ line(content, " graph.processor.schedule(new SessionTask(false) {");
+ line(content, " @Override");
+ line(content, " public void run(int thread) {");
+ line(content, " try {");
+ line(content, " assert(!isSync);");
+ line(content, " runner" + clazz + "(graph, r, parent, listener, procedure, isSync);");
+ line(content, " } catch (DatabaseException e) {");
+ line(content, " Logger.defaultLogError(e);");
+ line(content, " }");
+ line(content, " }");
+ line(content, " });");
+ line(content, " return;");
+ line(content, " }");
+ }
+ line(content, " " + signature[4] + " procedure_ = procedure != null ? procedure : emptyProcedure" + clazz + ";");
+ line(content, " ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);");
+ line(content, " if(entry.isReady()) entry.performFromCache(graph, procedure_);");
+ line(content, " else {");
+ line(content, " assert(entry.isPending());");
+ if(shortcut) line(content, " " + clazz + ".computeForEach(graph, " + signature[1] + ", entry, procedure_);");
+ else line(content, " entry.compute(graph, procedure_);");
+ line(content, " if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());");
+ line(content, " }");
+ line(content, "}");
+ line(content, "");
+
+ }
+
+ public void generateRemove(StringBuilder content, String clazz, String[] signature) {
+
+ String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
+
+ line(content, "void remove(" + clazz + " entry) {");
+ line(content, " synchronized(" + lower + "Map) {");
+ line(content, " " + lower + "Map.remove(" + signature[5] + ");");
+ line(content, " }");
+ line(content, "}");
+ line(content, "");
+
+ }
+
+ public void generateGetOrCreate(StringBuilder content, String clazz, String[] signature, boolean genAsync) {
+
+ String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
+
+ line(content, "" + clazz + " getOrCreate" + clazz + "(QueryProcessor processor, " + signature[0] + (genAsync ? ", boolean isSync" : "") + ") throws DatabaseException {");
+ line(content, " " + clazz + " existing = null;");
+ line(content, " synchronized(" + lower + "Map) {");
+ line(content, " existing = (" + clazz + ")" + lower + "Map.get(" + signature[1] + ");");
+ line(content, " if(existing == null) {");
+ line(content, " existing = new " + clazz + "(" + signature[1] + ");");
+ line(content, " existing.clearResult(querySupport);");
+ line(content, " existing.setPending();");
+ line(content, " " + lower + "Map.put(" + signature[2] + "(" + signature[1] + "), existing);");
+ line(content, " size++;");
+ line(content, " return existing;");
+ line(content, " }");
+ line(content, " if(existing.requiresComputation()) {");
+ line(content, " existing.setPending();");
+ line(content, " return existing;");
+ line(content, " }");
+ line(content, " }");
+ if(genAsync) {
+ line(content, " if(existing.isPending()) {");
+ line(content, " if(isSync) waitPending(processor, existing);");
+ line(content, " else return null;");
+ line(content, " }");
+ } else {
+ line(content, " if(existing.isPending()) waitPending(processor, existing);");
+ }
+ line(content, " return existing;");
+ line(content, "}");
+ line(content, "");
+
+ }
+
+ public void generate() {
+
+ URL classLocation = CodeGen.class.getResource(".");
+ if (classLocation != null) {
+ if (classLocation.getProtocol().equals("file")) {
+ try {
+ URL resource = new URL(classLocation, ".");
+ File path = new File(URLDecoder.decode(resource.getPath(), "UTF-8"));
+ String target = path.getAbsolutePath().replace("\\", "/");
+ target = target.replace("/bin/", "/src/") + "/QueryCache.java";
+ System.err.println("target=" + target);
+ File source = new File(target);
+ StringBuilder content = new StringBuilder();
+ content.append("package org.simantics.db.impl.query;\n");
+ content.append("\n");
+
+ content.append("import org.simantics.db.ObjectResourceIdMap;\n");
+ content.append("import org.simantics.db.RelationInfo;\n");
+ content.append("import org.simantics.db.common.utils.Logger;\n");
+ content.append("import org.simantics.db.exception.DatabaseException;\n");
+ content.append("import org.simantics.db.impl.graph.ReadGraphImpl;\n");
+ content.append("import org.simantics.db.impl.procedure.InternalProcedure;\n");
+ content.append("import org.simantics.db.impl.query.QueryProcessor.SessionTask;\n");
+ content.append("import org.simantics.db.procedure.AsyncMultiProcedure;\n");
+ content.append("import org.simantics.db.procedure.AsyncProcedure;\n");
+ content.append("import org.simantics.db.procedure.ListenerBase;\n");
+ content.append("import org.simantics.db.procedure.SyncMultiProcedure;\n");
+ content.append("import org.simantics.db.request.AsyncMultiRead;\n");
+ content.append("import org.simantics.db.request.AsyncRead;\n");
+ content.append("import org.simantics.db.request.ExternalRead;\n");
+ content.append("import org.simantics.db.request.MultiRead;\n");
+ content.append("import org.simantics.db.request.Read;\n");
+>>>>>>> 82fa68e Generate parts of db client query code
content.append("\n");
content.append("public class QueryCache extends QueryCacheBase {\n");