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(); } } }
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); }
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; }