예제 #1
0
 protected void commitRelationshipMaps(
     ArrayMap<String, RelIdArray> cowRelationshipAddMap,
     ArrayMap<String, RelIdArray> cowRelationshipRemoveMap) {
   if (relationshipMap == null) {
     // we will load full in some other tx
     return;
   }
   if (cowRelationshipAddMap != null) {
     for (String type : cowRelationshipAddMap.keySet()) {
       RelIdArray add = cowRelationshipAddMap.get(type);
       RelIdArray remove = null;
       if (cowRelationshipRemoveMap != null) {
         remove = cowRelationshipRemoveMap.get(type);
       }
       RelIdArray src = relationshipMap.get(type);
       relationshipMap.put(type, RelIdArray.from(src, add, remove));
     }
   }
   if (cowRelationshipRemoveMap != null) {
     for (String type : cowRelationshipRemoveMap.keySet()) {
       if (cowRelationshipAddMap != null && cowRelationshipAddMap.get(type) != null) {
         continue;
       }
       RelIdArray src = relationshipMap.get(type);
       RelIdArray remove = cowRelationshipRemoveMap.get(type);
       relationshipMap.put(type, RelIdArray.from(src, null, remove));
     }
   }
 }
예제 #2
0
  @Override
  public void attemptWaitForTxCompletionAndBlockFutureTransactions(long maxWaitTimeMillis) {
    msgLog.logMessage("TxManager is blocking new transactions and waiting for active to fail...");
    blocked = true;
    List<Transaction> failedTransactions = new ArrayList<Transaction>();
    synchronized (txThreadMap) {
      for (Transaction tx : txThreadMap.values()) {
        try {
          int status = tx.getStatus();
          if (status != Status.STATUS_COMMITTING
              && status
                  != Status
                      .STATUS_ROLLING_BACK) { // Set it to rollback only if it's not committing or
                                              // rolling back
            tx.setRollbackOnly();
          }
        } catch (IllegalStateException e) { // OK
          failedTransactions.add(tx);
        } catch (SystemException e) { // OK
          failedTransactions.add(tx);
        }
      }
    }
    msgLog.logMessage(
        "TxManager blocked transactions"
            + ((failedTransactions.isEmpty()
                ? ""
                : ", but failed for: " + failedTransactions.toString())));

    long endTime = System.currentTimeMillis() + maxWaitTimeMillis;
    while (txThreadMap.size() > 0 && System.currentTimeMillis() < endTime) Thread.yield();
  }
 ArrayMap<String, IntArray> getMoreRelationships(NodeImpl node) {
   int nodeId = (int) node.getId();
   RelationshipChainPosition position = node.getRelChainPosition();
   Iterable<RelationshipData> rels = persistenceManager.getMoreRelationships(nodeId, position);
   ArrayMap<String, IntArray> newRelationshipMap = new ArrayMap<String, IntArray>();
   for (RelationshipData rel : rels) {
     int relId = rel.getId();
     RelationshipImpl relImpl = relCache.get(relId);
     RelationshipType type = null;
     if (relImpl == null) {
       type = getRelationshipTypeById(rel.relationshipType());
       assert type != null;
       relImpl = new RelationshipImpl(relId, rel.firstNode(), rel.secondNode(), type, false, this);
       relCache.put(relId, relImpl);
     } else {
       type = relImpl.getType();
     }
     IntArray relationshipSet = newRelationshipMap.get(type.name());
     if (relationshipSet == null) {
       relationshipSet = new IntArray();
       newRelationshipMap.put(type.name(), relationshipSet);
     }
     relationshipSet.add(relId);
   }
   return newRelationshipMap;
 }
예제 #4
0
 private void receiveRelationships(
     Iterable<RelationshipRecord> rels,
     ArrayMap<Integer, RelIdArray> newRelationshipMap,
     List<RelationshipImpl> relsList,
     DirectionWrapper dir,
     boolean hasLoops) {
   for (RelationshipRecord rel : rels) {
     long relId = rel.getId();
     RelationshipImpl relImpl = relCache.get(relId);
     RelationshipType type = null;
     int typeId;
     if (relImpl == null) {
       typeId = rel.getType();
       type = getRelationshipTypeById(typeId);
       assert type != null;
       relImpl =
           newRelationshipImpl(
               relId, rel.getFirstNode(), rel.getSecondNode(), type, typeId, false);
       relsList.add(relImpl);
     } else {
       typeId = relImpl.getTypeId();
       type = getRelationshipTypeById(typeId);
     }
     RelIdArray relationshipSet = newRelationshipMap.get(typeId);
     if (relationshipSet == null) {
       relationshipSet = hasLoops ? new RelIdArrayWithLoops(typeId) : new RelIdArray(typeId);
       newRelationshipMap.put(typeId, relationshipSet);
     }
     relationshipSet.add(relId, dir);
   }
 }
예제 #5
0
 public T acquireResourceConnection() {
   T con = null;
   Transaction tx = this.getCurrentTransaction();
   if (tx == null) {
     throw new NotInTransactionException();
   }
   con = txConnectionMap.get(tx);
   if (con == null) {
     try {
       con = (T) newConnection();
       if (!tx.enlistResource(con.getXaResource())) {
         throw new RuntimeException("Unable to enlist '" + con.getXaResource() + "' in " + tx);
       }
       tx.registerSynchronization(new TxCommitHook(tx));
       txConnectionMap.put(tx, con);
     } catch (javax.transaction.RollbackException re) {
       String msg = "The transaction is marked for rollback only.";
       throw new RuntimeException(msg, re);
     } catch (javax.transaction.SystemException se) {
       String msg = "TM encountered an unexpected error condition.";
       throw new RuntimeException(msg, se);
     }
   }
   return con;
 }
 public CowRelElement relationshipElement(long id, boolean create) {
   CowRelElement result = relationships.get(id);
   if (result == null && create) {
     result = new CowRelElement(id);
     relationships.put(id, result);
   }
   return result;
 }
 public CowNodeElement nodeElement(long id, boolean create) {
   CowNodeElement result = nodes.get(id);
   if (result == null && create) {
     result = new CowNodeElement(id);
     nodes.put(id, result);
   }
   return result;
 }
예제 #8
0
파일: RWLock.java 프로젝트: naimdjon/neo4j
 private TxLockElement getOrCreateLockElement(Object tx) {
   assertTransaction(tx);
   TxLockElement tle = txLockElementMap.get(tx);
   if (tle == null) {
     txLockElementMap.put(tx, tle = new TxLockElement(tx));
   }
   return tle;
 }
 /** Closes this index service and frees all resources. */
 public void close() {
   for (IndexSearcher searcher : indexSearchers.values()) {
     try {
       searcher.close();
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
   indexSearchers.clear();
 }
 @Override
 public ArrayMap<Integer, Collection<Long>> getCowRelationshipRemoveMap(NodeImpl node) {
   if (primitiveElement != null) {
     ArrayMap<Long, CowNodeElement> cowElements = primitiveElement.nodes;
     CowNodeElement element = cowElements.get(node.getId());
     if (element != null) {
       return element.relationshipRemoveMap;
     }
   }
   return null;
 }
 public RelIdArray getRelationshipAddMap(int type, boolean create) {
   ArrayMap<Integer, RelIdArray> map = getRelationshipAddMap(create);
   if (map == null) {
     return null;
   }
   RelIdArray result = map.get(type);
   if (result == null && create) {
     result = new RelIdArrayWithLoops(type);
     map.put(type, result);
   }
   return result;
 }
 public SetAndDirectionCounter getRelationshipRemoveMap(int type, boolean create) {
   ArrayMap<Integer, SetAndDirectionCounter> map = getRelationshipRemoveMap(create);
   if (map == null) {
     return null;
   }
   SetAndDirectionCounter result = map.get(type);
   if (result == null && create) {
     result = new SetAndDirectionCounter();
     map.put(type, result);
   }
   return result;
 }
 private void releaseCows(int param) {
   if (primitiveElement == null) {
     return;
   }
   ArrayMap<Long, CowNodeElement> cowNodeElements = primitiveElement.nodes;
   Set<Entry<Long, CowNodeElement>> nodeEntrySet = cowNodeElements.entrySet();
   for (Entry<Long, CowNodeElement> entry : nodeEntrySet) {
     NodeImpl node = nodeManager.getNodeIfCached(entry.getKey());
     if (node != null) {
       CowNodeElement nodeElement = entry.getValue();
       if (param == Status.STATUS_COMMITTED) {
         node.commitRelationshipMaps(
             nodeElement.relationshipAddMap, nodeElement.relationshipRemoveMap);
         node.commitPropertyMaps(
             nodeElement.propertyAddMap, nodeElement.propertyRemoveMap, nodeElement.firstProp);
       } else if (param != Status.STATUS_ROLLEDBACK) {
         throw new TransactionFailureException("Unknown transaction status: " + param);
       }
       int sizeAfter = node.sizeOfObjectInBytesIncludingOverhead();
       nodeManager.updateCacheSize(node, sizeAfter);
     }
   }
   ArrayMap<Long, CowRelElement> cowRelElements = primitiveElement.relationships;
   Set<Entry<Long, CowRelElement>> relEntrySet = cowRelElements.entrySet();
   for (Entry<Long, CowRelElement> entry : relEntrySet) {
     RelationshipImpl rel = nodeManager.getRelIfCached(entry.getKey());
     if (rel != null) {
       CowRelElement relElement = entry.getValue();
       if (param == Status.STATUS_COMMITTED) {
         rel.commitPropertyMaps(
             relElement.propertyAddMap,
             relElement.propertyRemoveMap,
             Record.NO_NEXT_PROPERTY.intValue());
       } else if (param != Status.STATUS_ROLLEDBACK) {
         throw new TransactionFailureException("Unknown transaction status: " + param);
       }
       int sizeAfter = rel.sizeOfObjectInBytesIncludingOverhead();
       nodeManager.updateCacheSize(rel, sizeAfter);
     }
   }
   if (primitiveElement.graph != null && param == Status.STATUS_COMMITTED) {
     nodeManager
         .getGraphProperties()
         .commitPropertyMaps(
             primitiveElement.graph.getPropertyAddMap(false),
             primitiveElement.graph.getPropertyRemoveMap(false),
             Record.NO_NEXT_PROPERTY.intValue());
   }
 }
 public void shutdown() {
   try {
     for (IndexSearcher searcher : indexSearchers.values()) {
       searcher.close();
     }
     indexSearchers.clear();
     optimize();
     for (IndexWriterContext writer : indexWriters.values()) {
       writer.writer.close();
     }
     indexWriters.clear();
   } catch (IOException e) {
     throw new RuntimeException(e);
   }
 }
예제 #15
0
 String getStringKey(int keyId) {
   String stringKey = idToIndex.get(keyId);
   if (stringKey == null) {
     throw new NotFoundException("No such property index[" + keyId + "]");
   }
   return stringKey;
 }
예제 #16
0
파일: RWLock.java 프로젝트: naimdjon/neo4j
 private TxLockElement getLockElement(Object tx) {
   TxLockElement tle = txLockElementMap.get(tx);
   if (tle == null) {
     throw new LockNotFoundException("No transaction lock element found for " + tx);
   }
   return tle;
 }
예제 #17
0
파일: RWLock.java 프로젝트: naimdjon/neo4j
  /**
   * Releases the write lock held by the provided tx. If it is null then an attempt to acquire the
   * current transaction from the transaction manager will be made. This is to make safe calling
   * this method as an <code>afterCompletion()</code> hook where the transaction context is not
   * necessarily available. If write count is zero and there are waiting transactions in the queue
   * they will be interrupted if they can acquire the lock.
   */
  synchronized void releaseWriteLock(Object tx) throws LockNotFoundException {
    TxLockElement tle = getLockElement(tx);

    if (tle.writeCount == 0) {
      throw new LockNotFoundException("" + tx + " don't have writeLock");
    }

    totalWriteCount--;
    tle.writeCount--;
    if (tle.isFree()) {
      txLockElementMap.remove(tx);
      ragManager.lockReleased(this, tx);
    }

    // the threads in the waitingList cannot be currentThread
    // so we only have to wake other elements if writeCount is down to zero
    // (that is: If writeCount > 0 a waiting thread in the queue cannot be
    // the thread that holds the write locks because then it would never
    // have been put into wait mode)
    if (totalWriteCount == 0 && waitingThreadList.size() > 0) {
      // wake elements in queue until a write lock is found or queue is
      // empty
      do {
        WaitElement we = waitingThreadList.removeLast();
        if (!we.element.movedOn) {
          we.waitingThread.interrupt();
          if (we.lockType == LockType.WRITE) {
            break;
          }
        }
      } while (waitingThreadList.size() > 0);
    }
  }
예제 #18
0
 int getKeyId(String stringKey) {
   Integer keyId = propertyIndexes.get(stringKey);
   if (keyId != null) {
     return keyId;
   }
   return -1;
 }
  // after invoke the transaction must wait on the resource
  synchronized void checkWaitOn(Object resource, Transaction tx) throws DeadlockDetectedException {
    List<Transaction> lockingTxList = resourceMap.get(resource);
    if (lockingTxList == null) {
      throw new LockException("Illegal resource[" + resource + "], not found in map");
    }

    if (waitingTxMap.get(tx) != null) {
      throw new LockException(tx + " already waiting for resource");
    }

    Iterator<Transaction> itr = lockingTxList.iterator();
    List<Transaction> checkedTransactions = new LinkedList<Transaction>();
    Stack<Object> graphStack = new Stack<Object>();
    // has resource,transaction interleaved
    graphStack.push(resource);
    while (itr.hasNext()) {
      Transaction lockingTx = itr.next();
      // the if statement bellow is valid because:
      // t1 -> r1 -> t1 (can happened with RW locks) is ok but,
      // t1 -> r1 -> t1&t2 where t2 -> r1 is a deadlock
      // think like this, we have two transactions and one resource
      // o t1 takes read lock on r1
      // o t2 takes read lock on r1
      // o t1 wanna take write lock on r1 but has to wait for t2
      // to release the read lock ( t1->r1->(t1&t2), ok not deadlock yet
      // o t2 wanna take write lock on r1 but has to wait for t1
      // to release read lock....
      // DEADLOCK t1->r1->(t1&t2) and t2->r1->(t1&t2) ===>
      // t1->r1->t2->r1->t1, t2->r1->t1->r1->t2 etc...
      // to allow the first three steps above we check if lockingTx ==
      // waitingTx on first level.
      // because of this special case we have to keep track on the
      // already "checked" tx since it is (now) legal for one type of
      // circular reference to exist (t1->r1->t1) otherwise we may
      // traverse t1->r1->t2->r1->t2->r1->t2... until SOE
      // ... KISS to you too
      if (lockingTx.equals(tx)) {
        continue;
      }
      graphStack.push(tx);
      checkWaitOnRecursive(lockingTx, tx, checkedTransactions, graphStack);
      graphStack.pop();
    }

    // ok no deadlock, we can wait on resource
    waitingTxMap.put(tx, resource);
  }
예제 #20
0
 public int getStatus() {
   Thread thread = Thread.currentThread();
   TransactionImpl tx = txThreadMap.get(thread);
   if (tx != null) {
     return tx.getStatus();
   }
   return Status.STATUS_NO_TRANSACTION;
 }
예제 #21
0
 List<RelTypeElementIterator> getAllRelationships(NodeManager nodeManager) {
   ensureRelationshipMapNotNull(nodeManager);
   List<RelTypeElementIterator> relTypeList = new LinkedList<RelTypeElementIterator>();
   boolean hasModifications = nodeManager.getLockReleaser().hasRelationshipModifications(this);
   ArrayMap<String, RelIdArray> addMap = null;
   if (hasModifications) {
     addMap = nodeManager.getCowRelationshipAddMap(this);
   }
   for (String type : relationshipMap.keySet()) {
     RelIdArray src = relationshipMap.get(type);
     RelIdArray remove = null;
     RelIdArray add = null;
     if (hasModifications) {
       remove = nodeManager.getCowRelationshipRemoveMap(this, type);
       if (addMap != null) {
         add = addMap.get(type);
       }
     }
     //            if ( src != null || add != null )
     //            {
     relTypeList.add(RelTypeElement.create(type, this, src, add, remove));
     //            }
   }
   if (addMap != null) {
     for (String type : addMap.keySet()) {
       if (relationshipMap.get(type) == null) {
         RelIdArray remove = nodeManager.getCowRelationshipRemoveMap(this, type);
         RelIdArray add = addMap.get(type);
         relTypeList.add(RelTypeElement.create(type, this, null, add, remove));
       }
     }
   }
   return relTypeList;
 }
 List<RelTypeElementIterator> getAllRelationships(NodeManager nodeManager) {
   ensureRelationshipMapNotNull(nodeManager);
   List<RelTypeElementIterator> relTypeList = new LinkedList<RelTypeElementIterator>();
   ArrayMap<String, IntArray> addMap = nodeManager.getCowRelationshipAddMap(this);
   for (String type : relationshipMap.keySet()) {
     IntArray src = relationshipMap.get(type);
     IntArray remove = nodeManager.getCowRelationshipRemoveMap(this, type);
     IntArray add = null;
     if (addMap != null) {
       add = addMap.get(type);
     }
     if (src != null || add != null) {
       relTypeList.add(RelTypeElement.create(type, this, src, add, remove));
     }
   }
   if (addMap != null) {
     for (String type : addMap.keySet()) {
       if (relationshipMap.get(type) == null) {
         IntArray remove = nodeManager.getCowRelationshipRemoveMap(this, type);
         IntArray add = addMap.get(type);
         relTypeList.add(RelTypeElement.create(type, this, null, add, remove));
       }
     }
   }
   return relTypeList;
 }
예제 #23
0
 // need synch here so we don't create multiple lists
 private synchronized void addPropertyIndex(PropertyIndex index) {
   List<PropertyIndex> list = indexMap.get(index.getKey());
   if (list == null) {
     list = new CopyOnWriteArrayList<PropertyIndex>();
     indexMap.put(index.getKey(), list);
   }
   list.add(index);
   idToIndexMap.put(index.getKeyId(), index);
 }
예제 #24
0
 public void setRollbackOnly() throws IllegalStateException, SystemException {
   assertTmOk("tx set rollback only");
   Thread thread = Thread.currentThread();
   TransactionImpl tx = txThreadMap.get(thread);
   if (tx == null) {
     throw new IllegalStateException("Not in transaction");
   }
   tx.setRollbackOnly();
 }
예제 #25
0
 public void resume(Transaction tx) throws IllegalStateException, SystemException {
   assertTmOk("tx resume");
   Thread thread = Thread.currentThread();
   if (txThreadMap.get(thread) != null) {
     throw new IllegalStateException("Transaction already associated");
   }
   if (tx != null) {
     TransactionImpl txImpl = (TransactionImpl) tx;
     if (txImpl.getStatus() != Status.STATUS_NO_TRANSACTION) {
       if (txImpl.isActive()) {
         throw new IllegalStateException(txImpl + " already active");
       }
       txImpl.markAsActive();
       txThreadMap.put(thread, txImpl);
     }
     // generate pro-active event resume
   }
 }
예제 #26
0
 void commit(Transaction tx) {
   if (tx != null) {
     TxCommitHook hook = txCommitHooks.remove(tx);
     if (hook != null) {
       for (PropertyIndex index : hook.getAddedPropertyIndexes()) {
         addPropertyIndex(index);
       }
     }
   }
 }
 public void optimize() {
   try {
     for (IndexWriterContext writer : indexWriters.values()) {
       writer.writer.optimize(true);
       writer.modifiedFlag = true;
     }
   } catch (IOException e) {
     throw new RuntimeException(e);
   }
 }
  private IndexWriterContext getWriter(String key, boolean allowCreate) throws IOException {
    IndexWriterContext writer = indexWriters.get(key);
    Directory dir = instantiateDirectory(key);
    if (writer == null && (allowCreate || IndexReader.indexExists(dir))) {
      try {
        IndexWriter indexWriter = new IndexWriter(dir, fieldAnalyzer, MaxFieldLength.UNLIMITED);

        // TODO We should tamper with this value and see how it affects
        // the general performance. Lucene docs says rather >10 for
        // batch inserts
        //                indexWriter.setMergeFactor( 15 );
        writer = new IndexWriterContext(indexWriter);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
      indexWriters.put(key, writer);
    }
    return writer;
  }
예제 #29
0
 public Transaction suspend() throws SystemException {
   assertTmOk("tx suspend");
   // check for ACTIVE/MARKED_ROLLBACK?
   TransactionImpl tx = txThreadMap.remove(Thread.currentThread());
   if (tx != null) {
     // generate pro-active event suspend
     tx.markAsSuspended();
   }
   return tx;
 }
예제 #30
0
 // concurent transactions may create duplicate keys, oh well
 PropertyIndex createPropertyIndex(String key) {
   Transaction tx = getTransaction();
   if (tx == null) {
     throw new NotInTransactionException("Unable to create property index for " + key);
   }
   TxCommitHook hook = txCommitHooks.get(tx);
   if (hook == null) {
     hook = new TxCommitHook();
     txCommitHooks.put(tx, hook);
   }
   PropertyIndex index = hook.getIndex(key);
   if (index != null) {
     return index;
   }
   int id = (int) idGenerator.nextId(PropertyIndex.class);
   index = new PropertyIndex(key, id);
   hook.addIndex(index);
   persistenceManager.createPropertyIndex(key, id);
   return index;
 }