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); } } }
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); } }
@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])); }
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); }
@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; }
/** 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); } }); } }
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); } }
@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); } } } }
@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; }
/** 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 }
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(); } }
@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()); } }
/** 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)); } }