/******************************************************************************* * 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 * */ 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 threads = new ArrayList(); 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; } } }