Package com.tinkerpop.blueprints.impls.orient.asynch

Source Code of com.tinkerpop.blueprints.impls.orient.asynch.OrientGraphAsynch

/*
*
*  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
*  *
*  *  Licensed under the Apache License, Version 2.0 (the "License");
*  *  you may not use this file except in compliance with the License.
*  *  You may obtain a copy of the License at
*  *
*  *       http://www.apache.org/licenses/LICENSE-2.0
*  *
*  *  Unless required by applicable law or agreed to in writing, software
*  *  distributed under the License is distributed on an "AS IS" BASIS,
*  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  *  See the License for the specific language governing permissions and
*  *  limitations under the License.
*  *
*  * For more information: http://www.orientechnologies.com
*/

package com.tinkerpop.blueprints.impls.orient.asynch;

import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.orientechnologies.common.concur.ONeedRetryException;
import com.orientechnologies.common.exception.OException;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.common.util.OCallable;
import com.orientechnologies.orient.core.Orient;
import com.orientechnologies.orient.core.command.OCommandRequest;
import com.orientechnologies.orient.core.command.traverse.OTraverse;
import com.orientechnologies.orient.core.conflict.ORecordConflictStrategy;
import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.exception.OConcurrentModificationException;
import com.orientechnologies.orient.core.intent.OIntent;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.sql.OCommandSQL;
import com.orientechnologies.orient.core.storage.ORecordDuplicatedException;
import com.orientechnologies.orient.core.storage.OStorage;
import com.orientechnologies.orient.core.storage.OStorageEmbedded;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Features;
import com.tinkerpop.blueprints.GraphQuery;
import com.tinkerpop.blueprints.Index;
import com.tinkerpop.blueprints.Parameter;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.orient.OrientBaseGraph;
import com.tinkerpop.blueprints.impls.orient.OrientEdge;
import com.tinkerpop.blueprints.impls.orient.OrientEdgeType;
import com.tinkerpop.blueprints.impls.orient.OrientElement;
import com.tinkerpop.blueprints.impls.orient.OrientExtendedGraph;
import com.tinkerpop.blueprints.impls.orient.OrientExtendedVertex;
import com.tinkerpop.blueprints.impls.orient.OrientGraphFactory;
import com.tinkerpop.blueprints.impls.orient.OrientVertex;
import com.tinkerpop.blueprints.impls.orient.OrientVertexType;

import java.io.PrintStream;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicLong;

/**
* A Blueprints implementation of the graph database OrientDB (http://www.orientechnologies.com) that uses multi-threading to work
* against graph.
*
* @author Luca Garulli (http://www.orientechnologies.com)
*/
public class OrientGraphAsynch implements OrientExtendedGraph {
  private final Features                                FEATURES             = new Features();

  private final String                                  url;
  private final String                                  userName;
  private final String                                  userPassword;

  private OrientGraphFactory                            factory;
  private ConcurrentLinkedHashMap<Object, OrientVertex> vertexCache;
  private int                                           maxPoolSize          = 32;
  private int                                           maxRetries           = 16;
  private boolean                                       transactional        = false;
  private AtomicLong                                    operationStarted     = new AtomicLong();
  private AtomicLong                                    operationCompleted   = new AtomicLong();
  private String                                        keyFieldName;
  // STATISTICS
  private AtomicLong                                    reusedCachedVertex   = new AtomicLong();
  private AtomicLong                                    indexUniqueException = new AtomicLong();
  private AtomicLong                                    concurrentException  = new AtomicLong();
  private AtomicLong                                    unknownException     = new AtomicLong();
  private AtomicLong                                    verticesCreated      = new AtomicLong();
  private AtomicLong                                    edgesCreated         = new AtomicLong();
  private AtomicLong                                    verticesLoaded       = new AtomicLong();
  private AtomicLong                                    verticesRemoved      = new AtomicLong();
  private AtomicLong                                    verticesReloaded     = new AtomicLong();
  private PrintStream                                   outStats             = null;
  private ORecordConflictStrategy                       conflictStrategy     = null;

  protected enum MERGE_RESULT {
    MERGED, RETRY, ERROR
  }

  public OrientGraphAsynch(final String url) {
    this.url = url;
    this.userName = OrientBaseGraph.ADMIN;
    this.userPassword = OrientBaseGraph.ADMIN;
  }

  public OrientGraphAsynch(final String url, final String userName, final String userPassword) {
    this.url = url;
    this.userName = userName;
    this.userPassword = userPassword;
  }

  public String getKeyFieldName() {
    return keyFieldName;
  }

  public void setKeyFieldName(String keyFieldName) {
    this.keyFieldName = keyFieldName;
  }

  public PrintStream getOutStats() {
    return outStats;
  }

  public void setOutStats(PrintStream outStats) {
    this.outStats = outStats;
  }

  public OrientGraphAsynch setCache(final long iElements) {
    init();
    vertexCache = new ConcurrentLinkedHashMap.Builder<Object, OrientVertex>().maximumWeightedCapacity(iElements).build();
    factory.setKeepInMemoryReferences(true);
    return this;
  }

  public Vertex addOrUpdateVertex(final Object id, final Object... prop) {
    beginAsynchOperation();

    return new OrientVertexFuture(Orient.instance().getWorkers().submit(new Callable<OrientVertex>() {
      @Override
      public OrientVertex call() throws Exception {
        final OrientBaseGraph g = acquire();
        try {
          OrientVertex v = (OrientVertex) getVertex(id);
          if (v != null) {
            // System.out.printf("\nVertex loaded key=%d, v=%s", id, v);
            for (int retry = 0;; retry++) {
              MERGE_RESULT result = mergeAndSaveRecord(retry, v.getRecord(), prop);
              switch (result) {
              case MERGED:
                return v;
              case ERROR:
                throw new ORecordDuplicatedException("Cannot create a new vertices", v.getIdentity());
              case RETRY:
                if (retry > maxRetries)
                  break;
              }
            }
          }

          v = g.addVertex(id, prop);

          // System.out.printf("\nCreated vertex key=%d, v=%s", id, v);

          verticesCreated.incrementAndGet();

          return v;

        } catch (ORecordDuplicatedException e) {
          System.out.printf("\n*** Vertex already exists key=%d, v=%s", id, e.getRid());

          // ALREADY EXISTS, TRY TO MERGE IT
          for (int retry = 0;; retry++) {
            indexUniqueException.incrementAndGet();

            if (OLogManager.instance().isDebugEnabled())
              OLogManager.instance().debug(this, "Vertex %s already created, merge it and retry again (retry=%d/%d)", id, retry,
                  maxRetries);

            final ODocument existent = e.getRid().getRecord();

            final MERGE_RESULT result = mergeAndSaveRecord(retry, existent, prop);

            switch (result) {
            case MERGED:
              OrientVertex v = (OrientVertex) getVertex(existent);
              return v;
            case RETRY:
              break;
            case ERROR:
              throw e;
            }
          }
        } finally {
          g.shutdown();
          endAsynchOperation();
        }
      }
    }));
  }

  public Vertex addVertex(final Object id, final Object... prop) {
    beginAsynchOperation();

    return new OrientVertexFuture(Orient.instance().getWorkers().submit(new Callable<OrientVertex>() {
      @Override
      public OrientVertex call() throws Exception {
        final OrientBaseGraph g = acquire();
        try {
          OrientVertex v = g.addVertex(id, prop);

          verticesCreated.incrementAndGet();

          return v;

        } finally {
          g.shutdown();
          endAsynchOperation();
        }
      }
    }));
  }

  public OrientVertex getOrAddVertex(final Object id) {
    final OrientBaseGraph g = acquire();
    try {
      OrientVertex v = getFromCache(id);
      if (v != null)
        return v;

      v = g.addVertex(id);

      verticesCreated.incrementAndGet();

      return v;

    } finally {
      g.shutdown();
    }
  }

  @Override
  public Vertex addVertex(final Object id) {
    beginAsynchOperation();

    return new OrientVertexFuture(Orient.instance().getWorkers().submit(new Callable<OrientVertex>() {
      @Override
      public OrientVertex call() throws Exception {
        final OrientBaseGraph g = acquire();
        try {
          final OrientVertex v = g.addVertex(id);

          verticesCreated.incrementAndGet();

          return v;
        } finally {
          g.shutdown();
          endAsynchOperation();
        }
      }
    }));
  }

  @Override
  public void declareIntent(final OIntent iIntent) {
    init();
    factory.declareIntent(iIntent);
  }

  @Override
  public Vertex getVertex(final Object id) {
    if (id == null)
      return null;

    if (id instanceof OrientVertex)
      return (Vertex) id;

    init();

    if (id instanceof OIdentifiable)
      return new OrientVertex((OrientBaseGraph) null, (OIdentifiable) id);

    OrientVertex v = getFromCache(id);
    if (v != null) {
      return v;
    }

    final OrientBaseGraph g = acquire();
    try {
      // LOAD FROM DATABASE AND STORE IN CACHE
      v = (OrientVertex) g.getVertexByKey(keyFieldName, id);
      if (v != null) {
        verticesLoaded.incrementAndGet();
      }

      return v;

    } finally {
      g.shutdown();
    }
  }

  @Override
  public void removeVertex(final Vertex vertex) {
    beginAsynchOperation();

    Orient.instance().getWorkers().submit(new Callable<Object>() {
      @Override
      public Object call() throws Exception {
        final OrientBaseGraph g = acquire();
        try {
          if (vertexCache != null) {
            final Object field = vertex.getProperty(keyFieldName);
            if (field != null)
              vertexCache.remove(field);
          }

          g.removeVertex(vertex);

          verticesRemoved.incrementAndGet();
        } finally {
          g.shutdown();
          endAsynchOperation();
        }
        return null;
      }
    });
  }

  @Override
  public Iterable<Vertex> getVertices() {
    final OrientBaseGraph g = acquire();
    try {
      return g.getVertices();
    } finally {
      g.shutdown();
    }
  }

  @Override
  public Iterable<Vertex> getVertices(final String key, final Object value) {
    final OrientBaseGraph g = acquire();
    try {
      return g.getVertices(key, value);
    } finally {
      g.shutdown();
    }
  }

  public Edge addEdgeByVerticesKeys(final Object iOutVertex, final Object iInVertex, final String iEdgeLabel) {
    beginAsynchOperation();

    return new OrientEdgeFuture(Orient.instance().getWorkers().submit(new Callable<OrientEdge>() {
      @Override
      public OrientEdge call() throws Exception {
        final OrientBaseGraph g = acquire();
        try {
          final OrientExtendedVertex vOut = getOrAddVertex(iOutVertex);
          final OrientExtendedVertex vIn = getOrAddVertex(iInVertex);

          boolean reloaded = false;

          for (int retry = 0;; retry++) {
            try {

              final OrientEdge e = g.addEdge(null, vOut, vIn, iEdgeLabel);

              addInCache(vOut.getProperty(keyFieldName), vOut.getVertexInstance());
              addInCache(vIn.getProperty(keyFieldName), vIn.getVertexInstance());

              edgesCreated.incrementAndGet();

              return e;

            } catch (OConcurrentModificationException e) {
              concurrentException.incrementAndGet();
              reloadVertices(vOut, vIn, iEdgeLabel, retry, e);
              reloaded = true;
            } catch (ORecordDuplicatedException e) {
              indexUniqueException.incrementAndGet();
              reloadVertices(vOut, vIn, iEdgeLabel, retry, e);
              reloaded = true;
            } catch (Exception e) {
              unknownException.incrementAndGet();
              OLogManager.instance().warn(
                  this,
                  "Error on addEdge(" + iOutVertex + "," + iInVertex + "," + iEdgeLabel + "), retrying (retry=" + retry + "/"
                      + maxRetries + ") Thread: " + Thread.currentThread().getId());
              e.printStackTrace();
            }
          }
        } finally {
          g.shutdown();
          endAsynchOperation();
        }
      }
    }));
  }

  @Override
  public Edge addEdge(final Object id, final Vertex outVertex, final Vertex inVertex, final String label) {
    beginAsynchOperation();

    return new OrientEdgeFuture(Orient.instance().getWorkers().submit(new Callable<OrientEdge>() {
      @Override
      public OrientEdge call() throws Exception {
        final OrientBaseGraph g = acquire();
        try {
          // ASSURE ARE NOT REUSED FROM CACHE
          OrientVertex vOut = outVertex instanceof OrientVertexFuture ? ((OrientVertexFuture) outVertex).get()
              : (OrientVertex) outVertex;
          OrientVertex vIn = inVertex instanceof OrientVertexFuture ? ((OrientVertexFuture) inVertex).get()
              : (OrientVertex) inVertex;

          vOut.attach(g);
          vIn.attach(g);

          boolean reloaded = false;

          for (int retry = 0;; retry++) {
            try {

              final OrientEdge e = g.addEdge(id, vOut, vIn, label);

              addInCache(vOut.getProperty(keyFieldName), vOut);
              addInCache(vIn.getProperty(keyFieldName), vIn);

              edgesCreated.incrementAndGet();

              return e;

            } catch (OConcurrentModificationException e) {
              concurrentException.incrementAndGet();
              reloadVertices(vOut, vIn, label, retry, e);
              reloaded = true;
            } catch (ORecordDuplicatedException e) {
              indexUniqueException.incrementAndGet();
              reloadVertices(vOut, vIn, label, retry, e);
              reloaded = true;
            } catch (Exception e) {
              unknownException.incrementAndGet();
              OLogManager.instance().warn(
                  this,
                  "Error on addEdge(" + id + "," + outVertex + "," + inVertex + "," + label + "), retrying (retry=" + retry + "/"
                      + maxRetries + ") Thread: " + Thread.currentThread().getId());
              e.printStackTrace();
            }
          }
        } finally {
          g.shutdown();
          endAsynchOperation();
        }
      }
    }));
  }

  @Override
  public Edge getEdge(final Object id) {
    final OrientBaseGraph g = acquire();
    try {
      return g.getEdge(id);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public void removeEdge(final Edge edge) {
    beginAsynchOperation();

    Orient.instance().getWorkers().submit(new Callable<Object>() {
      @Override
      public Object call() throws Exception {
        final OrientBaseGraph g = acquire();
        try {
          g.removeEdge(edge);
        } finally {
          g.shutdown();
          endAsynchOperation();
        }
        return null;
      }
    });
  }

  @Override
  public Iterable<Edge> getEdges() {
    final OrientBaseGraph g = acquire();
    try {
      return g.getEdges();
    } finally {
      g.shutdown();
    }
  }

  @Override
  public Iterable<Edge> getEdges(final String key, final Object value) {

    final OrientBaseGraph g = acquire();
    try {
      return g.getEdges(key, value);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public void drop() {
    final OrientBaseGraph g = acquire();
    try {
      g.drop();
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientVertex addTemporaryVertex(final String iClassName, final Object... prop) {
    final OrientBaseGraph g = acquire();
    try {
      return g.addTemporaryVertex(iClassName, prop);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientVertexType getVertexBaseType() {
    final OrientBaseGraph g = acquire();
    try {
      return g.getVertexBaseType();
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientVertexType getVertexType(final String iClassName) {
    final OrientBaseGraph g = acquire();
    try {
      return g.getVertexType(iClassName);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientVertexType createVertexType(final String iClassName) {
    final OrientBaseGraph g = acquire();
    try {
      return g.createVertexType(iClassName);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientVertexType createVertexType(final String iClassName, final String iSuperClassName) {
    final OrientBaseGraph g = acquire();
    try {
      return g.createVertexType(iClassName, iSuperClassName);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientVertexType createVertexType(final String iClassName, final OClass iSuperClass) {
    final OrientBaseGraph g = acquire();
    try {
      return g.createVertexType(iClassName, iSuperClass);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public void dropVertexType(final String iClassName) {
    final OrientBaseGraph g = acquire();
    try {
      g.dropVertexType(iClassName);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientEdgeType getEdgeBaseType() {
    final OrientBaseGraph g = acquire();
    try {
      return g.getEdgeBaseType();
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientEdgeType getEdgeType(final String iClassName) {
    final OrientBaseGraph g = acquire();
    try {
      return g.getEdgeType(iClassName);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientEdgeType createEdgeType(final String iClassName) {
    final OrientBaseGraph g = acquire();
    try {
      return g.createEdgeType(iClassName);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientEdgeType createEdgeType(final String iClassName, final String iSuperClassName) {
    final OrientBaseGraph g = acquire();
    try {
      return g.createEdgeType(iClassName, iSuperClassName);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientEdgeType createEdgeType(final String iClassName, final OClass iSuperClass) {
    final OrientBaseGraph g = acquire();
    try {
      return g.createEdgeType(iClassName, iSuperClass);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public void dropEdgeType(final String iClassName) {
    final OrientBaseGraph g = acquire();
    try {
      g.dropEdgeType(iClassName);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientElement detach(final OrientElement iElement) {
    final OrientBaseGraph g = acquire();
    try {
      return g.detach(iElement);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public OrientElement attach(final OrientElement iElement) {
    final OrientBaseGraph g = acquire();
    try {
      return g.attach(iElement);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public GraphQuery query() {
    throw new UnsupportedOperationException("query");
  }

  @Override
  public OTraverse traverse() {
    throw new UnsupportedOperationException("traverse");
  }

  @Override
  public OCommandRequest command(final OCommandRequest iCommand) {
    throw new UnsupportedOperationException("command");
  }

  @Override
  public void shutdown() {
    synchronized (operationCompleted) {
      while (operationStarted.get() > operationCompleted.get()) {
        try {
          operationCompleted.wait();
        } catch (InterruptedException e) {
          Thread.interrupted();
          break;
        }
      }
    }

    if (vertexCache != null)
      vertexCache.clear();

    dumpStats();

    factory.close();
  }

  public Features getFeatures() {
    return FEATURES;
  }

  @Override
  public <T extends Element> Index<T> createIndex(final String indexName, final Class<T> indexClass,
      final Parameter... indexParameters) {
    final OrientBaseGraph g = acquire();
    try {
      return g.createIndex(indexName, indexClass, indexParameters);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public <T extends Element> Index<T> getIndex(final String indexName, final Class<T> indexClass) {
    final OrientBaseGraph g = acquire();
    try {
      return g.getIndex(indexName, indexClass);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public Iterable<Index<? extends Element>> getIndices() {
    final OrientBaseGraph g = acquire();
    try {
      return g.getIndices();
    } finally {
      g.shutdown();
    }
  }

  @Override
  public void dropIndex(final String indexName) {
    final OrientBaseGraph g = acquire();
    try {
      g.dropIndex(indexName);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public <T extends Element> void dropKeyIndex(final String key, final Class<T> elementClass) {
    final OrientBaseGraph g = acquire();
    try {
      g.dropKeyIndex(key, elementClass);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public <T extends Element> void createKeyIndex(final String key, final Class<T> elementClass, final Parameter... indexParameters) {
    final OrientBaseGraph g = acquire();
    try {
      g.createKeyIndex(key, elementClass, indexParameters);
    } finally {
      g.shutdown();
    }
  }

  @Override
  public <T extends Element> Set<String> getIndexedKeys(final Class<T> elementClass) {
    final OrientBaseGraph g = acquire();
    try {
      return g.getIndexedKeys(elementClass);
    } finally {
      g.shutdown();
    }
  }

  public OrientBaseGraph acquire() {
    init();
    final OrientBaseGraph g = factory.get();

    if (conflictStrategy != null) {
      final OStorage stg = g.getRawGraph().getStorage().getUnderlying();
      if (stg instanceof OStorageEmbedded)
        stg.setConflictStrategy(conflictStrategy);
    }

    return g;
  }

  public OCommandRequest command(final OCommandSQL iCommand) {

    final OrientBaseGraph g = acquire();
    try {
      return g.command(iCommand);
    } finally {

      g.shutdown();
    }
  }

  public long countVertices() {
    final OrientBaseGraph g = acquire();
    try {
      return g.countVertices();
    } finally {
      g.shutdown();
    }
  }

  @Override
  public long countVertices(String iClassName) {

    final OrientBaseGraph g = acquire();
    try {
      return g.countVertices(iClassName);
    } finally {
      g.shutdown();
    }
  }

  public long countEdges() {

    final OrientBaseGraph g = acquire();
    try {
      return g.countEdges();
    } finally {
      g.shutdown();
    }
  }

  @Override
  public long countEdges(String iClassName) {

    final OrientBaseGraph g = acquire();
    try {
      return g.countEdges(iClassName);
    } finally {
      g.shutdown();
    }
  }

  public <V> V execute(final OCallable<V, OrientBaseGraph> iCallable) {
    final OrientBaseGraph graph = acquire();
    try {
      return iCallable.call(graph);
    } finally {
      graph.shutdown();
    }
  }

  public int getMaxPoolSize() {
    return maxPoolSize;
  }

  public void setMaxPoolSize(final int maxPoolSize) {
    this.maxPoolSize = maxPoolSize;
  }

  public boolean isTransactional() {
    return transactional;
  }

  public void setTransactional(final boolean transactional) {
    this.transactional = transactional;
  }

  @Override
  public ODatabaseDocumentTx getRawGraph() {
    throw new UnsupportedOperationException("getRawGraph");
  }

  public int getMaxRetries() {
    return maxRetries;
  }

  public void setMaxRetries(final int maxRetries) {
    this.maxRetries = maxRetries;
  }

  public ORecordConflictStrategy getConflictStrategy() {
    return conflictStrategy;
  }

  public OrientGraphAsynch setConflictStrategy(final String iStrategyName) {
    conflictStrategy = Orient.instance().getRecordConflictStrategy().getStrategy(iStrategyName);
    return this;
  }

  public OrientGraphAsynch setConflictStrategy(final ORecordConflictStrategy iResolver) {
    conflictStrategy = iResolver;
    return this;
  }

  protected void init() {
    if (factory == null) {
      synchronized (this) {
        if (factory == null)
          factory = new OrientGraphFactory(url, userName, userPassword).setTransactional(transactional).setupPool(1, maxPoolSize);
      }
    }
  }

  protected MERGE_RESULT mergeAndSaveRecord(final int retry, final ODocument existent, final Object[] prop)
      throws InterruptedException {
    // MERGE RECORD WITH INPUT CONTENT
    if (mergeRecords(existent, prop)) {
      try {
        existent.save();

      } catch (ONeedRetryException ex) {
        concurrentException.incrementAndGet();
        if (retry < maxRetries) {
          verticesReloaded.incrementAndGet();
          existent.reload(null, true);
          return MERGE_RESULT.RETRY;
        } else
          return MERGE_RESULT.ERROR;
      }
    }

    return MERGE_RESULT.MERGED;
  }

  protected void reloadVertices(final OrientExtendedVertex vOut, final OrientExtendedVertex vIn, final String iLabel,
      final int retry, final OException e) {
    if (retry < maxRetries) {
      if (OLogManager.instance().isDebugEnabled())
        OLogManager.instance().debug(this, "Conflict on addEdge(%s,%s,%s), retrying (retry=%d/%d). Cause: %s. Thread: %d);", e,
            vOut, vIn, iLabel, retry, maxRetries, e, Thread.currentThread().getId());

      if (e instanceof OConcurrentModificationException) {
        // LOAD ONLY THE CONFLICTED RECORD ONLY
        if (((OConcurrentModificationException) e).getRid().equals(vOut.getIdentity()))
          vOut.reload();
        else
          vIn.reload();

        verticesReloaded.incrementAndGet();
      } else {
        // LOAD BOTH VERTICES'S RECORD
        if (!vOut.getRecord().getIdentity().isNew()) {
          vOut.reload();
          verticesReloaded.incrementAndGet();
          // } else {
          // v = getVertex( ((ORecordDuplicatedException)e).getRid() )
          // vOut.setProperty("@rid");
        }
        if (!vIn.getRecord().getIdentity().isNew()) {
          vIn.reload();
          verticesReloaded.incrementAndGet();
        }
      }

    } else
      throw e;
  }

  protected void dumpStats() {
    if (outStats == null)
      return;

    outStats.printf("\n---------------------------------");
    outStats.printf("\nOrientGraphAsynch stats");
    outStats.printf("\n---------------------------------");

    outStats.printf("\npool instances used.: %d", factory.getAvailableInstancesInPool());
    outStats.printf("\nverticesCreated.....: %d", verticesCreated.get());
    outStats.printf("\nedgesCreated........: %d", edgesCreated.get());
    outStats.printf("\nverticesRemoved.....: %d", verticesRemoved.get());
    outStats.printf("\nverticesLoaded......: %d", verticesLoaded.get());
    outStats.printf("\nverticesReloaded....: %d", verticesReloaded.get());
    outStats.printf("\nreusedCachedVertex..: %d", reusedCachedVertex.get());
    outStats.printf("\nindexUniqueException: %d", indexUniqueException.get());
    outStats.printf("\nconcurrentException.: %d", concurrentException.get());
    outStats.printf("\nunknownException....: %d", unknownException.get());
    outStats.println("\n");

    verticesCreated.set(0);
    edgesCreated.set(0);
    verticesLoaded.set(0);
    reusedCachedVertex.set(0);
    indexUniqueException.set(0);
    concurrentException.set(0);
    unknownException.set(0);
  }

  protected boolean mergeRecords(final ODocument iSource, final Object[] prop) throws InterruptedException {
    boolean modified = false;
    for (int i = 0; i < prop.length; i += 2) {
      final String pName = prop[i].toString();
      final Object pValue = prop[i + 1];

      final Object fieldValue = iSource.field(pName);
      if (fieldValue == null || (!fieldValue.equals(pValue))) {
        // OVERWRITE PROPERTY VALUE
        iSource.field(pName, fieldValue);
        modified = true;
      }
    }
    return modified;
  }

  protected OrientVertex getFromCache(final Object id) {
    if (vertexCache != null) {
      final OrientVertex v = vertexCache.remove(id);
      if (v != null) {
        reusedCachedVertex.incrementAndGet();
        // System.out.printf("\nThread " + Thread.currentThread().getId() + " Reused from cache key=%s v=%s", id, v);
        return v;
      }
    }

    return null;
  }

  protected void addInCache(final Object id, final OrientVertex v) {
    if (vertexCache != null && id != null && v != null) {
      if (v.getRecord().getIdentity().isNew()) {
        v.getRecord().setDirty();
        v.save();
      }

      if (!v.getRecord().getIdentity().isPersistent())
        OLogManager.instance().warn(this, "Cannot put a non persistent object in cache, key=%s, vertex=%s", id, v);

      vertexCache.put(id, v);
      // System.out.printf("\nPut in cache key=%s v=%s", id, v);
    }
  }

  protected void beginAsynchOperation() {
    init();
    operationStarted.incrementAndGet();
  }

  protected void endAsynchOperation() {
    operationCompleted.incrementAndGet();
    synchronized (operationCompleted) {
      operationCompleted.notifyAll();
    }
  }

  protected void config() {
    FEATURES.supportsDuplicateEdges = true;
    FEATURES.supportsSelfLoops = true;
    FEATURES.isPersistent = true;
    FEATURES.supportsVertexIteration = true;
    FEATURES.supportsVertexIndex = true;
    FEATURES.ignoresSuppliedIds = true;
    FEATURES.supportsTransactions = false;
    FEATURES.supportsVertexKeyIndex = true;
    FEATURES.supportsKeyIndices = true;
    FEATURES.isWrapper = false;
    FEATURES.supportsIndices = true;
    FEATURES.supportsVertexProperties = true;
    FEATURES.supportsEdgeProperties = true;

    // For more information on supported types, please see:
    // http://code.google.com/p/orient/wiki/Types
    FEATURES.supportsSerializableObjectProperty = true;
    FEATURES.supportsBooleanProperty = true;
    FEATURES.supportsDoubleProperty = true;
    FEATURES.supportsFloatProperty = true;
    FEATURES.supportsIntegerProperty = true;
    FEATURES.supportsPrimitiveArrayProperty = true;
    FEATURES.supportsUniformListProperty = true;
    FEATURES.supportsMixedListProperty = true;
    FEATURES.supportsLongProperty = true;
    FEATURES.supportsMapProperty = true;
    FEATURES.supportsStringProperty = true;
    FEATURES.supportsThreadedTransactions = false;
    FEATURES.supportsThreadIsolatedTransactions = false;
  }
}
TOP

Related Classes of com.tinkerpop.blueprints.impls.orient.asynch.OrientGraphAsynch

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.