示例#1
0
        private long GetOrAddIndex(string name, MappingDocumentType mappingDocumentType, DocumentDatabase systemDatabase)
        {
            var tries = 0;

            while (true)
            {
                try
                {
                    var key = Constants.Monitoring.Snmp.DatabaseMappingDocumentPrefix + databaseName + "/" + mappingDocumentType;

                    var mappingDocument = systemDatabase.Documents.Get(key, null) ?? new JsonDocument();

                    RavenJToken value;
                    if (mappingDocument.DataAsJson.TryGetValue(name, out value))
                    {
                        return(value.Value <int>());
                    }

                    var index = 0L;
                    systemDatabase.TransactionalStorage.Batch(actions =>
                    {
                        mappingDocument.DataAsJson[name] = index = actions.General.GetNextIdentityValue(key);
                        systemDatabase.Documents.Put(key, null, mappingDocument.DataAsJson, mappingDocument.Metadata, null);
                    });

                    return(index);
                }
                catch (Exception e)
                {
                    Exception _;
                    if (TransactionalStorageHelper.IsWriteConflict(e, out _) == false || tries >= 5)
                    {
                        throw;
                    }

                    Thread.Sleep(13);
                }
                finally
                {
                    tries++;
                }
            }
        }
        private Action ExecuteBatch(Action <IStorageActionsAccessor> action)
        {
            var snapshotRef   = new Reference <SnapshotReader>();
            var writeBatchRef = new Reference <WriteBatch>();

            var errorInUserAction = false;

            try
            {
                snapshotRef.Value   = tableStorage.CreateSnapshot();
                writeBatchRef.Value = new WriteBatch {
                    DisposeAfterWrite = false
                };                                                                // prevent from disposing after write to allow read from batch OnStorageCommit
                var storageActionsAccessor = new StorageActionsAccessor(uuidGenerator, _documentCodecs,
                                                                        documentCacher, writeBatchRef, snapshotRef,
                                                                        tableStorage, this, bufferPool);

                if (disableBatchNesting.Value == null)
                {
                    current.Value = storageActionsAccessor;
                }

                errorInUserAction = true;
                action(storageActionsAccessor);
                errorInUserAction = false;

                storageActionsAccessor.SaveAllTasks();
                storageActionsAccessor.ExecuteBeforeStorageCommit();

                tableStorage.Write(writeBatchRef.Value);

                try
                {
                    return(storageActionsAccessor.ExecuteOnStorageCommit);
                }
                finally
                {
                    storageActionsAccessor.ExecuteAfterStorageCommit();
                }
            }
            catch (Exception e)
            {
                var exception = e;
                var ae        = e as AggregateException;
                if (ae != null)
                {
                    exception = ae.ExtractSingleInnerException();
                }

                Exception _;
                if (TransactionalStorageHelper.IsVoronOutOfMemoryException(exception) ||
                    TransactionalStorageHelper.IsWriteConflict(e, out _))
                {
                    throw;
                }

                if (errorInUserAction == false)
                {
                    Log.ErrorException("Failed to execute transaction. Most likely something is really wrong here.", e);
                }

                throw;
            }
            finally
            {
                if (snapshotRef.Value != null)
                {
                    snapshotRef.Value.Dispose();
                }

                if (writeBatchRef.Value != null)
                {
                    writeBatchRef.Value.Dispose();
                }
            }
        }
示例#3
0
        private IndexingPerformanceStats HandleIndexingFor(IndexingBatchForIndex batchForIndex, Etag lastEtag, DateTime lastModified, CancellationToken token)
        {
            currentlyProcessedIndexes.TryAdd(batchForIndex.IndexId, batchForIndex.Index);

            IndexingPerformanceStats performanceResult = null;
            var wasOutOfMemory       = false;
            var wasOperationCanceled = false;

            try
            {
                transactionalStorage.Batch(actions =>
                {
                    performanceResult = IndexDocuments(actions, batchForIndex, token);
                });

                // This can be null if IndexDocument fails to execute and the exception is catched.
                if (performanceResult != null)
                {
                    performanceResult.RunCompleted();
                }
            }
            catch (OperationCanceledException)
            {
                wasOperationCanceled = true;
                throw;
            }
            catch (Exception e)
            {
                var exception          = e;
                var aggregateException = exception as AggregateException;
                if (aggregateException != null)
                {
                    exception = aggregateException.ExtractSingleInnerException();
                }

                if (TransactionalStorageHelper.IsWriteConflict(exception))
                {
                    return(null);
                }

                Log.WarnException(string.Format("Failed to index documents for index: {0}", batchForIndex.Index.PublicName), exception);

                wasOutOfMemory = TransactionalStorageHelper.IsOutOfMemoryException(exception);

                if (wasOutOfMemory == false)
                {
                    context.AddError(batchForIndex.IndexId, batchForIndex.Index.PublicName, null, exception);
                }
            }
            finally
            {
                if (performanceResult != null)
                {
                    performanceResult.OnCompleted = null;
                }

                if (Log.IsDebugEnabled)
                {
                    Log.Debug("After indexing {0} documents, the new last etag for is: {1} for {2}",
                              batchForIndex.Batch.Docs.Count,
                              lastEtag,
                              batchForIndex.Index.PublicName);
                }

                if (wasOutOfMemory == false && wasOperationCanceled == false)
                {
                    transactionalStorage.Batch(actions =>
                    {
                        // whatever we succeeded in indexing or not, we have to update this
                        // because otherwise we keep trying to re-index failed documents
                        actions.Indexing.UpdateLastIndexed(batchForIndex.IndexId, lastEtag, lastModified);
                    });
                }
                else if (wasOutOfMemory)
                {
                    HandleOutOfMemory(batchForIndex);
                }

                Index _;
                currentlyProcessedIndexes.TryRemove(batchForIndex.IndexId, out _);
            }

            return(performanceResult);
        }
示例#4
0
        private IndexingPerformanceStats HandleIndexingFor(IndexingBatchForIndex batchForIndex, Etag lastEtag, DateTime lastModified, CancellationToken token)
        {
            if (currentlyProcessedIndexes.TryAdd(batchForIndex.IndexId, batchForIndex.Index) == false)
            {
                Log.Error("Entered handle indexing with index {0} inside currentlyProcessedIndexes", batchForIndex.Index.PublicName);
                batchForIndex.SignalIndexingComplete();
                return null;
            }
            IndexingPerformanceStats performanceResult = null;
            var wasOutOfMemory = false;
            var wasOperationCanceled = false;
            try
            {
                transactionalStorage.Batch(actions => { performanceResult = IndexDocuments(actions, batchForIndex, token); });


                // This can be null if IndexDocument fails to execute and the exception is catched.
                if (performanceResult != null)
                    performanceResult.RunCompleted();
            }
            catch (OperationCanceledException)
            {
                wasOperationCanceled = true;
                throw;
            }
            catch (Exception e)
            {
                var exception = e;
                var aggregateException = exception as AggregateException;
                if (aggregateException != null)
                    exception = aggregateException.ExtractSingleInnerException();

                if (TransactionalStorageHelper.IsWriteConflict(exception))
                    return null;

                Log.WarnException(string.Format("Failed to index documents for index: {0}", batchForIndex.Index.PublicName), exception);

                wasOutOfMemory = TransactionalStorageHelper.IsOutOfMemoryException(exception);

                if (wasOutOfMemory == false)
                    context.AddError(batchForIndex.IndexId, batchForIndex.Index.PublicName, null, exception);
            }
            finally
            {
                if (performanceResult != null)
                {                    
                    performanceResult.OnCompleted = null;
                }				

                Index _;
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("After indexing {0} documents, the new last etag for is: {1} for {2}",
                              batchForIndex.Batch.Docs.Count,
                              lastEtag,
                              batchForIndex.Index.PublicName);
                }

                try
                {
                if (wasOutOfMemory == false && wasOperationCanceled == false)
                {
                        bool keepTrying = true;

                        for (int i = 0; i < 10 && keepTrying; i++)
                        {
                            keepTrying = false;
                    transactionalStorage.Batch(actions =>
                    {
                                try
                                {
                        // whatever we succeeded in indexing or not, we have to update this
                        // because otherwise we keep trying to re-index failed documents
                        actions.Indexing.UpdateLastIndexed(batchForIndex.IndexId, lastEtag, lastModified);
                                }
                                catch (Exception e)
                                {
                                    if (actions.IsWriteConflict(e))
                                    {
                                        keepTrying = true;
                                        return;
                                    }
                                    throw;
                                }
                    });

                            if (keepTrying)
                                Thread.Sleep(11);
                }
                    }
                else if (wasOutOfMemory)
                    HandleOutOfMemory(batchForIndex);
                }
                finally
                {
                currentlyProcessedIndexes.TryRemove(batchForIndex.IndexId, out _);
                    batchForIndex.SignalIndexingComplete();
                    batchForIndex.Index.IsMapIndexingInProgress = false;
            }
            }

            return performanceResult;
        }