private void InitForksDict() { var rawForks = new Dictionary <int, ForkRawData>(); var forkIds = (List <int>)BinarySerializerHelper.DeserializeObject(Store.Get(Store.DefaultType, KeyGenerator.GenerateForksKey(AppId), null)); foreach (var forkId in forkIds) { rawForks[forkId] = ProtoBufSerializerHelper.Deserialize <ForkRawData>(Store.Get(Store.DefaultType, KeyGenerator.GenerateForkKey(AppId, forkId), null)); _forksTimeStamps[forkId] = (DateTime)BinarySerializerHelper.DeserializeObject(Store.Get(Store.DefaultType, KeyGenerator.GenerateForkTimeStampKey(AppId, forkId), null)); } var masterForks = rawForks.Where(x => x.Value.ParentId == 0).Select(x => x.Key).ToArray(); foreach (var masterFork in masterForks) { CreateFork(rawForks, masterFork); } }
public IDictionary <string, T> Get <T>(TDataTypesEnum type, IEnumerable <Tuple <string, object> > keys) { var currentFork = Fork; var missingKeys = keys.Select(x => x.Item1).ToList(); // Easy access to tuple data var keysDict = keys.ToDictionary(x => x.Item1, x => x.Item2); var res = new Dictionary <string, T>(); while (currentFork != null) { var keysForGet = new List <Tuple <string, object> >(); var generatedKeyToOriginalKey = new Dictionary <string, string>(); foreach (var key in missingKeys) { var generatedKey = KeyGenerator.GenerateForkValueKey(AppId, currentFork.Id, key); keysForGet.Add(Tuple.Create(generatedKey, keysDict[key])); generatedKeyToOriginalKey[generatedKey] = key; } var byteValues = KeyValueStore.Get(type, keysForGet); if (typeof(T) == typeof(byte[])) { foreach (var key in byteValues.Keys) { res[generatedKeyToOriginalKey[key]] = (T)Convert.ChangeType(byteValues[key], typeof(T)); } } else { foreach (var key in byteValues.Keys) { res[generatedKeyToOriginalKey[key]] = (T)BinarySerializerHelper.DeserializeObject(byteValues[key]); } } missingKeys = missingKeys.Except(byteValues.Keys.Select(x => generatedKeyToOriginalKey[x])).ToList(); var nullMissingKeys = new List <string>(); foreach (var missingKey in missingKeys.ToList()) { if (KeyValueStore.Exists(type, KeyGenerator.GenerateForkNullKey(AppId, currentFork.Id, missingKey), keysDict[missingKey])) { nullMissingKeys.Add(missingKey); } } missingKeys = missingKeys.Except(nullMissingKeys).ToList(); if (missingKeys.Count == 0) { break; } currentFork = currentFork.Parent; } return(res); }
private void UpdateForks() { var changedForkIds = new HashSet <int>(); var updatedForkIds = (List <int>)BinarySerializerHelper.DeserializeObject(Store.Get(Store.DefaultType, KeyGenerator.GenerateForksKey(AppId), null)); var newForkIds = updatedForkIds.Except(_forks.Keys); foreach (var newForkId in newForkIds) { var bytesNewRawFork = Store.Get(Store.DefaultType, KeyGenerator.GenerateForkKey(AppId, newForkId), null); if (bytesNewRawFork == null) { continue; } var newRawFork = ProtoBufSerializerHelper.Deserialize <ForkRawData>(bytesNewRawFork); var bytesNewForkTimeStamp = Store.Get(Store.DefaultType, KeyGenerator.GenerateForkTimeStampKey(AppId, newForkId), null); if (bytesNewForkTimeStamp == null) { continue; } var newForkTimeStamp = (DateTime)BinarySerializerHelper.DeserializeObject(bytesNewForkTimeStamp); var parentFork = newRawFork.ParentId == 0 ? null : _forks[newRawFork.ParentId]; var newFork = new Fork { Id = newForkId, Name = newRawFork.Name, Description = newRawFork.Description, IsInGracePeriod = newRawFork.IsInGracePeriod, Parent = parentFork }; if (parentFork != null) { parentFork.Children.Add(newFork); changedForkIds.Add(parentFork.Id); } _forks[newForkId] = newFork; _forksTimeStamps[newForkId] = newForkTimeStamp; } var toDel = _forks.Keys.Except(updatedForkIds).ToList(); foreach (var toDelFork in toDel) { _forks.Remove(toDelFork); _forksTimeStamps.Remove(toDelFork); } foreach (var forkId in _forks.Keys.ToList()) { var newTimeStamp = (DateTime)BinarySerializerHelper.DeserializeObject(Store.Get(Store.DefaultType, KeyGenerator.GenerateForkTimeStampKey(AppId, forkId), null)); var _currentForkTimeStamp = _forksTimeStamps[forkId]; if (newTimeStamp > _currentForkTimeStamp) { var rawFork = ProtoBufSerializerHelper.Deserialize <ForkRawData>(Store.Get(Store.DefaultType, KeyGenerator.GenerateForkKey(AppId, forkId), null)); _forksTimeStamps[forkId] = newTimeStamp; UpdateFork(_forks[forkId], rawFork); changedForkIds.Add(forkId); } } RaiseForkChanged(changedForkIds.ToList()); }
private void SetFork(ForkRawData fork) { KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.GenerateForkKey(AppId, fork.Id), ProtoBufSerializerHelper.Serialize(fork), null); KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.GenerateForkTimeStampKey(AppId, fork.Id), BinarySerializerHelper.SerializeObject(DateTime.UtcNow), null); }
private void SetForkIds(List <int> forkIds) { KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.GenerateForksKey(AppId), BinarySerializerHelper.SerializeObject(forkIds), null); }
private List <int> GetForkIds() { return((List <int>)BinarySerializerHelper.DeserializeObject(KeyValueStore.Get(KeyValueStore.DefaultType, KeyGenerator.GenerateForksKey(AppId), null))); }
/// <summary> /// Merge all the keys from one fork to another fork, a new fork is created from the target with the new data /// </summary> /// <param name="originForkId">Origin fork id</param> /// <param name="targetForkId">Target fork id</param> /// <returns>New fork id, Target fork id is the parent</returns> public int MergeFork(int originForkId, int targetForkId) { var usedKeys = new HashSet <string>(); var valuesToSet = new List <Tuple <string, TDataTypesEnum, byte[], object> >(); var keysToDelete = new Dictionary <string, TDataTypesEnum>(); var currentFork = ForkProvider.GetFork(originForkId); var targetFork = ForkProvider.GetFork(targetForkId); while (!IsCommonParent(currentFork, targetFork)) { if (currentFork == null) { throw new ArgumentException($"No common parents between {originForkId} and {targetForkId}"); } var forkPattern = KeyGenerator.GenerateForkValuePattern(AppId, currentFork.Id); var keys = KeyValueStore.Keys($"{forkPattern}*"); foreach (var key in keys) { var originalKey = key.Substring(forkPattern.Length); // If the key was used/deleted in a lower fork, this key is not relevant if (usedKeys.Contains(originalKey) || keysToDelete.ContainsKey(originalKey)) { continue; } if (originalKey.EndsWith(KeyGenerator.NullKeyPostFix)) { var type = (TDataTypesEnum)BinarySerializerHelper.DeserializeObject(KeyValueStore.Get(KeyValueStore.DefaultType, key, null)); keysToDelete.Add(originalKey.Substring(0, originalKey.Length - KeyGenerator.NullKeyPostFix.Length), type); } else { var keyDataCollection = KeyValueStore.GetKeyData(key); foreach (var keyData in keyDataCollection) { valuesToSet.Add(Tuple.Create(originalKey, keyData.Item1, keyData.Item2, keyData.Item3)); } usedKeys.Add(originalKey); } } currentFork = currentFork.Parent; } var newForkId = CreateFork($"{targetFork.Name} Merge", "", targetFork.Id); var wrapper = GetWrapper(newForkId); foreach (var keyToDelete in keysToDelete) { wrapper.Delete(keyToDelete.Value, keyToDelete.Key); } foreach (var value in valuesToSet) { wrapper.Set(value.Item2, value.Item1, value.Item3, value.Item4); } return(newForkId); }