public void Test_Can_Serialize_Connection_Options()
        {
            var options = new FdbConnectionOptions();

            Assert.That(options.ToString(), Is.EqualTo("cluster_file=default"));

            options = new FdbConnectionOptions
            {
                ClusterFile = "X:\\some\\path\\to\\fdb.cluster",
                Root        = FdbPath.Parse("/Hello/World"),
            };
            Assert.That(options.ToString(), Is.EqualTo(@"cluster_file=X:\some\path\to\fdb.cluster; root=/Hello/World"));

            options = new FdbConnectionOptions
            {
                ClusterFile       = "X:\\some\\path\\to\\fdb.cluster",
                ReadOnly          = true,
                DefaultTimeout    = TimeSpan.FromSeconds(42.5),
                DefaultRetryLimit = 123,
                DataCenterId      = "AC/DC",
                MachineId         = "Marble Machine X"
            };
            Assert.That(options.ToString(), Is.EqualTo(@"cluster_file=X:\some\path\to\fdb.cluster; readonly; timeout=42.5; retry_limit=123; dc_id=AC/DC; machine_id=""Marble Machine X"""));

            options = new FdbConnectionOptions
            {
                ClusterFile    = "/etc/foundationdb/fdb.cluster",
                MachineId      = "James \"The Machine\" Wade",
                DefaultTimeout = TimeSpan.FromTicks((long)(Math.PI * TimeSpan.TicksPerSecond)),
            };
            Assert.That(options.ToString(), Is.EqualTo(@"cluster_file=/etc/foundationdb/fdb.cluster; timeout=3.1415926; machine_id=""James \""The Machine\"" Wade"""));
        }
Esempio n. 2
0
 private static Task <IFdbDatabase> ChangeDatabase(FdbConnectionOptions options, CancellationToken ct)
 {
     options.DefaultTimeout    = TimeSpan.FromSeconds(30);
     options.DefaultRetryLimit = 50;
     Program.StdOut("Connecting to cluster...", ConsoleColor.Gray);
     return(Fdb.OpenAsync(options, ct));
 }
        public async Task Test_Check_Timeout_On_Non_Existing_Database()
        {
            string clusterPath = Path.Combine(TestContext.CurrentContext.WorkDirectory, "notfound.cluster");

            File.WriteAllText(clusterPath, "local:[email protected]:4566");
            var options = new FdbConnectionOptions {
                ClusterFile = clusterPath
            };

            using (var db = await Fdb.OpenAsync(options, this.Cancellation))
            {
                bool exists = false;
                var  err    = FdbError.Success;
                try
                {
                    using (var tr = await db.BeginReadOnlyTransactionAsync(this.Cancellation))
                    {
                        tr.Timeout = 250;                         // ms
                        Log("check ...");
                        await tr.GetAsync(Slice.FromString("key_not_found"));

                        Log("Uhoh ...?");
                        exists = true;
                    }
                }
                catch (FdbException e)
                {
                    err = e.Code;
                }

                Assert.That(exists, Is.False);
                Assert.That(err, Is.EqualTo(FdbError.TransactionTimedOut));
            }
        }
        /// <summary>Connect to the local test partition</summary>
        public static Task <IFdbDatabase> OpenTestPartitionAsync(CancellationToken ct)
        {
            var options = new FdbConnectionOptions
            {
                ClusterFile    = TestClusterFile,
                Root           = FdbPath.Absolute(FdbPathSegment.Partition("Tests"), FdbPathSegment.Create("Fdb"), FdbPathSegment.Partition(Environment.MachineName)),
                DefaultTimeout = TimeSpan.FromMilliseconds(DefaultTimeout),
            };

            return(Fdb.OpenAsync(options, ct));
        }
        //TODO: move these methods to FdbTest ?

        /// <summary>Connect to the local test database</summary>
        public static Task <IFdbDatabase> OpenTestDatabaseAsync(CancellationToken ct)
        {
            var options = new FdbConnectionOptions
            {
                ClusterFile    = TestClusterFile,
                Root           = FdbPath.Root,       // core tests cannot rely on the DirectoryLayer!
                DefaultTimeout = TimeSpan.FromMilliseconds(DefaultTimeout),
            };

            return(Fdb.OpenAsync(options, ct));
        }
Esempio n. 6
0
        /// <summary>Connect to the local test database</summary>
        public static Task <IFdbDatabase> OpenTestPartitionAsync(CancellationToken ct)
        {
            var options = new FdbConnectionOptions
            {
                ClusterFile    = TestClusterFile,
                DbName         = TestDbName,
                PartitionPath  = TestPartition,
                DefaultTimeout = TimeSpan.FromMilliseconds(DefaultTimeout),
            };

            return(Fdb.OpenAsync(options, ct));
        }
Esempio n. 7
0
        //TODO: move these methods to FdbTest ?

        /// <summary>Connect to the local test database</summary>
        public static Task <IFdbDatabase> OpenTestDatabaseAsync(CancellationToken ct)
        {
            var options = new FdbConnectionOptions
            {
                ClusterFile    = TestClusterFile,
                DbName         = TestDbName,
                GlobalSpace    = KeySubspace.FromKey(TestGlobalPrefix),
                DefaultTimeout = TimeSpan.FromMilliseconds(DefaultTimeout),
            };

            return(Fdb.OpenAsync(options, ct));
        }
        public async Task Main()
        {
            ThreadPool.SetMinThreads(Environment.ProcessorCount, Environment.ProcessorCount);

            Fdb.Start(Fdb.GetMaxSafeApiVersion());
            var cts = new CancellationTokenSource();

            try
            {
                var options = new FdbConnectionOptions();
                //TODO: change options using the command line arguments?

                using (var db = await Fdb.OpenAsync(options, cts.Token))
                {
                    var location = await db.ReadWriteAsync(async tr =>
                    {
                        var subspace = await db.Directory.CreateOrOpenAsync(tr, new[] { "T", "WorkerPool" });
                        tr.ClearRange(subspace);
                        return(subspace);
                    }, cts.Token);

                    // failsafe: remove this when not debugging problems !
                    cts.CancelAfter(TimeSpan.FromSeconds(60));

                    const int N = 100;                   // msg/publiser
                    const int K = 2;                     // publishers
                    const int W = 2;                     // workers

                    await RunAsync(db, location, cts.Token, () => cts.Cancel(), N, K, W);
                }
            }
            catch (TaskCanceledException)
            {
                Console.WriteLine("CANCELED");
            }
            catch (Exception e)
            {
                cts.Cancel();
                Console.Error.WriteLine("CRASH: " + e.ToString());
                Console.Error.WriteLine();
            }
            finally
            {
                Fdb.Stop();
            }
        }
Esempio n. 9
0
        private static async Task MainAsync(string[] args, CancellationToken cancel)
        {
            #region Options Parsing...

            string clusterFile = null;
            var    partition   = FdbPath.Root;
            bool   showHelp    = false;
            int    timeout     = 30;
            int    maxRetries  = 10;
            string execCommand = null;

            var opts = new OptionSet()
            {
                {
                    "c|C|connfile=",
                    "The path of a file containing the connection string for the FoundationDB cluster.",
                    v => clusterFile = v
                },
                {
                    "p|partition=",
                    "The name of the database partition to open.",
                    v => partition = FdbPath.Parse(v.Trim())
                },
                {
                    "t|timeout=",
                    "Default timeout (in seconds) for failed transactions.",
                    (int v) => timeout = v
                },
                {
                    "r|retries=",
                    "Default max retry count for failed transactions.",
                    (int v) => maxRetries = v
                },
                {
                    "exec=",
                    "Execute this command, and exits immediately.",
                    v => execCommand = v
                },
                {
                    "h|help",
                    "Show this help and exit.",
                    v => showHelp = v != null
                }
            };

            var extra = opts.Parse(args);

            if (showHelp)
            {
                //TODO!
                opts.WriteOptionDescriptions(Console.Out);
                return;
            }

            string startCommand = null;
            if (!string.IsNullOrEmpty(execCommand))
            {
                startCommand = execCommand;
            }
            else if (extra.Count > 0)
            {             // the remainder of the command line will be the first command to execute
                startCommand = String.Join(" ", extra);
            }

            #endregion

            bool stop = false;
            Db = null;
            try
            {
                var cnxOptions = new FdbConnectionOptions
                {
                    ClusterFile = clusterFile,
                    Root        = partition
                };
                Db = await ChangeDatabase(cnxOptions, cancel);

                Db.DefaultTimeout    = Math.Max(0, timeout) * 1000;
                Db.DefaultRetryLimit = Math.Max(0, maxRetries);

                StdOut("Using API v" + Fdb.ApiVersion + " (max " + Fdb.GetMaxApiVersion() + ")", ConsoleColor.Gray);
                StdOut("Cluster file: " + (clusterFile ?? "<default>"), ConsoleColor.Gray);
                StdOut("");
                StdOut("FoundationDB Shell menu:");
                StdOut("\tcd\tChange the current directory");
                StdOut("\tdir\tList the sub-directories the current directory");
                StdOut("\tshow\tShow the content of the current directory");
                StdOut("\ttree\tShow all the directories under the current directory");
                StdOut("\tsampling\tDisplay statistics on random shards from the database");
                StdOut("\tcoordinators\tShow the current coordinators for the cluster");
                //StdOut("\thelp\tShow all the commands");
                StdOut("\tquit\tQuit");
                StdOut("");

                try
                {
                    var cf = await Fdb.System.GetCoordinatorsAsync(Db, cancel);

                    Description = cf.Description;
                    StdOut("Ready...", ConsoleColor.DarkGreen);
                }
                catch (Exception e)
                {
                    StdErr("Failed to get coordinators state from cluster: " + e.Message, ConsoleColor.DarkRed);
                    Description = "???";
                }

                StdOut("");

                var le = new LineEditor("FDBShell");

                string[] cmds = new string[]
                {
                    "cd",
                    "clear",
                    "coordinators",
                    "count",
                    "dir",
                    "dump",
                    "exit",
                    "gc",
                    "help",
                    "layer",
                    "map",
                    "mem",
                    "mkdir",
                    "mv",
                    "partition",
                    "pwd",
                    "quit",
                    "ren",
                    "rmdir",
                    "sampling",
                    "shards",
                    "show",
                    "status",
                    "topology",
                    "tree",
                    "version",
                    "wide",
                };

                le.AutoCompleteEvent = (txt, pos) =>
                {
                    string[] res;
                    int      p = txt.IndexOf(' ');
                    if (p > 0)
                    {
                        string cmd = txt.Substring(0, p);
                        string arg = txt.Substring(p + 1).Trim();

                        if (cmd == "cd" || cmd == "rmdir")
                        {                         // handle completion for directories
                            // txt: "cd foo" => prefix = "foo"
                            // txt: "cd foobar/b" => prefix = "b"

                            bool   hasLeadingSlash = arg.EndsWith("/");
                            var    path            = FdbPath.Parse(hasLeadingSlash ? (arg + "!") : arg);
                            var    parent          = path.Count > 1 ? path.GetParent() : path.IsAbsolute ? FdbPath.Root : FdbPath.Empty;
                            string search          = hasLeadingSlash ? "" : path.Name;

                            var subdirs = RunAsyncCommand((db, log, ct) => AutoCompleteDirectories(CombinePath(CurrentDirectoryPath, parent.ToString()), db, log, ct), cancel).GetAwaiter().GetResult();

                            if (!subdirs.HasValue || subdirs.Value == null)
                            {
                                return(new LineEditor.Completion(txt, null));
                            }

                            res = subdirs.Value
                                  .Where(s => s.StartsWith(search, StringComparison.Ordinal))
                                  .Select(s => (cmd + " " + parent[s]).Substring(txt.Length))
                                  .ToArray();

                            if (res.Length == 1 && res[0] == string.Empty)
                            {                             // someone was at "cd /Foo/Bar", pressed TAB again, and there is no other match
                                // => we interpret it as "want to go in the sub-folder

                                res = new[] { "/" };                                 // add a "slash"
                            }

                            return(new LineEditor.Completion(txt, res));
                        }

                        // unknown command
                        return(new LineEditor.Completion(txt, null));
                    }

                    // list of commands
                    res = cmds
                          .Where(cmd => cmd.StartsWith(txt, StringComparison.OrdinalIgnoreCase))
                          .Select(cmd => cmd.Substring(txt.Length))
                          .ToArray();
                    return(new LineEditor.Completion(txt, res));
                };
                le.TabAtStartCompletes = true;

                string prompt = null;

                void UpdatePrompt(FdbPath path)
                {
                    prompt = $"[fdb:{Description} {path.ToString()}]# ";
                }
                le.PromptColor = ConsoleColor.Cyan;
                UpdatePrompt(CurrentDirectoryPath);

                while (!stop)
                {
                    string s;
                    if (startCommand != null)
                    {
                        s            = startCommand;
                        startCommand = null;
                    }
                    else
                    {
                        s = startCommand ?? le.Edit(prompt, "");
                    }

                    if (s == null)
                    {
                        break;
                    }

                    //TODO: we need a tokenizer that recognizes binary keys, tuples, escaped paths, etc...
                    var    tokens = Tokenize(s);
                    string cmd    = tokens.Count > 0 ? tokens.Get <string>(0) : string.Empty;
                    var    extras = tokens.Count > 1 ? tokens.Substring(1) : STuple.Empty;

                    var trimmedCommand = cmd.Trim().ToLowerInvariant();
                    try
                    {
                        switch (trimmedCommand)
                        {
                        case "":
                        {
                            continue;
                        }

                        case "log":
                        {
                            string prm = PopParam(ref extras);
                            LogCommand(prm, extras, Console.Out);
                            break;
                        }

                        case "version":
                        {
                            await VersionCommand(extras, clusterFile, Console.Out, cancel);

                            break;
                        }

                        case "tree":
                        {
                            string prm  = PopParam(ref extras);
                            var    path = CombinePath(CurrentDirectoryPath, prm);
                            await RunAsyncCommand((db, log, ct) => BasicCommands.Tree(path, extras, db, log, ct), cancel);

                            break;
                        }

                        case "map":
                        {
                            string prm  = PopParam(ref extras);
                            var    path = CombinePath(CurrentDirectoryPath, prm);
                            await RunAsyncCommand((db, log, ct) => BasicCommands.Map(path, extras, db, log, ct), cancel);

                            break;
                        }

                        case "dir":
                        case "ls":
                        {
                            string prm  = PopParam(ref extras);
                            var    path = CombinePath(CurrentDirectoryPath, prm);
                            await RunAsyncCommand((db, log, ct) => BasicCommands.Dir(path, extras, BasicCommands.DirectoryBrowseOptions.Default, db, log, ct), cancel);

                            break;
                        }

                        case "ll":
                        {
                            string prm  = PopParam(ref extras);
                            var    path = CombinePath(CurrentDirectoryPath, prm);
                            await RunAsyncCommand((db, log, ct) => BasicCommands.Dir(path, extras, BasicCommands.DirectoryBrowseOptions.ShowCount, db, log, ct), cancel);

                            break;
                        }

                        case "count":
                        {
                            string prm  = PopParam(ref extras);
                            var    path = CombinePath(CurrentDirectoryPath, prm);
                            await RunAsyncCommand((db, log, ct) => BasicCommands.Count(path, extras, db, log, ct), cancel);

                            break;
                        }

                        case "show":
                        case "top":
                        {
                            await RunAsyncCommand((db, log, ct) => BasicCommands.Show(CurrentDirectoryPath, extras, false, db, log, ct), cancel);

                            break;
                        }

                        case "last":
                        {
                            await RunAsyncCommand((db, log, ct) => BasicCommands.Show(CurrentDirectoryPath, extras, true, db, log, ct), cancel);

                            break;
                        }

                        case "dump":
                        {
                            string output = PopParam(ref extras);
                            if (string.IsNullOrEmpty(output))
                            {
                                StdErr("You must specify a target file path.", ConsoleColor.Red);
                                break;
                            }
                            await RunAsyncCommand((db, log, ct) => BasicCommands.Dump(CurrentDirectoryPath, output, extras, db, log, ct), cancel);

                            break;
                        }

                        case "cd":
                        case "pwd":
                        {
                            string prm = PopParam(ref extras);
                            if (!string.IsNullOrEmpty(prm))
                            {
                                var newPath = CombinePath(CurrentDirectoryPath, prm);
                                var res     = await RunAsyncCommand(
                                    (db, log, ct) => db.ReadAsync(tr => BasicCommands.TryOpenCurrentDirectoryAsync(tr, newPath), ct),
                                    cancel
                                    );

                                if (res.Failed)
                                {
                                    StdErr($"# Failed to open Directory {newPath}: {res.Error.Message}", ConsoleColor.Red);
                                    Console.Beep();
                                }
                                else if (res.Value == null)
                                {
                                    StdOut($"# Directory {newPath} does not exist!", ConsoleColor.Red);
                                    Console.Beep();
                                }
                                else
                                {
                                    CurrentDirectoryPath = newPath;
                                    UpdatePrompt(CurrentDirectoryPath);
                                }
                            }
                            else
                            {
                                var res = await RunAsyncCommand(
                                    (db, log, ct) => db.ReadAsync(tr => BasicCommands.TryOpenCurrentDirectoryAsync(tr, CurrentDirectoryPath), ct),
                                    cancel
                                    );

                                if (res.Failed)
                                {
                                    StdErr($"# Failed to query Directory {Program.CurrentDirectoryPath}: {res.Error.Message}", ConsoleColor.Red);
                                }
                                else if (res.Value == null)
                                {
                                    StdOut($"# Directory {Program.CurrentDirectoryPath} does not exist anymore");
                                }
                            }

                            break;
                        }

                        case "mkdir":
                        case "md":
                        {                                 // "mkdir DIRECTORYNAME"
                            string prm = PopParam(ref extras);
                            if (!string.IsNullOrEmpty(prm))
                            {
                                var path = CombinePath(CurrentDirectoryPath, prm);
                                await RunAsyncCommand((db, log, ct) => BasicCommands.CreateDirectory(path, extras, db, log, ct), cancel);
                            }

                            break;
                        }

                        case "rmdir":
                        {                                 // "rmdir DIRECTORYNAME"
                            string prm = PopParam(ref extras);
                            if (!string.IsNullOrEmpty(prm))
                            {
                                var path = CombinePath(CurrentDirectoryPath, prm);
                                await RunAsyncCommand((db, log, ct) => BasicCommands.RemoveDirectory(path, extras, db, log, ct), cancel);
                            }

                            break;
                        }

                        case "mv":
                        case "ren":
                        {                                 // "mv SOURCE DESTINATION"
                            string prm     = PopParam(ref extras);
                            var    srcPath = CombinePath(CurrentDirectoryPath, prm);
                            var    dstPath = CombinePath(CurrentDirectoryPath, extras.Get <string>(0));
                            await RunAsyncCommand((db, log, ct) => BasicCommands.MoveDirectory(srcPath, dstPath, extras.Substring(1), db, log, ct), cancel);

                            break;
                        }

                        case "get":
                        {                                 // "get KEY"
                            if (extras.Count == 0)
                            {
                                StdErr("You must specify a key to read.", ConsoleColor.Red);
                                break;
                            }

                            await RunAsyncCommand((db, log, ct) => BasicCommands.Get(CurrentDirectoryPath, extras, db, log, ct), cancel);

                            break;
                        }

                        case "clear":
                        {                                 // "clear KEY"
                            if (extras.Count == 0)
                            {
                                StdErr("You must specify a key to clear.", ConsoleColor.Red);
                                break;
                            }

                            await RunAsyncCommand((db, log, ct) => BasicCommands.Clear(CurrentDirectoryPath, extras, db, log, ct), cancel);

                            break;
                        }

                        case "clearrange":
                        {                                 // "clear *" or "clear FROM TO"
                            if (extras.Count == 0)
                            {
                                StdErr("You must specify either '*', a prefix, or a key range.", ConsoleColor.Red);
                                break;
                            }

                            await RunAsyncCommand((db, log, ct) => BasicCommands.ClearRange(CurrentDirectoryPath, extras, db, log, ct), cancel);

                            break;
                        }

                        case "layer":
                        {
                            string prm = PopParam(ref extras);
                            if (string.IsNullOrEmpty(prm))
                            {                                     // displays the layer id of the current folder
                                await RunAsyncCommand((db, log, ct) => BasicCommands.ShowDirectoryLayer(CurrentDirectoryPath, extras, db, log, ct), cancel);
                            }
                            else
                            {                                     // change the layer id of the current folder
                                prm = prm.Trim();
                                // double or single quotes can be used to escape the value
                                if (prm.Length >= 2 && (prm.StartsWith("'") && prm.EndsWith("'")) || (prm.StartsWith("\"") && prm.EndsWith("\"")))
                                {
                                    prm = prm.Substring(1, prm.Length - 2);
                                }

                                await RunAsyncCommand((db, log, ct) => BasicCommands.ChangeDirectoryLayer(CurrentDirectoryPath, prm, extras, db, log, ct), cancel);
                            }

                            break;
                        }

                        case "mkpart":
                        {                                 // "mkpart PARTITIONNAME"
                            string prm = PopParam(ref extras);
                            if (!string.IsNullOrEmpty(prm))
                            {
                                var path = CombinePath(CurrentDirectoryPath, prm);
                                await RunAsyncCommand((db, log, ct) => BasicCommands.CreateDirectory(path, STuple.Create(FdbDirectoryPartition.LayerId).Concat(extras), db, log, ct), cancel);
                            }

                            break;
                        }

                        case "topology":
                        {
                            await RunAsyncCommand((db, log, ct) => BasicCommands.Topology(null, extras, db, log, ct), cancel);

                            break;
                        }

                        case "shards":
                        {
                            string prm  = PopParam(ref extras);
                            var    path = CombinePath(CurrentDirectoryPath, prm);
                            await RunAsyncCommand((db, log, ct) => BasicCommands.Shards(path, extras, db, log, ct), cancel);

                            break;
                        }

                        case "sampling":
                        {
                            string prm  = PopParam(ref extras);
                            var    path = CombinePath(CurrentDirectoryPath, prm);
                            await RunAsyncCommand((db, log, ct) => BasicCommands.Sampling(path, extras, db, log, ct), cancel);

                            break;
                        }

                        case "coordinators":
                        {
                            await RunAsyncCommand((db, log, ct) => CoordinatorsCommand(db, log, ct), cancel);

                            break;
                        }

                        case "partition":
                        {
                            string prm = PopParam(ref extras);
                            if (string.IsNullOrEmpty(prm))
                            {
                                StdOut($"# Current partition is {partition}");
                                //TODO: browse existing partitions ?
                                break;
                            }

                            var          newPartition = FdbPath.Parse(prm.Trim());
                            IFdbDatabase newDb        = null;
                            try
                            {
                                var options = new FdbConnectionOptions
                                {
                                    ClusterFile = clusterFile,
                                    Root        = newPartition
                                };
                                newDb = await ChangeDatabase(options, cancel);
                            }
                            catch (Exception)
                            {
                                newDb?.Dispose();
                                newDb = null;
                                throw;
                            }
                            finally
                            {
                                if (newDb != null)
                                {
                                    if (Db != null)
                                    {
                                        Db.Dispose();
                                        Db = null;
                                    }

                                    Db        = newDb;
                                    partition = newPartition;
                                    StdOut($"# Changed partition to {partition}");
                                }
                            }

                            break;
                        }

                        case "q":
                        case "x":
                        case "quit":
                        case "exit":
                        case "bye":
                        {
                            stop = true;
                            break;
                        }

                        case "gc":
                        {
                            long before = GC.GetTotalMemory(false);
                            Console.Write("Collecting garbage...");
                            GC.Collect();
                            GC.WaitForPendingFinalizers();
                            GC.Collect();
                            StdOut(" Done");
                            long after = GC.GetTotalMemory(false);
                            StdOut("- before = " + before.ToString("N0"));
                            StdOut("- after  = " + after.ToString("N0"));
                            StdOut("- delta  = " + (before - after).ToString("N0"));
                            break;
                        }

                        case "mem":
                        {
                            StdOut("Memory usage:");
                            StdOut("- Managed Mem  : " + GC.GetTotalMemory(false).ToString("N0"));
                            //TODO: how do we get these values on Linux/Mac?
#if !NETCOREAPP
                            StdOut("- Working Set  : " + PerfCounters.WorkingSet.NextValue().ToString("N0") + " (peak " + PerfCounters.WorkingSetPeak.NextValue().ToString("N0") + ")");
                            StdOut("- Virtual Bytes: " + PerfCounters.VirtualBytes.NextValue().ToString("N0") + " (peak " + PerfCounters.VirtualBytesPeak.NextValue().ToString("N0") + ")");
                            StdOut("- Private Bytes: " + PerfCounters.PrivateBytes.NextValue().ToString("N0"));
                            StdOut("- BytesInAlHeap: " + PerfCounters.ClrBytesInAllHeaps.NextValue().ToString("N0"));
#endif
                            break;
                        }

                        case "wide":
                        {
                            try
                            {
                                Console.WindowWidth = 160;
                            }
                            catch (Exception e)
                            {
                                StdErr("Failed to change console width: " + e.Message, ConsoleColor.DarkRed);
                            }

                            break;
                        }

                        case "status":
                        case "wtf":
                        {
                            var result = await RunAsyncCommand((_, log, ct) => FdbCliCommands.RunFdbCliCommand("status details", null, clusterFile, log, ct), cancel);

                            if (result.Failed)
                            {
                                break;
                            }
                            if (result.Value.ExitCode != 0)
                            {
                                StdErr($"# fdbcli exited with code {result.Value.ExitCode}", ConsoleColor.DarkRed);
                                StdOut("> StdErr:", ConsoleColor.DarkGray);
                                StdOut(result.Value.StdErr);
                                StdOut("> StdOut:", ConsoleColor.DarkGray);
                            }

                            StdOut(result.Value.StdOut);
                            break;
                        }

                        default:
                        {
                            StdErr($"Unknown command : '{trimmedCommand}'", ConsoleColor.Red);
                            break;
                        }
                        }
                    }
                    catch (Exception e)
                    {
                        StdErr($"Failed to execute command '{trimmedCommand}': " + e.Message, ConsoleColor.Red);
#if DEBUG
                        StdErr(e.ToString(), ConsoleColor.DarkRed);
#endif
                    }

                    if (!string.IsNullOrEmpty(execCommand))
                    {                     // only run one command, and then exit
                        break;
                    }
                }
            }
            finally
            {
                Program.Db?.Dispose();
            }
        }
 private static Task <IFdbDatabase> ChangeDatabase(FdbConnectionOptions options, CancellationToken ct)
 {
     options.DefaultTimeout    = TimeSpan.FromSeconds(30);
     options.DefaultRetryLimit = 50;
     return(Fdb.OpenAsync(options, ct));
 }
        private static async Task MainAsync(string[] args, CancellationToken cancel)
        {
            #region Options Parsing...

            string clusterFile = null;
            var    dbName      = "DB";
            var    partition   = new string[0];
            bool   showHelp    = false;
            int    timeout     = 30;
            int    maxRetries  = 10;
            string execCommand = null;

            var opts = new OptionSet()
            {
                {
                    "c|connfile=",
                    "The path of a file containing the connection string for the FoundationDB cluster.",
                    v => clusterFile = v
                },
                {
                    "p|partition=",
                    "The name of the database partition to open.",
                    v => partition = v.Trim().Split('/')
                },
                {
                    "t|timeout=",
                    "Default timeout (in seconds) for failed transactions.",
                    (int v) => timeout = v
                },
                {
                    "r|retries=",
                    "Default max retry count for failed transactions.",
                    (int v) => maxRetries = v
                },
                {
                    "exec=",
                    "Execute this command, and exits immediately.",
                    v => execCommand = v
                },
                {
                    "h|help",
                    "Show this help and exit.",
                    v => showHelp = v != null
                }
            };

            var extra = opts.Parse(args);

            if (showHelp)
            {
                //TODO!
                opts.WriteOptionDescriptions(Console.Out);
                return;
            }

            string startCommand = null;
            if (!string.IsNullOrEmpty(execCommand))
            {
                startCommand = execCommand;
            }
            else if (extra.Count > 0)
            {             // the remainder of the command line will be the first command to execute
                startCommand = String.Join(" ", extra);
            }

            #endregion

            bool stop = false;
            Db = null;
            try
            {
                var cnxOptions = new FdbConnectionOptions
                {
                    ClusterFile   = clusterFile,
                    DbName        = dbName,
                    PartitionPath = partition
                };
                Db = await ChangeDatabase(cnxOptions, cancel);

                Db.DefaultTimeout    = Math.Max(0, timeout) * 1000;
                Db.DefaultRetryLimit = Math.Max(0, maxRetries);

                Console.WriteLine("Using API v" + Fdb.ApiVersion + " (max " + Fdb.GetMaxApiVersion() + ")");
                Console.WriteLine("Cluster file: " + (clusterFile ?? "<default>"));
                Console.WriteLine();
                Console.WriteLine("FoundationDB Shell menu:");
                Console.WriteLine("\tdir\tShow the content of the current directory");
                Console.WriteLine("\ttree\tShow all the directories under the current directory");
                Console.WriteLine("\tsampling\tDisplay statistics on random shards from the database");
                Console.WriteLine("\tcoordinators\tShow the current coordinators for the cluster");
                Console.WriteLine("\tmem\tShow memory usage statistics");
                Console.WriteLine("\tgc\tTrigger garbage collection");
                Console.WriteLine("\tquit\tQuit");

                Console.WriteLine("Ready...");


                var le = new LineEditor("FDBShell");

                string[] cmds = new string[]
                {
                    "cd",
                    "coordinators",
                    "count",
                    "dir",
                    "exit",
                    "gc",
                    "help",
                    "layer",
                    "map",
                    "mem",
                    "mkdir",
                    "mv",
                    "partition",
                    "pwd",
                    "quit",
                    "ren",
                    "rmdir",
                    "sampling",
                    "shards",
                    "show",
                    "status",
                    "topology",
                    "tree",
                    "version",
                    "wide",
                };

                le.AutoCompleteEvent = (txt, pos) =>
                {
                    string[] res;
                    int      p = txt.IndexOf(' ');
                    if (p > 0)
                    {
                        string cmd = txt.Substring(0, p);
                        string arg = txt.Substring(p + 1);

                        if (cmd == "cd")
                        {                         // handle completion for directories
                            // txt: "cd foo" => prefix = "foo"
                            // txt: "cd foobar/b" => prefix = "b"

                            string path   = CurrentDirectoryPath;
                            string prefix = "";
                            string search = arg;
                            p = arg.LastIndexOf('/');
                            if (p > 0)
                            {
                                path   = Path.Combine(path, arg.Substring(0, p));
                                search = arg.Substring(p + 1);
                                prefix = arg.Substring(0, p + 1);
                            }

                            var subdirs = RunAsyncCommand((db, log, ct) => AutoCompleteDirectories(path, db, log, ct), cancel).GetAwaiter().GetResult();
                            if (!subdirs.HasValue || subdirs.Value == null)
                            {
                                return(new LineEditor.Completion(txt, null));
                            }

                            res = subdirs.Value
                                  .Where(s => s.StartsWith(search, StringComparison.Ordinal))
                                  .Select(s => (cmd + " " + prefix + s).Substring(txt.Length))
                                  .ToArray();
                            return(new LineEditor.Completion(txt, res));
                        }

                        // unknown command
                        return(new LineEditor.Completion(txt, null));
                    }

                    // list of commands
                    res = cmds
                          .Where(cmd => cmd.StartsWith(txt, StringComparison.OrdinalIgnoreCase))
                          .Select(cmd => cmd.Substring(txt.Length))
                          .ToArray();
                    return(new LineEditor.Completion(txt, res));
                };
                le.TabAtStartCompletes = true;

                string          prompt       = null;
                Action <string> updatePrompt = (path) => { prompt = String.Format("fdb:{0}> ", path); };
                updatePrompt(CurrentDirectoryPath);

                while (!stop)
                {
                    string s = startCommand != null ? startCommand : le.Edit(prompt, "");
                    startCommand = null;

                    if (s == null)
                    {
                        break;
                    }

                    var    tokens = s.Trim().Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    string cmd    = tokens.Length > 0 ? tokens[0] : String.Empty;
                    string prm    = tokens.Length > 1 ? tokens[1] : String.Empty;
                    var    extras = tokens.Length > 2 ? STuple.FromEnumerable <string>(tokens.Skip(2)) : STuple.Empty;

                    var trimmedCommand = cmd.Trim().ToLowerInvariant();
                    switch (trimmedCommand)
                    {
                    case "":
                    {
                        continue;
                    }

                    case "log":
                    {
                        LogCommand(prm, Console.Out);

                        break;
                    }

                    case "version":
                    {
                        await VersionCommand(prm, clusterFile, Console.Out, cancel);

                        break;
                    }

                    case "tree":
                    {
                        var path = ParsePath(CombinePath(CurrentDirectoryPath, prm));
                        await RunAsyncCommand((db, log, ct) => BasicCommands.Tree(path, extras, db, log, ct), cancel);

                        break;
                    }

                    case "map":
                    {
                        var path = ParsePath(CombinePath(CurrentDirectoryPath, prm));
                        await RunAsyncCommand((db, log, ct) => BasicCommands.Map(path, extras, db, log, ct), cancel);

                        break;
                    }

                    case "dir":
                    case "ls":
                    {
                        var path = ParsePath(CombinePath(CurrentDirectoryPath, prm));
                        await RunAsyncCommand((db, log, ct) => BasicCommands.Dir(path, extras, BasicCommands.DirectoryBrowseOptions.Default, db, log, ct), cancel);

                        break;
                    }

                    case "ll":
                    {
                        var path = ParsePath(CombinePath(CurrentDirectoryPath, prm));
                        await RunAsyncCommand((db, log, ct) => BasicCommands.Dir(path, extras, BasicCommands.DirectoryBrowseOptions.ShowCount, db, log, ct), cancel);

                        break;
                    }

                    case "count":
                    {
                        var path = ParsePath(CombinePath(CurrentDirectoryPath, prm));
                        await RunAsyncCommand((db, log, ct) => BasicCommands.Count(path, extras, db, log, ct), cancel);

                        break;
                    }

                    case "show":
                    case "top":
                    {
                        var path = ParsePath(CurrentDirectoryPath);
                        await RunAsyncCommand((db, log, ct) => BasicCommands.Show(path, extras, false, db, log, ct), cancel);

                        break;
                    }

                    case "last":
                    {
                        var path = ParsePath(CurrentDirectoryPath);
                        await RunAsyncCommand((db, log, ct) => BasicCommands.Show(path, extras, true, db, log, ct), cancel);

                        break;
                    }

                    case "cd":
                    case "pwd":
                    {
                        if (!string.IsNullOrEmpty(prm))
                        {
                            var newPath = CombinePath(CurrentDirectoryPath, prm);
                            var res     = await RunAsyncCommand((db, log, ct) => BasicCommands.TryOpenCurrentDirectoryAsync(ParsePath(newPath), db, ct), cancel);

                            if (res.Failed)
                            {
                                Console.Error.WriteLine("# Failed to open Directory {0}: {1}", newPath, res.Error.Message);
                                Console.Beep();
                            }
                            else if (res.Value == null)
                            {
                                Console.WriteLine("# Directory {0} does not exist!", newPath);
                                Console.Beep();
                            }
                            else
                            {
                                CurrentDirectoryPath = newPath;
                                updatePrompt(CurrentDirectoryPath);
                            }
                        }
                        else
                        {
                            var res = await RunAsyncCommand((db, log, ct) => BasicCommands.TryOpenCurrentDirectoryAsync(ParsePath(CurrentDirectoryPath), db, ct), cancel);

                            if (res.Failed)
                            {
                                Console.Error.WriteLine("# Failed to query Directory {0}: {1}", Program.CurrentDirectoryPath, res.Error.Message);
                            }
                            else if (res.Value == null)
                            {
                                Console.WriteLine("# Directory {0} does not exist anymore", CurrentDirectoryPath);
                            }
                            else
                            {
                                Console.WriteLine("# {0}", res);
                            }
                        }
                        break;
                    }

                    case "mkdir":
                    case "md":
                    {                             // "mkdir DIRECTORYNAME"
                        if (!string.IsNullOrEmpty(prm))
                        {
                            var path = ParsePath(CombinePath(CurrentDirectoryPath, prm));
                            await RunAsyncCommand((db, log, ct) => BasicCommands.CreateDirectory(path, extras, db, log, ct), cancel);
                        }
                        break;
                    }

                    case "rmdir":
                    {                             // "rmdir DIRECTORYNAME"
                        if (!string.IsNullOrEmpty(prm))
                        {
                            var path = ParsePath(CombinePath(CurrentDirectoryPath, prm));
                            await RunAsyncCommand((db, log, ct) => BasicCommands.RemoveDirectory(path, extras, db, log, ct), cancel);
                        }
                        break;
                    }

                    case "mv":
                    case "ren":
                    {                             // "mv SOURCE DESTINATION"
                        var srcPath = ParsePath(CombinePath(CurrentDirectoryPath, prm));
                        var dstPath = ParsePath(CombinePath(CurrentDirectoryPath, extras.Get <string>(0)));
                        await RunAsyncCommand((db, log, ct) => BasicCommands.MoveDirectory(srcPath, dstPath, extras.Substring(1), db, log, ct), cancel);

                        break;
                    }

                    case "layer":
                    {
                        if (string.IsNullOrEmpty(prm))
                        {                                 // displays the layer id of the current folder
                            var path = ParsePath(CurrentDirectoryPath);
                            await RunAsyncCommand((db, log, ct) => BasicCommands.ShowDirectoryLayer(path, extras, db, log, ct), cancel);
                        }
                        else
                        {                                 // change the layer id of the current folder
                            prm = prm.Trim();
                            // double or single quotes can be used to escape the value
                            if (prm.Length >= 2 && (prm.StartsWith("'") && prm.EndsWith("'")) || (prm.StartsWith("\"") && prm.EndsWith("\"")))
                            {
                                prm = prm.Substring(1, prm.Length - 2);
                            }
                            var path = ParsePath(CurrentDirectoryPath);
                            await RunAsyncCommand((db, log, ct) => BasicCommands.ChangeDirectoryLayer(path, prm, extras, db, log, ct), cancel);
                        }
                        break;
                    }

                    case "mkpart":
                    {                             // "mkpart PARTITIONNAME"
                        if (!string.IsNullOrEmpty(prm))
                        {
                            var path = ParsePath(CombinePath(CurrentDirectoryPath, prm));
                            await RunAsyncCommand((db, log, ct) => BasicCommands.CreateDirectory(path, STuple.Create(FdbDirectoryPartition.LayerId).Concat(extras), db, log, ct), cancel);
                        }

                        break;
                    }

                    case "topology":
                    {
                        await RunAsyncCommand((db, log, ct) => BasicCommands.Topology(null, extras, db, log, ct), cancel);

                        break;
                    }

                    case "shards":
                    {
                        var path = ParsePath(CombinePath(CurrentDirectoryPath, prm));
                        await RunAsyncCommand((db, log, ct) => BasicCommands.Shards(path, extras, db, log, ct), cancel);

                        break;
                    }

                    case "sampling":
                    {
                        var path = ParsePath(CombinePath(CurrentDirectoryPath, prm));
                        await RunAsyncCommand((db, log, ct) => BasicCommands.Sampling(path, extras, db, log, ct), cancel);

                        break;
                    }

                    case "coordinators":
                    {
                        await RunAsyncCommand((db, log, ct) => CoordinatorsCommand(db, log, ct), cancel);

                        break;
                    }

                    case "partition":
                    {
                        if (string.IsNullOrEmpty(prm))
                        {
                            Console.WriteLine("# Current partition is {0}", String.Join("/", partition));
                            //TODO: browse existing partitions ?
                            break;
                        }

                        var          newPartition = prm.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
                        IFdbDatabase newDb        = null;
                        try
                        {
                            var options = new FdbConnectionOptions
                            {
                                ClusterFile   = clusterFile,
                                DbName        = dbName,
                                PartitionPath = newPartition
                            };
                            newDb = await ChangeDatabase(options, cancel);
                        }
                        catch (Exception)
                        {
                            if (newDb != null)
                            {
                                newDb.Dispose();
                            }
                            newDb = null;
                            throw;
                        }
                        finally
                        {
                            if (newDb != null)
                            {
                                if (Db != null)
                                {
                                    Db.Dispose(); Db = null;
                                }
                                Db        = newDb;
                                partition = newPartition;
                                Console.WriteLine("# Changed partition to {0}", partition);
                            }
                        }
                        break;
                    }

                    case "q":
                    case "x":
                    case "quit":
                    case "exit":
                    case "bye":
                    {
                        stop = true;
                        break;
                    }

                    case "gc":
                    {
                        long before = GC.GetTotalMemory(false);
                        Console.Write("Collecting garbage...");
                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                        GC.Collect();
                        Console.WriteLine(" Done");
                        long after = GC.GetTotalMemory(false);
                        Console.WriteLine("- before = " + before.ToString("N0"));
                        Console.WriteLine("- after  = " + after.ToString("N0"));
                        Console.WriteLine("- delta  = " + (before - after).ToString("N0"));
                        break;
                    }

                    case "mem":
                    {
                        Console.WriteLine("Memory usage:");
                        Console.WriteLine("- Managed Mem  : " + GC.GetTotalMemory(false).ToString("N0"));
                        //TODO: how do we get these values on Linux/Mac?
#if !NETCOREAPP
                        Console.WriteLine("- Working Set  : " + PerfCounters.WorkingSet.NextValue().ToString("N0") + " (peak " + PerfCounters.WorkingSetPeak.NextValue().ToString("N0") + ")");
                        Console.WriteLine("- Virtual Bytes: " + PerfCounters.VirtualBytes.NextValue().ToString("N0") + " (peak " + PerfCounters.VirtualBytesPeak.NextValue().ToString("N0") + ")");
                        Console.WriteLine("- Private Bytes: " + PerfCounters.PrivateBytes.NextValue().ToString("N0"));
                        Console.WriteLine("- BytesInAlHeap: " + PerfCounters.ClrBytesInAllHeaps.NextValue().ToString("N0"));
#endif
                        break;
                    }

                    case "wide":
                    {
                        Console.WindowWidth = 160;
                        break;
                    }

                    case "status":
                    case "wtf":
                    {
                        var result = await RunAsyncCommand((_, log, ct) => FdbCliCommands.RunFdbCliCommand("status details", null, clusterFile, log, ct), cancel);

                        if (result.Failed)
                        {
                            break;
                        }
                        if (result.Value.ExitCode != 0)
                        {
                            Console.WriteLine("# fdbcli exited with code {0}", result.Value.ExitCode);
                            Console.WriteLine("> StdErr:");
                            Console.WriteLine(result.Value.StdErr);
                            Console.WriteLine("> StdOut:");
                        }
                        Console.WriteLine(result.Value.StdOut);
                        break;
                    }

                    default:
                    {
                        Console.WriteLine(string.Format("Unknown command : '{0}'", trimmedCommand));
                        break;
                    }
                    }

                    if (!string.IsNullOrEmpty(execCommand))
                    {                     // only run one command, and then exit
                        break;
                    }
                }
            }
            finally
            {
                if (Db != null)
                {
                    Db.Dispose();
                }
            }
        }
Esempio n. 12
0
        private static async Task MainAsync(string[] args, CancellationToken cancel)
        {
            Console.CursorVisible        = false;
            Console.TreatControlCAsInput = true;
            try
            {
                CancellationTokenSource cts = null;
                Task burner = null;

                const int CAPACITY = 4 * 2;
                var       history  = new Queue <Datum>(CAPACITY);

                var options = new FdbConnectionOptions
                {
                    ClusterFile    = Program.ClusterPath,
                    DefaultTimeout = TimeSpan.FromSeconds(10)
                };
                //TODO: proper parsing of command line arguments!

                using (var db = await Fdb.OpenAsync(options, cancel))
                {
                    bool exit    = false;
                    bool hot     = false;
                    bool repaint = true;

                    var processName       = Process.GetCurrentProcess().ProcessName;
                    var perCpu            = new PerformanceCounter("Process", "% Processor Time", processName);
                    var perfDiskReads     = new PerformanceCounter("PhysicalDisk", "Disk Read Bytes/sec", "0 C:");
                    var perfDiskWrites    = new PerformanceCounter("PhysicalDisk", "Disk Write Bytes/sec", "0 C:");
                    var perfDiskWriteIops = new PerformanceCounter("PhysicalDisk", "Disk Writes/sec", "0 C:");
                    var perfDiskReadIops  = new PerformanceCounter("PhysicalDisk", "Disk Reads/sec", "0 C:");

                    const int COL0 = 1;
                    const int COL1 = COL0 + 15;
                    const int COL2 = COL1 + 15;
                    const int COL3 = COL2 + 15;
                    const int COL4 = COL3 + 15;

                    while (!exit && !cancel.IsCancellationRequested)
                    {
                        if (Console.KeyAvailable)
                        {
                            var k = Console.ReadKey();
                            switch (k.Key)
                            {
                            case ConsoleKey.Escape:
                            {                                     // [ESC]
                                exit = true;
                                break;
                            }

                            case ConsoleKey.C:
                            {
                                if (k.Modifiers.HasFlag(ConsoleModifiers.Control))
                                {                                         // CTRL-C
                                    exit = true;
                                }
                                break;
                            }

                            case ConsoleKey.R:
                            {
                                Randomized = !Randomized;
                                repaint    = true;
                                break;
                            }

                            case ConsoleKey.V:
                            {                                     // Change Value Size
                                CurrentSize = (CurrentSize + 1) % VALUE_SIZES.Length;
                                Value       = Slice.Random(Rnd, VALUE_SIZES[CurrentSize]);
                                repaint     = true;
                                break;
                            }

                            case ConsoleKey.Spacebar:
                            {
                                hot     = !hot;
                                repaint = true;
                                if (hot)
                                {
                                    cts    = new CancellationTokenSource();
                                    burner = Task.Run(() => BurnerThread(db, cts.Token), cts.Token);
                                }
                                else
                                {
                                    cts.Cancel();
                                    try { await burner; }
                                    catch (TaskCanceledException) { }
                                    cts.Dispose();
                                }
                                break;
                            }
                            }
                        }

                        if (!repaint)
                        {
                            await Task.Delay(250);
                        }

                        long   curKeys        = Volatile.Read(ref Keys);
                        long   curTrans       = Volatile.Read(ref Transactions);
                        long   curBytes       = Volatile.Read(ref Bytes);
                        double curDiskWrites  = perfDiskWrites.NextValue();
                        double curDiskReads   = perfDiskReads.NextValue();
                        double curDiskWriteIo = perfDiskWriteIops.NextValue();
                        double curDiskReadIo  = perfDiskReadIops.NextValue();

                        while (history.Count >= CAPACITY)
                        {
                            history.Dequeue();
                        }

                        var now = DateTime.UtcNow;
                        history.Enqueue(new Datum
                        {
                            Date          = now,
                            Keys          = curKeys,
                            Commits       = curTrans,
                            Bytes         = curBytes,
                            DiskWriteBps  = curDiskWrites,
                            DiskReadBps   = curDiskReads,
                            DiskWriteIops = curDiskWriteIo,
                            DiskReadIops  = curDiskReadIo,
                        });

                        if (repaint)
                        {
                            Console.Title = "FdbBurner - " + (!hot ? "ICY COLD" : Randomized ? "HOT HOT HOT" : "HOT HOT");

                            Console.BackgroundColor = !hot ? ConsoleColor.DarkCyan : Randomized ? ConsoleColor.DarkRed : ConsoleColor.DarkGreen;
                            Console.Clear();
                            Console.ForegroundColor = ConsoleColor.Gray;
                            WriteAt(COL0, 1, "Pattern   : {0,10}", "");
                            WriteAt(COL2, 1, "Value Size: {0,6} bytes", "");
                            WriteAt(COL0, 3, "{0,-12}", "Transactions");
                            WriteAt(COL1, 3, "{0,-12}", "Keys");
                            WriteAt(COL2, 3, "{0,-10}", "Written Bytes");
                            WriteAt(COL3, 3, "{0,-10}", "Disk Writes");
                            WriteAt(COL4, 3, "{0,-10}", "Disk Reads");
                            WriteAt(COL3, 7, "{0,-10}", "Write IOPS");
                            WriteAt(COL4, 7, "{0,-10}", "Read IOPS");

                            repaint = false;
                        }

                        Console.ForegroundColor = ConsoleColor.White;
                        WriteAt(COL0 + 12, 1, "{0,-10}", Randomized ? "Random" : "Sequential");
                        WriteAt(COL2 + 12, 1, "{0,6:N0}", Value.Count);

                        WriteAt(COL0, 4, "{0,12:N0}", curTrans);
                        WriteAt(COL1, 4, "{0,12:N0}", curKeys);
                        WriteAt(COL2, 4, "{0,10:N1} MB", curBytes / 1048576.0);
                        WriteAt(COL3, 4, "{0,10:N1} MB/s", curDiskWrites / 1048576.0);
                        WriteAt(COL4, 4, "{0,10:N1} MB/s", curDiskReads / 1048576.0);

                        if (history.Count > 1)
                        {
                            var    old = history.Peek();
                            var    dur = (now - old.Date).TotalSeconds;
                            double speed;

                            Console.ForegroundColor = ConsoleColor.White;

                            speed = (curTrans - old.Commits) / dur;
                            WriteAt(COL0, 5, "{0,12:N0}", speed);

                            speed = (curKeys - old.Keys) / dur;
                            WriteAt(COL1, 5, "{0,12:N0}", speed);

                            speed = (curBytes - old.Bytes) / dur;
                            WriteAt(COL2, 5, "{0,10:N1} MB/s", speed / 1048576.0);

                            var writeSpeed = history.Average(d => d.DiskWriteBps);
                            var readSpeed  = history.Average(d => d.DiskReadBps);
                            WriteAt(COL3, 5, "{0,10:N1} MB/s", writeSpeed / 1048576.0);
                            WriteAt(COL4, 5, "{0,10:N1} MB/s", readSpeed / 1048576.0);

                            var writeIops = history.Average(d => d.DiskWriteIops);
                            var readIops  = history.Average(d => d.DiskReadIops);
                            WriteAt(COL3, 8, "{0,10:N0} iops", writeIops);
                            WriteAt(COL4, 8, "{0,10:N0} iops", readIops);

                            var factor = speed > 0 ? writeSpeed / speed : 0;
                            WriteLarge(0, 16, "{0,8:F3}", speed / 1048576.0);
                            WriteLarge(0, 24, "{0,8:F3}", writeSpeed / 1048576.0);
                            WriteLarge(0, 32, "X{0,5:F1}", factor);
                        }


                        Console.SetCursorPosition(0, 0);
                    }
                }
            }
            finally
            {
                Console.CursorVisible = true;
                Console.ResetColor();
                Console.Clear();
            }
        }
Esempio n. 13
0
 public static IFdbDatabaseProviderBuilder WithConnectionString([NotNull] this IFdbDatabaseProviderBuilder builder, [NotNull] FdbConnectionOptions options)
 {
     Contract.NotNull(options, nameof(options));
     builder.Services.Configure <FdbDatabaseProviderOptions>(c =>
     {
         c.ConnectionOptions = options;
     });
     return(builder);
 }
Esempio n. 14
0
        static void Main(string[] args)
        {
            bool stop = false;

            string clusterFile = null;
            var    partition   = FdbPath.Root;

            int    pStart       = 0;
            string startCommand = null;

            while (pStart < args.Length)
            {
                if (args[pStart].StartsWith("-"))
                {
                    switch (args[pStart].Substring(1))
                    {
                    case "C":
                    case "c":
                    {
                        clusterFile = args[pStart + 1];
                        pStart     += 2;
                        break;
                    }

                    case "P":
                    case "p":
                    {
                        partition = FdbPath.Parse(args[pStart + 1].Trim());
                        pStart   += 2;
                        break;
                    }

                    default:
                    {
                        Console.WriteLine($"Unknown option : '{args[pStart]}'");
                        pStart++;
                        break;
                    }
                    }
                }
                else
                {
                    break;
                }
            }

            if (args.Length > 0 && pStart < args.Length)
            {             // the remainder of the command line will be the first command to execute
                startCommand = String.Join(" ", args, pStart, args.Length - pStart);
            }

            var go = new CancellationTokenSource();

            // Initialize FDB
            Fdb.Start(Fdb.GetDefaultApiVersion());
            try
            {
                var options = new FdbConnectionOptions
                {
                    ClusterFile = clusterFile,
                    Root        = partition,
                };
                Db = Fdb.OpenAsync(options, go.Token).GetAwaiter().GetResult();

                using (Db)
                {
                    Db.DefaultTimeout    = 30 * 1000;
                    Db.DefaultRetryLimit = 10;

                    Console.WriteLine("Using API v" + Fdb.ApiVersion + " (max " + Fdb.GetMaxApiVersion() + ")");
                    Console.WriteLine("Cluster file: " + (clusterFile ?? "<default>"));

                    Console.WriteLine();
                    Console.WriteLine("FoundationDB Samples menu:");
                    Console.WriteLine("\t1\tRun Class Scheduling sample");
                    Console.WriteLine("\tL\tRun Leak test");
                    Console.WriteLine("\tbench\tRun synthetic benchmarks");
                    Console.WriteLine("\tgc\tTrigger a .NET garbage collection");
                    Console.WriteLine("\tmem\tDisplay memory usage statistics");
                    Console.WriteLine("\tq\tQuit");

                    Console.WriteLine("Ready...");

                    while (!stop)
                    {
                        Console.Write("> ");
                        string s = startCommand != null ? startCommand : Console.ReadLine();
                        startCommand = null;

                        var    tokens = s.Trim().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                        string cmd    = tokens.Length > 0 ? tokens[0] : String.Empty;
                        string prm    = tokens.Length > 1 ? tokens[1] : String.Empty;

                        var trimmedCommand = cmd.Trim().ToLowerInvariant();
                        switch (trimmedCommand)
                        {
                        case "":
                        {
                            continue;
                        }

                        case "1":
                        {                                 // Class Scheduling
                            RunAsyncTest(new ClassScheduling(), go.Token);
                            break;
                        }

                        case "log":
                        {
                            switch (prm.ToLowerInvariant())
                            {
                            case "on":
                            {
                                LogEnabled = true;
                                Console.WriteLine("# Logging enabled");
                                break;
                            }

                            case "off":
                            {
                                LogEnabled = false;
                                Console.WriteLine("# Logging disabled");
                                break;
                            }

                            default:
                            {
                                Console.WriteLine("# Logging is {0}", LogEnabled ? "ON" : "OFF");
                                break;
                            }
                            }
                            break;
                        }

                        case "bench":
                        {                                 // Benchs
                            switch (prm.ToLowerInvariant())
                            {
                            case "read":
                            {
                                RunAsyncTest(new BenchRunner(BenchRunner.BenchMode.GetReadVersion), go.Token);
                                break;
                            }

                            case "get":
                            {
                                RunAsyncTest(new BenchRunner(BenchRunner.BenchMode.Get), go.Token);
                                break;
                            }

                            case "get10":
                            {
                                RunAsyncTest(new BenchRunner(BenchRunner.BenchMode.Get, 10), go.Token);
                                break;
                            }

                            case "set":
                            {                                             // Bench Set
                                RunAsyncTest(new BenchRunner(BenchRunner.BenchMode.Set), go.Token);
                                break;
                            }

                            case "watch":
                            {                                             // Bench Set
                                RunAsyncTest(new BenchRunner(BenchRunner.BenchMode.Watch), go.Token);
                                break;
                            }
                            }

                            break;
                        }

                        case "msg":
                        {
                            switch (prm.ToLowerInvariant())
                            {
                            case "producer":
                            {                                             // Queue Producer
                                RunAsyncTest(new MessageQueueRunner(PerfCounters.ProcessName + "[" + PerfCounters.ProcessId + "]", MessageQueueRunner.AgentRole.Producer, TimeSpan.FromMilliseconds(50), TimeSpan.FromMilliseconds(200)), go.Token);
                                break;
                            }

                            case "worker":
                            {                                             // Queue Worker
                                RunAsyncTest(new MessageQueueRunner(PerfCounters.ProcessName + "[" + PerfCounters.ProcessId + "]", MessageQueueRunner.AgentRole.Worker, TimeSpan.FromMilliseconds(10), TimeSpan.FromMilliseconds(10)), go.Token);
                                break;
                            }

                            case "clear":
                            {                                             // Queue Clear
                                RunAsyncTest(new MessageQueueRunner(PerfCounters.ProcessName + "[" + PerfCounters.ProcessId + "]", MessageQueueRunner.AgentRole.Clear, TimeSpan.Zero, TimeSpan.Zero), go.Token);
                                break;
                            }

                            case "status":
                            {                                             // Queue Status
                                RunAsyncTest(new MessageQueueRunner(PerfCounters.ProcessName + "[" + PerfCounters.ProcessId + "]", MessageQueueRunner.AgentRole.Status, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10)), go.Token);
                                break;
                            }
                            }
                            break;
                        }

                        case "leak":
                        {                                 // LeastTest
                            switch (prm.ToLowerInvariant())
                            {
                            case "fast": RunAsyncTest(new LeakTest(100, 100, 1000, TimeSpan.FromSeconds(0)), go.Token); break;

                            case "slow": RunAsyncTest(new LeakTest(100, 100, 1000, TimeSpan.FromSeconds(30)), go.Token); break;

                            default: RunAsyncTest(new LeakTest(100, 100, 1000, TimeSpan.FromSeconds(1)), go.Token); break;
                            }
                            break;
                        }

                        case "sampling":
                        {                                 // SamplingTest
                            RunAsyncTest(new SamplerTest(0.1), go.Token);
                            break;
                        }

                        case "q":
                        case "x":
                        case "quit":
                        case "exit":
                        {
                            stop = true;
                            break;
                        }

                        case "gc":
                        {
                            long before = GC.GetTotalMemory(false);
                            Console.Write("Collecting garbage...");
                            GC.Collect();
                            GC.WaitForPendingFinalizers();
                            GC.Collect();
                            Console.WriteLine(" Done");
                            long after = GC.GetTotalMemory(false);
                            Console.WriteLine("- before = " + before.ToString("N0"));
                            Console.WriteLine("- after  = " + after.ToString("N0"));
                            Console.WriteLine("- delta  = " + (before - after).ToString("N0"));
                            break;
                        }

                        case "mem":
                        {
                            Console.WriteLine("Memory usage:");
                            Console.WriteLine("- Managed Mem  : " + GC.GetTotalMemory(false).ToString("N0"));
#if !NETCOREAPP
                            Console.WriteLine("- Working Set  : " + PerfCounters.WorkingSet.NextValue().ToString("N0") + " (peak " + PerfCounters.WorkingSetPeak.NextValue().ToString("N0") + ")");
                            Console.WriteLine("- Virtual Bytes: " + PerfCounters.VirtualBytes.NextValue().ToString("N0") + " (peak " + PerfCounters.VirtualBytesPeak.NextValue().ToString("N0") + ")");
                            Console.WriteLine("- Private Bytes: " + PerfCounters.PrivateBytes.NextValue().ToString("N0"));
                            Console.WriteLine("- BytesInAlHeap: " + PerfCounters.ClrBytesInAllHeaps.NextValue().ToString("N0"));
#endif
                            break;
                        }

                        default:
                        {
                            Console.WriteLine(string.Format("Unknown command : '{0}'", trimmedCommand));
                            break;
                        }
                        }
                    }
                }
            }
            finally
            {
                go.Cancel();
                Fdb.Stop();
                Console.WriteLine("Bye");
            }
        }
 public static IFdbDatabaseProviderBuilder WithConnectionString(this IFdbDatabaseProviderBuilder builder, FdbConnectionOptions options)
 {
     builder.Services.Configure <FdbDatabaseProviderOptions>(c =>
     {
         c.ConnectionOptions = options;
     });
     return(builder);
 }
        private static async Task MainAsync(CancellationToken ct)
        {
            // change the path to the native lib if not default
            if (NATIVE_PATH != null)
            {
                Fdb.Options.SetNativeLibPath(NATIVE_PATH);
            }

            // uncomment this to enable network thread tracing
            // FdbCore.TracePath = Path.Combine(Path.GetTempPath(), "fdb");

            int apiVersion = Fdb.GetMaxApiVersion();

            Console.WriteLine("Max API Version: " + apiVersion);

            try
            {
                Console.WriteLine("Starting network thread...");
                Fdb.Start(Fdb.GetDefaultApiVersion());
                Console.WriteLine("> Up and running");

                var settings = new FdbConnectionOptions()
                {
                    ClusterFile = CLUSTER_FILE,
                    Root        = FdbPath.Parse("/Sandbox"),
                };

                Console.WriteLine("Connecting to local cluster...");
                using (var db = await Fdb.OpenAsync(settings, ct))
                {
                    Console.WriteLine("> Connected!");

                    // get coordinators
                    var cf = await Fdb.System.GetCoordinatorsAsync(db, ct);

                    Console.WriteLine("Coordinators: " + cf.ToString());

                    // clear everything
                    using (var tr = await db.BeginTransactionAsync(ct))
                    {
                        Console.WriteLine("Clearing subspace " + db.Root + " ...");
                        var subspace = await db.Root.Resolve(tr);

                        tr.ClearRange(subspace);
                        await tr.CommitAsync();

                        Console.WriteLine("> Database cleared");
                    }

                    Console.WriteLine();

                    await TestSimpleTransactionAsync(db, ct);

                    await BenchInsertSmallKeysAsync(db, N, 16, ct);                     // some guid
                    await BenchInsertSmallKeysAsync(db, N, 60 * 4, ct);                 // one Int32 per minutes, over an hour
                    await BenchInsertSmallKeysAsync(db, N, 512, ct);                    // small JSON payload
                    await BenchInsertSmallKeysAsync(db, N / 5, 4096, ct);               // typical small cunk size
                    await BenchInsertSmallKeysAsync(db, N / 100, 65536, ct);            // typical medium chunk size
                    await BenchInsertSmallKeysAsync(db, 20, 100_000, ct);               // Maximum value size (as of beta 1)

                    // insert keys in parrallel
                    await BenchConcurrentInsert(db, 1, 100, 512, ct);
                    await BenchConcurrentInsert(db, 1, 1_000, 512, ct);
                    await BenchConcurrentInsert(db, 1, 10_000, 512, ct);

                    await BenchConcurrentInsert(db, 1, N, 16, ct);
                    await BenchConcurrentInsert(db, 2, N, 16, ct);
                    await BenchConcurrentInsert(db, 4, N, 16, ct);
                    await BenchConcurrentInsert(db, 8, N, 16, ct);
                    await BenchConcurrentInsert(db, 16, N, 16, ct);

                    await BenchSerialWriteAsync(db, N, ct);
                    await BenchSerialReadAsync(db, N, ct);
                    await BenchConcurrentReadAsync(db, N, ct);

                    await BenchClearAsync(db, N, ct);

                    await BenchUpdateSameKeyLotsOfTimesAsync(db, 1000, ct);

                    await BenchUpdateLotsOfKeysAsync(db, 1000, ct);

                    await BenchBulkInsertThenBulkReadAsync(db, 100_000, 50, 128, ct);
                    await BenchBulkInsertThenBulkReadAsync(db, 100_000, 128, 50, ct);
                    await BenchBulkInsertThenBulkReadAsync(db, 1_000_000, 50, 128, ct);

                    await BenchMergeSortAsync(db, 100, 3, 20, ct);
                    await BenchMergeSortAsync(db, 1_000, 10, 100, ct);
                    await BenchMergeSortAsync(db, 100, 100, 100, ct);
                    await BenchMergeSortAsync(db, 100, 1_000, 100, ct);

                    Console.WriteLine("time to say goodbye...");
                }
            }
            finally
            {
                Console.WriteLine("### DONE ###");
                Fdb.Stop();
            }
#if DEBUG
            Console.ReadLine();
#endif
        }