예제 #1
0
        public override TransactionStatistics.TransactionStatisticsInternal GetTransactionStatistics(long Identifier)
        {
            TransactionStatistics stats = TransactionStatistics.TransactionList[Identifier];

            stats.UpdateInternals();
            return(stats.StatisticsInternal);
        }
예제 #2
0
        public void ExecuteTransaction(IList <DataRequest> requests)
        {
            var request = new TransactionRequest(requests)
            {
                IsSingleStage = true, TransactionId = Guid.NewGuid()
            };

            TransactionStatistics.ExecutedAsSingleStage();


            var response = Channel.SendRequest(request);

            if (response is NullResponse)
            {
                return;
            }

            if (response is ExceptionResponse exResponse)
            {
                if (exResponse.ExceptionType != ExceptionType.FailedToAcquireLock)
                {
                    throw new CacheException(exResponse.Message, exResponse.ExceptionType);
                }
            }


            TransactionStatistics.NewTransactionCompleted();
        }
예제 #3
0
        public void ExecuteTransaction(IList <DataRequest> requests)
        {
            // the same connector will not execute transactions in parallel
            lock (_transactionSync)
            {
                var status = new TransactionState();

                status.Initialize(requests, CacheClients);

                status.CheckStatus(TransactionState.Status.Initialized);

                status.TryExecuteAsSingleStage();

                if (status.CurrentStatus == TransactionState.Status.Completed)
                {
                    TransactionStatistics.ExecutedAsSingleStage();

                    return;
                }


                // stage zero : send the transaction request to the servers and wait for them to acquire write locks
                status.AcquireLock();

                status.CheckStatus(TransactionState.Status.LocksAcquired);


                // first stage: the durable transaction is written in the transaction log
                status.ProceedWithFirstStage();


                // second stage: commit or rollback only the servers that processed successfully the first stage
                // (if a server answered with an exception response the transaction was already rolled back on this server)

                if (status.CurrentStatus == TransactionState.Status.FirstStageCompleted)
                {
                    // commit the transaction
                    status.CommitSecondStage();

                    status.CheckStatus(TransactionState.Status.SecondStageCompleted);

                    // close the transaction
                    status.CloseTransaction();

                    status.CheckStatus(TransactionState.Status.Completed);

                    TransactionStatistics.NewTransactionCompleted();
                }
                else
                {
                    status.Rollback();

                    throw new CacheException(
                              $"Error in two stage transaction. The transaction was successfully rolled back: {status.ExceptionType}", status.ExceptionType);
                }
            }
        }
예제 #4
0
        public List <TransactionStatistics> GetStats(DateTime date)
        {
            var transacStatsList = new List <TransactionStatistics>();
            var transacs         = _ctx.Transactions.Where(t => t.Date.Year == date.Year).ToList();

            for (var i = 1; i <= 12; i++)
            {
                var monthlyTransacStats = new TransactionStatistics {
                    Month = i - 1
                };
                var i1 = i;
                var transacsThisMonth = transacs.Where(t => t.Date.Month == i1);
                foreach (var transactionOfMonth in transacsThisMonth)
                {
                    var transaclyStats = new TransactionStatistics();
                    foreach (var transactionItem in transactionOfMonth.TransactionItems)
                    {
                        var transacItemlyStats = new TransactionStatistics();
                        switch (transactionOfMonth.TransactionType)
                        {
                        case TransactionType.Sale:
                            // profit/loss is only calculated duting a sale
                            // this is done by getting the difference between an item's
                            // buying and selling price
                            if (transactionItem.Item.Deleted <= 0)
                            {
                                transacItemlyStats.Sales        += transactionItem.Amount;
                                transacItemlyStats.PurchaseCost += transactionItem.Item.PurchaseCost * transactionItem.Quantity;
                            }
                            break;

                        case TransactionType.Purchase:
                            // this is to show how much was spent buying stuff
                            // operational cost, i think
                            transacItemlyStats.Purchases += transactionItem.Amount;
                            break;

                        default:
                            throw new Exception("Invalid TransactionType");
                        }
                        // for each transactionItem, add its stats to the containing transaction's stats
                        transaclyStats.Sales        += transacItemlyStats.Sales;
                        transaclyStats.PurchaseCost += transacItemlyStats.PurchaseCost;
                        transaclyStats.Purchases    += transacItemlyStats.Purchases;
                    }
                    // for each transaction, add its stats to that month's transaction stats
                    monthlyTransacStats.Sales        += transaclyStats.Sales;
                    monthlyTransacStats.PurchaseCost += transaclyStats.PurchaseCost;
                    monthlyTransacStats.Purchases    += transaclyStats.Purchases;
                }
                // calculate profit for that month, and add that month's stats to list of monthly stats
                monthlyTransacStats.ProfitLoss = monthlyTransacStats.Sales - monthlyTransacStats.PurchaseCost;
                transacStatsList.Add(monthlyTransacStats);
            }

            return(transacStatsList);
        }
예제 #5
0
        public void Init()
        {
            for (var i = 0; i < ServerCount; i++)
            {
                if (Directory.Exists($"server{i:D2}"))
                {
                    Directory.Delete($"server{i:D2}", true);
                }
            }


            StartServers();

            TransactionStatistics.Reset();
        }
        private static void CalculateAverageGainAndLossOnTransaction(SimulationResultDto resultDto, IList <int> companyIds)
        {
            var transactionDiffs        = companyIds.ToDictionary(companyId => companyId, companyId => 0m);
            var gain                    = 0m;
            var loss                    = 0m;
            int successes               = 0;
            int losses                  = 0;
            TransactionStatistics stats = new TransactionStatistics();

            foreach (var trans in resultDto.TransactionsLog)
            {
                if (trans.Action == SignalAction.Buy)
                {
                    transactionDiffs[trans.CompanyId] += trans.Quantity * trans.Price;
                }
                else if (trans.Action == SignalAction.Sell)
                {
                    decimal buyValue  = transactionDiffs[trans.CompanyId];
                    decimal sellValue = trans.Quantity * trans.Price;
                    transactionDiffs[trans.CompanyId] = 0;
                    var diff = sellValue - buyValue;
                    if (diff > 0m)
                    {
                        gain += diff;
                        successes++;
                    }
                    else
                    {
                        loss += diff;
                        losses++;
                    }
                }
            }
            if (successes + losses != 0)
            {
                stats.SuccessTransactionPercentage = Math.Round(100 * ((double)successes) / (successes + losses), 2);
                stats.FailedTransactionPercentage  = Math.Round(100 * ((double)losses) / (successes + losses), 2);
            }
            else
            {
                stats.SuccessTransactionPercentage = 0;
                stats.FailedTransactionPercentage  = 0;
            }
            stats.AverageGainOnTransaction  = new AverageTransactionResult(gain, successes);
            stats.AverageLossOnTransaction  = new AverageTransactionResult(loss, losses);
            resultDto.TransactionStatistics = stats;
        }
예제 #7
0
        private static void PerfTest(Connector connector)
        {
            TransactionStatistics.Reset();
            // first delete all data to start with a clean database
            connector.AdminInterface().DropDatabase();

            connector.DeclareCollection <Account>();
            connector.DeclareCollection <MoneyTransfer>();

            var accounts = connector.DataSource <Account>();


            // create the accounts
            for (int i = 0; i < TestIterations; i++)
            {
                accounts.Put(new Account {
                    Id = i, Balance = 1000
                });
            }


            var tids = Enumerable.Range(0, TestIterations).ToArray();

            try
            {
                tids = connector.GenerateUniqueIds("transfer_id", TestIterations);
            }
            catch (Exception)
            {
                // ignore (means testing with non persistent server)
            }


            var rand = new Random();

            int failed = 0;

            var sw = new Stopwatch();

            sw.Start();

            for (int i = 0; i < TestIterations; i++)
            {
                var src = rand.Next(1, 1000);
                var dst = src + 1 > 999? src - 1:src + 1;

                var transferred = rand.Next(1, 1000);

                var srcAccount = accounts[src];
                var dstAccount = accounts[dst];

                srcAccount.Balance -= transferred;
                dstAccount.Balance += transferred;

                var transaction = connector.BeginTransaction();
                transaction.UpdateIf(srcAccount, account => account.Balance >= transferred);
                transaction.Put(dstAccount);
                transaction.Put(new MoneyTransfer
                {
                    Amount             = transferred,
                    Date               = DateTime.Today,
                    SourceAccount      = src,
                    DestinationAccount = dst,
                    Id = tids[i]
                });

                try
                {
                    transaction.Commit();
                }
                catch (CacheException e)
                {
                    if (e.IsTransactionException)
                    {
                        failed++;
                    }
                }
            }

            sw.Stop();

            Console.WriteLine($"{TestIterations} transactions took {sw.ElapsedMilliseconds} milliseconds. Rolled back transactions: {failed}. ");
            var stats = TransactionStatistics.AsString();

            Console.WriteLine(stats);

            // check that all accounts have positive balance
            var negatives = accounts.Count(acc => acc.Balance < 0);

            if (negatives > 0)
            {
                Console.WriteLine("Some accounts have negative balance");
            }
            else
            {
                Console.WriteLine("All accounts have positive balance");
            }
        }
예제 #8
0
        public IActionResult Statistics()
        {
            TransactionStatistics statistics = foxCoinService.GetStatistics();

            return(View(statistics));
        }
        public void No_deadlock_if_same_objects_are_updated_in_parallel_by_multiple_clients()
        {
            List <Account> myAccounts;

            using (var connector = new Connector(_clientConfig))
            {
                var accounts = connector.DataSource <Account>();

                var accountIds = connector.GenerateUniqueIds("account_id", 2);

                accounts.Put(new Account {
                    Id = accountIds[0], Balance = 1000
                });
                accounts.Put(new Account {
                    Id = accountIds[1], Balance = 0
                });

                myAccounts = accounts.ToList();
            }

            Parallel.Invoke(
                () =>
            {
                using (var connector1 = new Connector(_clientConfig))
                {
                    for (var i = 0; i < 100; i++)
                    {
                        var transfer = new MoneyTransfer
                        {
                            Amount             = 10,
                            Date               = DateTime.Today,
                            SourceAccount      = myAccounts[0].Id,
                            DestinationAccount = myAccounts[1].Id
                        };

                        myAccounts[0].Balance -= 10;
                        myAccounts[1].Balance += 10;

                        var transaction = connector1.BeginTransaction();
                        transaction.Put(myAccounts[0]);
                        transaction.Put(myAccounts[1]);
                        transaction.Put(transfer);
                        transaction.Commit();
                    }
                }
            },
                () =>
            {
                using (var connector2 = new Connector(_clientConfig))
                {
                    for (var i = 0; i < 100; i++)
                    {
                        var transfer = new MoneyTransfer
                        {
                            Amount             = 10,
                            Date               = DateTime.Today,
                            SourceAccount      = myAccounts[0].Id,
                            DestinationAccount = myAccounts[1].Id
                        };

                        myAccounts[0].Balance -= 10;
                        myAccounts[1].Balance += 10;

                        var transaction = connector2.BeginTransaction();
                        transaction.Put(myAccounts[0]);
                        transaction.Put(myAccounts[1]);
                        transaction.Put(transfer);
                        transaction.Commit();
                    }
                }
            },
                () =>
            {
                using (var connector3 = new Connector(_clientConfig))
                {
                    for (var i = 0; i < 100; i++)
                    {
                        var transfer = new MoneyTransfer
                        {
                            Amount             = 10,
                            Date               = DateTime.Today,
                            SourceAccount      = myAccounts[0].Id,
                            DestinationAccount = myAccounts[1].Id
                        };

                        myAccounts[0].Balance -= 10;
                        myAccounts[1].Balance += 10;

                        var transaction = connector3.BeginTransaction();
                        transaction.Put(myAccounts[0]);
                        transaction.Put(myAccounts[1]);
                        transaction.Put(transfer);
                        transaction.Commit();
                    }
                }
            });

            TransactionStatistics.Display();


            using (var connector = new Connector(_clientConfig))
            {
                var accounts = connector.DataSource <Account>();


                myAccounts = accounts.ToList();

                Console.WriteLine($"balance1={myAccounts[0].Balance} balance2={myAccounts[1].Balance}");

                Assert.AreEqual(1000, myAccounts[0].Balance + myAccounts[1].Balance);
            }
        }
예제 #10
0
        public async Task <TransactionResponse> SaveAsync(Guid playerId, IEnumerable <Transaction> transactions)
        {
            if (transactions.Count() == 0)
            {
                return(new TransactionResponse("Empty transactions"));
            }

            var existingPlayer = await _playerRepository.FindByIdAsync(playerId);

            if (existingPlayer == null)
            {
                return(new TransactionResponse("Player not exist"));
            }

            try
            {
                TransactionStatistics transactionStatistics = new TransactionStatistics();

                // traverse through transactions
                foreach (var transaction in transactions)
                {
                    try
                    {
                        transaction.PlayerId = playerId;
                        transaction.Player   = existingPlayer;

                        var existingTransaction = await _transactionRepository.FindByIdAsync(transaction.TransactionId);

                        if (existingTransaction == null)
                        {
                            // execute transaction
                            await _transactionCommand.ExecuteAction(transaction);

                            // create a new instance of the transaction in the repository
                            transaction.Status = ETransactionStatus.Succeed;
                            await _transactionRepository.AddAsync(transaction);

                            // update successfully processed transaction statistics
                            transactionStatistics.AppliedTransactions.Add(transaction.TransactionId);
                        }
                        else
                        {
                            // duplicated transaction => return cached result
                            if (existingTransaction.Status == ETransactionStatus.Succeed)
                            {
                                transactionStatistics.AppliedTransactions.Add(transaction.TransactionId);
                            }
                            else
                            {
                                transactionStatistics.FailedTransactions.Add(new FailedTransaction {
                                    TransactionId = transaction.TransactionId, Message = existingTransaction.Message
                                });
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // update failed transaction statistics
                        transactionStatistics.FailedTransactions.Add(new FailedTransaction {
                            TransactionId = transaction.TransactionId, Message = ex.Message
                        });
                        transaction.Status  = ETransactionStatus.Failed;
                        transaction.Message = ex.Message;
                        await _transactionRepository.AddAsync(transaction);
                    }
                }

                // story changes
                await _unitOfWork.CompleteAsync();

                return(new TransactionResponse(transactionStatistics));
            }
            catch (Exception ex)
            {
                return(new TransactionResponse($"An error occurred when saving the transaction: {ex.Message}"));
            }
        }