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 } }); }
public void IncrementVersion() { VersionKey = VersionGenerator.ConvertKeyToString(VersionGenerator.GenerateNextVersion(VersionGenerator.GetKeyFromString(VersionKey))); IsChanged = false; }