// <summary> /// Initializes a server that has never synchronized before. /// </summary> /// <remarks> /// Thread safety: this is NOT thread safe. Because it is NOT meant to run multi-threaded. /// Callers MUST ensure thread-safety. /// </remarks> private SyncBootState InitializeColdBootState() { lock (_locko) { if (_cancellationToken.IsCancellationRequested) { return(SyncBootState.Unknown); } SyncBootState syncState = _syncBootStateAccessor.GetSyncBootState(); if (syncState == SyncBootState.ColdBoot) { // Get the last id in the db and store it. // Note: Do it BEFORE initializing otherwise some instructions might get lost // when doing it before. Some instructions might run twice but this is not an issue. var maxId = CacheInstructionService.GetMaxInstructionId(); // if there is a max currently, or if we've never synced if (maxId > 0 || _lastSyncedFileManager.LastSyncedId < 0) { _lastSyncedFileManager.SaveLastSyncedId(maxId); } } return(syncState); } }
private SyncBootState BootInternal() { // weight:10, must release *before* the published snapshot service, because once released // the service will *not* be able to properly handle our notifications anymore const int weight = 10; if (!(_runtime is RuntimeState runtime)) { throw new NotSupportedException($"Unsupported IRuntimeState implementation {_runtime.GetType().FullName}, expecting {typeof(RuntimeState).FullName}."); } var registered = runtime.MainDom.Register( () => { lock (_locko) { _released = true; // no more syncs } // wait a max of 5 seconds and then return, so that we don't block // the entire MainDom callbacks chain and prevent the AppDomain from // properly releasing MainDom - a timeout here means that one refresher // is taking too much time processing, however when it's done we will // not update lastId and stop everything var idle = _syncIdle.WaitOne(5000); if (idle == false) { Logger.Warn <DatabaseServerMessenger>("The wait lock timed out, application is shutting down. The current instruction batch will be re-processed."); } }, weight); SyncBootState bootState = SyncBootState.Unknown; if (registered == false) { return(bootState); } ReadLastSynced(); // get _lastId using (var scope = ScopeProvider.CreateScope()) { EnsureInstructions(scope.Database); // reset _lastId if instructions are missing bootState = Initialize(scope.Database); // boot scope.Complete(); } return(bootState); }
/// <summary> /// On first http request schedule an index rebuild for any empty indexes (or all if it's a cold boot) /// </summary> /// <param name="notification"></param> public void Handle(UmbracoRequestBeginNotification notification) { if (_runtimeState.Level != RuntimeLevel.Run) { return; } LazyInitializer.EnsureInitialized( ref _isReady, ref _isReadSet, ref _isReadyLock, () => { SyncBootState bootState = _syncBootStateAccessor.GetSyncBootState(); _backgroundIndexRebuilder.RebuildIndexes( // if it's not a cold boot, only rebuild empty ones bootState != SyncBootState.ColdBoot, TimeSpan.FromMinutes(1)); return(true); }); }
public TestSyncBootStateAccessor(SyncBootState syncBootState) { _syncBootState = syncBootState; }
/// <summary> /// Lazily populates the stores only when they are first requested /// </summary> internal void EnsureCaches() => LazyInitializer.EnsureInitialized( ref _isReady, ref _isReadSet, ref _isReadyLock, () => { // lock this entire call, we only want a single thread to be accessing the stores at once and within // the call below to mainDom.Register, a callback may occur on a threadpool thread to MainDomRelease // at the same time as we are trying to write to the stores. MainDomRelease also locks on _storesLock so // it will not be able to close the stores until we are done populating (if the store is empty) lock (_storesLock) { if (!_options.IgnoreLocalDb) { _mainDom.Register(MainDomRegister, MainDomRelease); // stores are created with a db so they can write to it, but they do not read from it, // stores need to be populated, happens in OnResolutionFrozen which uses _localDbExists to // figure out whether it can read the databases or it should populate them from sql _logger.LogInformation("Creating the content store, localContentDbExists? {LocalContentDbExists}", _localContentDbExists); _contentStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory, _localContentDb); _logger.LogInformation("Creating the media store, localMediaDbExists? {LocalMediaDbExists}", _localMediaDbExists); _mediaStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory, _localMediaDb); } else { _logger.LogInformation("Creating the content store (local db ignored)"); _contentStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory); _logger.LogInformation("Creating the media store (local db ignored)"); _mediaStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory); } _domainStore = new SnapDictionary <int, Domain>(); var okContent = false; var okMedia = false; SyncBootState bootState = _syncBootStateAccessor.GetSyncBootState(); try { if (bootState != SyncBootState.ColdBoot && _localContentDbExists) { okContent = LockAndLoadContent(() => LoadContentFromLocalDbLocked(true)); if (!okContent) { _logger.LogWarning("Loading content from local db raised warnings, will reload from database."); } } if (bootState != SyncBootState.ColdBoot && _localMediaDbExists) { okMedia = LockAndLoadMedia(() => LoadMediaFromLocalDbLocked(true)); if (!okMedia) { _logger.LogWarning("Loading media from local db raised warnings, will reload from database."); } } if (!okContent) { LockAndLoadContent(() => LoadContentFromDatabaseLocked(true)); } if (!okMedia) { LockAndLoadMedia(() => LoadMediaFromDatabaseLocked(true)); } LockAndLoadDomains(); } catch (Exception ex) { _logger.LogCritical(ex, "Panic, exception while loading cache data."); throw; } return(true); } });