예제 #1
0
        /// <summary>
        /// Transfers the data with the key and entry to the local store.
        /// </summary>
        /// <param name="entry"></param>
        /// <param name="value"></param>
        /// <param name="dht"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        async Task TransferAsync(IKsStoreEntry <TKey> entry, KsHashTableValue value, KsHashTableEntry dht, CancellationToken cancellationToken)
        {
            foreach (var uri in dht.Endpoints)
            {
                // we can't pull the value from ourselves, move to secondaries
                if (uri == options.Value.Uri)
                {
                    continue;
                }

                var client = clients.Get(uri);
                if (client == null)
                {
                    throw new KsException($"Could not obtain client for remote host: '{uri}'");
                }

                // existing token if we're resuming an operation after failure
                var t = await entry.GetOwnerTokenAsync(cancellationToken);

                var v = await client.ShiftLockAsync(entry.Key, t, cancellationToken);

                // current owner returns no value, must not really own it, nothing to transfer
                if (v == null)
                {
                    return;
                }

                // track down owner by following forwards
                while (v.Value.ForwardUri != null)
                {
                    client = clients.Get(v.Value.ForwardUri);
                    v      = await client.ShiftLockAsync(entry.Key, t, cancellationToken);
                }

                if (v.Value.Data == null)
                {
                    throw new KsException("Data not retrieved.");
                }
                if (v.Value.Data == null)
                {
                    throw new KsException("Data retrieved, but not token.");
                }

                // update local entry with latest information
                await entry.SetOwnerTokenAsync(t = v.Value.Token);

                await entry.SetAsync(v.Value.Data);

                // finalize shift on remote node and publish entry
                await client.ShiftAsync(entry.Key, t, options.Value.Uri, cancellationToken);

                await hashtable.AddAsync(entry.Key, new KsHashTableValue(Serialize(new KsHashTableEntry(new[] { options.Value.Uri })), value.Version + 1, TimeSpan.FromDays(1)));

                // we succeeded, exit loop
                break;
            }

            // zero out lock token if we successfully complete process
            await entry.SetOwnerTokenAsync(null);
        }
예제 #2
0
        async Task <KsHostShiftLockResult> ShiftLockAsyncImpl(IKsStoreEntry <TKey> entry, string token, CancellationToken cancellationToken)
        {
            // freeze
            var f = await entry.FreezeAsync(token, TimeSpan.FromSeconds(5), cancellationToken);

            if (f.ForwardUri != null)
            {
                return(new KsHostShiftLockResult(null, null, f.ForwardUri));
            }

            // get existing value
            var d = await entry.GetAsync(f.Token, cancellationToken);

            if (d.ForwardUri != null)
            {
                return(new KsHostShiftLockResult(null, null, d.ForwardUri));
            }

            return(new KsHostShiftLockResult(f.Token, d.Data, null));
        }
예제 #3
0
        async Task <byte[]> GetAsyncImpl(IKsStoreEntry <TKey> entry, CancellationToken cancellationToken)
        {
            var r = await entry.GetAsync(null, cancellationToken);

            return(r.Data);
        }
예제 #4
0
        async Task ShiftAsyncImpl(IKsStoreEntry <TKey> entry, string token, Uri forwardUri, CancellationToken cancellationToken)
        {
            await hashtable.RemoveAsync(entry.Key, CancellationToken.None);

            await entry.ForwardAsync(token, forwardUri, CancellationToken.None);
        }