private bool LoadEntitiesFromLocalDbLocked(bool onStartup, BPlusTree <int, ContentNodeKit> localDb, ContentStore store, string entityType) { var kits = localDb.Select(x => x.Value) .OrderBy(x => x.Node.Level) .ThenBy(x => x.Node.ParentContentId) .ThenBy(x => x.Node.SortOrder) // IMPORTANT sort by level + parentId + sortOrder .ToList(); if (kits.Count == 0) { // If there's nothing in the local cache file, we should return false? YES even though the site legitately might be empty. // Is it possible that the cache file is empty but the database is not? YES... (well, it used to be possible) // * A new file is created when one doesn't exist, this will only be done when MainDom is acquired // * The new file will be populated as soon as LoadCachesOnStartup is called // * If the appdomain is going down the moment after MainDom was acquired and we've created an empty cache file, // then the MainDom release callback is triggered from on a different thread, which will close the file and // set the cache file reference to null. At this moment, it is possible that the file is closed and the // reference is set to null BEFORE LoadCachesOnStartup which would mean that the current appdomain would load // in the in-mem cache via DB calls, BUT this now means that there is an empty cache file which will be // loaded by the next appdomain and it won't check if it's empty, it just assumes that since the cache // file is there, that is correct. // Update: We will still return false here even though the above mentioned race condition has been fixed since we now // lock the entire operation of creating/populating the cache file with the same lock as releasing/closing the cache file _logger.LogInformation("Tried to load {entityType} from the local cache file but it was empty.", entityType); return(false); } return(onStartup ? store.SetAllFastSortedLocked(kits, false) : store.SetAllLocked(kits)); }
private bool LoadMediaFromDatabaseLocked(bool onStartup) { // locks & notes: see content var mediaTypes = _serviceContext.MediaTypeService.GetAll() .Select(x => _publishedContentTypeFactory.CreateContentType(x)); _mediaStore.SetAllContentTypesLocked(mediaTypes); using (_profilingLogger.TraceDuration <PublishedSnapshotService>("Loading media from database")) { // beware! at that point the cache is inconsistent, // assuming we are going to SetAll content items! _localMediaDb?.Clear(); _logger.LogDebug("Loading media from database..."); // IMPORTANT GetAllMediaSources sorts kits by level + parentId + sortOrder var kits = _publishedContentService.GetAllMediaSources(); return(onStartup ? _mediaStore.SetAllFastSortedLocked(kits, true) : _mediaStore.SetAllLocked(kits)); } }
private bool LoadContentFromDatabaseLocked(bool onStartup) { // locks: // contentStore is wlocked (1 thread) // content (and types) are read-locked var contentTypes = _serviceContext.ContentTypeService.GetAll().ToList(); _contentStore.SetAllContentTypesLocked(contentTypes.Select(x => _publishedContentTypeFactory.CreateContentType(x))); using (_profilingLogger.TraceDuration <PublishedSnapshotService>("Loading content from database")) { // beware! at that point the cache is inconsistent, // assuming we are going to SetAll content items! _localContentDb?.Clear(); // IMPORTANT GetAllContentSources sorts kits by level + parentId + sortOrder var kits = _publishedContentService.GetAllContentSources(); return(onStartup ? _contentStore.SetAllFastSortedLocked(kits, true) : _contentStore.SetAllLocked(kits)); } }