static int StopApplier (TRI_replication_applier_t* applier, bool resetError) { TRI_replication_applier_state_t* state; state = &applier->_state; if (! state->_active) { return TRI_ERROR_INTERNAL; } state->_active = false; SetTerminateFlag(applier, true); TRI_SetProgressReplicationApplier(applier, "applier stopped", false); if (resetError) { if (state->_lastError._msg != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, state->_lastError._msg); state->_lastError._msg = NULL; } state->_lastError._code = TRI_ERROR_NO_ERROR; TRI_GetTimeStampReplication(state->_lastError._time, sizeof(state->_lastError._time) - 1); } TRI_LockCondition(&applier->_runStateChangeCondition); TRI_SignalCondition(&applier->_runStateChangeCondition); TRI_UnlockCondition(&applier->_runStateChangeCondition); return TRI_ERROR_NO_ERROR; }
int TRI_StopReplicationApplier (TRI_replication_applier_t* applier, bool resetError) { int res; res = TRI_ERROR_NO_ERROR; LOG_TRACE("requesting replication applier stop"); TRI_WriteLockReadWriteLock(&applier->_statusLock); if (! applier->_state._active) { TRI_WriteUnlockReadWriteLock(&applier->_statusLock); return res; } res = StopApplier(applier, resetError); TRI_WriteUnlockReadWriteLock(&applier->_statusLock); // join the thread without the status lock (otherwise it would probably not join) if (res == TRI_ERROR_NO_ERROR) { res = TRI_JoinThread(&applier->_thread); } else { // keep original error code TRI_JoinThread(&applier->_thread); } SetTerminateFlag(applier, false); LOG_INFO("stopped replication applier for database '%s'", applier->_databaseName); return res; }
static int StartApplier (TRI_replication_applier_t* applier, TRI_voc_tick_t initialTick, bool useTick) { TRI_replication_applier_state_t* state; void* fetcher; state = &applier->_state; if (state->_active) { return TRI_ERROR_INTERNAL; } if (applier->_configuration._endpoint == NULL) { return SetError(applier, TRI_ERROR_REPLICATION_INVALID_APPLIER_CONFIGURATION, "no endpoint configured"); } if (applier->_configuration._database == NULL) { return SetError(applier, TRI_ERROR_REPLICATION_INVALID_APPLIER_CONFIGURATION, "no database configured"); } fetcher = (void*) TRI_CreateContinuousSyncerReplication(applier->_vocbase, &applier->_configuration, initialTick, useTick); if (fetcher == NULL) { return TRI_ERROR_OUT_OF_MEMORY; } // reset error if (state->_lastError._msg != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, state->_lastError._msg); state->_lastError._msg = NULL; } state->_lastError._code = TRI_ERROR_NO_ERROR; TRI_GetTimeStampReplication(state->_lastError._time, sizeof(state->_lastError._time) - 1); SetTerminateFlag(applier, false); state->_active = true; TRI_InitThread(&applier->_thread); if (! TRI_StartThread(&applier->_thread, "[applier]", ApplyThread, fetcher)) { TRI_DeleteContinuousSyncerReplication(fetcher); return TRI_ERROR_INTERNAL; } LOG_INFO("started replication applier for database '%s'", applier->_databaseName); return TRI_ERROR_NO_ERROR; }
static int StartApplier (TRI_replication_applier_t* applier, TRI_voc_tick_t initialTick, bool useTick) { TRI_replication_applier_state_t* state = &applier->_state; if (state->_active) { return TRI_ERROR_INTERNAL; } if (applier->_configuration._endpoint == nullptr) { return SetError(applier, TRI_ERROR_REPLICATION_INVALID_APPLIER_CONFIGURATION, "no endpoint configured"); } if (applier->_configuration._database == nullptr) { return SetError(applier, TRI_ERROR_REPLICATION_INVALID_APPLIER_CONFIGURATION, "no database configured"); } // TODO: prevent restart of the applier with a tick after a shutdown auto fetcher = new triagens::arango::ContinuousSyncer(applier->_server, applier->_vocbase, &applier->_configuration, initialTick, useTick); if (fetcher == nullptr) { return TRI_ERROR_OUT_OF_MEMORY; } // reset error if (state->_lastError._msg != nullptr) { TRI_FreeString(TRI_CORE_MEM_ZONE, state->_lastError._msg); state->_lastError._msg = nullptr; } state->_lastError._code = TRI_ERROR_NO_ERROR; TRI_GetTimeStampReplication(state->_lastError._time, sizeof(state->_lastError._time) - 1); SetTerminateFlag(applier, false); state->_active = true; TRI_InitThread(&applier->_thread); if (! TRI_StartThread(&applier->_thread, nullptr, "[applier]", ApplyThread, static_cast<void*>(fetcher))) { delete fetcher; return TRI_ERROR_INTERNAL; } LOG_INFO("started replication applier for database '%s'", applier->_databaseName); return TRI_ERROR_NO_ERROR; }
TRI_replication_applier_t* TRI_CreateReplicationApplier (TRI_vocbase_t* vocbase) { TRI_replication_applier_t* applier; int res; applier = TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(TRI_replication_applier_t), false); if (applier == NULL) { return NULL; } TRI_InitConfigurationReplicationApplier(&applier->_configuration); TRI_InitStateReplicationApplier(&applier->_state); res = LoadConfiguration(vocbase, &applier->_configuration); if (res != TRI_ERROR_NO_ERROR && res != TRI_ERROR_FILE_NOT_FOUND) { TRI_set_errno(res); TRI_DestroyStateReplicationApplier(&applier->_state); TRI_DestroyConfigurationReplicationApplier(&applier->_configuration); TRI_Free(TRI_CORE_MEM_ZONE, applier); return NULL; } res = TRI_LoadStateReplicationApplier(vocbase, &applier->_state); if (res != TRI_ERROR_NO_ERROR && res != TRI_ERROR_FILE_NOT_FOUND) { TRI_set_errno(res); TRI_DestroyStateReplicationApplier(&applier->_state); TRI_DestroyConfigurationReplicationApplier(&applier->_configuration); TRI_Free(TRI_CORE_MEM_ZONE, applier); return NULL; } TRI_InitReadWriteLock(&applier->_statusLock); TRI_InitSpin(&applier->_threadLock); TRI_InitCondition(&applier->_runStateChangeCondition); applier->_vocbase = vocbase; applier->_databaseName = TRI_DuplicateStringZ(TRI_CORE_MEM_ZONE, vocbase->_name); SetTerminateFlag(applier, false); assert(applier->_databaseName != NULL); TRI_SetProgressReplicationApplier(applier, "applier created", false); return applier; }
int TRI_ShutdownReplicationApplier (TRI_replication_applier_t* applier) { if (applier == nullptr) { return TRI_ERROR_NO_ERROR; } LOG_TRACE("requesting replication applier shutdown"); if (applier->_vocbase->_type == TRI_VOCBASE_TYPE_COORDINATOR) { return TRI_ERROR_CLUSTER_UNSUPPORTED; } TRI_WriteLockReadWriteLock(&applier->_statusLock); if (! applier->_state._active) { TRI_WriteUnlockReadWriteLock(&applier->_statusLock); return TRI_ERROR_NO_ERROR; } int res = StopApplier(applier, true); TRI_WriteUnlockReadWriteLock(&applier->_statusLock); // join the thread without the status lock (otherwise it would probably not join) if (res == TRI_ERROR_NO_ERROR) { res = TRI_JoinThread(&applier->_thread); } else { // stop the thread but keep original error code int res2 = TRI_JoinThread(&applier->_thread); if (res2 != TRI_ERROR_NO_ERROR) { LOG_ERROR("could not join replication applier for database '%s': %s", applier->_databaseName, TRI_errno_string(res2)); } } SetTerminateFlag(applier, false); TRI_WriteLockReadWriteLock(&applier->_statusLock); // really abort all ongoing transactions applier->abortRunningRemoteTransactions(); TRI_WriteUnlockReadWriteLock(&applier->_statusLock); LOG_INFO("stopped replication applier for database '%s'", applier->_databaseName); return res; }
TRI_replication_applier_t* TRI_CreateReplicationApplier (TRI_server_t* server, TRI_vocbase_t* vocbase) { TRI_replication_applier_t* applier = new TRI_replication_applier_t(server, vocbase); if (applier == nullptr) { return nullptr; } TRI_InitConfigurationReplicationApplier(&applier->_configuration); TRI_InitStateReplicationApplier(&applier->_state); if (vocbase->_type == TRI_VOCBASE_TYPE_NORMAL) { int res = LoadConfiguration(vocbase, &applier->_configuration); if (res != TRI_ERROR_NO_ERROR && res != TRI_ERROR_FILE_NOT_FOUND) { TRI_set_errno(res); TRI_DestroyStateReplicationApplier(&applier->_state); TRI_DestroyConfigurationReplicationApplier(&applier->_configuration); delete applier; return nullptr; } res = TRI_LoadStateReplicationApplier(vocbase, &applier->_state); if (res != TRI_ERROR_NO_ERROR && res != TRI_ERROR_FILE_NOT_FOUND) { TRI_set_errno(res); TRI_DestroyStateReplicationApplier(&applier->_state); TRI_DestroyConfigurationReplicationApplier(&applier->_configuration); delete applier; return nullptr; } } SetTerminateFlag(applier, false); TRI_ASSERT(applier->_databaseName != nullptr); TRI_SetProgressReplicationApplier(applier, "applier created", false); return applier; }