/// <inheritdoc /> public override Task <uint256> Rewind() { Task <uint256> task = Task.Run(() => { this.logger.LogTrace("()"); uint256 res = null; using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.SynchronizeTables("BlockHash", "Coins", "Rewind"); if (this.GetRewindIndex(transaction) == -1) { transaction.RemoveAllKeys("Coins", true); this.SetBlockHash(transaction, this.network.GenesisHash); res = this.network.GenesisHash; } else { transaction.ValuesLazyLoadingIsOn = false; Row <int, RewindData> firstRow = transaction.SelectBackward <int, RewindData>("Rewind").FirstOrDefault(); transaction.RemoveKey("Rewind", firstRow.Key); this.SetBlockHash(transaction, firstRow.Value.PreviousBlockHash); foreach (uint256 txId in firstRow.Value.TransactionsToRemove) { this.logger.LogTrace("Outputs of transaction ID '{0}' will be removed.", txId); transaction.RemoveKey("Coins", txId.ToBytes(false)); } foreach (UnspentOutputs coin in firstRow.Value.OutputsToRestore) { this.logger.LogTrace("Outputs of transaction ID '{0}' will be restored.", coin.TransactionId); transaction.Insert("Coins", coin.TransactionId.ToBytes(false), coin.ToCoins()); } res = firstRow.Value.PreviousBlockHash; } transaction.Commit(); } this.logger.LogTrace("(-):'{0}'", res); return(res); }); return(task); }
public void Delete(byte[] key) { using (DBreeze.Transactions.Transaction t = this.engine.GetTransaction()) { t.RemoveKey(this.table, key); t.Commit(); } }
/// <inheritdoc /> public HashHeightPair Rewind() { HashHeightPair res = null; using (DBreeze.Transactions.Transaction transaction = this.CreateTransaction()) { transaction.SynchronizeTables("BlockHash", "Coins", "Rewind"); transaction.ValuesLazyLoadingIsOn = false; HashHeightPair current = this.GetTipHash(transaction); Row <int, byte[]> row = transaction.Select <int, byte[]>("Rewind", current.Height); if (!row.Exists) { throw new InvalidOperationException($"No rewind data found for block `{current}`"); } transaction.RemoveKey("Rewind", row.Key); var rewindData = this.dBreezeSerializer.Deserialize <RewindData>(row.Value); this.SetBlockHash(transaction, rewindData.PreviousBlockHash); foreach (OutPoint outPoint in rewindData.OutputsToRemove) { this.logger.LogTrace("Outputs of outpoint '{0}' will be removed.", outPoint); transaction.RemoveKey("Coins", outPoint.ToBytes()); } foreach (RewindDataOutput rewindDataOutput in rewindData.OutputsToRestore) { this.logger.LogTrace("Outputs of outpoint '{0}' will be restored.", rewindDataOutput.OutPoint); transaction.Insert("Coins", rewindDataOutput.OutPoint.ToBytes(), this.dBreezeSerializer.Serialize(rewindDataOutput.Coins)); } res = rewindData.PreviousBlockHash; transaction.Commit(); } return(res); }
/// <inheritdoc /> public uint256 Rewind() { uint256 res = null; using (DBreeze.Transactions.Transaction transaction = this.CreateTransaction()) { transaction.SynchronizeTables("BlockHash", "Coins", "Rewind"); if (this.GetRewindIndex(transaction) == 0) { transaction.RemoveAllKeys("Coins", true); this.SetBlockHash(transaction, this.network.GenesisHash); res = this.network.GenesisHash; } else { transaction.ValuesLazyLoadingIsOn = false; Row <int, byte[]> firstRow = transaction.SelectBackward <int, byte[]>("Rewind").FirstOrDefault(); transaction.RemoveKey("Rewind", firstRow.Key); var rewindData = this.dBreezeSerializer.Deserialize <RewindData>(firstRow.Value); this.SetBlockHash(transaction, rewindData.PreviousBlockHash); foreach (uint256 txId in rewindData.TransactionsToRemove) { this.logger.LogDebug("Outputs of transaction ID '{0}' will be removed.", txId); transaction.RemoveKey("Coins", txId.ToBytes(false)); } foreach (UnspentOutputs coin in rewindData.OutputsToRestore) { this.logger.LogDebug("Outputs of transaction ID '{0}' will be restored.", coin.TransactionId); transaction.Insert("Coins", coin.TransactionId.ToBytes(false), this.dBreezeSerializer.Serialize(coin.ToCoins())); } res = rewindData.PreviousBlockHash; } transaction.Commit(); } return(res); }
/// <summary>Removes polls for the provided ids.</summary> /// <param name="transaction">See <see cref="DBreeze.Transactions.Transaction"/>.</param> /// <param name="ids">The ids of the polls to remove.</param> public void DeletePollsAndSetHighestPollId(DBreeze.Transactions.Transaction transaction, params int[] ids) { lock (this.lockObject) { foreach (int pollId in ids.OrderBy(a => a)) { transaction.RemoveKey <byte[]>(DataTable, pollId.ToBytes()); } List <Poll> polls = GetAllPolls(transaction); this.highestPollId = (polls.Count == 0) ? -1 : polls.Max(a => a.Id); } }
private void DropIndex(string name, DBreeze.Transactions.Transaction transaction) { var indexTableName = IndexTableName(name); if (transaction.Select <string, string>("Common", indexTableName).Exists) { transaction.RemoveAllKeys(indexTableName, true); transaction.RemoveKey <string>("Common", indexTableName); if (this.tableNames.Contains(indexTableName)) { this.tableNames.Remove(indexTableName); } } }
/// <summary>Removes polls under provided ids.</summary> /// <param name="transaction">See <see cref="DBreeze.Transactions.Transaction"/>.</param> /// <param name="ids">The ids of the polls to remove.</param> public void RemovePolls(DBreeze.Transactions.Transaction transaction, params int[] ids) { lock (this.lockObject) { foreach (int pollId in ids.OrderBy(id => id).Reverse()) { if (this.highestPollId != pollId) { throw new ArgumentException("Only deletion of the most recent item is allowed!"); } transaction.RemoveKey <byte[]>(DataTable, pollId.ToBytes()); this.highestPollId--; } } }
/// <summary>Removes polls under provided ids.</summary> public void RemovePolls(params int[] ids) { using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { foreach (int pollId in ids.Reverse()) { if (this.highestPollId != pollId) { throw new ArgumentException("Only deletion of the most recent item is allowed!"); } transaction.RemoveKey <byte[]>(TableName, pollId.ToBytes()); this.highestPollId--; this.SaveHighestPollId(transaction); } transaction.Commit(); } }
private void DropIndex(string name, DBreeze.Transactions.Transaction transaction) { Guard.NotNull(name, nameof(name)); Guard.NotNull(transaction, nameof(transaction)); string indexTableName = GetIndexTableName(name); if (transaction.Select <string, string>("Common", indexTableName).Exists) { transaction.RemoveAllKeys(indexTableName, true); transaction.RemoveKey <string>("Common", indexTableName); if (this.tableNames.Contains(indexTableName)) { this.tableNames.Remove(indexTableName); } if (this.Indexes.ContainsKey(name)) { this.Indexes.TryRemove(name, out Index index); } } }
/// <summary>Removes polls for the provided ids.</summary> public void DeletePollsAndSetHighestPollId(params int[] ids) { lock (this.lockObject) { using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { foreach (int pollId in ids.OrderBy(a => a)) { transaction.RemoveKey <byte[]>(TableName, pollId.ToBytes()); } transaction.Commit(); } List <Poll> polls = GetAllPolls(); this.highestPollId = (polls.Count == 0) ? -1 : polls.Max(a => a.Id); using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { SaveHighestPollId(transaction); transaction.Commit(); } } }
/// <inheritdoc /> public override Task SaveChangesAsync(IEnumerable <UnspentOutputs> unspentOutputs, IEnumerable <TxOut[]> originalOutputs, uint256 oldBlockHash, uint256 nextBlockHash) { this.logger.LogTrace("({0}.Count():{1},{2}.Count():{3},{4}:'{5}',{6}:'{7}')", nameof(unspentOutputs), unspentOutputs?.Count(), nameof(originalOutputs), originalOutputs?.Count(), nameof(oldBlockHash), oldBlockHash, nameof(nextBlockHash), nextBlockHash); RewindData rewindData = originalOutputs != null ? new RewindData(oldBlockHash) : null; int insertedEntities = 0; List <UnspentOutputs> all = unspentOutputs.ToList(); Dictionary <uint256, TxOut[]> unspentToOriginal = new Dictionary <uint256, TxOut[]>(all.Count); using (new StopwatchDisposable(o => this.PerformanceCounter.AddInsertTime(o))) { if (originalOutputs != null) { IEnumerator <TxOut[]> originalEnumerator = originalOutputs.GetEnumerator(); foreach (UnspentOutputs output in all) { originalEnumerator.MoveNext(); unspentToOriginal.Add(output.TransactionId, originalEnumerator.Current); } } } Task task = Task.Run(() => { this.logger.LogTrace("()"); using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.ValuesLazyLoadingIsOn = false; transaction.SynchronizeTables("BlockHash", "Coins", "Rewind"); transaction.Technical_SetTable_OverwriteIsNotAllowed("Coins"); using (new StopwatchDisposable(o => this.PerformanceCounter.AddInsertTime(o))) { uint256 current = this.GetCurrentHash(transaction); if (current != oldBlockHash) { this.logger.LogTrace("(-)[BLOCKHASH_MISMATCH]"); throw new InvalidOperationException("Invalid oldBlockHash"); } this.SetBlockHash(transaction, nextBlockHash); all.Sort(UnspentOutputsComparer.Instance); foreach (UnspentOutputs coin in all) { this.logger.LogTrace("Outputs of transaction ID '{0}' are {1} and will be {2} to the database.", coin.TransactionId, coin.IsPrunable ? "PRUNABLE" : "NOT PRUNABLE", coin.IsPrunable ? "removed" : "inserted"); if (coin.IsPrunable) { transaction.RemoveKey("Coins", coin.TransactionId.ToBytes(false)); } else { transaction.Insert("Coins", coin.TransactionId.ToBytes(false), coin.ToCoins()); } if (originalOutputs != null) { TxOut[] original = null; unspentToOriginal.TryGetValue(coin.TransactionId, out original); if (original == null) { // This one haven't existed before, if we rewind, delete it. rewindData.TransactionsToRemove.Add(coin.TransactionId); } else { // We'll need to restore the original outputs. UnspentOutputs clone = coin.Clone(); clone._Outputs = original.ToArray(); rewindData.OutputsToRestore.Add(clone); } } } if (rewindData != null) { int nextRewindIndex = this.GetRewindIndex(transaction) + 1; this.logger.LogTrace("Rewind state #{0} created.", nextRewindIndex); transaction.Insert("Rewind", nextRewindIndex, rewindData); } insertedEntities += all.Count; transaction.Commit(); } } this.PerformanceCounter.AddInsertedEntities(insertedEntities); this.logger.LogTrace("(-)"); }); this.logger.LogTrace("(-)"); return(task); }
/// <inheritdoc /> public Task SaveChangesAsync(IList <UnspentOutputs> unspentOutputs, IEnumerable <TxOut[]> originalOutputs, uint256 oldBlockHash, uint256 nextBlockHash, int height, List <RewindData> rewindDataList = null) { Task task = Task.Run(() => { int insertedEntities = 0; using (DBreeze.Transactions.Transaction transaction = this.CreateTransaction()) { transaction.ValuesLazyLoadingIsOn = false; transaction.SynchronizeTables("BlockHash", "Coins", "Rewind"); // Speed can degrade when keys are in random order and, especially, if these keys have high entropy. // This settings helps with speed, see dBreeze documentations about details. // We should double check if this settings help in our scenario, or sorting keys and operations is enough. // Refers to issue #2483. https://github.com/stratisproject/StratisBitcoinFullNode/issues/2483 transaction.Technical_SetTable_OverwriteIsNotAllowed("Coins"); using (new StopwatchDisposable(o => this.performanceCounter.AddInsertTime(o))) { uint256 current = this.GetTipHash(transaction); if (current != oldBlockHash) { this.logger.LogTrace("(-)[BLOCKHASH_MISMATCH]"); throw new InvalidOperationException("Invalid oldBlockHash"); } this.SetBlockHash(transaction, nextBlockHash); // Here we'll add items to be inserted in a second pass. List <UnspentOutputs> toInsert = new List <UnspentOutputs>(); foreach (var coin in unspentOutputs.OrderBy(utxo => utxo.TransactionId, new UInt256Comparer())) { if (coin.IsPrunable) { this.logger.LogTrace("Outputs of transaction ID '{0}' are prunable and will be removed from the database.", coin.TransactionId); transaction.RemoveKey("Coins", coin.TransactionId.ToBytes(false)); } else { // Add the item to another list that will be used in the second pass. // This is for performance reasons: dBreeze is optimized to run the same kind of operations, sorted. toInsert.Add(coin); } } for (int i = 0; i < toInsert.Count; i++) { var coin = toInsert[i]; this.logger.LogTrace("Outputs of transaction ID '{0}' are NOT PRUNABLE and will be inserted into the database. {1}/{2}.", coin.TransactionId, i, toInsert.Count); transaction.Insert("Coins", coin.TransactionId.ToBytes(false), coin.ToCoins()); } if (rewindDataList != null) { int nextRewindIndex = this.GetRewindIndex(transaction) + 1; foreach (RewindData rewindData in rewindDataList) { this.logger.LogTrace("Rewind state #{0} created.", nextRewindIndex); transaction.Insert("Rewind", nextRewindIndex, rewindData); nextRewindIndex++; } } insertedEntities += unspentOutputs.Count; transaction.Commit(); } } this.performanceCounter.AddInsertedEntities(insertedEntities); }); return(task); }
/// <inheritdoc /> public Task SaveChangesAsync(IEnumerable <UnspentOutputs> unspentOutputs, IEnumerable <TxOut[]> originalOutputs, uint256 oldBlockHash, uint256 nextBlockHash, List <RewindData> rewindDataList = null) { List <UnspentOutputs> all = unspentOutputs.ToList(); this.logger.LogTrace("({0}.Count():{1},{2}:'{3}',{4}:'{5}')", nameof(unspentOutputs), all.Count, nameof(oldBlockHash), oldBlockHash, nameof(nextBlockHash), nextBlockHash); int insertedEntities = 0; Task task = Task.Run(() => { this.logger.LogTrace("()"); using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.ValuesLazyLoadingIsOn = false; transaction.SynchronizeTables("BlockHash", "Coins", "Rewind"); //transaction.Technical_SetTable_OverwriteIsNotAllowed("Coins"); // Why it was there and what is it for? No one knows. using (new StopwatchDisposable(o => this.PerformanceCounter.AddInsertTime(o))) { uint256 current = this.GetTipHash(transaction); if (current != oldBlockHash) { this.logger.LogTrace("(-)[BLOCKHASH_MISMATCH]"); throw new InvalidOperationException("Invalid oldBlockHash"); } this.SetBlockHash(transaction, nextBlockHash); all.Sort(UnspentOutputsComparer.Instance); foreach (UnspentOutputs coin in all) { this.logger.LogTrace("Outputs of transaction ID '{0}' are {1} and will be {2} to the database.", coin.TransactionId, coin.IsPrunable ? "PRUNABLE" : "NOT PRUNABLE", coin.IsPrunable ? "removed" : "inserted"); if (coin.IsPrunable) { transaction.RemoveKey("Coins", coin.TransactionId.ToBytes(false)); } else { transaction.Insert("Coins", coin.TransactionId.ToBytes(false), coin.ToCoins()); } } if (rewindDataList != null) { int nextRewindIndex = this.GetRewindIndex(transaction) + 1; foreach (RewindData rewindData in rewindDataList) { this.logger.LogTrace("Rewind state #{0} created.", nextRewindIndex); transaction.Insert("Rewind", nextRewindIndex, rewindData); nextRewindIndex++; } } insertedEntities += all.Count; transaction.Commit(); } } this.PerformanceCounter.AddInsertedEntities(insertedEntities); this.logger.LogTrace("(-)"); }); this.logger.LogTrace("(-)"); return(task); }
private void DeleteBusinessData(DBreeze.Transactions.Transaction t, BusinessDataModel businessDataModel) { t.RemoveKey <string>(businessDataModel.tableName, businessDataModel.key, out bool wasremoved); }
private void DeleteBusinessType(DBreeze.Transactions.Transaction t, BusinessTypeModel _model) { t.RemoveKey(Datalog._Business_Type, _model.key, out bool wasremoved); t.RemoveAllKeys(_model.key, true); }