/// <summary>
        /// Sets the app Id
        /// </summary>
        /// <param name="appId"></param>
        public void SetApp(int appId)
        {
            if (appId == 0)
            {
                throw new ArgumentException(nameof(appId));
            }

            //Check if app exists
            var        bytesAppIds = KeyValueStore.Get(KeyValueStore.DefaultType, KeyGenerator.AppsKey, null);
            List <int> appIds      = null;

            if (bytesAppIds != null)
            {
                appIds = (List <int>)BinarySerializerHelper.DeserializeObject(bytesAppIds);
            }

            if (appIds == null || !appIds.Contains(appId))
            {
                throw new ArgumentException($"{nameof(appId)} - doesn't exist");
            }

            AppId = appId;

            ForkProvider = new ForkProvider <TDataTypesEnum>(KeyValueStore, AppId);
        }
        public T Get <T>(TDataTypesEnum type, string key, object extraParams = null)
        {
            var currentFork = Fork;

            while (currentFork != null)
            {
                var byteValue = KeyValueStore.Get(type, KeyGenerator.GenerateForkValueKey(AppId, currentFork.Id, key), extraParams);

                if (byteValue != null)
                {
                    if (typeof(T) == typeof(byte[]))
                    {
                        return((T)Convert.ChangeType(byteValue, typeof(T)));
                    }

                    return((T)BinarySerializerHelper.DeserializeObject(byteValue));
                }

                if (KeyValueStore.Exists(type, KeyGenerator.GenerateForkNullKey(AppId, currentFork.Id, key), null))
                {
                    return(default(T));
                }

                currentFork = currentFork.Parent;
            }

            return(default(T));
        }
        public List <DTOs.App> GetApps()
        {
            var        bytesAppIds = KeyValueStore.Get(KeyValueStore.DefaultType, KeyGenerator.AppsKey, null);
            List <int> appIds      = null;

            if (bytesAppIds == null)
            {
                return(new List <DTOs.App>());
            }

            appIds = (List <int>)BinarySerializerHelper.DeserializeObject(bytesAppIds);

            var res = new List <DTOs.App>();

            foreach (var appId in appIds)
            {
                var bytesApp = KeyValueStore.Get(KeyValueStore.DefaultType, KeyGenerator.GenerateAppKey(appId), null);
                if (bytesApp == null)
                {
                    continue;
                }

                var app = ProtoBufSerializerHelper.Deserialize <App>(bytesApp);

                res.Add(new DTOs.App
                {
                    Id          = app.Id,
                    Name        = app.Name,
                    Description = app.Description
                });
            }

            return(res);
        }
        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);
            }
        }
예제 #5
0
        public void StackExchangeRedisKeyValueStore_String()
        {
            var store = new StackExchangeRedisKeyValueStore("localhost:6379");

            store.Set(StackExchangeRedisDataTypesEnum.String, "testKey1", BinarySerializerHelper.SerializeObject(123));
            var res = (int)BinarySerializerHelper.DeserializeObject(store.Get(StackExchangeRedisDataTypesEnum.String, "testKey1"));

            Assert.AreEqual(123, res);

            store.Set(StackExchangeRedisDataTypesEnum.String, new List <Tuple <string, byte[], object> >
            {
                Tuple.Create <string, byte[], object>("testKey1_1", BinarySerializerHelper.SerializeObject(1), null),
                Tuple.Create <string, byte[], object>("testKey1_2", BinarySerializerHelper.SerializeObject(2), null),
                Tuple.Create <string, byte[], object>("testKey1_3", BinarySerializerHelper.SerializeObject(3), null)
            });

            var multipleRes = store.Get(StackExchangeRedisDataTypesEnum.String, new List <Tuple <string, object> >
            {
                Tuple.Create <string, object>("testKey1_1", null),
                Tuple.Create <string, object>("testKey1_2", null),
                Tuple.Create <string, object>("testKey1_3", null)
            });

            Assert.AreEqual(1, (int)BinarySerializerHelper.DeserializeObject(multipleRes["testKey1_1"]));
            Assert.AreEqual(2, (int)BinarySerializerHelper.DeserializeObject(multipleRes["testKey1_2"]));
            Assert.AreEqual(3, (int)BinarySerializerHelper.DeserializeObject(multipleRes["testKey1_3"]));


            store.Delete(StackExchangeRedisDataTypesEnum.String, new List <Tuple <string, object> >
            {
                Tuple.Create <string, object>("testKey1_1", null),
                Tuple.Create <string, object>("testKey1_2", null)
            });

            multipleRes = store.Get(StackExchangeRedisDataTypesEnum.String, new List <Tuple <string, object> >
            {
                Tuple.Create <string, object>("testKey1_1", null),
                Tuple.Create <string, object>("testKey1_2", null),
                Tuple.Create <string, object>("testKey1_3", null)
            });

            Assert.AreEqual(3, (int)BinarySerializerHelper.DeserializeObject(multipleRes["testKey1_3"]));
            Assert.AreEqual(1, multipleRes.Count);
        }
        /// <summary>
        /// Creates a new app and a master fork
        /// On success sets the app id
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="name"></param>
        /// <param name="description"></param>
        public void CreateApp(int appId, string name, string description)
        {
            var        bytesAppIds = KeyValueStore.Get(KeyValueStore.DefaultType, KeyGenerator.AppsKey, null);
            List <int> appIds      = null;

            if (bytesAppIds != null)
            {
                appIds = (List <int>)BinarySerializerHelper.DeserializeObject(bytesAppIds);
            }
            else
            {
                appIds = new List <int>();
                KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.AppsKey, BinarySerializerHelper.SerializeObject(appIds), null);
            }

            if (appIds.Contains(appId))
            {
                throw new ArgumentException(nameof(appId));
            }

            appIds.Add(appId);

            KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.AppsKey, BinarySerializerHelper.SerializeObject(appIds), null);

            var res = new App
            {
                Id          = appId,
                Name        = name,
                Description = description
            };

            KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.GenerateAppKey(appId), ProtoBufSerializerHelper.Serialize(res), null);
            KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.GenerateForksKey(appId), BinarySerializerHelper.SerializeObject(new List <int>()), null);

            SetApp(appId);

            CreateMasterFork();
        }
예제 #7
0
        public void StackExchangeRedisKeyValueStore_Hash()
        {
            var store = new StackExchangeRedisKeyValueStore("localhost:6379");

            store.Set(StackExchangeRedisDataTypesEnum.Hash, "testKey2", BinarySerializerHelper.SerializeObject(123), new StackExchangeRedisHashParams {
                HashField = "testKey2Hash"
            });
            var res = (int)BinarySerializerHelper.DeserializeObject(store.Get(StackExchangeRedisDataTypesEnum.Hash, "testKey2", new StackExchangeRedisHashParams {
                HashField = "testKey2Hash"
            }));

            Assert.AreEqual(123, res);

            store.Set(StackExchangeRedisDataTypesEnum.Hash, new List <Tuple <string, byte[], object> >
            {
                Tuple.Create <string, byte[], object>("testKey2_1", BinarySerializerHelper.SerializeObject(4), new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_1"
                }),
                Tuple.Create <string, byte[], object>("testKey2_1", BinarySerializerHelper.SerializeObject(5), new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_2"
                }),
                Tuple.Create <string, byte[], object>("testKey2_1", BinarySerializerHelper.SerializeObject(6), new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_3"
                })
            });

            var multipleRes = store.Get(StackExchangeRedisDataTypesEnum.Hash, new List <Tuple <string, object> >
            {
                Tuple.Create <string, object>("testKey2_1", new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_1"
                }),
                Tuple.Create <string, object>("testKey2_1", new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_2"
                }),
                Tuple.Create <string, object>("testKey2_1", new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_3"
                })
            });

            Assert.AreEqual(4, (int)BinarySerializerHelper.DeserializeObject(multipleRes["testKey2_1_1"]));
            Assert.AreEqual(5, (int)BinarySerializerHelper.DeserializeObject(multipleRes["testKey2_1_2"]));
            Assert.AreEqual(6, (int)BinarySerializerHelper.DeserializeObject(multipleRes["testKey2_1_3"]));


            store.Delete(StackExchangeRedisDataTypesEnum.Hash, new List <Tuple <string, object> >
            {
                Tuple.Create <string, object>("testKey2_1", new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_2"
                }),
                Tuple.Create <string, object>("testKey2_1", new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_3"
                })
            });
            multipleRes = store.Get(StackExchangeRedisDataTypesEnum.Hash, new List <Tuple <string, object> >
            {
                Tuple.Create <string, object>("testKey2_1", new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_1"
                }),
                Tuple.Create <string, object>("testKey2_1", new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_2"
                }),
                Tuple.Create <string, object>("testKey2_1", new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_3"
                })
            });

            Assert.AreEqual(4, (int)BinarySerializerHelper.DeserializeObject(multipleRes["testKey2_1_1"]));
            Assert.AreEqual(1, multipleRes.Count);

            store.Delete(StackExchangeRedisDataTypesEnum.Hash, "testKey2_1", null);
            multipleRes = store.Get(StackExchangeRedisDataTypesEnum.Hash, new List <Tuple <string, object> >
            {
                Tuple.Create <string, object>("testKey2_1", new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_1"
                }),
                Tuple.Create <string, object>("testKey2_1", new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_2"
                }),
                Tuple.Create <string, object>("testKey2_1", new StackExchangeRedisHashParams {
                    HashField = "testKey2_1_3"
                })
            });
            Assert.AreEqual(0, multipleRes.Count);
        }
        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 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);
        }