/// <summary> /// Sets up Dilithium's cache for all configurations passed in, if they use the DilithiumDataStore. /// </summary> /// <param name="force">Force reinitialization (reread from SQL)</param> /// <param name="specificRoots">If passed, overrides the predicate roots in the configurations registered. Used for partial sync/partial reserialize.</param> /// <returns>True if initialized successfully (or if already inited), false if no configurations were using Dilithium</returns> public InitResult Initialize(bool force, params IItemData[] specificRoots) { if (Initialized && !force) { return(new InitResult(false)); } lock (SyncLock) { if (Initialized && !force) { return(new InitResult(false)); } var timer = new Stopwatch(); timer.Start(); // if specific roots are passed we init the collection with them var allPredicateRoots = new List <TreeRoot>(specificRoots.Select(root => new TreeRoot(string.Empty, root.Path, root.DatabaseName))); HashSet <Guid> intersectedIgnoredFields = null; IPredicate predicate; ConfigurationDataStore sourceDataStore; IEnumerableFieldFilter fieldFilter; foreach (var configuration in _configurations) { // check that config is using Dilithium (if not we don't need to load it) sourceDataStore = configuration.Resolve <ISourceDataStore>() as ConfigurationDataStore; if (!(sourceDataStore?.InnerDataStore is DilithiumSitecoreDataStore)) { continue; } // unless specific roots are passed we add all predicate roots if (specificRoots.Length == 0) { // add configuration's predicate roots to the pile of dilithium store roots predicate = configuration.Resolve <IPredicate>(); allPredicateRoots.AddRange(predicate.GetRootPaths()); } // acquire list of ignored fields for configuration fieldFilter = configuration.Resolve <IEnumerableFieldFilter>(); // if there is no field filter we can enumerate, then we must assume all fields are included. // defining the hashset here will prevent anything from intersecting with it later. if (fieldFilter == null) { intersectedIgnoredFields = new HashSet <Guid>(); } if (intersectedIgnoredFields == null) { // if set not started, all initial values go into it for intersecting with later configsets // we want to end up with fields that _all_ configs ignore that we care about intersectedIgnoredFields = new HashSet <Guid>(fieldFilter.Excludes); } // already have some fields, so we intersect with the current field filter to produce only those in both sets else if (fieldFilter != null) { intersectedIgnoredFields.IntersectWith(fieldFilter.Excludes); } } // no configurations were initialized that included Dilithium if (allPredicateRoots.Count == 0) { Initialized = true; _databaseCores = new Dictionary <string, SqlDataCache>(); return(new InitResult(false)); } // calculate root path uniqueness (e.g. if /sitecore/templates and /sitecore/templates/foo are both here // we must remove /sitecore/templates/foo because Dilithium is strictly descendants and follows no exclusions) for (var index = allPredicateRoots.Count - 1; index >= 0; index--) { var compareAgainstItem = allPredicateRoots[index]; var compareAgainstPath = compareAgainstItem.Path + "/"; for (var longerIndex = allPredicateRoots.Count - 1; longerIndex >= 0; longerIndex--) { var longerIndexItem = allPredicateRoots[longerIndex]; if (longerIndexItem.DatabaseName.Equals(compareAgainstItem.DatabaseName) && longerIndexItem.Path.StartsWith(compareAgainstPath, StringComparison.OrdinalIgnoreCase)) { allPredicateRoots.RemoveAt(longerIndex); index++; if (index >= allPredicateRoots.Count) { index = allPredicateRoots.Count - 1; } break; } } } // generate unique database names involved and roots within var databases = new Dictionary <string, List <RootData> >(); foreach (var root in allPredicateRoots) { if (!databases.ContainsKey(root.DatabaseName)) { databases.Add(root.DatabaseName, new List <RootData>()); } var rootItem = Factory.GetDatabase(root.DatabaseName).GetItem(root.Path); // if the root item is null, its path does not exist in the DB. // so we'll just not add it, and items will return null // which is correct, since we want those items to get created from serialized if (rootItem != null) { databases[root.DatabaseName].Add(new RootData(root.Path, rootItem.ID.Guid)); } } // generate a data core for each database, which contains all the predicated items' item data var dataCores = new Dictionary <string, SqlDataCache>(databases.Count, StringComparer.Ordinal); bool coreLoadError = false; foreach (var database in databases) { var dataCore = new SqlDataCache(database.Key); using (var sqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings[database.Key].ConnectionString)) { sqlConnection.Open(); using (var sqlCommand = ConstructSqlBatch(database.Value.Select(v => v.Id).ToArray(), intersectedIgnoredFields?.ToArray())) { sqlCommand.Connection = sqlConnection; using (var reader = sqlCommand.ExecuteReader()) { if (!dataCore.Ingest(reader, database.Value)) { coreLoadError = true; } } } } dataCores.Add(database.Key, dataCore); } timer.Stop(); Initialized = true; _databaseCores = dataCores; return(new InitResult(true, coreLoadError, dataCores.Values.Select(core => core.Count).Sum(), (int)timer.ElapsedMilliseconds)); } }
public SqlItemData(SqlDataCache sourceDataCore) { _sourceDataCore = sourceDataCore; }