示例#1
0
        public ClientSideTypeDescription RegisterType(Type type, bool forceReindex = false)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }


            var typeDescription = ClientSideTypeDescription.RegisterType(type);

            KnownTypes[typeDescription.FullTypeName] = typeDescription;


            var request = new RegisterTypeRequest(typeDescription.AsTypeDescription, ShardIndex, ShardsCount);

            var response = Channel.SendRequest(request);

            if (response is ExceptionResponse exResponse)
            {
                throw new CacheException("Error while registering a type on the server", exResponse.Message,
                                         exResponse.CallStack);
            }

            return(typeDescription);
        }
示例#2
0
        /// <summary>
        ///     Explicitly registers a type on the client and the server. In order to use this version of the method
        ///     the type need to be tagged(attributes need to be associated to its public properties used as keys)
        ///     Explicit type registration is not required.
        ///     It is done automatically when the first Put() is executed for an item of the specified type
        ///     or when a query is first built
        ///     <br />
        ///     As type registration is an expensive operation, you may want to do it during the client initialization.
        /// </summary>
        /// <param name="type"></param>
        public ClientSideTypeDescription RegisterTypeIfNeeded(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (KnownTypes.TryGetValue(type.FullName ?? throw new InvalidOperationException(), out var typeDescription))
            {
                return(typeDescription);
            }

            typeDescription = ClientSideTypeDescription.RegisterType(type);
            KnownTypes[typeDescription.FullTypeName] = typeDescription;


            var request = new RegisterTypeRequest(typeDescription.AsTypeDescription, ShardIndex, ShardsCount);

            var response = Channel.SendRequest(request);

            if (response is ExceptionResponse exResponse)
            {
                throw new CacheException("Error while registering a type on the server", exResponse.Message,
                                         exResponse.CallStack);
            }

            return(typeDescription);
        }
示例#3
0
        public void InitializeFromDump(string path)
        {
            path = DumpHelper.NormalizeDumpPath(path);

            var schemaPath = Path.Combine(path, "schema.json");

            var json = File.ReadAllText(schemaPath);

            var schema = SerializationHelper.DeserializeJson <Schema>(json);

            foreach (var typeDescription in schema.TypeDescriptions)
            {
                // register the type on the server

                var shard = 0;
                foreach (var client in CacheClients)
                {
                    var request = new RegisterTypeRequest(typeDescription, shard, CacheClients.Count);

                    var response = client.Channel.SendRequest(request);

                    if (response is ExceptionResponse exResponse)
                    {
                        throw new CacheException("Error while registering a type on the server", exResponse.Message,
                                                 exResponse.CallStack);
                    }

                    shard++;
                }

                FeedMany(DumpHelper.ObjectsInDump(path, typeDescription), true);
            }

            // reinitialize the sequences. As the shard count has probably changed reinitialize all the sequences in each shard
            // starting with the maximum value

            var maxValues = new Dictionary <string, int>();

            var files = Directory.EnumerateFiles(path, "sequence_*.json");

            foreach (var file in files)
            {
                var sequenceJson = File.ReadAllText(file);
                var seq          = SerializationHelper.DeserializeJson <Dictionary <string, int> >(sequenceJson);
                foreach (var pair in seq)
                {
                    var keyFound = maxValues.ContainsKey(pair.Key);
                    if (keyFound && maxValues[pair.Key] < pair.Value || !keyFound)
                    {
                        maxValues[pair.Key] = pair.Value;
                    }
                }
            }

            // resync sequences on the server

            ResyncUniqueIds(maxValues);
        }
        public void StreamUnstreamMessagesOneByOne()
        {
            var schema = TypedSchemaFactory.FromType(typeof(CacheableTypeOk));

            var qbuilder = new QueryBuilder(typeof(CacheableTypeOk));

            var put  = new PutRequest(typeof(CacheableTypeOk));
            var item = new CacheableTypeOk(3, 1003, "AHA", new DateTime(2010, 10, 02), 8);

            var typeDescription =
                TypedSchemaFactory.FromType(typeof(CacheableTypeOk));

            put.Items.Add(PackedObject.Pack(item, schema));

            var remove = new RemoveRequest(typeof(CacheableTypeOk), new KeyValue(1, schema.PrimaryKeyField));

            var register = new RegisterTypeRequest(typeDescription);

            using (var stream = new MemoryStream())
            {
                //request
                Streamer.ToStream(stream, new GetRequest(qbuilder.FromSql("select from CacheableTypeOk where IndexKeyValue > 1000")));
                Streamer.ToStream(stream, put);
                Streamer.ToStream(stream, remove);
                Streamer.ToStream(stream, register);

                //response
                Streamer.ToStream(stream, new NullResponse());
                Streamer.ToStream(stream, new ExceptionResponse(new Exception("fake exception")));
                Streamer.ToStream(stream, new ServerDescriptionResponse());

                stream.Seek(0, SeekOrigin.Begin);
                object reloaded = Streamer.FromStream <Request>(stream);
                Assert.IsTrue(reloaded is GetRequest);

                //request
                reloaded = Streamer.FromStream <Request>(stream);
                Assert.IsTrue(reloaded is PutRequest);

                reloaded = Streamer.FromStream <Request>(stream);
                Assert.IsTrue(reloaded is RemoveRequest);

                reloaded = Streamer.FromStream <Request>(stream);
                Assert.IsTrue(reloaded is RegisterTypeRequest);

                ////response
                reloaded = Streamer.FromStream <Response>(stream);
                Assert.IsTrue(reloaded is NullResponse);

                reloaded = Streamer.FromStream <Response>(stream);
                Assert.IsTrue(reloaded is ExceptionResponse);

                reloaded = Streamer.FromStream <Response>(stream);
                Assert.IsTrue(reloaded is ServerDescriptionResponse);
            }
        }
示例#5
0
        /// <summary>
        ///     Creates the associated <see cref="DataStore" /> for new cacheable type
        /// </summary>
        /// <param name="request"></param>
        /// <param name="client"></param>
        private void RegisterType(RegisterTypeRequest request, IClient client)
        {
            try
            {
                var typeDescription = request.CollectionSchema;

                var collectionName = typeDescription.CollectionName;

                var dataStore = DataStores.TryGetValue(collectionName);


                if (ShardCount == 0) // not initialized
                {
                    ShardIndex = request.ShardIndex;
                    ShardCount = request.ShardsInCluster;
                }
                else // check it didn't change
                {
                    if (ShardIndex != request.ShardIndex || ShardCount != request.ShardsInCluster)
                    {
                        throw new NotSupportedException(
                                  $"Cluster configuration changed. This node was shard {ShardIndex} / {ShardCount} and now is {request.ShardIndex} / {request.ShardsInCluster}");
                    }
                }

                if (dataStore != null) //type already registered
                {
                    //if the type description changed reindex
                    if (!typeDescription.Equals(dataStore.CollectionSchema))
                    {
                        var newDataStore = DataStore.Reindex(dataStore, typeDescription);

                        DataStores[collectionName] = newDataStore;

                        _serviceContainer.SchemaPersistence.SaveSchema(GenerateSchema());
                    }
                }
                else // new type, store it in the type dictionary and initialize its DataStore
                {
                    var newDataStore =
                        new DataStore(typeDescription, new NullEvictionPolicy(), _serviceContainer.NodeConfig.FullTextConfig);


                    DataStores.Add(collectionName, newDataStore);

                    _serviceContainer.SchemaPersistence.SaveSchema(GenerateSchema());
                }

                client?.SendResponse(new NullResponse());
            }
            catch (Exception e)
            {
                client?.SendResponse(new ExceptionResponse(e));
            }
        }
示例#6
0
 /// <summary>
 ///     Creates the associated <see cref="DataStore" /> for new cacheable type
 /// </summary>
 /// <param name="request"></param>
 /// <param name="client"></param>
 private void RegisterType(RegisterTypeRequest request, IClient client)
 {
     if (client != null) // client request
     {
         ProcessRegisterType(request, client);
     }
     else // called internally (while loading data)
     {
         InternalProcessRegisterType(request);
     }
 }
示例#7
0
        public void StreamUnstreamMessagesOneByOne()
        {
            QueryBuilder qbuilder = new QueryBuilder(typeof(CacheableTypeOk));

            PutRequest      put  = new PutRequest(typeof(CacheableTypeOk));
            CacheableTypeOk item = new CacheableTypeOk(3, 1003, "AHA", new DateTime(2010, 10, 02), 8);

            TypeDescription typeDescription =
                ClientSideTypeDescription.RegisterType(typeof(CacheableTypeOk)).AsTypeDescription;

            put.Items.Add(CachedObject.Pack(item));

            RemoveRequest remove = new RemoveRequest(typeof(CacheableTypeOk), typeDescription.MakePrimaryKeyValue(1));

            RegisterTypeRequest register = new RegisterTypeRequest(typeDescription);

            using (MemoryStream stream = new MemoryStream())
            {
                //request
                Streamer.ToStream(stream, new GetRequest(qbuilder.GetManyWhere("IndexKeyValue > 1000")));
                Streamer.ToStream(stream, put);
                Streamer.ToStream(stream, remove);
                Streamer.ToStream(stream, register);

                //response
                Streamer.ToStream(stream, new NullResponse());
                Streamer.ToStream(stream, new ExceptionResponse(new Exception("fake exception")));
                Streamer.ToStream(stream, new ServerDescriptionResponse());

                stream.Seek(0, SeekOrigin.Begin);
                object reloaded = Streamer.FromStream <Request>(stream);
                Assert.IsTrue(reloaded is GetRequest);

                //request
                reloaded = Streamer.FromStream <Request>(stream);
                Assert.IsTrue(reloaded is PutRequest);

                reloaded = Streamer.FromStream <Request>(stream);
                Assert.IsTrue(reloaded is RemoveRequest);

                reloaded = Streamer.FromStream <Request>(stream);
                Assert.IsTrue(reloaded is RegisterTypeRequest);

                ////response
                reloaded = Streamer.FromStream <Response>(stream);
                Assert.IsTrue(reloaded is NullResponse);

                reloaded = Streamer.FromStream <Response>(stream);
                Assert.IsTrue(reloaded is ExceptionResponse);

                reloaded = Streamer.FromStream <Response>(stream);
                Assert.IsTrue(reloaded is ServerDescriptionResponse);
            }
        }
示例#8
0
        private void InternalProcessRegisterType(RegisterTypeRequest request)
        {
            var typeDescription = request.TypeDescription;

            if (ShardCount == 0) // not initialized
            {
                ShardIndex = request.ShardIndex;
                ShardCount = request.ShardsInCluster;
            }
            else // check it didn't change
            {
                if (ShardIndex != request.ShardIndex || ShardCount != request.ShardsInCluster)
                {
                    throw new NotSupportedException(
                              $"Cluster configuration changed. This node was shard {ShardIndex} / {ShardCount} and now is {request.ShardIndex} / {request.ShardsInCluster}");
                }
            }

            if (_knownTypes.ContainsKey(typeDescription.FullTypeName)) //type already registered
            {
                //check that the type description is the same
                if (!typeDescription.Equals(_knownTypes[typeDescription.FullTypeName]))
                {
                    var message =
                        $"The type {typeDescription.FullTypeName} is already registered but the type description is different";
                    throw new NotSupportedException(message);
                }
            }
            else // new type, store it in the type dictionary and initialize its DataStore
            {
                _knownTypes.Add(typeDescription.FullTypeName, typeDescription);

                PersistenceEngine?.UpdateSchema(GenerateSchema());


                var cfg = Config.ConfigByType.ContainsKey(typeDescription.FullTypeName)
                    ? Config.ConfigByType[typeDescription.FullTypeName]
                    : new ServerDatastoreConfig();

                var evictionPolicy = EvictionPolicyFactory.CreateEvictionPolicy(cfg.Eviction);

                var newDataStore =
                    new DataStore(typeDescription, evictionPolicy);


                Dbg.CheckThat(Profiler != null);

                newDataStore.Profiler = Profiler;
                DataStores.Add(typeDescription.FullTypeName, newDataStore);
            }
        }
示例#9
0
 private void ProcessRegisterType(RegisterTypeRequest request, IClient client)
 {
     lock (DataStores)
     {
         try
         {
             InternalProcessRegisterType(request);
             client.SendResponse(new NullResponse());
         }
         catch (Exception e)
         {
             client.SendResponse(new ExceptionResponse(e));
         }
     }
 }
示例#10
0
        public void DeclareCollection(string collectionName, CollectionSchema schema, int shard = -1)
        {
            // do not modify the original
            schema = schema.Clone();

            schema.CollectionName = collectionName;

            var request = new RegisterTypeRequest(schema, shard == -1 ? ShardIndex:shard, ShardsCount);

            var response = Channel.SendRequest(request);

            if (response is ExceptionResponse exResponse)
            {
                throw new CacheException("Error while registering a type on the server", exResponse.Message,
                                         exResponse.CallStack);
            }
        }
示例#11
0
        /// <summary>
        ///     Register a type as cacheable with an external description
        ///     Cacheable type descriptions can be provided by attributes on the public properties
        ///     or as <see cref="TypeDescriptionConfig" />.
        ///     If an external description is required, the type must be explicitly registered.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="description"></param>
        public ClientSideTypeDescription RegisterTypeIfNeeded(Type type, TypeDescriptionConfig description)
        {
            if (KnownTypes.TryGetValue(description.FullTypeName, out var typeDescription))
            {
                return(typeDescription);
            }

            typeDescription = ClientSideTypeDescription.RegisterType(type, description);

            KnownTypes[typeDescription.FullTypeName] = typeDescription;


            var request = new RegisterTypeRequest(typeDescription.AsTypeDescription, ShardIndex, ShardsCount);

            var response = Channel.SendRequest(request);

            if (response is ExceptionResponse exResponse)
            {
                throw new CacheException("Error while registering a type on the server", exResponse.Message,
                                         exResponse.CallStack);
            }

            return(typeDescription);
        }