--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.tests.client;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.event.SessionEvent;
+import org.simantics.db.event.SessionListener;
+import org.simantics.db.testing.base.ExistingDatabaseTest;
+import org.simantics.db.testing.common.Tests;
+import org.simantics.db.testing.common.WriteQuery;
+import org.simantics.db.tests.common.Configuration;
+import org.simantics.layer0.Layer0;
+
+import fi.vtt.simantics.procore.SessionManagerSource;
+
+/**
+ * Tests how server handles multiple simultaneous connections.
+ *
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
+ *
+ */
+public class ConnectionTest extends ExistingDatabaseTest {
+
+ private static final int RECONNECT_COUNT = Configuration.get().connectionReconnectCount;
+ private static final int THREAD_COUNT = Configuration.get().connectionThreadCount;
+ private static final int WAIT_TIME = 10;
+ private static boolean WRITE = false;
+
+ private Throwable error;
+ private List<ConnectionThread> threads = new ArrayList<ConnectionThread>();
+ private volatile int count = 0; // not totally correct code but works for me
+ public void setError(Throwable error) {
+ if (this.error == null) {
+ this.error = error;
+ for (ConnectionThread t : threads) {
+ t.dispose();
+ }
+ }
+ }
+
+ private boolean notDone() {
+ for (ConnectionThread t : threads) {
+ if(!t.isDone()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests how server can handle multiple simultaneous connections
+ * @throws Exception
+ */
+ static int sessionClosed = 0;
+ private synchronized void inc() {
+ ++sessionClosed;
+ }
+ @Test
+ public void testConnection() throws Exception {
+ for (int i = 0; i < THREAD_COUNT; i++) {
+ ConnectionThread t = new ConnectionThread();
+ threads.add(t);
+ t.start();
+ }
+ if (DEBUG)
+ System.out.println("Created " + THREAD_COUNT + " threads.");
+ sessionClosed = 0;
+ SessionManagerSource.getSessionManager().addSessionListener(
+ new SessionListener() {
+ @Override
+ public void sessionClosed(SessionEvent e) {
+ if (DEBUG)
+ System.out.println("Session closed s=" + e.getSession());
+ if (null != e.getCause())
+ e.getCause().printStackTrace();
+ else
+ inc();
+ }
+
+ @Override
+ public void sessionOpened(SessionEvent e) {
+ if (DEBUG)
+ System.out.println("Session opened s=" + e.getSession());
+ }
+
+ @Override
+ public void sessionException(SessionEvent e) {
+ if (DEBUG)
+ System.out.println("Session exception s=" + e.getSession());
+ if (null != e.getCause())
+ e.getCause().printStackTrace();
+ }
+ }
+ );
+ // Wait for correct number of closes.
+ while (RECONNECT_COUNT * THREAD_COUNT != sessionClosed) {
+ checkException();
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ if (DEBUG)
+ System.out.println("Interrupted.");
+ }
+ }
+
+ // Wait for write request to complete
+ while (notDone()) {
+ checkException();
+ int currentCount = count;
+ try {
+ Thread.sleep(WAIT_TIME * 1000);
+ } catch (InterruptedException e) {
+ if (DEBUG)
+ System.out.println("Interrupted.");
+ }
+ if (DEBUG)
+ System.out.println(count);
+ if (count == currentCount)
+ break;
+ }
+ checkException();
+ // check success flag
+ if (error != null) {
+ throw new Exception("First error was",error);
+ }
+ if (notDone())
+ throw new Exception("Test was not completed, server did not resepond for "
+ + WAIT_TIME + " seconds");
+ }
+
+
+ private class ConnectionThread extends Thread {
+ private boolean done = false;
+ private boolean disposed = false;
+ public ConnectionThread() {
+ }
+ @Override
+ public void run() {
+ for (int i = 0; i < RECONNECT_COUNT; i++) {
+ if (disposed)
+ return;
+ try {
+ final Session session = Tests.getTestHandler().getSession();
+ final Resource rootLibrary = session.getRootLibrary();
+ assertTrue(rootLibrary != null);
+ final String name = this.getName() + " " + Integer.toString(i);
+ if (WRITE) {
+ session.syncRequest(new WriteQuery(ConnectionTest.this) {
+ @Override
+ public void run(WriteGraph g) throws Throwable {
+ Layer0 b = Layer0.getInstance(g);
+ Resource newResource = g.newResource();
+ g.claim(newResource, b.InstanceOf, null, b.Type);
+ g.claimLiteral(newResource, b.HasName, name);
+ g.claim(rootLibrary, b.ConsistsOf, newResource);
+ }
+ });
+ }
+ Tests.closeSession(session);
+ } catch (Exception e) {
+ setError(e);
+ return;
+ }
+ ++count;
+ }
+ if (DEBUG)
+ System.out.println("count=" + count);
+ done = true;
+ }
+
+ public boolean isDone() {
+ return done;
+ }
+
+ public void dispose() {
+ disposed = true;
+ }
+ }
+
+}