Ejemplo n.º 1
0
        public void ReportIndexingBatchStarted(int documentsCount, long documentsSize)
        {
            var indexingBatchInfo = new IndexingBatchInfo
            {
                TotalDocumentCount = documentsCount,
                TotalDocumentSize  = documentsSize,
                Timestamp          = SystemTime.UtcNow
            };

            lastActualIndexingBatchInfo.Add(indexingBatchInfo);
        }
Ejemplo n.º 2
0
        public void ReportIndexingBatchStarted(int documentsCount, long documentsSize, List <string> indexesToWorkOn, out IndexingBatchInfo indexingBatchInfo)
        {
            indexingBatchInfo = new IndexingBatchInfo
            {
                IndexesToWorkOn    = indexesToWorkOn,
                TotalDocumentCount = documentsCount,
                TotalDocumentSize  = documentsSize,
                StartedAt          = SystemTime.UtcNow,
                PerformanceStats   = new ConcurrentDictionary <string, IndexingPerformanceStats>()
            };

            lastActualIndexingBatchInfo.Add(indexingBatchInfo);
        }
Ejemplo n.º 3
0
        public void IndexPrecomputedBatch(PrecomputedIndexingBatch precomputedBatch, CancellationToken token)
        {
            token.ThrowIfCancellationRequested();

            context.MetricsCounters.IndexedPerSecond.Mark(precomputedBatch.Documents.Count);

            var indexToWorkOn = new IndexToWorkOn
            {
                Index           = precomputedBatch.Index,
                IndexId         = precomputedBatch.Index.indexId,
                LastIndexedEtag = Etag.Empty
            };

            using (LogContext.WithDatabase(context.DatabaseName))
                using (MapIndexingInProgress(new List <IndexToWorkOn> {
                    indexToWorkOn
                }))
                {
                    var indexingBatchForIndex =
                        FilterIndexes(new List <IndexToWorkOn> {
                        indexToWorkOn
                    }, precomputedBatch.Documents,
                                      precomputedBatch.LastIndexed).FirstOrDefault();

                    if (indexingBatchForIndex == null)
                    {
                        return;
                    }

                    IndexingBatchInfo        batchInfo   = null;
                    IndexingPerformanceStats performance = null;
                    try
                    {
                        batchInfo = context.ReportIndexingBatchStarted(precomputedBatch.Documents.Count, -1, new List <string>
                        {
                            indexToWorkOn.Index.PublicName
                        });

                        batchInfo.BatchType = BatchType.Precomputed;

                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug("Going to index precomputed documents for a new index {0}. Count of precomputed docs {1}",
                                      precomputedBatch.Index.PublicName, precomputedBatch.Documents.Count);
                        }

                        performance = HandleIndexingFor(indexingBatchForIndex, precomputedBatch.LastIndexed, precomputedBatch.LastModified, token);
                    }
                    finally
                    {
                        if (batchInfo != null)
                        {
                            if (performance != null)
                            {
                                batchInfo.PerformanceStats.TryAdd(indexingBatchForIndex.Index.PublicName, performance);
                            }

                            context.ReportIndexingBatchCompleted(batchInfo);
                        }
                    }
                }

            indexReplacer.ReplaceIndexes(new [] { indexToWorkOn.IndexId });
        }
Ejemplo n.º 4
0
        private Etag DoActualIndexing(IList <IndexToWorkOn> indexesToWorkOn, List <JsonDocument> jsonDocs, IndexingBatchInfo indexingBatchInfo)
        {
            var lastByEtag   = PrefetchingBehavior.GetHighestJsonDocumentByEtag(jsonDocs);
            var lastModified = lastByEtag.LastModified.Value;
            var lastEtag     = lastByEtag.Etag;

            context.MetricsCounters.IndexedPerSecond.Mark(jsonDocs.Count);

            var result = FilterIndexes(indexesToWorkOn, jsonDocs, lastEtag).OrderByDescending(x => x.Index.LastQueryTime).ToList();

            BackgroundTaskExecuter.Instance.ExecuteAllInterleaved(context, result,
                                                                  index =>
            {
                using (LogContext.WithDatabase(context.DatabaseName))
                {
                    var performance = HandleIndexingFor(index, lastEtag, lastModified, CancellationToken.None);

                    if (performance != null)
                    {
                        indexingBatchInfo.PerformanceStats.TryAdd(index.Index.PublicName, performance);
                    }
                }
            });

            return(lastEtag);
        }
Ejemplo n.º 5
0
        protected override void ExecuteIndexingWork(IList <IndexToWorkOn> indexes)
        {
            var indexingGroups = context.Configuration.IndexingClassifier.GroupMapIndexes(indexes);

            indexingGroups = indexingGroups.OrderByDescending(x => x.Key).ToDictionary(x => x.Key, x => x.Value);

            if (indexingGroups.Count == 0)
            {
                return;
            }

            var usedPrefetchers = new ConcurrentSet <PrefetchingBehavior>();

            var groupedIndexes = indexingGroups.Select(x =>
            {
                var result = new IndexingGroup
                {
                    LastIndexedEtag     = x.Key,
                    Indexes             = x.Value,
                    LastQueryTime       = x.Value.Max(y => y.Index.LastQueryTime),
                    PrefetchingBehavior = GetPrefetcherFor(x.Key, usedPrefetchers)
                };

                result.PrefetchingBehavior.AdditionalInfo = string.Format("Default prefetcher: {0}. For indexing group: [Indexes: {1}, LastIndexedEtag: {2}]",
                                                                          result.PrefetchingBehavior == defaultPrefetchingBehavior, string.Join(", ", result.Indexes.Select(y => y.Index.PublicName)), result.LastIndexedEtag);

                return(result);
            }).OrderByDescending(x => x.LastQueryTime).ToList();

            var maxIndexOutputsPerDoc    = groupedIndexes.Max(x => x.Indexes.Max(y => y.Index.MaxIndexOutputsPerDocument));
            var containsMapReduceIndexes = groupedIndexes.Any(x => x.Indexes.Any(y => y.Index.IsMapReduce));

            var recoverTunerState = ((IndexBatchSizeAutoTuner)autoTuner).ConsiderLimitingNumberOfItemsToProcessForThisBatch(maxIndexOutputsPerDoc, containsMapReduceIndexes);

            BackgroundTaskExecuter.Instance.ExecuteAll(context, groupedIndexes, (indexingGroup, i) =>
            {
                context.CancellationToken.ThrowIfCancellationRequested();
                using (LogContext.WithDatabase(context.DatabaseName))
                {
                    var prefetchingBehavior = indexingGroup.PrefetchingBehavior;
                    var indexesToWorkOn     = indexingGroup.Indexes;

                    var operationCancelled    = false;
                    TimeSpan indexingDuration = TimeSpan.Zero;
                    var lastEtag = Etag.Empty;

                    List <JsonDocument> jsonDocs;
                    IndexingBatchInfo batchInfo = null;

                    using (MapIndexingInProgress(indexesToWorkOn))
                        using (prefetchingBehavior.DocumentBatchFrom(indexingGroup.LastIndexedEtag, out jsonDocs))
                        {
                            try
                            {
                                if (Log.IsDebugEnabled)
                                {
                                    Log.Debug("Found a total of {0} documents that requires indexing since etag: {1}: ({2})",
                                              jsonDocs.Count, indexingGroup.LastIndexedEtag, string.Join(", ", jsonDocs.Select(x => x.Key)));
                                }

                                batchInfo = context.ReportIndexingBatchStarted(jsonDocs.Count, jsonDocs.Sum(x => x.SerializedSizeOnDisk), indexesToWorkOn.Select(x => x.Index.PublicName).ToList());

                                context.CancellationToken.ThrowIfCancellationRequested();

                                if (jsonDocs.Count <= 0)
                                {
                                    return;
                                }

                                var sw = Stopwatch.StartNew();

                                lastEtag = DoActualIndexing(indexesToWorkOn, jsonDocs, batchInfo);

                                indexingDuration = sw.Elapsed;
                            }
                            catch (InvalidDataException e)
                            {
                                Log.ErrorException("Failed to index because of data corruption. ", e);
                                indexesToWorkOn.ForEach(index =>
                                                        context.AddError(index.IndexId, index.Index.PublicName, null, string.Format("Failed to index because of data corruption. Reason: {0}", e.Message)));
                            }
                            catch (OperationCanceledException)
                            {
                                operationCancelled = true;
                            }
                            finally
                            {
                                if (operationCancelled == false && jsonDocs != null && jsonDocs.Count > 0)
                                {
                                    prefetchingBehavior.CleanupDocuments(lastEtag);
                                    prefetchingBehavior.UpdateAutoThrottler(jsonDocs, indexingDuration);
                                }

                                prefetchingBehavior.BatchProcessingComplete();
                                if (batchInfo != null)
                                {
                                    context.ReportIndexingBatchCompleted(batchInfo);
                                }
                            }
                        }
                }
            });

            if (recoverTunerState != null)
            {
                recoverTunerState();
            }

            RemoveUnusedPrefetchers(usedPrefetchers);
        }
Ejemplo n.º 6
0
        public void IndexPrecomputedBatch(PrecomputedIndexingBatch precomputedBatch)
        {
            context.MetricsCounters.IndexedPerSecond.Mark(precomputedBatch.Documents.Count);

            var indexToWorkOn = new IndexToWorkOn()
            {
                Index           = precomputedBatch.Index,
                IndexId         = precomputedBatch.Index.indexId,
                LastIndexedEtag = Etag.Empty
            };

            using (MapIndexingInProgress(new List <IndexToWorkOn> {
                indexToWorkOn
            }))
            {
                var indexingBatchForIndex =
                    FilterIndexes(new List <IndexToWorkOn>()
                {
                    indexToWorkOn
                }, precomputedBatch.Documents,
                                  precomputedBatch.LastIndexed).FirstOrDefault();

                if (indexingBatchForIndex == null)
                {
                    return;
                }

                IndexingBatchInfo batchInfo = null;

                try
                {
                    context.ReportIndexingBatchStarted(precomputedBatch.Documents.Count, precomputedBatch.Documents.Sum(x => x.SerializedSizeOnDisk), new List <string>()
                    {
                        indexToWorkOn.Index.PublicName
                    }, out batchInfo);

                    batchInfo.BatchType = BatchType.Precomputed;

                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug("Going to index precomputed documents for a new index {0}. Count of precomputed docs {1}",
                                  precomputedBatch.Index.PublicName, precomputedBatch.Documents.Count);
                    }

                    HandleIndexingFor(indexingBatchForIndex, precomputedBatch.LastIndexed, precomputedBatch.LastModified);
                }
                finally
                {
                    var performance = indexingBatchForIndex.Batch.GetIndexingPerformance();

                    if (batchInfo != null)
                    {
                        if (performance != null)
                        {
                            batchInfo.PerformanceStats.TryAdd(indexingBatchForIndex.Index.PublicName, performance);
                        }

                        batchInfo.BatchCompleted();
                    }
                }
            }
        }
Ejemplo n.º 7
0
 public void ReportIndexingBatchCompleted(IndexingBatchInfo batchInfo)
 {
     batchInfo.BatchCompleted();
     batchInfo.Id = Interlocked.Increment(ref nextIndexingBatchInfoId);
     LastActualIndexingBatchInfo.Add(batchInfo);
 }
Ejemplo n.º 8
0
 public void ReportIndexingBatchCompleted(IndexingBatchInfo batchInfo)
 {
     batchInfo.BatchCompleted();
     lastActualIndexingBatchInfo.Add(batchInfo);
 }
Ejemplo n.º 9
0
        protected override void ExecuteIndexingWork(IList <IndexToWorkOn> indexes)
        {
            var indexingGroups = context.Configuration.IndexingClassifier.GroupMapIndexes(indexes);

            indexingGroups = indexingGroups.OrderByDescending(x => x.Key).ToDictionary(x => x.Key, x => x.Value);

            if (indexingGroups.Count == 0)
            {
                return;
            }

            var usedPrefetchers = new ConcurrentSet <PrefetchingBehavior>();

            var groupedIndexes = indexingGroups.Select(x =>
            {
                var result = new IndexingGroup
                {
                    LastIndexedEtag = x.Key,
                    Indexes         = x.Value,
                    LastQueryTime   = x.Value.Max(y => y.Index.LastQueryTime),
                };

                SetPrefetcherForIndexingGroup(result, usedPrefetchers);

                return(result);
            }).OrderByDescending(x => x.LastQueryTime).ToList();


            var maxIndexOutputsPerDoc    = groupedIndexes.Max(x => x.Indexes.Max(y => y.Index.MaxIndexOutputsPerDocument));
            var containsMapReduceIndexes = groupedIndexes.Any(x => x.Indexes.Any(y => y.Index.IsMapReduce));

            var recoverTunerState = ((IndexBatchSizeAutoTuner)autoTuner).ConsiderLimitingNumberOfItemsToProcessForThisBatch(maxIndexOutputsPerDoc, containsMapReduceIndexes);

            BackgroundTaskExecuter.Instance.ExecuteAll(context, groupedIndexes, (indexingGroup, i) =>
            {
                context.CancellationToken.ThrowIfCancellationRequested();
                using (LogContext.WithDatabase(context.DatabaseName))
                {
                    var prefetchingBehavior = indexingGroup.PrefetchingBehavior;
                    var indexesToWorkOn     = indexingGroup.Indexes;

                    var operationCanceled     = false;
                    TimeSpan indexingDuration = TimeSpan.Zero;
                    var lastEtag = Etag.Empty;

                    IndexingBatchInfo batchInfo = null;

                    try
                    {
                        using (MapIndexingInProgress(indexesToWorkOn))
                        {
                            List <JsonDocument> jsonDocs;
                            using (prefetchingBehavior.DocumentBatchFrom(indexingGroup.LastIndexedEtag, out jsonDocs))
                            {
                                try
                                {
                                    if (Log.IsDebugEnabled)
                                    {
                                        Log.Debug("Found a total of {0} documents that requires indexing since etag: {1}: ({2})",
                                                  jsonDocs.Count, indexingGroup.LastIndexedEtag, string.Join(", ", jsonDocs.Select(x => x.Key)));
                                    }

                                    batchInfo = context.ReportIndexingBatchStarted(jsonDocs.Count, jsonDocs.Sum(x => x.SerializedSizeOnDisk), indexesToWorkOn.Select(x => x.Index.PublicName).ToList());

                                    context.CancellationToken.ThrowIfCancellationRequested();

                                    if (jsonDocs.Count <= 0)
                                    {
                                        return;
                                    }

                                    var sw = Stopwatch.StartNew();

                                    lastEtag = DoActualIndexing(indexesToWorkOn, jsonDocs, batchInfo);

                                    indexingDuration = sw.Elapsed;
                                }
                                catch (InvalidDataException e)
                                {
                                    Log.ErrorException("Failed to index because of data corruption. ", e);
                                    indexesToWorkOn.ForEach(index =>
                                                            context.AddError(index.IndexId, index.Index.PublicName, null, string.Format("Failed to index because of data corruption. Reason: {0}", e.Message)));
                                }
                                catch (OperationCanceledException)
                                {
                                    operationCanceled = true;
                                }
                                catch (AggregateException e)
                                {
                                    var allOperationsCanceled = e
                                                                .InnerExceptions
                                                                .All(x => x is OperationCanceledException);

                                    if (allOperationsCanceled == false)
                                    {
                                        throw;
                                    }

                                    operationCanceled = true;
                                }
                                catch (Exception)
                                {
                                    //we should not clean docs from prefetching behavior because something
                                    //unexpected has thrown
                                    //logging will be done in catch in the outer scope
                                    operationCanceled = true;
                                    // ReSharper disable once ThrowingSystemException
                                    throw;
                                }
                                finally
                                {
                                    if (operationCanceled == false && jsonDocs != null && jsonDocs.Count > 0)
                                    {
                                        prefetchingBehavior.CleanupDocuments(lastEtag);
                                        prefetchingBehavior.UpdateAutoThrottler(jsonDocs, indexingDuration);
                                    }

                                    prefetchingBehavior.BatchProcessingComplete();
                                    if (batchInfo != null)
                                    {
                                        context.ReportIndexingBatchCompleted(batchInfo);
                                    }
                                }
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        //expected exception here, nothing to do
                    }
                    catch (AggregateException e)
                    {
                        var allOperationsCanceled = e
                                                    .InnerExceptions
                                                    .All(x => x is OperationCanceledException);

                        if (allOperationsCanceled == false)
                        {
                            var message = string.Format("Unexpected AggregateException happened during execution of indexing batch...this is not supposed to happen. Reason: {0}", e);
                            Log.Error(message, e);
                            indexesToWorkOn.ForEach(index => context.AddError(index.IndexId, index.Index.PublicName, null, message));
                        }
                    }
                    catch (Exception e)
                    {
                        //this is a precaution, no exception should happen at this point
                        var message = string.Format("Unexpected exception happened during execution of indexing batch...this is not supposed to happen. Reason: {0}", e);
                        Log.Error(message, e);
                        indexesToWorkOn.ForEach(index => context.AddError(index.IndexId, index.Index.PublicName, null, message));

                        //rethrow because we do not want to interrupt the existing exception flow
                        // ReSharper disable once ThrowingSystemException
                        throw;
                    }
                }
            });

            if (recoverTunerState != null)
            {
                recoverTunerState();
            }

            RemoveUnusedPrefetchers(usedPrefetchers);
        }