/// <inheritdoc/>
 public void TruncateNamespace(string nsName)
 {
     using (var nsNameRx = nsName.GetHandle())
         Assert.ThrowIfError(() =>
                             ReindexerBinding.reindexer_truncate_namespace(Rx, nsNameRx, _ctxInfo)
                             );
 }
 /// <inheritdoc/>
 public void RenameNamespace(string oldName, string newName)
 {
     using (var oldNameRx = oldName.GetHandle())
         using (var newNameRx = newName.GetHandle())
             Assert.ThrowIfError(() =>
                                 ReindexerBinding.reindexer_rename_namespace(Rx, oldNameRx, newNameRx, _ctxInfo));
 }
 /// <summary>
 /// Disables logger.
 /// </summary>
 public static void DisableLogger()
 {
     lock (_logWriterLocker)
     {
         ReindexerBinding.reindexer_disable_logger();//if we free previous delegate before disabling, gc may collect before enabling.
         _logWriter = null;
     }
 }
        public void InitReindexer()
        {
            _rx = ReindexerBinding.init_reindexer();
            Assert.AreNotEqual(UIntPtr.Zero, _rx);

            _logWriter = new LogWriterAction(Log);
            ReindexerBinding.reindexer_enable_logger(_logWriter);
            Connect();
        }
        private static LogWriterAction _logWriter; //we must pin the delegate before informing to reindexer, so we keep a reference to it, so gc won't collect it.

        /// <summary>
        /// Enables logger and send internal reindexer logs to <paramref name="logWriterAction"/>.
        /// </summary>
        /// <param name="logWriterAction">Action to send logs</param>
        public static void EnableLogger(LogWriterAction logWriterAction)
        {
            lock (_logWriterLocker)
            {
                ReindexerBinding.reindexer_disable_logger(); //if we free previous delegate before disabling, gc may collect before enabling.
                _logWriter = logWriterAction;
                ReindexerBinding.reindexer_enable_logger(_logWriter);
            }
        }
 public void OpenNamespace()
 {
     AssertError(ReindexerBinding.reindexer_open_namespace(_rx, "OpenNamespaceTest".GetHandle(),
                                                           new StorageOpts {
         options = StorageOpt.kStorageOptCreateIfMissing | StorageOpt.kStorageOptEnabled
     },
                                                           _ctxInfo));
     AssertError(ReindexerBinding.reindexer_drop_namespace(_rx, "OpenNamespaceTest".GetHandle(), _ctxInfo));
 }
        public void EnableStorage()
        {
            var dbPath = Path.Combine(Path.GetTempPath(), "TestDbForEnableStorage");

            if (Directory.Exists(dbPath))
            {
                Directory.Delete(dbPath, true);
            }
            AssertError(ReindexerBinding.reindexer_enable_storage(ReindexerBinding.init_reindexer(), dbPath.GetHandle(), _ctxInfo));
        }
 /// <inheritdoc/>
 public void DropIndex(string nsName, params string[] indexName)
 {
     using (var nsNameRx = nsName.GetHandle())
         foreach (var iname in indexName)
         {
             using (var inameRx = iname.GetHandle())
                 Assert.ThrowIfError(() =>
                                     ReindexerBinding.reindexer_drop_index(Rx, nsNameRx, inameRx, _ctxInfo)
                                     );
         }
 }
 public void Connect()
 {
     AssertError(
         ReindexerBinding.reindexer_connect(_rx,
                                            $"builtin://{Path.Combine(Path.GetTempPath(), "ReindexerBindingTest")}".GetHandle(),
                                            new ConnectOpts
     {
         options           = ConnectOpt.kConnectOptAllowNamespaceErrors,
         storage           = StorageTypeOpt.kStorageTypeOptLevelDB,
         expectedClusterID = 0
     }, ReindexerBinding.ReindexerVersion.GetHandle()));
 }
        public void DropNamespace()
        {
            var error = ReindexerBinding.reindexer_drop_namespace(_rx, "DropNamespaceTest".GetHandle(), _ctxInfo);

            Assert.AreNotEqual(0, error.code);
            AssertError(ReindexerBinding.reindexer_open_namespace(_rx, "DropNamespaceTest".GetHandle(),
                                                                  new StorageOpts {
                options = StorageOpt.kStorageOptCreateIfMissing | StorageOpt.kStorageOptEnabled
            },
                                                                  _ctxInfo));
            AssertError(ReindexerBinding.reindexer_drop_namespace(_rx, "DropNamespaceTest".GetHandle(), _ctxInfo));
        }
        /// <inheritdoc/>
        public ReindexerTransaction StartTransaction(string nsName)
        {
            UIntPtr tr = UIntPtr.Zero;

            using (var nsNameRx = nsName.GetHandle())
                Assert.ThrowIfError(() =>
                {
                    var rsp = ReindexerBinding.reindexer_start_transaction(Rx, nsNameRx);
                    tr      = rsp.tx_id;
                    return(rsp.err);
                });
            return(new ReindexerTransaction(new EmbeddedTransactionInvoker(Rx, tr, _ctxInfo)));
        }
Пример #12
0
        /// <summary>
        /// Starts the server with server yaml and waits for ready for 5 seconds. Use <see cref="Connect(string, ConnectionOptions)"/> instead.
        /// </summary>
        /// <param name="serverConfigYaml">Reindexer server configuration yaml</param>
        /// <param name="dbName"></param>
        /// <param name="user"></param>
        /// <param name="pass"></param>
        /// <param name="waitTimeoutForReady">Wait timeout for the server is ready. Default is 60sec.</param>
        /// <exception cref="TimeoutException">Throws if the server doesn't start in timeout interval.</exception>
        public void Start(string serverConfigYaml, string dbName, string user = null, string pass = null, TimeSpan?waitTimeoutForReady = null)
        {
            lock (_serverStartupLocker)                                //for not spinning extra threads and double checking lock.
            {
                if (Interlocked.Read(ref _isServerThreadStarted) == 1) //Interlocked for not extra locking in future to check is startup
                {
                    return;
                }
                _serverThread = new Thread(() =>
                {
                    Interlocked.Exchange(ref _isServerThreadStarted, 1);
                    try
                    {
                        DebugHelper.Log("Starting reindexer server...");
                        using (var configYaml = serverConfigYaml.GetHandle())
                            ReindexerBinding.start_reindexer_server(_pServer, configYaml);
                    }
                    catch (Exception e)
                    {
                        DebugHelper.Log(e.Message);
                    }
                    finally
                    {
                        Interlocked.Exchange(ref _isServerThreadStarted, 0);
                    }
                })
                {
                    IsBackground = false
                };
                _serverThread.Start();
            }

            var waitTimeout = waitTimeoutForReady ?? TimeSpan.FromSeconds(60);
            var startTime   = DateTime.UtcNow;

            while (ReindexerBinding.check_server_ready(_pServer) == 0)
            {
                if (DateTime.UtcNow - startTime > waitTimeout)
                {
                    throw new TimeoutException($"Reindexer Embedded Server couldn't be started in {waitTimeout.TotalSeconds} seconds. Check configs.");
                }
                Thread.Sleep(100);
            }
            DebugHelper.Log("Reindexer server is started.");
            using (var dbNameRx = dbName.GetHandle())
                using (var userRx = user.GetHandle())
                    using (var passRx = pass.GetHandle())
                        Assert.ThrowIfError(() => ReindexerBinding.get_reindexer_instance(_pServer, dbNameRx, userRx, passRx, ref Rx));
        }
        /// <inheritdoc/>
        public virtual void Connect(string connectionString, ConnectionOptions options = null)
        {
            if (!Directory.Exists(connectionString))
            {
                Directory.CreateDirectory(connectionString); //reindexer sometimes throws permission exception from c++ mkdir func. so we try to crate directory before.
            }

            using (var dsn = $"builtin://{connectionString}".GetHandle())
                using (var version = ReindexerBinding.ReindexerVersion.GetHandle())
                    Assert.ThrowIfError(() =>
                                        ReindexerBinding.reindexer_connect(Rx,
                                                                           dsn,
                                                                           options ?? new ConnectionOptions(),
                                                                           version)
                                        );
        }
Пример #14
0
        public int Commit()
        {
            var rsp = Assert.ThrowIfError(() => ReindexerBinding.reindexer_commit_transaction(_rx, _tr, _ctxInfo));

            try
            {
                var reader         = new CJsonReader(rsp.@out);
                var rawQueryParams = reader.ReadRawQueryParams();

                return(rawQueryParams.count);
            }
            finally
            {
                [email protected]();
            }
        }
 /// <inheritdoc/>
 public void OpenNamespace(string nsName, NamespaceOptions options = null)
 {
     using (var nsNameRx = nsName.GetHandle())
         Assert.ThrowIfError(() =>
         {
             reindexer_error rsp = default;
             for (int retry = 0; retry < 2; retry++)
             {
                 rsp = ReindexerBinding.reindexer_open_namespace(Rx, nsNameRx, options ?? new NamespaceOptions(), _ctxInfo);
                 if (rsp.code != 0)
                 {
                     ReindexerBinding.reindexer_close_namespace(Rx, nsNameRx, _ctxInfo);
                 }
             }
             return(rsp);
         });
 }
        /// <inheritdoc/>
        public QueryItemsOf <T> ExecuteSql <T>(string sql, Func <byte[], T> deserializeItem)
        {
            var result = new QueryItemsOf <T>
            {
                Items = new List <T>()
            };

            using (var sqlRx = sql.GetHandle())
            {
                var rsp = Assert.ThrowIfError(() => ReindexerBinding.reindexer_select(Rx, sqlRx, 1, new int[0], 0, _ctxInfo));
                try
                {
                    var reader         = new CJsonReader(rsp.@out);
                    var rawQueryParams = reader.ReadRawQueryParams();
                    var explain        = rawQueryParams.explainResults;

                    result.QueryTotalItems = rawQueryParams.totalcount != 0 ? rawQueryParams.totalcount : rawQueryParams.count;
                    if (explain.Length > 0)
                    {
                        result.Explain = JsonSerializer.Deserialize <ExplainDef>(explain.ToArray(), //todo: use span when utf8json supports it.
                                                                                 StandardResolver.ExcludeNull);
                    }

                    for (var i = 0; i < rawQueryParams.count; i++)
                    {
                        var item = reader.ReadRawItemParams();
                        if (item.data.Length > 0)
                        {
                            result.Items.Add(deserializeItem(item.data.ToArray())); //todo: use span when utf8json supports it.
                        }
                    }

                    if ((rawQueryParams.flags & CJsonReader.ResultsWithJoined) != 0 && reader.GetVarUInt() != 0)
                    {
                        throw new NotImplementedException("Sorry, not implemented: Can't return join query results as json");
                    }

                    return(result);
                }
                finally
                {
                    [email protected]();
                }
            }
        }
 /// <inheritdoc/>
 public void AddIndex(string nsName, params Index[] indexDefinitions)
 {
     using (var nsNameRx = nsName.GetHandle())
         foreach (var index in indexDefinitions)
         {
             if (index.JsonPaths == null || index.JsonPaths.Count == 0)
             {
                 index.JsonPaths = new List <string> {
                     index.Name
                 }
             }
             ;
             using (var jsonRx = SerializeJson(index).GetStringHandle())
                 Assert.ThrowIfError(() =>
                                     ReindexerBinding.reindexer_add_index(Rx, nsNameRx, jsonRx, _ctxInfo)
                                     );
         }
 }
        public void SelectSql()
        {
            ModifyItemPacked();

            var rsp = ReindexerBinding.reindexer_select(_rx,
                                                        $"SELECT * FROM {DataTestNamespace}".GetHandle(),
                                                        1, new int[0], 0, _ctxInfo);

            if (rsp.err_code != 0)
            {
                Assert.AreEqual(null, (string)rsp.@out);
            }
            Assert.AreNotEqual(UIntPtr.Zero, [email protected]_ptr);

            var(json, offsets, explain) = BindingHelpers.RawResultToJson(rsp.@out, "items", "total_count");

            Assert.AreNotEqual(0, json.Length);
            Assert.AreNotEqual(0, offsets.Count);
        }
Пример #19
0
        /// <summary>
        /// Stops the server.
        /// </summary>
        public void Stop()
        {
            DebugHelper.Log("Stopping reindexer server...");
            try
            {
                foreach (var ns in ExecuteSql <Namespace>(GetNamespacesQuery).Items)
                {
                    CloseNamespace(ns.Name);
                }
            }
            catch
            { //sometimes server had been stopped before this stop method because of ctrl+c on console or any sigterm signal.
            }

            Assert.ThrowIfError(() =>
                                ReindexerBinding.stop_reindexer_server(_pServer)
                                );

            var waitTimeout = TimeSpan.FromSeconds(10);
            var startTime   = DateTime.UtcNow;

            while (IsStarted)
            {
                if (DateTime.UtcNow - startTime > waitTimeout)
                {
                    DebugHelper.Log($"Reindexer Embedded Server couldn't be stopped in {waitTimeout.TotalSeconds} seconds.");
                    break;
                }
                Thread.Sleep(100);
            }

            lock (_serverStartupLocker)
            {
                if (_serverThread.IsAlive)
                {
                    _serverThread.Join();
                }
            }

            Rx = default;
            DebugHelper.Log("Reindexer server is stopped.");
        }
        /// <inheritdoc/>
        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing && Rx != default)
                {
                    foreach (var ns in ExecuteSql <Namespace>(GetNamespacesQuery).Items)
                    {
                        CloseNamespace(ns.Name);
                    }

                    if (Rx != default)
                    {
                        ReindexerBinding.destroy_reindexer(Rx);
                    }
                }

                Rx = default;

                disposedValue = true;
            }
        }
        /// <inheritdoc/>
        public int ModifyItem(string nsName, ItemModifyMode mode, byte[] itemJson, params string[] precepts)
        {
            var result = 0;

            using (var writer = new CJsonWriter())
            {
                writer.PutVString(nsName);
                writer.PutVarCUInt((int)DataFormat.FormatJson); //format
                writer.PutVarCUInt((int)mode);                  //mode
                writer.PutVarCUInt(0);                          //stateToken

                writer.PutVarCUInt(precepts.Length);            //len(precepts)
                foreach (var precept in precepts)
                {
                    writer.PutVString(precept);
                }

                reindexer_buffer.PinBufferFor(writer.CurrentBuffer, args =>
                {
                    using (var data = reindexer_buffer.From(itemJson))
                    {
                        var rsp = Assert.ThrowIfError(() => ReindexerBinding.reindexer_modify_item_packed(Rx, args, data, _ctxInfo));
                        try
                        {
                            var reader         = new CJsonReader(rsp.@out);
                            var rawQueryParams = reader.ReadRawQueryParams();

                            result = rawQueryParams.count;
                        }
                        finally
                        {
                            [email protected]();
                        }
                    }
                });
            }

            return(result);
        }
        public void DeleteSql()
        {
            AssertError(ReindexerBinding.reindexer_open_namespace(_rx, DataTestNamespace.GetHandle(),
                                                                  new StorageOpts {
                options = StorageOpt.kStorageOptCreateIfMissing | StorageOpt.kStorageOptEnabled
            },
                                                                  _ctxInfo));

            ModifyItemPacked($"{{\"Id\":2, \"Guid\":\"{Guid.NewGuid()}\"}}");

            var delRsp = ReindexerBinding.reindexer_select(_rx,
                                                           $"DELETE FROM {DataTestNamespace} WHERE Id=2".GetHandle(),
                                                           1, new int[0], 0, _ctxInfo);

            if (delRsp.err_code != 0)
            {
                Assert.AreEqual(null, (string)delRsp.@out);
            }
            Assert.AreNotEqual(UIntPtr.Zero, [email protected]_ptr);

            var(json, offsets, explain) = BindingHelpers.RawResultToJson(delRsp.@out, "items", "total_count");
            Assert.AreNotEqual(0, json.Length);
            Assert.AreNotEqual(0, offsets.Count);

            var selRsp = ReindexerBinding.reindexer_select(_rx,
                                                           $"SELECT * FROM {DataTestNamespace} WHERE Id=2".GetHandle(),
                                                           1, new int[] { 0 }, 1, _ctxInfo);

            if (selRsp.err_code != 0)
            {
                Assert.AreEqual(null, (string)selRsp.@out);
            }
            Assert.AreNotEqual(UIntPtr.Zero, [email protected]_ptr);

            (json, offsets, explain) = BindingHelpers.RawResultToJson(selRsp.@out, "items", "total_count");
            Assert.AreNotEqual(0, json.Length);
            Assert.AreEqual(0, offsets.Count);
        }
Пример #23
0
        public void ModifyItem(ItemModifyMode mode, byte[] itemJson, params string[] precepts)
        {
            using (var writer = new CJsonWriter())
            {
                writer.PutVarCUInt((int)DataFormat.FormatJson); // format
                writer.PutVarCUInt((int)mode);                  // mode
                writer.PutVarCUInt(0);                          // stateToken

                writer.PutVarCUInt(precepts.Length);            // len(precepts)
                foreach (var precept in precepts)
                {
                    writer.PutVString(precept);
                }

                reindexer_buffer.PinBufferFor(writer.CurrentBuffer, args =>
                {
                    using (var data = itemJson.GetHandle())
                    {
                        Assert.ThrowIfError(() => ReindexerBinding.reindexer_modify_item_packed_tx(_rx, _tr, args, data.Buffer));
                    }
                });
            }
        }
Пример #24
0
 public void Rollback()
 {
     Assert.ThrowIfError(() => ReindexerBinding.reindexer_rollback_transaction(_rx, _tr));
 }
        public void ParallelModifyItemPacked()
        {
            var nsName = "ParallelTestNs";

            AssertError(ReindexerBinding.reindexer_open_namespace(_rx, nsName.GetHandle(),
                                                                  new StorageOpts {
                options = StorageOpt.kStorageOptCreateIfMissing | StorageOpt.kStorageOptEnabled
            },
                                                                  _ctxInfo));

            var indexDefJson = JsonSerializer.ToJsonString(
                new Index
            {
                Name      = "Id",
                IsPk      = true,
                FieldType = FieldType.Int64,
                IndexType = IndexType.Hash,
                JsonPaths = new List <string> {
                    "Id"
                }
            }, Utf8Json.Resolvers.StandardResolver.ExcludeNull);

            AssertError(ReindexerBinding.reindexer_add_index(_rx, nsName.GetHandle(), indexDefJson.GetHandle(), _ctxInfo));

            using (var ser1 = new CJsonWriter())
            {
                ser1.PutVString(nsName);
                ser1.PutVarCUInt((int)DataFormat.FormatJson);
                ser1.PutVarCUInt((int)ItemModifyMode.Upsert);
                ser1.PutVarCUInt(0);
                ser1.PutVarCUInt(0);

                reindexer_buffer.PinBufferFor(ser1.CurrentBuffer, args =>
                {
                    Parallel.For(0, 30000, i =>
                    {
                        var dataHandle = reindexer_buffer.From(Encoding.UTF8.GetBytes($"{{\"Id\":{i}, \"Guid\":\"{Guid.NewGuid()}\"}}"));
                        var rsp        = ReindexerBinding.reindexer_modify_item_packed(_rx, args, dataHandle.Buffer, _ctxInfo);
                        try
                        {
                            if (rsp.err_code != 0)
                            {
                                Assert.AreEqual(null, (string)rsp.@out);
                            }

                            Assert.AreNotEqual(UIntPtr.Zero, [email protected]_ptr);

                            var reader         = new CJsonReader(rsp.@out);
                            var rawQueryParams = reader.ReadRawQueryParams();

                            Assert.AreEqual(1, rawQueryParams.count);

                            reader.ReadRawItemParams();
                        }
                        finally
                        {
                            dataHandle.Dispose();
                            [email protected]();
                        }
                    });
                });
            }

            Thread.Sleep(6000);
#pragma warning disable S1215 // "GC.Collect" should not be called
            GC.Collect();
            GC.WaitForPendingFinalizers();
#pragma warning restore S1215 // "GC.Collect" should not be called
            AssertError(ReindexerBinding.reindexer_truncate_namespace(_rx, nsName.GetHandle(), _ctxInfo));
        }
 public void DestroyReindexer()
 {
     ReindexerBinding.destroy_reindexer(_rx);
 }
 public void Ping()
 {
     AssertError(ReindexerBinding.reindexer_ping(_rx));
 }
 public void InitSystemNamespaces()
 {
     AssertError(ReindexerBinding.reindexer_init_system_namespaces(_rx));
 }
        };                                                                                              //TODO: Implement async/await logic.

        /// <summary>
        /// Creates a new embedded Reindexer database.
        /// </summary>
        public ReindexerEmbedded()
        {
            Rx = ReindexerBinding.init_reindexer();
        }
 /// <inheritdoc/>
 public void Ping()
 {
     Assert.ThrowIfError(() =>
                         ReindexerBinding.reindexer_ping(Rx));
 }