Example #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);
        }
Example #2
0
 /// <summary>
 /// Serializes the entry information.
 /// </summary>
 /// <param name="entry"></param>
 /// <returns></returns>
 byte[] Serialize(KsHashTableEntry entry)
 {
     return(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(entry)));
 }