public static FdbError FutureGetVersion(FutureHandle future, out long version) { #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_get_version(0x" + future.Handle.ToString("x") + ")"); #endif return(NativeMethods.fdb_future_get_version(future, out version)); }
public Task <Slice[]> GetKeysAsync(KeySelector[] selectors, bool snapshot, CancellationToken ct) { Contract.Requires(selectors != null); if (selectors.Length == 0) { return(Task.FromResult(Array.Empty <Slice>())); } var futures = new FutureHandle[selectors.Length]; try { for (int i = 0; i < selectors.Length; i++) { futures[i] = FdbNative.TransactionGetKey(m_handle, selectors[i], snapshot); } } catch { for (int i = 0; i < selectors.Length; i++) { if (futures[i] == null) { break; } futures[i].Dispose(); } throw; } return(FdbFuture.CreateTaskFromHandleArray(futures, (h) => GetKeyResult(h), ct)); }
public Task <Slice[]> GetValuesAsync(ReadOnlySpan <Slice> keys, bool snapshot, CancellationToken ct) { Contract.Requires(keys != null); if (keys.Length == 0) { return(Task.FromResult(Array.Empty <Slice>())); } var futures = new FutureHandle[keys.Length]; try { //REVIEW: as of now (700), there is no way to read multiple keys in a single API call for (int i = 0; i < keys.Length; i++) { futures[i] = FdbNative.TransactionGet(m_handle, keys[i].Span, snapshot); } } catch { // cancel all requests leading up to the failure for (int i = 0; i < futures.Length; i++) { if (futures[i] == null) { break; } futures[i].Dispose(); } throw; } return(FdbFuture.CreateTaskFromHandleArray(futures, (h) => GetValueResultBytes(h), ct)); }
public Task <Slice[]> GetValuesAsync(Slice[] keys, bool snapshot, CancellationToken cancellationToken) { Contract.Requires(keys != null); if (keys.Length == 0) { return(Task.FromResult(Array.Empty <Slice>())); } var futures = new FutureHandle[keys.Length]; try { for (int i = 0; i < keys.Length; i++) { futures[i] = FdbNative.TransactionGet(m_handle, keys[i], snapshot); } } catch { for (int i = 0; i < keys.Length; i++) { if (futures[i] == null) { break; } futures[i].Dispose(); } throw; } return(FdbFuture.CreateTaskFromHandleArray(futures, (h) => GetValueResultBytes(h), cancellationToken)); }
public static FdbError FutureSetCallback(FutureHandle future, FdbFutureCallback callback, IntPtr callbackParameter) { var err = NativeMethods.fdb_future_set_callback(future, callback, callbackParameter); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_set_callback(0x" + future.Handle.ToString("x") + ", 0x" + ptrCallback.ToString("x") + ") => err=" + err); #endif return(err); }
private static KeyValuePair <Slice, Slice>[] GetKeyValueArrayResult(FutureHandle h, out bool more) { var err = FdbNative.FutureGetKeyValueArray(h, out var result, out more); Fdb.DieOnError(err); //note: result can only be null if an error occured! Contract.Ensures(result != null); return(result); }
private static Slice GetValueResultBytes(FutureHandle h) { Contract.Requires(h != null); if (!TryGetValueResult(h, out Slice result)) { return(Slice.Nil); } return(result); }
public static FdbError FutureGetCluster(FutureHandle future, out ClusterHandle cluster) { var err = NativeMethods.fdb_future_get_cluster(future, out cluster); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_get_cluster(0x" + future.Handle.ToString("x") + ") => err=" + err + ", handle=0x" + cluster.Handle.ToString("x")); #endif //TODO: check if err == Success ? return(err); }
public static FdbError FutureGetDatabase(FutureHandle future, out DatabaseHandle database) { var err = NativeMethods.fdb_future_get_database(future, out database); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_get_database(0x" + future.Handle.ToString("x") + ") => err=" + err + ", handle=0x" + database.Handle.ToString("x")); #endif //TODO: check if err == Success ? return(err); }
public static FdbError FutureBlockUntilReady(FutureHandle future) { #if DEBUG_NATIVE_CALLS Debug.WriteLine("calling fdb_future_block_until_ready(0x" + future.Handle.ToString("x") + ")..."); #endif var err = NativeMethods.fdb_future_block_until_ready(future); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_block_until_ready(0x" + future.Handle.ToString("x") + ") => err=" + err); #endif return(err); }
/// <summary>Extract a chunk of result from a completed Future</summary> /// <param name="h">Handle to the completed Future</param> /// <param name="more">Receives true if there are more result, or false if all results have been transmitted</param> /// <param name="first">Receives the first key in the page, or default if page is empty</param> /// <param name="last">Receives the last key in the page, or default if page is empty</param> /// <returns>Array of key/value pairs, or an exception</returns> private static KeyValuePair <Slice, Slice>[] GetKeyValueArrayResultKeysOnly(FutureHandle h, out bool more, out Slice first, out Slice last) { var err = FdbNative.FutureGetKeyValueArrayKeysOnly(h, out var result, out more); Fdb.DieOnError(err); //note: result can only be null if an error occured! Contract.Ensures(result != null); first = result.Length > 0 ? result[0].Key : default; last = result.Length > 0 ? result[result.Length - 1].Key : default; return(result); }
private static bool TryGetValueResult(FutureHandle h, out Slice result) { Contract.Requires(h != null); var err = FdbNative.FutureGetValue(h, out bool present, out result); #if DEBUG_TRANSACTIONS Debug.WriteLine("FdbTransaction[].TryGetValueResult() => err=" + err + ", present=" + present + ", valueLength=" + result.Count); #endif Fdb.DieOnError(err); return(present); }
private static Slice GetKeyResult(FutureHandle h) { Contract.Requires(h != null); var err = FdbNative.FutureGetKey(h, out ReadOnlySpan <byte> result); #if DEBUG_TRANSACTIONS Debug.WriteLine("FdbTransaction[].GetKeyResult() => err=" + err + ", result=" + result.ToString()); #endif Fdb.DieOnError(err); return(Slice.Copy(result)); }
private static VersionStamp GetVersionStampResult(FutureHandle h) { Contract.Requires(h != null); var err = FdbNative.FutureGetVersionStamp(h, out VersionStamp stamp); #if DEBUG_TRANSACTIONS Debug.WriteLine("FdbTransaction[" + m_id + "].FutureGetVersionStamp() => err=" + err + ", vs=" + stamp + ")"); #endif Fdb.DieOnError(err); return(stamp); }
private static Slice GetValueResultBytes(FutureHandle h) { Contract.Debug.Requires(h != null); var err = FdbNative.FutureGetValue(h, out bool present, out ReadOnlySpan <byte> result); #if DEBUG_TRANSACTIONS Debug.WriteLine("FdbTransaction[].TryGetValueResult() => err=" + err + ", present=" + present + ", valueLength=" + result.Count); #endif Fdb.DieOnError(err); return(present ? Slice.Copy(result) : Slice.Nil); }
private static string[] GetStringArrayResult(FutureHandle h) { Contract.Requires(h != null); var err = FdbNative.FutureGetStringArray(h, out var result); #if DEBUG_TRANSACTIONS Debug.WriteLine("FdbTransaction[].FutureGetStringArray() => err=" + err + ", results=" + (result == null ? "<null>" : result.Length.ToString())); #endif Fdb.DieOnError(err); Contract.Ensures(result != null); // can only be null in case of an error return(result !); }
public static void FutureReleaseMemory(FutureHandle futureHandle) { NativeMethods.fdb_future_release_memory(futureHandle); }
public static bool FutureIsReady(FutureHandle futureHandle) { return(NativeMethods.fdb_future_is_ready(futureHandle)); }
public static extern FdbError fdb_future_get_string_array(FutureHandle future, out byte **strings, out int count);
public static extern FdbError fdb_future_get_database(FutureHandle future, out DatabaseHandle database);
public static FdbError FutureGetError(FutureHandle future) { return NativeMethods.fdb_future_get_error(future); }
public static extern FdbError fdb_future_get_error(FutureHandle futureHandle);
public static extern FdbError fdb_future_get_key(FutureHandle future, out byte* key, out int keyLength);
public static FdbError FutureGetValue(FutureHandle future, out bool valuePresent, out Slice value) { byte* ptr; int valueLength; var err = NativeMethods.fdb_future_get_value(future, out valuePresent, out ptr, out valueLength); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_get_value(0x" + future.Handle.ToString("x") + ") => err=" + err + ", present=" + valuePresent + ", valueLength=" + valueLength); #endif if (ptr != null && valueLength >= 0) { var bytes = new byte[valueLength]; Marshal.Copy(new IntPtr(ptr), bytes, 0, valueLength); value = new Slice(bytes, 0, valueLength); } else { value = Slice.Nil; } return err; }
public static FdbError FutureGetVersion(FutureHandle future, out long version) { #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_get_version(0x" + future.Handle.ToString("x") + ")"); #endif return NativeMethods.fdb_future_get_version(future, out version); }
public static FdbError FutureGetDatabase(FutureHandle future, out DatabaseHandle database) { var err = NativeMethods.fdb_future_get_database(future, out database); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_get_database(0x" + future.Handle.ToString("x") + ") => err=" + err + ", handle=0x" + database.Handle.ToString("x")); #endif //TODO: check if err == Success ? return err; }
public static FdbError FutureGetCluster(FutureHandle future, out ClusterHandle cluster) { var err = NativeMethods.fdb_future_get_cluster(future, out cluster); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_get_cluster(0x" + future.Handle.ToString("x") + ") => err=" + err + ", handle=0x" + cluster.Handle.ToString("x")); #endif //TODO: check if err == Success ? return err; }
public static FdbError FutureSetCallback(FutureHandle future, FdbFutureCallback callback, IntPtr callbackParameter) { var err = NativeMethods.fdb_future_set_callback(future, callback, callbackParameter); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_set_callback(0x" + future.Handle.ToString("x") + ", 0x" + ptrCallback.ToString("x") + ") => err=" + err); #endif return err; }
public static FdbError FutureBlockUntilReady(FutureHandle future) { #if DEBUG_NATIVE_CALLS Debug.WriteLine("calling fdb_future_block_until_ready(0x" + future.Handle.ToString("x") + ")..."); #endif var err = NativeMethods.fdb_future_block_until_ready(future); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_block_until_ready(0x" + future.Handle.ToString("x") + ") => err=" + err); #endif return err; }
public static extern FdbError fdb_future_get_string_array(FutureHandle future, out byte** strings, out int count);
public static FdbError FutureGetKey(FutureHandle future, out Slice key) { byte* ptr; int keyLength; var err = NativeMethods.fdb_future_get_key(future, out ptr, out keyLength); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_get_key(0x" + future.Handle.ToString("x") + ") => err=" + err + ", keyLength=" + keyLength); #endif // note: fdb_future_get_key is allowed to return NULL for the empty key (not to be confused with a key that has an empty value) Contract.Assert(keyLength >= 0 && keyLength <= Fdb.MaxKeySize); if (keyLength <= 0 || ptr == null) { // from the spec: "If a key selector would otherwise describe a key off the beginning of the database, it instead resolves to the empty key ''." key = Slice.Empty; } else { key = Slice.Create(ptr, keyLength); } return err; }
public static extern FdbError fdb_future_get_version(FutureHandle future, out long version);
public static FdbError FutureGetKeyValueArray(FutureHandle future, out KeyValuePair<Slice, Slice>[] result, out bool more) { result = null; int count; FdbKeyValue* kvp; var err = NativeMethods.fdb_future_get_keyvalue_array(future, out kvp, out count, out more); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_get_keyvalue_array(0x" + future.Handle.ToString("x") + ") => err=" + err + ", count=" + count + ", more=" + more); #endif if (Fdb.Success(err)) { Contract.Assert(count >= 0, "Return count was negative"); result = new KeyValuePair<Slice, Slice>[count]; if (count > 0) { // convert the keyvalue result into an array Contract.Assert(kvp != null, "We have results but array pointer was null"); // in order to reduce allocations, we want to merge all keys and values // into a single byte{] and return list of Slice that will // link to the different chunks of this buffer. // first pass to compute the total size needed int total = 0; for (int i = 0; i < count; i++) { //TODO: protect against negative values or values too big ? Contract.Assert(kvp[i].KeyLength >= 0 && kvp[i].ValueLength >= 0); total += kvp[i].KeyLength + kvp[i].ValueLength; } // allocate all memory in one chunk, and make the key/values point to it // Does fdb allocate all keys into a single buffer ? We could copy everything in one pass, // but it would rely on implementation details that could break at anytime... //TODO: protect against too much memory allocated ? // what would be a good max value? we need to at least be able to handle FDB_STREAMING_MODE_WANT_ALL var page = new byte[total]; int p = 0; for (int i = 0; i < result.Length; i++) { int kl = kvp[i].KeyLength; int vl = kvp[i].ValueLength; //TODO: some keys/values will be small (32 bytes or less) while other will be big //consider having to copy methods, optimized for each scenario ? Marshal.Copy(kvp[i].Key, page, p, kl); Marshal.Copy(kvp[i].Value, page, p + kl, vl); result[i] = new KeyValuePair<Slice, Slice>( new Slice(page, p, kl), new Slice(page, p + kl, vl) ); p += kl + vl; } Contract.Assert(p == total); } } return err; }
public static FdbError FutureGetStringArray(FutureHandle future, out string[] result) { result = null; int count; byte** strings; var err = NativeMethods.fdb_future_get_string_array(future, out strings, out count); #if DEBUG_NATIVE_CALLS Debug.WriteLine("fdb_future_get_string_array(0x" + future.Handle.ToString("x") + ") => err=" + err + ", count=" + count); #endif if (Fdb.Success(err)) { Contract.Assert(count >= 0, "Return count was negative"); result = new string[count]; if (count > 0) { // convert the keyvalue result into an array Contract.Assert(strings != null, "We have results but array pointer was null"); //TODO: if pointers are corrupted, or memory is garbled, we could very well walk around the heap, randomly copying a bunch of stuff (like passwords or jpegs of cats...) // there is no real way to ensure that pointers are valid, except maybe having a maximum valid size for strings, and they should probably only contain legible text ? for (int i = 0; i < result.Length; i++) { result[i] = ToManagedString(strings[i]); } } } return err; }
private static bool TryGetValueResult(FutureHandle h, out Slice result) { Contract.Requires(h != null); bool present; var err = FdbNative.FutureGetValue(h, out present, out result); #if DEBUG_TRANSACTIONS Debug.WriteLine("FdbTransaction[].TryGetValueResult() => err=" + err + ", present=" + present + ", valueLength=" + result.Count); #endif Fdb.DieOnError(err); return present; }
public static extern FdbError fdb_future_get_cluster(FutureHandle future, out ClusterHandle cluster);
private static Slice GetValueResultBytes(FutureHandle h) { Contract.Requires(h != null); Slice result; if (!TryGetValueResult(h, out result)) { return Slice.Nil; } return result; }
public static extern FdbError fdb_future_get_value(FutureHandle future, out bool present, out byte *value, out int valueLength);
public Task<Slice[]> GetValuesAsync(Slice[] keys, bool snapshot, CancellationToken cancellationToken) { Contract.Requires(keys != null); if (keys.Length == 0) return Task.FromResult(Slice.EmptySliceArray); var futures = new FutureHandle[keys.Length]; try { for (int i = 0; i < keys.Length; i++) { futures[i] = FdbNative.TransactionGet(m_handle, keys[i], snapshot); } } catch { for (int i = 0; i < keys.Length; i++) { if (futures[i] == null) break; futures[i].Dispose(); } throw; } return FdbFuture.CreateTaskFromHandleArray(futures, (h) => GetValueResultBytes(h), cancellationToken); }
public static extern FdbError fdb_future_get_keyvalue_array(FutureHandle future, out FdbKeyValue *kv, out int count, out bool more);
/// <summary>Create a new <see cref="FdbFutureSingle{T}"/> from an FDBFuture* pointer</summary> /// <typeparam name="T">Type of the result of the task</typeparam> /// <param name="handle">FDBFuture* pointer</param> /// <param name="selector">Func that will be called to get the result once the future completes (and did not fail)</param> /// <param name="ct">Optional cancellation token that can be used to cancel the future</param> /// <returns>Object that tracks the execution of the FDBFuture handle</returns> public static FdbFutureSingle <T> FromHandle <T>(FutureHandle handle, Func <FutureHandle, T> selector, CancellationToken ct) { return(new FdbFutureSingle <T>(handle, selector, ct)); }
public static void FutureCancel(FutureHandle futureHandle) { NativeMethods.fdb_future_cancel(futureHandle); }
public static FdbError FutureGetError(FutureHandle future) { return(NativeMethods.fdb_future_get_error(future)); }
public Task<Slice[]> GetKeysAsync(FdbKeySelector[] selectors, bool snapshot, CancellationToken cancellationToken) { Contract.Requires(selectors != null); var futures = new FutureHandle[selectors.Length]; try { for (int i = 0; i < selectors.Length; i++) { futures[i] = FdbNative.TransactionGetKey(m_handle, selectors[i], snapshot); } } catch { for (int i = 0; i < selectors.Length; i++) { if (futures[i] == null) break; futures[i].Dispose(); } throw; } return FdbFuture.CreateTaskFromHandleArray(futures, (h) => GetKeyResult(h), cancellationToken); }
public static extern FdbError fdb_future_get_value(FutureHandle future, out bool present, out byte* value, out int valueLength);
private static string[] GetStringArrayResult(FutureHandle h) { Contract.Requires(h != null); string[] result; var err = FdbNative.FutureGetStringArray(h, out result); #if DEBUG_TRANSACTIONS Debug.WriteLine("FdbTransaction[].FutureGetStringArray() => err=" + err + ", results=" + (result == null ? "<null>" : result.Length.ToString())); #endif Fdb.DieOnError(err); Contract.Ensures(result != null); // can only be null in case of an errror return result; }
public static bool FutureIsReady(FutureHandle futureHandle) { return NativeMethods.fdb_future_is_ready(futureHandle); }
public static FdbFutureSingle <T> FromHandle <T>([NotNull] FutureHandle handle, [NotNull] Func <FutureHandle, T> selector, CancellationToken cancellationToken) { return(new FdbFutureSingle <T>(handle, selector, cancellationToken)); }
public static extern FdbError fdb_future_get_keyvalue_array(FutureHandle future, out FdbKeyValue* kv, out int count, out bool more);
public static extern FdbError fdb_future_set_callback(FutureHandle future, FdbFutureCallback callback, IntPtr callbackParameter);
public static extern bool fdb_future_is_ready(FutureHandle futureHandle);
public static extern FdbError fdb_future_get_key(FutureHandle future, out byte *key, out int keyLength);
private static KeyValuePair<Slice, Slice>[] GetKeyValueArrayResult(FutureHandle h, out bool more) { KeyValuePair<Slice, Slice>[] result; var err = FdbNative.FutureGetKeyValueArray(h, out result, out more); Fdb.DieOnError(err); //note: result can only be null if an error occured! Contract.Ensures(result != null); return result; }
/// <summary>Wrap a FDBFuture* pointer into a <see cref="Task{T}"/></summary> /// <typeparam name="T">Type of the result of the task</typeparam> /// <param name="handle">FDBFuture* pointer</param> /// <param name="continuation">Lambda that will be called once the future completes successfully, to extract the result from the future handle.</param> /// <param name="ct">Optional cancellation token that can be used to cancel the future</param> /// <returns>Task that will either return the result of the continuation lambda, or an exception</returns> public static Task <T> CreateTaskFromHandle <T>(FutureHandle handle, Func <FutureHandle, T> continuation, CancellationToken ct) { return(new FdbFutureSingle <T>(handle, continuation, ct).Task); }
private static Slice GetKeyResult(FutureHandle h) { Contract.Requires(h != null); Slice result; var err = FdbNative.FutureGetKey(h, out result); #if DEBUG_TRANSACTIONS Debug.WriteLine("FdbTransaction[].GetKeyResult() => err=" + err + ", result=" + result.ToString()); #endif Fdb.DieOnError(err); return result; }