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));
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        public Task <IFdbDatabaseHandler> OpenDatabaseAsync(string databaseName, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled <IFdbDatabaseHandler>(cancellationToken));
            }

            var future = FdbNative.ClusterCreateDatabase(m_handle, databaseName);

            return(FdbFuture.CreateTaskFromHandle(
                       future,
                       (h) =>
            {
                DatabaseHandle database;
                var err = FdbNative.FutureGetDatabase(h, out database);
                if (err != FdbError.Success)
                {
                    database.Dispose();
                    throw Fdb.MapToException(err);
                }
                var handler = new FdbNativeDatabase(database);
                return (IFdbDatabaseHandler)handler;
            },
                       cancellationToken
                       ));
        }
Beispiel #4
0
        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));
        }
Beispiel #5
0
 public Task <Slice> GetAsync(ReadOnlySpan <byte> key, bool snapshot, CancellationToken ct)
 {
     return(FdbFuture.CreateTaskFromHandle(
                FdbNative.TransactionGet(m_handle, key, snapshot),
                (h) => GetValueResultBytes(h),
                ct
                ));
 }
Beispiel #6
0
        public FdbWatch Watch(Slice key, CancellationToken ct)
        {
            var future = FdbNative.TransactionWatch(m_handle, key.Span);

            return(new FdbWatch(
                       FdbFuture.FromHandle <Slice>(future, (h) => key, ct),
                       key
                       ));
        }
Beispiel #7
0
 public Task <(FdbValueCheckResult Result, Slice Actual)> CheckValueAsync(ReadOnlySpan <byte> key, Slice expected, bool snapshot, CancellationToken ct)
 {
     return(FdbFuture.CreateTaskFromHandle(
                FdbNative.TransactionGet(m_handle, key, snapshot),
                (h) =>
     {
         if (TryPeekValueResultBytes(h, out var actual))
         {                         // key exists
             return !expected.IsNull && expected.Span.SequenceEqual(actual) ? (FdbValueCheckResult.Success, expected) : (FdbValueCheckResult.Failed, Slice.Copy(actual));
         }
Beispiel #8
0
        /// <inheritdoc />
        public Task <string[]> GetAddressesForKeyAsync(ReadOnlySpan <byte> key, CancellationToken ct)
        {
            var future = FdbNative.TransactionGetAddressesForKey(m_handle, key);

            return(FdbFuture.CreateTaskFromHandle(
                       future,
                       (h) => GetStringArrayResult(h),
                       ct
                       ));
        }
Beispiel #9
0
        public Task <Slice> GetKeyAsync(KeySelector selector, bool snapshot, CancellationToken ct)
        {
            var future = FdbNative.TransactionGetKey(m_handle, selector, snapshot);

            return(FdbFuture.CreateTaskFromHandle(
                       future,
                       (h) => GetKeyResult(h),
                       ct
                       ));
        }
        private static async ValueTask <IFdbDatabaseHandler> CreateDatabaseLegacyAsync(string?clusterFile, CancellationToken ct)
        {
            // In legacy API versions, you first had to create "cluster" handle and then obtain a database handle that that cluster.
            // The API is async, but the future always completed inline...

            ClusterHandle? cluster  = null;
            DatabaseHandle?database = null;

            try
            {
                cluster = await FdbFuture.CreateTaskFromHandle(
                    FdbNative.CreateCluster(clusterFile),
                    h =>
                {
                    var err = FdbNative.FutureGetCluster(h, out var handle);
                    if (Fdb.Failed(err))
                    {
                        throw Fdb.MapToException(err) !;
                    }

                    return(handle);
                },
                    ct).ConfigureAwait(false);

                database = await FdbFuture.CreateTaskFromHandle(
                    FdbNative.ClusterCreateDatabase(cluster, "DB"),
                    h =>
                {
                    var err = FdbNative.FutureGetDatabase(h, out var handle);
                    if (Fdb.Failed(err))
                    {
                        throw Fdb.MapToException(err) !;
                    }

                    return(handle);
                },
                    ct).ConfigureAwait(false);

                return(new FdbNativeDatabase(database, clusterFile, cluster));
            }
            catch (Exception)
            {
                database?.Dispose();
                cluster?.Dispose();
                throw;
            }
        }
Beispiel #11
0
        public Task <long> GetReadVersionAsync(CancellationToken ct)
        {
            var future = FdbNative.TransactionGetReadVersion(m_handle);

            return(FdbFuture.CreateTaskFromHandle(future,
                                                  (h) =>
            {
                var err = FdbNative.FutureGetVersion(h, out long version);
#if DEBUG_TRANSACTIONS
                Debug.WriteLine("FdbTransaction[" + m_id + "].GetReadVersion() => err=" + err + ", version=" + version);
#endif
                Fdb.DieOnError(err);
                return version;
            },
                                                  ct
                                                  ));
        }
Beispiel #12
0
        /// <summary>Asynchronously fetch a new page of results</summary>
        /// <returns>True if Chunk contains a new page of results. False if all results have been read.</returns>
        public Task <FdbRangeChunk> GetRangeAsync(KeySelector begin, KeySelector end, FdbRangeOptions options, int iteration, bool snapshot, CancellationToken ct)
        {
            Contract.Requires(options != null);

            bool reversed = options.Reverse ?? false;
            var  future   = FdbNative.TransactionGetRange(m_handle, begin, end, options.Limit ?? 0, options.TargetBytes ?? 0, options.Mode ?? FdbStreamingMode.Iterator, iteration, snapshot, reversed);

            return(FdbFuture.CreateTaskFromHandle(
                       future,
                       (h) =>
            {
                var mode = options.Read ?? FdbReadMode.Both;
                KeyValuePair <Slice, Slice>[] items;
                bool hasMore;
                Slice first, last;
                switch (mode)
                {
                case FdbReadMode.Both:
                    {
                        items = GetKeyValueArrayResult(h, out hasMore, out first, out last);
                        break;
                    }

                case FdbReadMode.Keys:
                    {
                        items = GetKeyValueArrayResultKeysOnly(h, out hasMore, out first, out last);
                        break;
                    }

                case FdbReadMode.Values:
                    {
                        items = GetKeyValueArrayResultValuesOnly(h, out hasMore, out first, out last);
                        break;
                    }

                default:
                    {
                        throw new InvalidOperationException();
                    }
                }
                return new FdbRangeChunk(items, hasMore, iteration, reversed, mode, first, last);
            },
                       ct
                       ));
        }
Beispiel #13
0
        /// <summary>Asynchronously fetch a new page of results</summary>
        /// <returns>True if Chunk contains a new page of results. False if all results have been read.</returns>
        public Task <FdbRangeChunk> GetRangeAsync(KeySelector begin, KeySelector end, FdbRangeOptions options, int iteration, bool snapshot, CancellationToken ct)
        {
            Contract.Requires(options != null);

            bool reversed = options.Reverse ?? false;
            var  future   = FdbNative.TransactionGetRange(m_handle, begin, end, options.Limit ?? 0, options.TargetBytes ?? 0, options.Mode ?? FdbStreamingMode.Iterator, iteration, snapshot, reversed);

            return(FdbFuture.CreateTaskFromHandle(
                       future,
                       (h) =>
            {
                // TODO: quietly return if disposed
                var chunk = GetKeyValueArrayResult(h, out bool hasMore);
                return new FdbRangeChunk(hasMore, chunk, iteration, reversed);
            },
                       ct
                       ));
        }
        public static Task <IFdbClusterHandler> CreateClusterAsync(string clusterFile, CancellationToken ct)
        {
            var future = FdbNative.CreateCluster(clusterFile);

            return(FdbFuture.CreateTaskFromHandle(future,
                                                  (h) =>
            {
                var err = FdbNative.FutureGetCluster(h, out ClusterHandle cluster);
                if (err != FdbError.Success)
                {
                    cluster.Dispose();
                    throw Fdb.MapToException(err);
                }
                var handler = new FdbNativeCluster(cluster);
                return (IFdbClusterHandler)handler;
            },
                                                  ct
                                                  ));
        }
Beispiel #15
0
        /// <summary>Asynchronously fetch a new page of results</summary>
        /// <returns>True if Chunk contains a new page of results. False if all results have been read.</returns>
        public Task <FdbRangeChunk> GetRangeAsync(KeySelector begin, KeySelector end, int limit, bool reversed, int targetBytes, FdbStreamingMode mode, FdbReadMode read, int iteration, bool snapshot, CancellationToken ct)
        {
            var future = FdbNative.TransactionGetRange(m_handle, begin, end, limit, targetBytes, mode, iteration, snapshot, reversed);

            return(FdbFuture.CreateTaskFromHandle(
                       future,
                       (h) =>
            {
                KeyValuePair <Slice, Slice>[] items;
                bool hasMore;
                Slice first, last;
                switch (read)
                {
                case FdbReadMode.Both:
                    {
                        items = GetKeyValueArrayResult(h, out hasMore, out first, out last);
                        break;
                    }

                case FdbReadMode.Keys:
                    {
                        items = GetKeyValueArrayResultKeysOnly(h, out hasMore, out first, out last);
                        break;
                    }

                case FdbReadMode.Values:
                    {
                        items = GetKeyValueArrayResultValuesOnly(h, out hasMore, out first, out last);
                        break;
                    }

                default:
                    {
                        throw new InvalidOperationException();
                    }
                }
                return new FdbRangeChunk(items, hasMore, iteration, reversed, read, first, last);
            },
                       ct
                       ));
        }
Beispiel #16
0
        /// <inheritdoc />
        public Task <long> GetApproximateSizeAsync(CancellationToken ct)
        {
            // API was introduced in 6.2
            if (Fdb.ApiVersion < 620)
            {
                throw new NotSupportedException($"The GetApproximateSize method is only available for version 6.2 or greater. Your application has selected API version {Fdb.ApiVersion} which is too low. You willl need to select API version 620 or greater.");
            }
            //TODO: for lesser version, maybe we could return our own estimation?

            var future = FdbNative.TransactionGetReadVersion(m_handle);

            return(FdbFuture.CreateTaskFromHandle(future,
                                                  (h) =>
            {
                var err = FdbNative.FutureGetInt64(h, out long size);
#if DEBUG_TRANSACTIONS
                Debug.WriteLine("FdbTransaction[" + m_id + "].GetApproximateSize() => err=" + err + ", size=" + size);
#endif
                Fdb.DieOnError(err);
                return size;
            },
                                                  ct
                                                  ));
        }
Beispiel #17
0
        public Task OnErrorAsync(FdbError code, CancellationToken ct)
        {
            var future = FdbNative.TransactionOnError(m_handle, code);

            return(FdbFuture.CreateTaskFromHandle <object?>(future, (h) => { ResetInternal(); return null; }, ct));
        }
Beispiel #18
0
        /// <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));
        }
Beispiel #19
0
        public Task <VersionStamp> GetVersionStampAsync(CancellationToken ct)
        {
            var future = FdbNative.TransactionGetVersionStamp(m_handle);

            return(FdbFuture.CreateTaskFromHandle <VersionStamp>(future, GetVersionStampResult, ct));
        }
        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));
        }