private void UmbracoModule_RouteAttempt(object sender, RoutableAttemptEventArgs e)
        {
            if (!_initialized)
            {
                lock (_locker)
                {
                    // double check lock, we must only do this once
                    if (!_initialized)
                    {
                        _initialized = true;

                        UmbracoModule.RouteAttempt -= UmbracoModule_RouteAttempt;

                        if (!_mainDom.IsMainDom)
                        {
                            return;
                        }

                        var bootState = _syncBootStateAccessor.GetSyncBootState();

                        _examineManager.ConfigureIndexes(_mainDom, _logger);

                        // if it's a cold boot, rebuild all indexes including non-empty ones
                        // delay one minute since a cold boot also triggers nucache rebuilds
                        _indexRebuilder.RebuildIndexes(bootState != SyncBootState.ColdBoot, 60000);
                    }
                }
            }
        }
        // <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);
            }
        }
Example #3
0
        /// <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);
            });
        }
Example #4
0
        /// <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);
            }
        });