public override void Atomic(Slice key, Slice param, FdbMutationType mutation)
 {
     Execute(
         new FdbTransactionLog.AtomicCommand(Grab(key), Grab(param), mutation),
         (_tr, _cmd) => _tr.Atomic(_cmd.Key, _cmd.Param, _cmd.Mutation)
         );
 }
        public void Atomic(Slice key, Slice param, FdbMutationType type)
        {
            FdbNative.TransactionAtomicOperation(m_handle, key, param, type);

            //TODO: what is the overhead for atomic operations?
            Interlocked.Add(ref m_payloadBytes, key.Count + param.Count);
        }
Beispiel #3
0
        /// <inheritdoc />
        public void Atomic(ReadOnlySpan <byte> key, ReadOnlySpan <byte> param, FdbMutationType type)
        {
            FdbNative.TransactionAtomicOperation(m_handle, key, param, type);

            //TODO: what is the overhead for atomic operations?
            Interlocked.Add(ref m_payloadBytes, key.Length + param.Length);
        }
        /// <summary>Checks that this type of mutation is supported by the currently selected API level</summary>
        /// <param name="mutation">Mutation type</param>
        /// <param name="selectedApiVersion">Select API level (200, 300, ...)</param>
        /// <exception cref="FdbException">An error with code <see cref="FdbError.InvalidMutationType"/> if the type of mutation is not supported by this API level.</exception>
        private static void EnsureMutationTypeIsSupported(FdbMutationType mutation, int selectedApiVersion)
        {
            if (selectedApiVersion < 200)
            {             // mutations were not available at this time
                if (Fdb.GetMaxApiVersion() >= 200)
                {         // but the installed client could support it
                    throw new FdbException(FdbError.InvalidMutationType, "Atomic mutations are only supported starting from API level 200. You need to select API level 200 or more at the start of your process.");
                }
                else
                {                 // not supported by the local client
                    throw new FdbException(FdbError.InvalidMutationType, "Atomic mutations are only supported starting from client version 2.x. You need to update the version of the client, and select API level 200 or more at the start of your process.");
                }
            }

            if (mutation == FdbMutationType.Add || mutation == FdbMutationType.BitAnd || mutation == FdbMutationType.BitOr || mutation == FdbMutationType.BitXor)
            {             // these mutations are available since v200
                return;
            }

            if (mutation == FdbMutationType.Max || mutation == FdbMutationType.Min)
            {             // these mutations are available since v300
                if (selectedApiVersion < 300)
                {
                    if (Fdb.GetMaxApiVersion() >= 300)
                    {
                        throw new FdbException(FdbError.InvalidMutationType, "Atomic mutations Max and Min are only supported starting from API level 300. You need to select API level 300 or more at the start of your process.");
                    }
                    else
                    {
                        throw new FdbException(FdbError.InvalidMutationType, "Atomic mutations Max and Min are only supported starting from client version 3.x. You need to update the version of the client, and select API level 300 or more at the start of your process..");
                    }
                }
                // ok!
                return;
            }

            // this could be a new mutation type, or an invalid value.
            throw new FdbException(FdbError.InvalidMutationType, "An invalid mutation type was issued. If you are attempting to call a new mutation type, you will need to update the version of this assembly, and select the latest API level.");
        }
Beispiel #5
0
        public void Atomic(Slice key, Slice param, FdbMutationType mutation)
        {
            // check
            if (key.IsNullOrEmpty)
            {
                throw new ArgumentException("Key cannot be null or empty");
            }
            if (param.IsNull)
            {
                throw new ArgumentNullException("Parameter cannot be null");
            }
            CheckAccessToSystemKeys(key);

            if (mutation != FdbMutationType.Add && mutation != FdbMutationType.BitAnd && mutation != FdbMutationType.BitOr && mutation != FdbMutationType.BitXor && mutation != FdbMutationType.Max && mutation != FdbMutationType.Min)
            {
                //TODO: throw an FdbException instead?
                throw new ArgumentException("Invalid mutation type", "mutation");
            }

            FdbKeyRange range;

            lock (m_buffer)
            {
                range = m_buffer.InternRangeFromKey(key);
                param = m_buffer.Intern(param);
            }

            lock (m_lock)
            {
                if (!ConsumeNextWriteNoConflict_NeedsLocking())
                {
                    AddWriteConflict_NeedsLocking(range);
                }
                AddWriteCommand_NeedsLocking(new WriteCommand((Operation)mutation, range.Begin, param));
            }
        }
        /// <summary>Modify the database snapshot represented by this transaction to perform the operation indicated by <paramref name="mutation"/> with operand <paramref name="param"/> to the value stored by the given key.</summary>
        /// <param name="key">Name of the key whose value is to be mutated.</param>
        /// <param name="param">Parameter with which the atomic operation will mutate the value associated with key_name.</param>
        /// <param name="mutation">Type of mutation that should be performed on the key</param>
        public void Atomic(Slice key, Slice param, FdbMutationType mutation)
        {
            //note: this method as many names in the various bindings:
            // - C API   : fdb_transaction_atomic_op(...)
            // - Java    : tr.Mutate(..)
            // - Node.js : tr.add(..), tr.max(..), ...

            EnsureCanWrite();

            m_database.EnsureKeyIsValid(ref key);
            m_database.EnsureValueIsValid(ref param);

            //The C API does not fail immediately if the mutation type is not valid, and only fails at commit time.
            EnsureMutationTypeIsSupported(mutation, Fdb.ApiVersion);

#if DEBUG
            if (Logging.On && Logging.IsVerbose)
            {
                Logging.Verbose(this, "AtomicCore", String.Format("Atomic {0} on '{1}' = {2}", mutation.ToString(), FdbKey.Dump(key), Slice.Dump(param)));
            }
#endif

            m_handler.Atomic(key, param, mutation);
        }
Beispiel #7
0
 /// <inheritdoc />
 public virtual void Atomic(ReadOnlySpan <byte> key, ReadOnlySpan <byte> param, FdbMutationType mutation)
 {
     ThrowIfDisposed();
     m_transaction.Atomic(key, param, mutation);
 }
Beispiel #8
0
		/// <summary>Performs (x OP y) and ensure that the result is correct</summary>
		private async Task PerformAtomicOperationAndCheck(IFdbDatabase db, Slice key, int x, FdbMutationType type, int y)
		{

			int expected = 0;
			switch(type)
			{
				case FdbMutationType.BitAnd: expected = x & y; break;
				case FdbMutationType.BitOr: expected = x | y; break;
				case FdbMutationType.BitXor: expected = x ^ y; break;
				case FdbMutationType.Add: expected = x + y; break;
				default: Assert.Fail("Invalid operation type"); break;
			}

			// set key = x
			using (var tr = db.BeginTransaction(this.Cancellation))
			{
				tr.Set(key, Slice.FromFixed32(x));
				await tr.CommitAsync();
			}

			// atomic key op y
			using (var tr = db.BeginTransaction(this.Cancellation))
			{
				tr.Atomic(key, Slice.FromFixed32(y), type);
				await tr.CommitAsync();
			}

			// read key
			using (var tr = db.BeginTransaction(this.Cancellation))
			{
				var data = await tr.GetAsync(key);
				Assert.That(data.Count, Is.EqualTo(4), "data.Count");

				Assert.That(data.ToInt32(), Is.EqualTo(expected), "0x{0} {1} 0x{2} = 0x{3}", x.ToString("X8"), type.ToString(), y.ToString("X8"), expected.ToString("X8"));
			}
		}
		/// <summary>Checks that this type of mutation is supported by the currently selected API level</summary>
		/// <param name="mutation">Mutation type</param>
		/// <param name="selectedApiVersion">Select API level (200, 300, ...)</param>
		/// <exception cref="FdbException">An error with code <see cref="FdbError.InvalidMutationType"/> if the type of mutation is not supported by this API level.</exception>
		private static void EnsureMutationTypeIsSupported(FdbMutationType mutation, int selectedApiVersion)
		{
			if (selectedApiVersion < 200)
			{ // mutations were not available at this time

				if (Fdb.GetMaxApiVersion() >= 200)
				{ // but the installed client could support it
					throw new FdbException(FdbError.InvalidMutationType, "Atomic mutations are only supported starting from API level 200. You need to select API level 200 or more at the start of your process.");
				}
				else
				{ // not supported by the local client
					throw new FdbException(FdbError.InvalidMutationType, "Atomic mutations are only supported starting from client version 2.x. You need to update the version of the client, and select API level 200 or more at the start of your process.");
				}
			}

			if (mutation == FdbMutationType.Add || mutation == FdbMutationType.BitAnd || mutation == FdbMutationType.BitOr || mutation == FdbMutationType.BitXor )
			{ // these mutations are available since v200
				return;
			}

			if (mutation == FdbMutationType.Max || mutation == FdbMutationType.Min)
			{ // these mutations are available since v300
				if (selectedApiVersion < 300)
				{
					if (Fdb.GetMaxApiVersion() >= 300)
					{
						throw new FdbException(FdbError.InvalidMutationType, "Atomic mutations Max and Min are only supported starting from API level 300. You need to select API level 300 or more at the start of your process.");
					}
					else
					{
						throw new FdbException(FdbError.InvalidMutationType, "Atomic mutations Max and Min are only supported starting from client version 3.x. You need to update the version of the client, and select API level 300 or more at the start of your process..");
					}
				}
				// ok!
				return;
			}

			// this could be a new mutation type, or an invalid value.
			throw new FdbException(FdbError.InvalidMutationType, "An invalid mutation type was issued. If you are attempting to call a new mutation type, you will need to update the version of this assembly, and select the latest API level.");
		}
Beispiel #10
0
 public AtomicCommand(Slice key, Slice param, FdbMutationType mutation)
 {
     this.Key      = key;
     this.Param    = param;
     this.Mutation = mutation;
 }
		public override void Atomic(Slice key, Slice param, FdbMutationType mutation)
		{
			base.Atomic(Encode(key), param, mutation);
		}
Beispiel #12
0
 public static extern void fdb_transaction_atomic_op(TransactionHandle transaction, byte *keyName, int keyNameLength, byte *param, int paramLength, FdbMutationType operationType);
 public virtual void Atomic(Slice key, Slice param, FdbMutationType mutation)
 {
     ThrowIfDisposed();
     m_transaction.Atomic(key, param, mutation);
 }
		public virtual void Atomic(Slice key, Slice param, FdbMutationType mutation)
		{
			ThrowIfDisposed();
			m_transaction.Atomic(key, param, mutation);
		}
Beispiel #15
0
 public override void Atomic(Slice key, Slice param, FdbMutationType mutation)
 {
     base.Atomic(Encode(key), param, mutation);
 }
		public void Atomic(Slice key, Slice param, FdbMutationType type)
		{
			FdbNative.TransactionAtomicOperation(m_handle, key, param, type);

			//TODO: what is the overhead for atomic operations?
			Interlocked.Add(ref m_payloadBytes, key.Count + param.Count);

		}
		/// <summary>Modify the database snapshot represented by this transaction to perform the operation indicated by <paramref name="mutation"/> with operand <paramref name="param"/> to the value stored by the given key.</summary>
		/// <param name="key">Name of the key whose value is to be mutated.</param>
		/// <param name="param">Parameter with which the atomic operation will mutate the value associated with key_name.</param>
		/// <param name="mutation">Type of mutation that should be performed on the key</param>
		public void Atomic(Slice key, Slice param, FdbMutationType mutation)
		{
			//note: this method as many names in the various bindings:
			// - C API   : fdb_transaction_atomic_op(...)
			// - Java    : tr.Mutate(..)
			// - Node.js : tr.add(..), tr.max(..), ...

			EnsureCanWrite();

			m_database.EnsureKeyIsValid(ref key);
			m_database.EnsureValueIsValid(ref param);

			//The C API does not fail immediately if the mutation type is not valid, and only fails at commit time.
			EnsureMutationTypeIsSupported(mutation, Fdb.ApiVersion);

#if DEBUG
			if (Logging.On && Logging.IsVerbose) Logging.Verbose(this, "AtomicCore", String.Format("Atomic {0} on '{1}' = {2}", mutation.ToString(), FdbKey.Dump(key), Slice.Dump(param)));
#endif

			m_handler.Atomic(key, param, mutation);
		}
			public static extern void fdb_transaction_atomic_op(TransactionHandle transaction, byte* keyName, int keyNameLength, byte* param, int paramLength, FdbMutationType operationType);
Beispiel #19
0
		/// <summary>
		/// Modify the database snapshot represented by this transaction to perform the operation indicated by <paramref name="mutation"/> with operand <paramref name="param"/> to the value stored by the given key.
		/// </summary>
		/// <param name="key">Name of the key whose value is to be mutated.</param>
		/// <param name="param">Parameter with which the atomic operation will mutate the value associated with key_name.</param>
		/// <param name="mutation">Type of mutation that should be performed on the key</param>
		public void Atomic(Slice key, Slice param, FdbMutationType mutation)
		{
			EnsureCanWrite();

			m_database.EnsureKeyIsValid(key);
			m_database.EnsureValueIsValid(param);

			//The C API does not fail immediately if the mutation type is not valid, and only fails at commit time.
			if (mutation != FdbMutationType.Add && mutation != FdbMutationType.BitAnd && mutation != FdbMutationType.BitOr && mutation != FdbMutationType.BitXor)
				throw new FdbException(FdbError.InvalidMutationType, "An invalid mutation type was issued");

#if DEBUG
			if (Logging.On && Logging.IsVerbose) Logging.Verbose(this, "AtomicCore", String.Format("Atomic {0} on '{1}' = {2}", mutation.ToString(), FdbKey.Dump(key), Slice.Dump(param)));
#endif

			m_handler.Atomic(key, param, mutation);
		}
		public static void TransactionAtomicOperation(TransactionHandle transaction, Slice key, Slice param, FdbMutationType operationType)
		{
			fixed (byte* pKey = key.Array)
			fixed (byte* pParam = param.Array)
			{
#if DEBUG_NATIVE_CALLS
				Debug.WriteLine("fdb_transaction_atomic_op(0x" + transaction.Handle.ToString("x") + ", key: '" + FdbKey.Dump(key) + "', param: '" + FdbKey.Dump(param) + "', " + operationType.ToString() + ")");
#endif
				NativeMethods.fdb_transaction_atomic_op(transaction, pKey + key.Offset, key.Count, pParam + param.Offset, param.Count, operationType);
			}
		}