예제 #1
0
        private async Task SerializeAllTransactionsNoLockAsync()
        {
            List <SmartTransaction> transactionsClone;

            lock (TransactionsLock)
            {
                transactionsClone = Transactions.Values.ToList();
            }

            await TransactionsFileManager.WriteAllLinesAsync(transactionsClone.ToBlockchainOrderedLines()).ConfigureAwait(false);
        }
예제 #2
0
        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;
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
 public void Save(string path) =>
 TransactionsFileManager.SaveTransacciones(transacciones.ToArray(), path);