// <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);
            }
        }
示例#2
0
        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);
        }
示例#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);
            });
        }
示例#4
0
 public TestSyncBootStateAccessor(SyncBootState syncBootState)
 {
     _syncBootState = syncBootState;
 }
示例#5
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);
            }
        });