Ejemplo n.º 1
0
        /// <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));
            }
        }
Ejemplo n.º 2
0
 public SqlItemData(SqlDataCache sourceDataCore)
 {
     _sourceDataCore = sourceDataCore;
 }