public PutResult Put(PutRequest request)
        {
            var hash     = GetSha256Hash(request);
            var versions = GatherActiveVersions(request.Key);

            if (versions.Length == 1)
            {
                // Test that the key doesn't already exist with matching value
                var values = Get(new GetRequest {
                    Key = request.Key, SpecifiedVersion = versions[0]
                });
                if (values.Length == 1 && values[0].Sha256Hash.SequenceEqual(hash))
                {
                    return(new PutResult
                    {
                        ConflictExists = false,
                        Version = versions[0]
                    });
                }
            }

            // we always accept read only put requests, because
            // we assume that there can never be a conflict with them
            // since they are read only values.
            var doesAllVersionsMatch =
                request.IsReadOnly
                                        ?
                request.IsReadOnly
                                        :
                DoesAllVersionsMatch(request.Key, request.ParentVersions);

            if (doesAllVersionsMatch == false &&
                request.OptimisticConcurrency)
            {
                return(new PutResult
                {
                    ConflictExists = true,
                    Version = null
                });
            }

            // always remove the active versions from the cache
            commitSyncronization.Add(() => cache.Remove(GetKey(request.Key)));
            if (doesAllVersionsMatch)
            {
                // we only remove existing versions from the
                // cache if we delete them from the database
                foreach (var parentVersion in versions)
                {
                    var copy = parentVersion;
                    commitSyncronization.Add(() => cache.Remove(GetKey(request.Key, copy)));
                }
                DeleteAllKeyValuesForVersions(request.Key, versions);
            }

            var instanceIdForRow = instanceId;

            if (request.ReplicationVersion != null)
            {
                instanceIdForRow = request.ReplicationVersion.InstanceId;
            }

            var versionNumber = request.ReplicationVersion == null
                                                                        ? versionGenerator.GenerateNextVersion()
                                                                        : request.ReplicationVersion.Number;

            using (var update = new Update(session, keys, JET_prep.Insert))
            {
                Api.SetColumn(session, keys, keysColumns["key"], request.Key, Encoding.Unicode);

                Api.SetColumn(session, keys, keysColumns["version_instance_id"], instanceIdForRow.ToByteArray());
                Api.SetColumn(session, keys, keysColumns["version_number"], versionNumber);

                if (request.Tag.HasValue)
                {
                    Api.SetColumn(session, keys, keysColumns["tag"], request.Tag.Value);
                }

                if (request.ExpiresAt.HasValue)
                {
                    Api.SetColumn(session, keys, keysColumns["expiresAt"], request.ExpiresAt.Value.ToOADate());
                }

                update.Save();
            }

            using (var update = new Update(session, data, JET_prep.Insert))
            {
                Api.SetColumn(session, data, dataColumns["key"], request.Key, Encoding.Unicode);
                Api.SetColumn(session, data, dataColumns["version_number"], versionNumber);
                Api.SetColumn(session, data, dataColumns["version_instance_id"], instanceIdForRow.ToByteArray());
                Api.SetColumn(session, data, dataColumns["data"], request.Bytes);
                Api.SetColumn(session, data, dataColumns["sha256_hash"], hash);
                Api.SetColumn(session, data, dataColumns["readonly"], request.IsReadOnly);

                var timestamp = DateTime.Now.ToOADate();

                if (request.Tag.HasValue)
                {
                    Api.SetColumn(session, data, dataColumns["tag"], request.Tag.Value);
                }

                if (request.ReplicationTimeStamp.HasValue)
                {
                    timestamp = request.ReplicationTimeStamp.Value.ToOADate();
                }
                Api.SetColumn(session, data, dataColumns["timestamp"], timestamp);

                if (request.ExpiresAt.HasValue)
                {
                    Api.SetColumn(session, data, dataColumns["expiresAt"], request.ExpiresAt.Value.ToOADate());
                }

                WriteAllParentVersions(request.ParentVersions, data, dataColumns);

                update.Save();
            }

            return(new PutResult
            {
                ConflictExists = doesAllVersionsMatch == false,
                Version = new ValueVersion
                {
                    InstanceId = instanceIdForRow,
                    Number = versionNumber
                }
            });
        }
예제 #2
0
 public void IncrementVersion()
 {
     VersionKey = VersionGenerator.ConvertKeyToString(VersionGenerator.GenerateNextVersion(VersionGenerator.GetKeyFromString(VersionKey)));
     IsChanged  = false;
 }