private async Task SerializeAllTransactionsNoLockAsync() { List <SmartTransaction> transactionsClone; lock (TransactionsLock) { transactionsClone = Transactions.Values.ToList(); } await TransactionsFileManager.WriteAllLinesAsync(transactionsClone.ToBlockchainOrderedLines()).ConfigureAwait(false); }
private async Task InitializeTransactionsNoLockAsync(CancellationToken cancel) { try { IoHelpers.EnsureFileExists(TransactionsFileManager.FilePath); cancel.ThrowIfCancellationRequested(); var allLines = await TransactionsFileManager.ReadAllLinesAsync(cancel).ConfigureAwait(false); var allTransactions = allLines .Select(x => SmartTransaction.FromLine(x, Network)) .OrderByBlockchain(); var added = false; var updated = false; lock (TransactionsLock) { foreach (var tx in allTransactions) { var(isAdded, isUpdated) = TryAddOrUpdateNoLockNoSerialization(tx); if (isAdded) { added = true; } if (isUpdated) { updated = true; } } } if (added || updated) { cancel.ThrowIfCancellationRequested(); // Another process worked into the file and appended the same transaction into it. // In this case we correct the file by serializing the unique set. await SerializeAllTransactionsNoLockAsync().ConfigureAwait(false); } } catch (Exception ex) when(ex is not OperationCanceledException) { // We found a corrupted entry. Stop here. // Delete the currupted file. // Do not try to autocorrect, because the internal data structures are throwing events that may confuse the consumers of those events. Logger.LogError($"{TransactionsFileManager.FileNameWithoutExtension} file got corrupted. Deleting it..."); TransactionsFileManager.DeleteMe(); throw; } }
public void OpenFile(string path) { var response = TransactionsFileManager.GetTransacciones(path); if (response.Type != ResponseType.Ok) { // error return; } var newTransacciones = response.Data; transacciones.Clear(); transacciones.AddRange(newTransacciones); }
private async Task TryCommitToFileAsync(ITxStoreOperation operation) { try { if (operation is null || operation.IsEmpty) { return; } // Make sure that only one call can continue. lock (OperationsLock) { var isRunning = Operations.Any(); Operations.Add(operation); if (isRunning) { return; } } // Wait until the operation list calms down. IEnumerable <ITxStoreOperation> operationsToExecute; while (true) { var count = Operations.Count; await Task.Delay(100).ConfigureAwait(false); lock (OperationsLock) { if (count == Operations.Count) { // Merge operations. operationsToExecute = OperationMerger.Merge(Operations).ToList(); Operations.Clear(); break; } } } using (await TransactionsFileManager.Mutex.LockAsync().ConfigureAwait(false)) { foreach (ITxStoreOperation op in operationsToExecute) { if (op is Append appendOperation) { var toAppends = appendOperation.Transactions; try { await TransactionsFileManager.AppendAllLinesAsync(toAppends.ToBlockchainOrderedLines()).ConfigureAwait(false); } catch { await SerializeAllTransactionsNoMutexAsync().ConfigureAwait(false); } } else if (op is Remove removeOperation) { var toRemoves = removeOperation.Transactions; string[] allLines = await TransactionsFileManager.ReadAllLinesAsync().ConfigureAwait(false); var toSerialize = new List <string>(); foreach (var line in allLines) { var startsWith = false; foreach (var toRemoveString in toRemoves.Select(x => x.ToString())) { startsWith = startsWith || line.StartsWith(toRemoveString, StringComparison.Ordinal); } if (!startsWith) { toSerialize.Add(line); } } try { await TransactionsFileManager.WriteAllLinesAsync(toSerialize).ConfigureAwait(false); } catch { await SerializeAllTransactionsNoMutexAsync().ConfigureAwait(false); } } else if (op is Update updateOperation) { var toUpdates = updateOperation.Transactions; string[] allLines = await TransactionsFileManager.ReadAllLinesAsync().ConfigureAwait(false); IEnumerable <SmartTransaction> allTransactions = allLines.Select(x => SmartTransaction.FromLine(x, Network)); var toSerialize = new List <SmartTransaction>(); foreach (SmartTransaction tx in allTransactions) { var txsToUpdateWith = toUpdates.Where(x => x == tx); foreach (var txToUpdateWith in txsToUpdateWith) { tx.TryUpdate(txToUpdateWith); } toSerialize.Add(tx); } try { await TransactionsFileManager.WriteAllLinesAsync(toSerialize.ToBlockchainOrderedLines()).ConfigureAwait(false); } catch { await SerializeAllTransactionsNoMutexAsync().ConfigureAwait(false); } } else { throw new NotSupportedException(); } } } } catch (Exception ex) { Logger.LogError(ex); } }
public void Save(string path) => TransactionsFileManager.SaveTransacciones(transacciones.ToArray(), path);