1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.tests.api.request.misc;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.UUID;
18 import org.junit.Test;
19 import org.simantics.databoard.Bindings;
20 import org.simantics.db.ReadGraph;
21 import org.simantics.db.Resource;
22 import org.simantics.db.Session;
23 import org.simantics.db.WriteGraph;
24 import org.simantics.db.exception.DatabaseException;
25 import org.simantics.db.procedure.Listener;
26 import org.simantics.db.request.Read;
27 import org.simantics.db.testing.base.ExistingDatabaseTest;
28 import org.simantics.db.testing.common.WriteQuery;
29 import org.simantics.db.tests.common.Configuration;
30 import org.simantics.layer0.Layer0;
33 * This test uses several threads to write the graph information and queries to react information changes.
35 * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
38 public class ComplexReadWriteQueryTest extends ExistingDatabaseTest {
40 public static int NUM_THREADS = Configuration.get().rwQueryThreds;;
41 public static int MAX_CHANGES = Configuration.get().rwQueryCount;
43 List<NameUpdateThread> threads = new ArrayList<NameUpdateThread>();
44 int changes; // not quite correct but works for me
45 volatile int endCount = 0;
47 boolean ended = false;
49 private synchronized void incChanges() {
50 // System.out.println("changes = " + changes);
55 public void test() throws Exception {
56 final Resource rootLib = getSession().getRootLibrary();
57 for (int i = 0; i < NUM_THREADS; i++) {
58 getSession().asyncRequest(new WriteQuery(this) {
60 public void run(WriteGraph g) throws Throwable {
61 //System.out.println("creating test resource");
62 Layer0 b = Layer0.getInstance(g);
63 Resource newResource = g.newResource();
64 g.claim(newResource, b.InstanceOf, b.Type);
65 g.claim(rootLib, b.ConsistsOf, newResource);
66 String name = getRandomString();
67 g.claimLiteral(newResource, b.HasName, name, Bindings.STRING);
68 NameUpdateThread t = new NameUpdateThread(getSession(),newResource,name);
75 System.out.println("Created " + NUM_THREADS + " threads.");
76 self = Thread.currentThread();
78 int lastChanges = changes;
82 } catch (InterruptedException e) {
84 System.out.println("Interrupted.");
87 if (test && lastChanges == changes) {
89 throw new Exception("No changes in ten seconds, probably database has died. changes="+changes);
93 } catch (Exception e) {
100 System.out.println("ended, changes = " + changes);
106 for (NameUpdateThread t : threads) {
111 } catch (InterruptedException e) {
117 static volatile int threadCount=0;
118 public class NameUpdateThread extends Thread {
119 private boolean disposed = false;
120 private Resource resource;
121 private String currentName;
122 private Session session;
123 //private NameQuery query;
124 private Listener<String> procedure;
125 private NameRead nameRead;
126 public NameUpdateThread(Session session, Resource resource, String name) {
127 super("RWQueryTest-" + ++threadCount);
128 this.currentName = name;
129 this.resource = resource;
130 this.session = session;
135 procedure = new Listener<String>() {
137 public void execute(String result) {
138 NameUpdateThread.this.interrupt();
142 public void exception(Throwable t) {
143 ComplexReadWriteQueryTest.fail();
147 public boolean isDisposed() {
154 nameRead = new NameRead(resource);
155 //System.out.println("creating query");
156 session.asyncRequest(new WriteQuery(ComplexReadWriteQueryTest.this) {
158 public void run(WriteGraph g) throws Throwable {
159 g.syncRequest(nameRead, procedure);
162 // sleep until interrupted (if query fails, we still are updating the value)
163 Thread.sleep(1000000000);
164 } catch (InterruptedException e) {
174 public void updateName() {
175 session.asyncRequest(new WriteQuery(ComplexReadWriteQueryTest.this) {
177 public void run(WriteGraph g) throws Throwable {
178 Layer0 b = Layer0.getInstance(g);
179 String graphName = g.getRelatedValue(resource, b.HasName);
180 if(!graphName.equals(currentName)) {
181 throw new Exception("Graph contains name " + graphName + " while name was set to " + currentName);
183 currentName = UUID.randomUUID().toString();
184 g.claimLiteral(resource, b.HasName, currentName, Bindings.STRING);
185 if (changes >= MAX_CHANGES) {
190 // System.out.println("changes="+changes);
191 //System.out.println("Name change " +procedure.toString());
197 public void dispose() {
200 if (endCount >= NUM_THREADS) {
211 public class NameRead implements Read<String> {
212 private Resource resource;
214 public NameRead(Resource resource) {
215 this.resource = resource;
219 public String perform(ReadGraph graph) throws DatabaseException {
220 Layer0 b = Layer0.getInstance(graph);
221 String name = graph.getRelatedValue(resource, b.HasName, Bindings.STRING);