protected override void Destroy(IntPtr handle) { FdbNative.ClusterDestroy(handle); Interlocked.Decrement(ref DebugCounters.ClusterHandles); }
protected override void Destroy(IntPtr handle) { FdbNative.TransactionDestroy(handle); Interlocked.Decrement(ref DebugCounters.TransactionHandles); }
/// <summary>Update the Task with the state of a ready Future</summary> /// <param name="fromCallback">If true, the method is called from the network thread and must defer the continuations from the Thread Pool</param> /// <returns>True if we got a result, or false in case of error (or invalid state)</returns> private void HandleCompletion(bool fromCallback) { if (HasAnyFlags(FdbFuture.Flags.DISPOSED | FdbFuture.Flags.COMPLETED)) { return; } #if DEBUG_FUTURES Debug.WriteLine("FutureArray<" + typeof(T).Name + ">.Callback(...) handling completion on thread #" + Thread.CurrentThread.ManagedThreadId.ToString()); #endif try { UnregisterCancellationRegistration(); List <Exception> errors = null; bool cancellation = false; var selector = m_resultSelector; var results = selector != null ? new T[m_handles.Length] : null; for (int i = 0; i < m_handles.Length; i++) { var handle = m_handles[i]; if (handle != null && !handle.IsClosed && !handle.IsInvalid) { FdbError err = FdbNative.FutureGetError(handle); if (Fdb.Failed(err)) { // it failed... if (err != FdbError.OperationCancelled) { // get the exception from the error code var ex = Fdb.MapToException(err); (errors ?? (errors = new List <Exception>())).Add(ex); } else { cancellation = true; break; } } else { // it succeeded... // try to get the result... if (selector != null) { //note: result selector will execute from network thread, but this should be our own code that only calls into some fdb_future_get_XXXX(), which should be safe... results[i] = selector(handle); } } } } if (cancellation) { // the transaction has been cancelled SetCanceled(fromCallback); } else if (errors != null) { // there was at least one error SetFaulted(errors, fromCallback); } else { // success SetResult(results, fromCallback); } } catch (Exception e) { // something went wrong if (e is ThreadAbortException) { SetCanceled(fromCallback); throw; } SetFaulted(e, fromCallback); } finally { TryCleanup(); } }
internal FdbFutureArray([NotNull] FutureHandle[] handles, [NotNull] Func <FutureHandle, T> selector, CancellationToken ct) { Contract.NotNullOrEmpty(handles, nameof(handles)); Contract.NotNull(selector, nameof(selector)); m_handles = handles; m_resultSelector = selector; bool abortAllHandles = false; try { if (ct.IsCancellationRequested) { // already cancelled, we must abort everything SetFlag(FdbFuture.Flags.COMPLETED); abortAllHandles = true; m_resultSelector = null; this.TrySetCanceled(); return; } // add this instance to the list of pending futures var prm = RegisterCallback(this); foreach (var handle in handles) { if (FdbNative.FutureIsReady(handle)) { // this handle is already done continue; } Interlocked.Increment(ref m_pending); // register the callback handler var err = FdbNative.FutureSetCallback(handle, CallbackHandler, prm); if (Fdb.Failed(err)) { // uhoh Debug.WriteLine("Failed to set callback for Future<" + typeof(T).Name + "> 0x" + handle.Handle.ToString("x") + " !!!"); throw Fdb.MapToException(err); } } // allow the callbacks to handle completion TrySetFlag(FdbFuture.Flags.READY); if (Volatile.Read(ref m_pending) == 0) { // all callbacks have already fired (or all handles were already completed) UnregisterCallback(this); HandleCompletion(fromCallback: false); m_resultSelector = null; abortAllHandles = true; SetFlag(FdbFuture.Flags.COMPLETED); } else if (ct.CanBeCanceled) { // register for cancellation (if needed) RegisterForCancellation(ct); } } catch { // this is bad news, since we are in the constructor, we need to clear everything SetFlag(FdbFuture.Flags.DISPOSED); UnregisterCancellationRegistration(); UnregisterCallback(this); abortAllHandles = true; // this is technically not needed, but just to be safe... this.TrySetCanceled(); throw; } finally { if (abortAllHandles) { CloseHandles(handles); } } GC.KeepAlive(this); }
protected override void Destroy(IntPtr handle) { FdbNative.DatabaseDestroy(handle); Interlocked.Decrement(ref DebugCounters.DatabaseHandles); }
public void Cancel() { FdbNative.TransactionCancel(m_handle); }
/// <summary> /// Attempts to commit the sets and clears previously applied to the database snapshot represented by this transaction to the actual database. /// The commit may or may not succeed – in particular, if a conflicting transaction previously committed, then the commit must fail in order to preserve transactional isolation. /// If the commit does succeed, the transaction is durably committed to the database and all subsequently started transactions will observe its effects. /// </summary> /// <returns>Task that succeeds if the transaction was committed successfully, or fails if the transaction failed to commit.</returns> /// <remarks>As with other client/server databases, in some failure scenarios a client may be unable to determine whether a transaction succeeded. In these cases, CommitAsync() will throw CommitUnknownResult error. The OnErrorAsync() function treats this error as retryable, so retry loops that don’t check for CommitUnknownResult could execute the transaction twice. In these cases, you must consider the idempotence of the transaction.</remarks> public Task CommitAsync(CancellationToken ct) { var future = FdbNative.TransactionCommit(m_handle); return(FdbFuture.CreateTaskFromHandle <object>(future, (h) => null, ct)); }
public DatabaseHandle CreateDatabase(string databaseName) { FdbNative.CreateDatabase(databaseName, out d_handle); return(d_handle); }
public void AddConflictRange(Slice beginKeyInclusive, Slice endKeyExclusive, FdbConflictRangeType type) { FdbError err = FdbNative.TransactionAddConflictRange(m_handle, beginKeyInclusive, endKeyExclusive, type); Fdb.DieOnError(err); }
public Task <VersionStamp> GetVersionStampAsync(CancellationToken ct) { var future = FdbNative.TransactionGetVersionStamp(m_handle); return(FdbFuture.CreateTaskFromHandle <VersionStamp>(future, GetVersionStampResult, ct)); }
public void ClearRange(Slice beginKeyInclusive, Slice endKeyExclusive) { FdbNative.TransactionClearRange(m_handle, beginKeyInclusive, endKeyExclusive); // There is an overhead of 28-byte per operation Interlocked.Add(ref m_payloadBytes, beginKeyInclusive.Count + endKeyExclusive.Count + 28); }
public void Clear(Slice key) { FdbNative.TransactionClear(m_handle, key); // The key is converted to range [key, key.'\0'), and there is an overhead of 28-byte per operation Interlocked.Add(ref m_payloadBytes, (key.Count * 2) + 28 + 1); }
public Task <Slice> GetAsync(Slice key, bool snapshot, CancellationToken ct) { var future = FdbNative.TransactionGet(m_handle, key, snapshot); return(FdbFuture.CreateTaskFromHandle(future, (h) => GetValueResultBytes(h), ct)); }
/// <summary>Update the Task with the state of a ready Future</summary> /// <param name="fromCallback">If true, we are called from the network thread</param> /// <returns>True if we got a result, or false in case of error (or invalid state)</returns> private void HandleCompletion(bool fromCallback) { // note: if fromCallback is true, we are running on the network thread // this means that we have to signal the TCS from the threadpool, if not continuations on the task may run inline. // this is very frequent when we are called with await, or ContinueWith(..., TaskContinuationOptions.ExecuteSynchronously) if (HasAnyFlags(FdbFuture.Flags.DISPOSED | FdbFuture.Flags.COMPLETED)) { return; } #if DEBUG_FUTURES var sw = Stopwatch.StartNew(); #endif try { var handle = m_handle; if (handle != null && !handle.IsClosed && !handle.IsInvalid) { UnregisterCancellationRegistration(); FdbError err = FdbNative.FutureGetError(handle); if (Fdb.Failed(err)) { // it failed... #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> has FAILED: " + err); #endif if (err != FdbError.OperationCancelled) { // get the exception from the error code var ex = Fdb.MapToException(err); SetFaulted(ex, fromCallback); return; } //else: will be handle below } else { // it succeeded... // try to get the result... #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> has completed successfully"); #endif var selector = m_resultSelector; if (selector != null) { //note: result selector will execute from network thread, but this should be our own code that only calls into some fdb_future_get_XXXX(), which should be safe... var result = selector(handle); SetResult(result, fromCallback); return; } //else: it will be handled below } } // most probably the future was cancelled or we are shutting down... SetCanceled(fromCallback); } catch (Exception e) { // something went wrong if (e is ThreadAbortException) { SetCanceled(fromCallback); throw; } SetFaulted(e, fromCallback); } finally { #if DEBUG_FUTURES sw.Stop(); Debug.WriteLine("Future<" + typeof(T).Name + "> callback completed in " + sw.Elapsed.TotalMilliseconds.ToString() + " ms"); #endif TryCleanup(); } }
public Task OnErrorAsync(FdbError code, CancellationToken ct) { var future = FdbNative.TransactionOnError(m_handle, code); return(FdbFuture.CreateTaskFromHandle <object>(future, (h) => { ResetInternal(); return null; }, ct)); }
internal FdbFutureSingle([NotNull] FutureHandle handle, [NotNull] Func <FutureHandle, T> selector, CancellationToken cancellationToken) { if (handle == null) { throw new ArgumentNullException("handle"); } if (selector == null) { throw new ArgumentNullException("selector"); } m_handle = handle; m_resultSelector = selector; try { if (handle.IsInvalid) { // it's dead, Jim ! SetFlag(FdbFuture.Flags.COMPLETED); m_resultSelector = null; return; } if (FdbNative.FutureIsReady(handle)) { // either got a value or an error #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> 0x" + handle.Handle.ToString("x") + " was already ready"); #endif HandleCompletion(fromCallback: false); #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> 0x" + handle.Handle.ToString("x") + " completed inline"); #endif return; } // register for cancellation (if needed) if (cancellationToken.CanBeCanceled) { if (cancellationToken.IsCancellationRequested) { // we have already been cancelled #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> 0x" + handle.Handle.ToString("x") + " will complete later"); #endif // Abort the future and simulate a Canceled task SetFlag(FdbFuture.Flags.COMPLETED); // note: we don't need to call fdb_future_cancel because fdb_future_destroy will take care of everything handle.Dispose(); // also, don't keep a reference on the callback because it won't be needed m_resultSelector = null; this.TrySetCanceled(); return; } // token still active RegisterForCancellation(cancellationToken); } #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> 0x" + handle.Handle.ToString("x") + " will complete later"); #endif TrySetFlag(FdbFuture.Flags.READY); // add this instance to the list of pending futures var prm = RegisterCallback(this); // register the callback handler var err = FdbNative.FutureSetCallback(handle, CallbackHandler, prm); if (Fdb.Failed(err)) { // uhoh #if DEBUG_FUTURES Debug.WriteLine("Failed to set callback for Future<" + typeof(T).Name + "> 0x" + handle.Handle.ToString("x") + " !!!"); #endif throw Fdb.MapToException(err); } } catch { // this is bad news, since we are in the constructor, we need to clear everything SetFlag(FdbFuture.Flags.DISPOSED); UnregisterCancellationRegistration(); UnregisterCallback(this); // kill the future handle m_handle.Dispose(); // this is technically not needed, but just to be safe... this.TrySetCanceled(); throw; } GC.KeepAlive(this); }
public void Reset() { FdbNative.TransactionReset(m_handle); ResetInternal(); }
public void SetReadVersion(long version) { FdbNative.TransactionSetReadVersion(m_handle, version); }
/// <summary>Update the Task with the state of a ready Future</summary> /// <returns>True if we got a result, or false in case of error (or invalid state)</returns> private void HandleCompletion() { if (HasAnyFlags(FdbFuture.Flags.DISPOSED | FdbFuture.Flags.COMPLETED)) { return; } #if DEBUG_FUTURES var sw = Stopwatch.StartNew(); #endif try { var handle = m_handle; if (handle != null && !handle.IsClosed && !handle.IsInvalid) { UnregisterCancellationRegistration(); FdbError err = FdbNative.FutureGetError(handle); if (Fdb.Failed(err)) { // it failed... #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> has FAILED: " + err); #endif if (err != FdbError.OperationCancelled) { // get the exception from the error code var ex = Fdb.MapToException(err) !; TrySetException(ex); return; } //else: will be handle below } else { // it succeeded... // try to get the result... #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> has completed successfully"); #endif var selector = m_resultSelector; if (selector != null) { //note: result selector will execute from network thread, but this should be our own code that only calls into some fdb_future_get_XXXX(), which should be safe... var result = selector(handle); TrySetResult(result); return; } //else: it will be handled below } } // most probably the future was cancelled or we are shutting down... TrySetCanceled(); } catch (Exception e) { // something went wrong if (e is ThreadAbortException) { TrySetCanceled(); throw; } TrySetException(e); } finally { #if DEBUG_FUTURES sw.Stop(); Debug.WriteLine("Future<" + typeof(T).Name + "> callback completed in " + sw.Elapsed.TotalMilliseconds.ToString() + " ms"); #endif TryCleanup(); } }