/*******************************************************************************
* 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 fi.vtt.simantics.procore.internal;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.core.runtime.Platform;
import org.simantics.databoard.Bindings;
import org.simantics.db.AsyncReadGraph;
import org.simantics.db.ChangeSet;
import org.simantics.db.DevelopmentKeys;
import org.simantics.db.ExternalValueSupport;
import org.simantics.db.Metadata;
import org.simantics.db.MonitorContext;
import org.simantics.db.MonitorHandler;
import org.simantics.db.Resource;
import org.simantics.db.ResourceSerializer;
import org.simantics.db.Session;
import org.simantics.db.SessionManager;
import org.simantics.db.SessionVariables;
import org.simantics.db.VirtualGraph;
import org.simantics.db.WriteGraph;
import org.simantics.db.authentication.UserAuthenticationAgent;
import org.simantics.db.authentication.UserAuthenticator;
import org.simantics.db.common.Indexing;
import org.simantics.db.common.TransactionPolicyRelease;
import org.simantics.db.common.procedure.adapter.AsyncMultiProcedureAdapter;
import org.simantics.db.common.procedure.adapter.ProcedureAdapter;
import org.simantics.db.common.procedure.wrapper.NoneToAsyncListener;
import org.simantics.db.common.procedure.wrapper.NoneToAsyncMultiListener;
import org.simantics.db.common.procedure.wrapper.NoneToAsyncMultiProcedure;
import org.simantics.db.common.procedure.wrapper.NoneToAsyncProcedure;
import org.simantics.db.common.procedure.wrapper.SyncToAsyncListener;
import org.simantics.db.common.procedure.wrapper.SyncToAsyncMultiListener;
import org.simantics.db.common.procedure.wrapper.SyncToAsyncMultiProcedure;
import org.simantics.db.common.procedure.wrapper.SyncToAsyncProcedure;
import org.simantics.db.common.service.ServiceActivityMonitorImpl;
import org.simantics.db.common.service.ServiceActivityUpdaterForWriteTransactions;
import org.simantics.db.common.utils.Logger;
import org.simantics.db.event.ChangeEvent;
import org.simantics.db.event.ChangeListener;
import org.simantics.db.event.SessionEventListener;
import org.simantics.db.exception.CancelTransactionException;
import org.simantics.db.exception.ClusterSetExistException;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.exception.ImmutableException;
import org.simantics.db.exception.InvalidResourceReferenceException;
import org.simantics.db.exception.ResourceNotFoundException;
import org.simantics.db.exception.RuntimeDatabaseException;
import org.simantics.db.exception.ServiceException;
import org.simantics.db.exception.ServiceNotFoundException;
import org.simantics.db.impl.ClusterBase;
import org.simantics.db.impl.ClusterI;
import org.simantics.db.impl.ClusterTraitsBase;
import org.simantics.db.impl.ClusterTranslator;
import org.simantics.db.impl.ResourceImpl;
import org.simantics.db.impl.TransientGraph;
import org.simantics.db.impl.VirtualGraphImpl;
import org.simantics.db.impl.graph.DelayedWriteGraph;
import org.simantics.db.impl.graph.ReadGraphImpl;
import org.simantics.db.impl.graph.WriteGraphImpl;
import org.simantics.db.impl.graph.WriteSupport;
import org.simantics.db.impl.internal.RandomAccessValueSupport;
import org.simantics.db.impl.procedure.ResultCallWrappedQueryProcedure4;
import org.simantics.db.impl.procedure.ResultCallWrappedSingleQueryProcedure4;
import org.simantics.db.impl.query.QueryProcessor;
import org.simantics.db.impl.query.QueryProcessor.SessionRead;
import org.simantics.db.impl.query.QueryProcessor.SessionTask;
import org.simantics.db.impl.service.QueryDebug;
import org.simantics.db.impl.support.VirtualGraphServerSupport;
import org.simantics.db.impl.support.WriteRequestScheduleSupport;
import org.simantics.db.procedure.AsyncListener;
import org.simantics.db.procedure.AsyncMultiListener;
import org.simantics.db.procedure.AsyncMultiProcedure;
import org.simantics.db.procedure.AsyncProcedure;
import org.simantics.db.procedure.Listener;
import org.simantics.db.procedure.ListenerBase;
import org.simantics.db.procedure.MultiListener;
import org.simantics.db.procedure.MultiProcedure;
import org.simantics.db.procedure.Procedure;
import org.simantics.db.procedure.SyncListener;
import org.simantics.db.procedure.SyncMultiListener;
import org.simantics.db.procedure.SyncMultiProcedure;
import org.simantics.db.procedure.SyncProcedure;
import org.simantics.db.procore.cluster.ClusterImpl;
import org.simantics.db.procore.cluster.ClusterTraits;
import org.simantics.db.procore.protocol.Constants;
import org.simantics.db.procore.protocol.DebugPolicy;
import org.simantics.db.request.AsyncMultiRead;
import org.simantics.db.request.AsyncRead;
import org.simantics.db.request.DelayedWrite;
import org.simantics.db.request.DelayedWriteResult;
import org.simantics.db.request.ExternalRead;
import org.simantics.db.request.MultiRead;
import org.simantics.db.request.Read;
import org.simantics.db.request.ReadInterface;
import org.simantics.db.request.UndoTraits;
import org.simantics.db.request.Write;
import org.simantics.db.request.WriteInterface;
import org.simantics.db.request.WriteOnly;
import org.simantics.db.request.WriteOnlyResult;
import org.simantics.db.request.WriteResult;
import org.simantics.db.request.WriteTraits;
import org.simantics.db.service.ByteReader;
import org.simantics.db.service.ClusterBuilder;
import org.simantics.db.service.ClusterBuilderFactory;
import org.simantics.db.service.ClusterControl;
import org.simantics.db.service.ClusterSetsSupport;
import org.simantics.db.service.ClusterUID;
import org.simantics.db.service.ClusteringSupport;
import org.simantics.db.service.CollectionSupport;
import org.simantics.db.service.DebugSupport;
import org.simantics.db.service.DirectQuerySupport;
import org.simantics.db.service.GraphChangeListenerSupport;
import org.simantics.db.service.InitSupport;
import org.simantics.db.service.LifecycleSupport;
import org.simantics.db.service.ManagementSupport;
import org.simantics.db.service.QueryControl;
import org.simantics.db.service.SerialisationSupport;
import org.simantics.db.service.ServerInformation;
import org.simantics.db.service.ServiceActivityMonitor;
import org.simantics.db.service.SessionEventSupport;
import org.simantics.db.service.SessionMonitorSupport;
import org.simantics.db.service.SessionUserSupport;
import org.simantics.db.service.StatementSupport;
import org.simantics.db.service.TransactionPolicySupport;
import org.simantics.db.service.TransactionSupport;
import org.simantics.db.service.TransferableGraphSupport;
import org.simantics.db.service.UndoRedoSupport;
import org.simantics.db.service.VirtualGraphSupport;
import org.simantics.db.service.XSupport;
import org.simantics.layer0.Layer0;
import org.simantics.utils.DataContainer;
import org.simantics.utils.Development;
import org.simantics.utils.datastructures.Callback;
import org.simantics.utils.threads.logger.ITask;
import org.simantics.utils.threads.logger.ThreadLogger;
import gnu.trove.procedure.TLongProcedure;
import gnu.trove.set.hash.TLongHashSet;
public abstract class SessionImplSocket implements Session, WriteRequestScheduleSupport {
protected static final boolean DEBUG = false;
private static final boolean DIAGNOSTICS = false;
private TransactionPolicySupport transactionPolicy;
final private ClusterControl clusterControl;
final protected BuiltinSupportImpl builtinSupport;
final protected VirtualGraphServerSupportImpl virtualGraphServerSupport;
final protected ClusterSetsSupport clusterSetsSupport;
final protected LifecycleSupportImpl lifecycleSupport;
protected QuerySupportImpl querySupport;
protected ResourceSupportImpl resourceSupport;
protected WriteSupport writeSupport;
public ClusterTranslator clusterTranslator;
boolean dirtyPrimitives = false;
public static final int SERVICE_MODE_CREATE = 2;
public static final int SERVICE_MODE_ALLOW = 1;
public int serviceMode = 0;
public boolean createdImmutableClusters = false;
public TLongHashSet createdClusters = new TLongHashSet();
private Layer0 L0;
/**
* The service locator maintained by the workbench. These services are
* initialized during workbench during the init
method.
*/
final protected ServiceLocatorImpl serviceLocator = new ServiceLocatorImpl();
final public ResourceSerializerImpl resourceSerializer = new ResourceSerializerImpl();
final CopyOnWriteArrayList changeListeners2 = new CopyOnWriteArrayList();
final CopyOnWriteArrayList metadataListeners = new CopyOnWriteArrayList();
final CopyOnWriteArrayList eventListeners = new CopyOnWriteArrayList();
final HashSet sessionThreads = new HashSet();
final BijectionMap monitorContexts = new BijectionMap();
final protected State state = new State();
protected GraphSession graphSession = null;
protected SessionManager sessionManagerImpl = null;
protected UserAuthenticationAgent authAgent = null;
protected UserAuthenticator authenticator = null;
protected Resource user = null;
protected ClusterStream clusterStream = null;
protected SessionRequestManager requestManager = null;
public ClusterTable clusterTable = null;
public QueryProcessor queryProvider2 = null;
ClientChangesImpl clientChanges = null;
MonitorHandler[] monitorHandlers = new MonitorHandler[0];
// protected long newClusterId = Constants.NullClusterId;
protected int flushCounter = 0;
protected boolean writeOnly = false;
WriteState> writeState = null;
WriteStateBase> delayedWriteState = null;
protected Resource defaultClusterSet = null; // If not null then used for newResource().
public SessionImplSocket(SessionManager sessionManagerImpl, UserAuthenticationAgent authAgent) {
// if (authAgent == null)
// throw new IllegalArgumentException("null authentication agent");
File t = StaticSessionProperties.virtualGraphStoragePath;
if (null == t)
t = new File(".");
this.clusterTable = new ClusterTable(this, t);
this.builtinSupport = new BuiltinSupportImpl(this);
this.sessionManagerImpl = sessionManagerImpl;
this.user = null;
// this.authAgent = authAgent;
serviceLocator.registerService(Session.class, this);
serviceLocator.registerService(InitSupport.class, new InitSupportImpl(this));
serviceLocator.registerService(ManagementSupport.class, new ManagementSupportImpl(this));
serviceLocator.registerService(QueryControl.class, new QueryControlImpl(this));
serviceLocator.registerService(SessionUserSupport.class, new SessionUserSupportImpl(this));
serviceLocator.registerService(GraphChangeListenerSupport.class, new GraphChangeListenerSupportImpl(this));
serviceLocator.registerService(SessionEventSupport.class, new SessionEventSupportImpl(this));
serviceLocator.registerService(SerialisationSupport.class, new SerialisationSupportImpl(this));
serviceLocator.registerService(UndoRedoSupport.class, new UndoRedoSupportImpl(this));
serviceLocator.registerService(ClusteringSupport.class, new ClusteringSupportImpl(this));
serviceLocator.registerService(TransactionSupport.class, new TransactionSupportImpl(this));
serviceLocator.registerService(SessionMonitorSupport.class, new SessionMonitorSupportImpl(this));
serviceLocator.registerService(TransferableGraphSupport.class, new TransferableGraphSupportImpl(this));
serviceLocator.registerService(QueryDebug.class, new QueryDebugImpl(this));
serviceLocator.registerService(CollectionSupport.class, new CollectionSupportImpl(this));
serviceLocator.registerService(StatementSupport.class, new StatementSupportImpl(this));
serviceLocator.registerService(DirectQuerySupport.class, new DirectQuerySupportImpl(this));
serviceLocator.registerService(XSupport.class, new XSupportImpl(this));
serviceLocator.registerService(DebugSupport.class, new DebugSupportImpl());
serviceLocator.registerService(ExternalValueSupport.class, new ExternalValueSupportImpl(this));
serviceLocator.registerService(RandomAccessValueSupport.class, new RandomAccessValueSupportImpl());
serviceLocator.registerService(ServiceActivityMonitor.class, new ServiceActivityMonitorImpl());
ServiceActivityUpdaterForWriteTransactions.register(this);
this.virtualGraphServerSupport = new VirtualGraphServerSupportImpl(this, t);
serviceLocator.registerService(VirtualGraphSupport.class, virtualGraphServerSupport);
serviceLocator.registerService(VirtualGraphServerSupport.class, virtualGraphServerSupport);
this.lifecycleSupport = new LifecycleSupportImpl(this);
serviceLocator.registerService(LifecycleSupport.class, lifecycleSupport);
this.transactionPolicy = new TransactionPolicyRelease();
serviceLocator.registerService(TransactionPolicySupport.class, transactionPolicy);
this.clusterControl = new ClusterControlImpl(this);
serviceLocator.registerService(ClusterControl.class, clusterControl);
this.clusterSetsSupport = new ClusterSetsSupportImpl2(); // Using same path as virtual graphs.
this.clusterSetsSupport.setReadDirectory(t.toPath());
this.clusterSetsSupport.updateWriteDirectory(t.toPath());
serviceLocator.registerService(ClusterSetsSupport.class, clusterSetsSupport);
}
/*
*
* Session interface
*/
@Override
public Resource getRootLibrary() {
return queryProvider2.getRootLibraryResource();
}
void refresh(int thread, ClusterUID[] clusterUID, long csid) throws DatabaseException {
if (!graphSession.dbSession.refreshEnabled())
return;
try {
getClusterTable().refresh(csid, this, clusterUID);
} catch (Throwable t) {
Logger.defaultLogError("Refesh failed.", t);
}
}
static final class TaskHelper {
private final String name;
private Object result;
final Semaphore sema = new Semaphore(0);
private Throwable throwable = null;
final Callback callback = new Callback() {
@Override
public void run(DatabaseException e) {
synchronized (TaskHelper.this) {
throwable = e;
}
}
};
final Procedure