예제 #1
0
 public void rotateLogicalLogs() {
   for (XaDataSource dataSource : dataSources.values()) {
     try {
       dataSource.rotateLogicalLog();
     } catch (IOException e) {
       msgLog.logMessage("Couldn't rotate logical log for " + dataSource.getName(), e);
     }
   }
 }
예제 #2
0
 public Response<Pair<Integer, Long>> getMasterIdForCommittedTx(long txId, StoreId storeId) {
   XaDataSource nioneoDataSource = graphDb.getXaDataSourceManager().getNeoStoreDataSource();
   try {
     Pair<Integer, Long> masterId = nioneoDataSource.getMasterForCommittedTx(txId);
     return ServerUtil.packResponseWithoutTransactionStream(graphDb.getStoreId(), masterId);
   } catch (IOException e) {
     throw new RuntimeException("Couldn't get master ID for " + txId, e);
   }
 }
예제 #3
0
 @SuppressWarnings("unchecked")
 private SlaveContext slaveContextOf(GraphDatabaseService graphDb) {
   XaDataSourceManager dsManager =
       ((AbstractGraphDatabase) graphDb).getConfig().getTxModule().getXaDataSourceManager();
   List<Pair<String, Long>> txs = new ArrayList<Pair<String, Long>>();
   for (XaDataSource ds : dsManager.getAllRegisteredDataSources()) {
     txs.add(Pair.of(ds.getName(), ds.getLastCommittedTxId()));
   }
   return new SlaveContext(0, 0, txs.toArray(new Pair[0]));
 }
예제 #4
0
 private void getLastCommittedTxs(GraphDatabaseService graphDb) {
   for (XaDataSource ds :
       ((AbstractGraphDatabase) graphDb)
           .getConfig()
           .getTxModule()
           .getXaDataSourceManager()
           .getAllRegisteredDataSources()) {
     lastCommittedTxs.put(ds.getName(), ds.getLastCommittedTxId());
   }
 }
 protected void configureSourceDb(final EmbeddedGraphDatabase graphDb) {
   XaDataSource neoStoreXaDataSource =
       graphDb
           .getConfig()
           .getPersistenceModule()
           .getPersistenceManager()
           .getPersistenceSource()
           .getXaDataSource();
   neoStoreXaDataSource.keepLogicalLogs(true);
   XaDataSourceManager xaDsm = graphDb.getConfig().getTxModule().getXaDataSourceManager();
   XaDataSource ds = xaDsm.getXaDataSource("lucene");
   ((LuceneDataSource) ds).keepLogicalLogs(true);
 }
예제 #6
0
 @Override
 public Object call() throws Exception {
   String provider = config.get(PROVIDER);
   String dataSourceName = getIndexProvider(provider).getDataSourceName();
   XaDataSource dataSource = xaDataSourceManager.getXaDataSource(dataSourceName);
   IndexXaConnection connection = (IndexXaConnection) dataSource.getXaConnection();
   try (Transaction tx = graphDatabaseAPI.tx().begin()) {
     javax.transaction.Transaction javaxTx = txManager.getTransaction();
     connection.enlistResource(javaxTx);
     connection.createIndex(cls, indexName, config);
     tx.success();
   }
   return null;
 }
예제 #7
0
 /** Public for testing purpose. Do not use. */
 public synchronized void registerDataSource(final XaDataSource dataSource) {
   dataSources.put(dataSource.getName(), dataSource);
   branchIdMapping.put(UTF8.decode(dataSource.getBranchId()), dataSource);
   sourceIdMapping.put(dataSource.getName(), dataSource.getBranchId());
   life.add(dataSource);
   if (life.getStatus().equals(LifecycleStatus.STARTED)) {
     Listeners.notifyListeners(
         dsRegistrationListeners,
         new Listeners.Notification<DataSourceRegistrationListener>() {
           @Override
           public void notify(DataSourceRegistrationListener listener) {
             listener.registeredDataSource(dataSource);
           }
         });
   }
 }
예제 #8
0
 public Response<Long> commitSingleResourceTransaction(
     RequestContext context, String resource, TxExtractor txGetter) {
   Transaction otherTx = suspendOtherAndResumeThis(context, false);
   try {
     XaDataSource dataSource = graphDb.getXaDataSourceManager().getXaDataSource(resource);
     final long txId = dataSource.applyPreparedTransaction(txGetter.extract());
     Predicate<Long> upUntilThisTx =
         new Predicate<Long>() {
           public boolean accept(Long item) {
             return item < txId;
           }
         };
     return packResponse(context, txId, upUntilThisTx);
   } catch (IOException e) {
     throw new RuntimeException(e);
   } finally {
     suspendThisAndResumeOther(otherTx, context);
   }
 }
예제 #9
0
 @Override
 public void start() {
   for (XaDataSource ds : xaDsm.getAllRegisteredDataSources()) {
     if (ds.getName().equals(Config.DEFAULT_DATA_SOURCE_NAME)) {
       // load and verify from PS
       NameData[] relTypes = null;
       NameData[] propertyIndexes = null;
       // beginTx();
       relTypes = persistenceManager.loadAllRelationshipTypes();
       propertyIndexes = persistenceManager.loadPropertyIndexes(INDEX_COUNT);
       // commitTx();
       addRawRelationshipTypes(relTypes);
       addPropertyIndexes(propertyIndexes);
       if (propertyIndexes.length < INDEX_COUNT) {
         setHasAllpropertyIndexes(true);
       }
     }
   }
 }
예제 #10
0
  @Override
  public void doRecovery() throws Throwable {
    TransactionResourceManager trm =
        new TransactionResourceManager() {
          @Override
          public void returnXAResource(String rmName, XAResource rmXares) {
            return;
          }
        };

    try {
      for (XaDataSource xaDs : xaDataSourceManager.getAllRegisteredDataSources()) {
        Current.getTransactionRecovery()
            .registerResourceManager(
                xaDs.getName(), xaDs.getXaConnection().getXaResource(), xaDs.getName(), trm);
      }
      Current.getTransactionRecovery().startResourceManagerRecovery();
    } catch (XAException e) {
      throw new Error("Error registering xa datasource", e);
    }
  }
 private boolean setupGreeting() {
   if (retries > 20) {
     close();
   }
   if (!acquireWriteBuffer()) {
     retries++;
     return false;
   }
   buffer.put(HeaderConstants.SLAVE_GREETING);
   buffer.putLong(xaDs.getRandomIdentifier());
   buffer.putLong(xaDs.getCreationTime());
   buffer.putLong(xaDs.getCurrentLogVersion());
   byte[] bytes = xaDsName.getBytes();
   buffer.putInt(bytes.length);
   buffer.put(bytes);
   buffer.flip();
   log("Setup greeting");
   setStatus(Status.SEND_GREETING);
   retries = 0;
   return true;
 }
예제 #12
0
  /** Public for testing purpose. Do not use. */
  public synchronized void unregisterDataSource(String name) {
    final XaDataSource dataSource = dataSources.get(name);
    if (dataSource == null) {
      return;
    }

    byte branchId[] = getBranchId(dataSource.getXaConnection().getXaResource());
    dataSources.remove(name);
    branchIdMapping.remove(UTF8.decode(branchId));
    sourceIdMapping.remove(name);
    Listeners.notifyListeners(
        dsRegistrationListeners,
        new Listeners.Notification<DataSourceRegistrationListener>() {
          @Override
          public void notify(DataSourceRegistrationListener listener) {
            listener.unregisteredDataSource(dataSource);
          }
        });
    life.remove(dataSource);
    // No need for shutdown, removing does that
  }
예제 #13
0
 synchronized byte[] getBranchId(XAResource xaResource) {
   if (xaResource instanceof XaResource) {
     byte branchId[] = ((XaResource) xaResource).getBranchId();
     if (branchId != null) {
       return branchId;
     }
   }
   for (Map.Entry<String, XaDataSource> entry : dataSources.entrySet()) {
     XaDataSource dataSource = entry.getValue();
     XAResource resource = dataSource.getXaConnection().getXaResource();
     try {
       if (resource.isSameRM(xaResource)) {
         String name = entry.getKey();
         return sourceIdMapping.get(name);
       }
     } catch (XAException e) {
       throw new TransactionFailureException("Unable to check is same resource", e);
     }
   }
   throw new TransactionFailureException(
       "Unable to find mapping for XAResource[" + xaResource + "]");
 }
 private boolean getResponse() {
   if (retries > 20) {
     close();
   }
   if (!acquireReadBuffer()) {
     retries++;
     return false;
   }
   try {
     // HEADER(1) + DB_VERISON(8)
     buffer.limit(9);
     int read = connection.read();
     log("Get greeting response");
     if (read == 1 || read == 9) {
       buffer.flip();
       byte masterGreeting = buffer.get();
       if (masterGreeting == HeaderConstants.BYE) {
         log("Problem connecting to master " + connection + ". Got BYE.");
         close();
         return true;
       } else if (masterGreeting != HeaderConstants.MASTER_GREETING) {
         log("Got unkown greeting[" + masterGreeting + "] from " + connection);
         close();
       } else if (read != 9) {
         retries++;
         connection.pushBackAllReadData();
         return false;
       }
       masterVersion = buffer.getLong();
       log("Got master version: " + masterVersion);
       if (masterVersion < xaDs.getCurrentLogVersion()) {
         log("Got wrong version [" + masterVersion + "]");
         close();
         return true;
       }
       setNoRequeue();
       setChainJob(new HandleMasterConnection(connection, slave, masterVersion, xaDs));
       return true;
     } else {
       retries++;
       if (read > 0) {
         connection.pushBackAllReadData();
       }
       return false;
     }
   } finally {
     releaseReadBuffer();
   }
 }
예제 #15
0
 @Test
 public void hasAllXaManagerBeans() {
   for (XaDataSource xaDataSource :
       graphDb.getXaDataSourceManager().getAllRegisteredDataSources()) {
     XaResourceInfo info = getByName(xaDataSource.getName());
     assertEquals(
         "wrong branchid for XA data source " + xaDataSource.getName(),
         XaManagerBean.toHexString(xaDataSource.getBranchId()),
         info.getBranchId());
     assertEquals(
         "wrong log version for XA data source " + xaDataSource.getName(),
         xaDataSource.getCurrentLogVersion(),
         info.getLogVersion());
     assertEquals(
         "wrong last tx ID for XA data source " + xaDataSource.getName(),
         xaDataSource.getLastCommittedTxId(),
         info.getLastTxId());
   }
 }
예제 #16
0
  /** Recover all datasources */
  public void recover(Iterator<List<TxLog.Record>> knownDanglingRecordList) {
    // contains NonCompletedTransaction that needs to be committed
    List<NonCompletedTransaction> commitList = new ArrayList<NonCompletedTransaction>();

    // contains Xids that should be rolledback
    final List<Xid> rollbackList = new LinkedList<Xid>();

    // key = Resource(branchId) value = XAResource
    final Map<Resource, XaDataSource> resourceMap = new HashMap<Resource, XaDataSource>();
    buildRecoveryInfo(commitList, rollbackList, resourceMap, knownDanglingRecordList);
    // invoke recover on all xa resources found
    final List<Xid> recoveredXidsList = new LinkedList<Xid>();

    try {

      for (XaDataSource xaDataSource : dataSources.values()) {
        XAResource xaRes = xaDataSource.getXaConnection().getXaResource();
        Xid xids[] = xaRes.recover(XAResource.TMNOFLAGS);

        for (Xid xid : xids) {
          if (XidImpl.isThisTm(xid.getGlobalTransactionId())) {
            // linear search
            if (rollbackList.contains(xid)) {
              msgLog.logMessage("TM: Found pre commit " + xid + " rolling back ... ", true);
              rollbackList.remove(xid);
              xaRes.rollback(xid);
            } else {
              Resource resource = new Resource(xid.getBranchQualifier());
              if (!resourceMap.containsKey(resource)) {
                resourceMap.put(resource, xaDataSource);
              }
              recoveredXidsList.add(xid);
            }
          } else {
            msgLog.warn("Unknown xid: " + xid);
          }
        }
      }

      // sort the commit list after sequence number
      Collections.sort(commitList);

      // go through and commit
      for (NonCompletedTransaction nct : commitList) {
        int seq = nct.getSequenceNumber();
        Xid xids[] = nct.getXids();
        msgLog.debug("Marked as commit tx-seq[" + seq + "] branch length: " + xids.length);
        for (Xid xid : xids) {
          if (!recoveredXidsList.contains(xid)) {
            msgLog.debug(
                "Tx-seq["
                    + seq
                    + "]["
                    + xid
                    + "] not found in recovered xid list, "
                    + "assuming already committed");
            continue;
          }
          recoveredXidsList.remove(xid);
          Resource resource = new Resource(xid.getBranchQualifier());
          if (!resourceMap.containsKey(resource)) {
            final TransactionFailureException ex =
                new TransactionFailureException("Couldn't find XAResource for " + xid);
            throw logAndReturn("TM: recovery error", ex);
          }
          msgLog.debug("TM: Committing tx " + xid);
          resourceMap.get(resource).getXaConnection().getXaResource().commit(xid, false);
        }
      }

      // rollback the rest
      for (Xid xid : recoveredXidsList) {
        Resource resource = new Resource(xid.getBranchQualifier());
        if (!resourceMap.containsKey(resource)) {
          final TransactionFailureException ex =
              new TransactionFailureException("Couldn't find XAResource for " + xid);
          throw logAndReturn("TM: recovery error", ex);
        }
        msgLog.debug("TM: no match found for " + xid + " removing");
        resourceMap.get(resource).getXaConnection().getXaResource().rollback(xid);
      }
      if (rollbackList.size() > 0) {
        msgLog.debug(
            "TxLog contained unresolved "
                + "xids that needed rollback. They couldn't be matched to "
                + "any of the XAResources recover list. "
                + "Assuming "
                + rollbackList.size()
                + " transactions already rolled back.");
      }

      // Rotate the logs of the participated data sources, making sure that
      // done-records are written so that even if the tm log gets truncated,
      // which it will be after this recovery, that transaction information
      // doesn't get lost.
      for (XaDataSource participant : MapUtil.reverse(resourceMap).keySet()) {
        participant.rotateLogicalLog();
      }
    } catch (IOException | XAException e) {
      throw logAndReturn(
          "TM: recovery failed", new TransactionFailureException("Recovery failed.", e));
    }
  }