Exemple #1
0
        private async Task <MongoDbRecord> LockRecord(byte[] lockToken, Record r)
        {
            var key     = r.Key.ToByteArray();
            var version = r.Version.ToByteArray();

            if (version.Length != 0)
            {
                var res = await RecordCollection.FindOneAndUpdateAsync(
                    x => x.Key.Equals(key) && x.Version.Equals(version) && (x.TransactionLock == null || x.TransactionLock.Equals(lockToken)),
                    Builders <MongoDbRecord> .Update
                    .Set(x => x.TransactionLock, lockToken)
                    );

                if (res == null)
                {
                    var e = new ConcurrentMutationException(r);
                    e.Data["ExceptionType"] = "LockRecord";
                    throw e;
                }
#if DEBUG
                Logger.LogDebug($"Locked token {new ByteString(lockToken)} {r.Key.ToString()}");
#endif
                return(res);
            }
            return(null);
        }
Exemple #2
0
        private async Task RollbackTransaction(byte[] hash)
        {
            // Rollback is idempotent && reentrant : may be call twice even at the same time
            try
            {
#if DEBUG
                Logger.LogDebug($"Rollbacking transaction {new ByteString(hash)}");
#endif
                // get affected records
                var trn = await PendingTransactionCollection.Find(x => x.TransactionHash.Equals(hash)).SingleOrDefaultAsync();

                if (trn != null)
                {
                    // revert records values & version
                    foreach (var r in trn.InitialRecords)
                    {
                        await RecordCollection.FindOneAndUpdateAsync(
                            x => x.Key.Equals(r.Key) && x.TransactionLock.Equals(trn.LockToken),
                            Builders <MongoDbRecord> .Update.Set(x => x.Value, r.Value).Set(x => x.Version, r.Version).Unset(x => x.TransactionLock)
                            );
                    }

                    foreach (var r in trn.AddedRecords)
                    {
                        await RecordCollection.FindOneAndDeleteAsync(
                            x => x.Key.Equals(r) && x.TransactionLock.Equals(trn.LockToken)
                            );
                    }

                    // remove transaction
                    await TransactionCollection.DeleteOneAsync(x => x.TransactionHash.Equals(hash));

                    await RecordCollection.UpdateOneAsync(
                        x => x.TransactionLock == trn.LockToken,
                        Builders <MongoDbRecord> .Update
                        .Unset(x => x.TransactionLock)
                        );

                    // remove pending transaction
                    await PendingTransactionCollection.DeleteOneAsync(x => x.TransactionHash.Equals(hash));

                    Logger.LogInformation($"Transaction {new ByteString(hash)} rollbacked");
                }
            }
            catch (Exception ex)
            {
                var msg = "Error rollbacking transaction : " + new ByteString(hash).ToString();
                Logger.LogCritical(msg, ex);
                throw new Exception(msg, ex);
            }
        }
        private async Task <MongoDbRecord> LockRecord(byte[] lockToken, Record r)
        {
            var key     = r.Key.ToByteArray();
            var version = r.Version.ToByteArray();

            if (version.Length != 0)
            {
                var res = await RecordCollection.FindOneAndUpdateAsync(
                    x => x.Key.Equals(key) && x.Version.Equals(version) && (x.TransactionLock == null || x.TransactionLock.Equals(lockToken)),
                    Builders <MongoDbRecord> .Update
                    .Set(x => x.TransactionLock, lockToken)
                    );

                if (res == null)
                {
                    throw new ConcurrentMutationException(r);
                }
                return(res);
            }
            return(null);
        }