package fi.vtt.simantics.procore.internal; import java.util.concurrent.CopyOnWriteArrayList; import org.simantics.db.SessionManager; import org.simantics.db.SessionReference; import org.simantics.db.common.TransactionPolicyRelease; import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.InternalException; import org.simantics.db.exception.TimeoutException; import org.simantics.db.impl.query.QueryProcessor; import org.simantics.db.service.LifecycleSupport; import org.simantics.db.service.TransactionPolicySupport; public class LifecycleSupportImpl implements LifecycleSupport { final private SessionImplSocket session; final private CopyOnWriteArrayList listeners = new CopyOnWriteArrayList(); LifecycleSupportImpl(SessionImplSocket session) { this.session = session; } @Override public long getId() { return session.graphSession.getSessionId(); } @Override public boolean isClosing() { return session.state.isClosing(); } @Override public boolean isClosed() { return session.state.isClosed(); } @Override final public SessionReference getSessionReference() { if (session.graphSession == null) return null; return session.graphSession.getSessionReference(); } @Override final public SessionManager getSessionManager() { return session.sessionManagerImpl; } @Override public void ping() throws DatabaseException { session.graphSession.execute(""); } @Override public void close() throws DatabaseException { GraphSession graphSession = session.graphSession; try { this.close(0, false); } catch (TimeoutException e) { this.close(-1, true); } finally { if (null != graphSession) try { // Graph session expects start and stop. // If we miss stop then server will not know that we disconnected deliberately. graphSession.stop(); } catch (InternalException e) { Logger.defaultLogError("GraphSession.stop failed.", e); } } } @Override final public void close(long timeout, boolean force) throws DatabaseException { session.registerService(TransactionPolicySupport.class, new TransactionPolicyRelease()); State.WaitStatus status = session.state.waitClosing(timeout); switch (status) { case IsClosed: case IsClosing: return; case Timeout: if (!force) throw new TimeoutException("Close timeout, use force!"); // Intentionally dropping to next case. case CanBeClosed: try { QueryProcessor prosessor = session.getQueryProvider2(); if (prosessor!=null) prosessor.dispose(); session.virtualGraphServerSupport.disposeVirtualGraphs(); session.removeTemporaryData(); // Release the session from the manager. session.graphSession.close(); session.serviceLocator.dispose(); // This will close local sessions created when registering services. } finally { session.state.close(); session.clusterTable.dispose(); session.clusterTable = null; session.sessionManagerImpl.shutdown(session, null); session.sessionManagerImpl = null; session.user = null; session.graphSession = null; } break; default: throw new DatabaseException(); } } @Override public void addListener(LifecycleListener listener) { listeners.add(listener); } @Override public void removeListener(LifecycleListener listener) { listeners.remove(listener); } void fireListeners(LifecycleState newState) { for(LifecycleListener listener : listeners) listener.stateChanged(newState); } }