Beispiel #1
0
        private void DownloadDatabase(StoreId localStoreId)
        {
            try
            {
                _localDatabase.stopForStoreCopy();
                _enableDisableOnStoreCopy.disable();
            }
            catch (Exception throwable)
            {
                throw new Exception(throwable);
            }

            try
            {
                MemberId source = _selectionStrategy.bestUpstreamDatabase();
                AdvertisedSocketAddress fromAddress = _topologyService.findCatchupAddress(source).orElseThrow(() => new TopologyLookupException(source));
                _storeCopyProcess.replaceWithStoreFrom(new CatchupAddressProvider_SingleAddressProvider(fromAddress), localStoreId);
            }
            catch (Exception e) when(e is IOException || e is StoreCopyFailedException || e is UpstreamDatabaseSelectionException || e is TopologyLookupException)
            {
                _log.warn("Error copying store. Will retry shortly.", e);
                return;
            }
            catch (DatabaseShutdownException e)
            {
                _log.warn("Store copy aborted due to shutdown.", e);
                return;
            }

            try
            {
                _localDatabase.start();
                _enableDisableOnStoreCopy.enable();
            }
            catch (Exception throwable)
            {
                throw new Exception(throwable);
            }

            _latestTxIdOfUpStream = 0;               // we will find out on the next pull request response
            _state = TX_PULLING;
            _applier.refreshFromNewStore();
        }
Beispiel #2
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void syncStoreWithUpstream(org.neo4j.causalclustering.identity.MemberId source) throws java.io.IOException, org.neo4j.causalclustering.catchup.storecopy.StoreIdDownloadFailedException, org.neo4j.causalclustering.catchup.storecopy.StoreCopyFailedException, org.neo4j.causalclustering.core.state.snapshot.TopologyLookupException, org.neo4j.causalclustering.catchup.storecopy.DatabaseShutdownException
        private void SyncStoreWithUpstream(MemberId source)
        {
            if (_localDatabase.Empty)
            {
                _debugLog.info("Local database is empty, attempting to replace with copy from upstream server %s", source);

                _debugLog.info("Finding store id of upstream server %s", source);
                AdvertisedSocketAddress fromAddress = _topologyService.findCatchupAddress(source).orElseThrow(() => new TopologyLookupException(source));
                StoreId storeId = _remoteStore.getStoreId(fromAddress);

                _debugLog.info("Copying store from upstream server %s", source);
                _localDatabase.delete();
                _storeCopyProcess.replaceWithStoreFrom(new CatchupAddressProvider_SingleAddressProvider(fromAddress), storeId);

                _debugLog.info("Restarting local database after copy.", source);
            }
            else
            {
                EnsureSameStoreIdAs(source);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Tries to catchup this instance by downloading a snapshot. A snapshot consists of both the
        /// comparatively small state of the cluster state machines as well as the database store. The
        /// store is however caught up using two different approach. If it is possible to catchup by
        /// pulling transactions, then this will be sufficient, but if the store is lagging too far
        /// behind then a complete store copy will be attempted.
        /// </summary>
        /// <param name="addressProvider"> Provider of addresses to catchup from. </param>
        /// <returns> True if the operation succeeded, and false otherwise. </returns>
        /// <exception cref="LifecycleException"> A major database component failed to start or stop. </exception>
        /// <exception cref="IOException"> An issue with I/O. </exception>
        /// <exception cref="DatabaseShutdownException"> The database is shutting down. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: boolean downloadSnapshot(org.neo4j.causalclustering.catchup.CatchupAddressProvider addressProvider) throws org.neo4j.kernel.lifecycle.LifecycleException, java.io.IOException, org.neo4j.causalclustering.catchup.storecopy.DatabaseShutdownException
        internal virtual bool DownloadSnapshot(CatchupAddressProvider addressProvider)
        {
            /* Extract some key properties before shutting it down. */
            bool isEmptyStore = _localDatabase.Empty;

            /*
             *  There is no reason to try to recover if there are no transaction logs and in fact it is
             *  also problematic for the initial transaction pull during the snapshot download because the
             *  kernel will create a transaction log with a header where previous index points to the same
             *  index as that written down into the metadata store. This is problematic because we have no
             *  guarantee that there are later transactions and we need at least one transaction in
             *  the log to figure out the Raft log index (see {@link RecoverConsensusLogIndex}).
             */
            if (_commitStateHelper.hasTxLogs(_localDatabase.databaseLayout()))
            {
                _log.info("Recovering local database");
                Ensure(_localDatabase.start, "start local database");
                Ensure(_localDatabase.stop, "stop local database");
            }

            AdvertisedSocketAddress primary;
            StoreId remoteStoreId;

            try
            {
                primary       = addressProvider.Primary();
                remoteStoreId = _remoteStore.getStoreId(primary);
            }
            catch (Exception e) when(e is CatchupAddressResolutionException || e is StoreIdDownloadFailedException)
            {
                _log.warn("Store copy failed", e);
                return(false);
            }

            if (!isEmptyStore && !remoteStoreId.Equals(_localDatabase.storeId()))
            {
                _log.error("Store copy failed due to store ID mismatch");
                return(false);
            }

            Ensure(_suspendOnStoreCopy.disable, "disable auxiliary services before store copy");
            Ensure(_localDatabase.stopForStoreCopy, "stop local database for store copy");

            _log.info("Downloading snapshot from core server at %s", primary);

            /* The core snapshot must be copied before the store, because the store has a dependency on
             * the state of the state machines. The store will thus be at or ahead of the state machines,
             * in consensus log index, and application of commands will bring them in sync. Any such commands
             * that carry transactions will thus be ignored by the transaction/token state machines, since they
             * are ahead, and the correct decisions for their applicability have already been taken as encapsulated
             * in the copied store. */

            CoreSnapshot coreSnapshot;

            try
            {
                coreSnapshot = _catchUpClient.makeBlockingRequest(primary, new CoreSnapshotRequest(), new CatchUpResponseAdaptorAnonymousInnerClass(this));
            }
            catch (CatchUpClientException e)
            {
                _log.warn("Store copy failed", e);
                return(false);
            }

            if (!isEmptyStore)
            {
                StoreId       localStoreId = _localDatabase.storeId();
                CatchupResult catchupResult;
                try
                {
                    catchupResult = _remoteStore.tryCatchingUp(primary, localStoreId, _localDatabase.databaseLayout(), false, false);
                }
                catch (StoreCopyFailedException e)
                {
                    _log.warn("Failed to catch up", e);
                    return(false);
                }

                if (catchupResult == E_TRANSACTION_PRUNED)
                {
                    _log.warn(format("Failed to pull transactions from (%s). They may have been pruned away", primary));
                    _localDatabase.delete();
                    isEmptyStore = true;
                }
                else if (catchupResult != SUCCESS_END_OF_STREAM)
                {
                    _log.warn(format("Unexpected catchup operation result %s from %s", catchupResult, primary));
                    return(false);
                }
            }

            if (isEmptyStore)
            {
                try
                {
                    _storeCopyProcess.replaceWithStoreFrom(addressProvider, remoteStoreId);
                }
                catch (StoreCopyFailedException e)
                {
                    _log.warn("Failed to copy and replace store", e);
                    return(false);
                }
            }

            /* We install the snapshot after the store has been downloaded,
             * so that we are not left with a state ahead of the store. */
            _snapshotService.installSnapshot(coreSnapshot);
            _log.info("Core snapshot installed: " + coreSnapshot);

            /* Starting the database will invoke the commit process factory in
             * the EnterpriseCoreEditionModule, which has important side-effects. */
            _log.info("Starting local database");
            Ensure(_localDatabase.start, "start local database after store copy");

            _coreStateMachines.installCommitProcess(_localDatabase.CommitProcess);
            Ensure(_suspendOnStoreCopy.enable, "enable auxiliary services after store copy");

            return(true);
        }