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""")); }
private static FdbPath RemoveIndirection(FdbPath path) { Contract.Requires(path.IsAbsolute, "Path must be absolute"); var segments = new Stack <FdbPathSegment>(path.Count); foreach (var seg in path.Segments.Span) { if (seg.Name == ".") { continue; } if (seg.Name == "..") { if (segments.Count == 0) { throw new InvalidOperationException("The specified path is invalid."); } segments.Pop(); continue; } segments.Push(seg); } return(FdbPath.Absolute(segments.ToArray())); }
/// <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)); }
private static bool HasIndirection(FdbPath path) { foreach (var seg in path) { if (seg.Name == "." || seg.Name == "..") { return(true); } } return(false); }
public void Test_FdbPath_Substring_Absolute() { var path = FdbPath.Absolute("Foo", "Bar", "Baz"); var slice = path.Substring(0, 2); Assert.That(slice.IsAbsolute, Is.True); Assert.That(slice[0].Name, Is.EqualTo("Foo")); Assert.That(slice[0].LayerId, Is.EqualTo(string.Empty)); Assert.That(slice[1].Name, Is.EqualTo("Bar")); Assert.That(slice[1].LayerId, Is.EqualTo(string.Empty)); }
private static async Task <string[]> AutoCompleteDirectories(FdbPath path, IFdbDatabase db, TextWriter log, CancellationToken ct) { var parent = await db.ReadAsync(tr => BasicCommands.TryOpenCurrentDirectoryAsync(tr, path), ct); if (parent == null) { return(null); } var paths = await db.ReadAsync(tr => parent.ListAsync(tr), ct); return(paths.Select(p => p.Name).ToArray()); }
/// <summary>Remove a directory and all its data</summary> public static async Task RemoveDirectory(FdbPath path, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct) { if (log == null) { log = Console.Out; } // "-r|--recursive" is used to allow removing an entire sub-tree string[] args = extras.ToArray <string>(); bool recursive = args.Contains("-r", StringComparer.Ordinal) || args.Contains("--recursive", StringComparer.Ordinal); bool force = args.Contains("-f", StringComparer.Ordinal) || args.Contains("--force", StringComparer.Ordinal); var res = await db.ReadWriteAsync(async tr => { var folder = await db.DirectoryLayer.TryOpenAsync(tr, path); if (folder == null) { Program.Error(log, $"# Directory {path} does not exist"); return(false); } // are there any subdirectories ? if (!recursive) { var subDirs = await folder.TryListAsync(tr); if (subDirs != null && subDirs.Count > 0) { //TODO: "-r" flag ? Program.Error(log, $"# Cannot remove {path} because it still contains {subDirs.Count:N0} sub-directories."); Program.StdOut(log, "Use the -r|--recursive flag to override this warning."); return(false); } } if (!force) { //TODO: ask for confirmation? } await folder.RemoveAsync(tr); return(true); }, ct); if (res) { Program.Success(log, $"Deleted directory {path}"); } }
public static Task ChangeDirectoryLayer(FdbPath path, string layer, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct) { return(db.WriteAsync(async tr => { var dir = await BasicCommands.TryOpenCurrentDirectoryAsync(tr, path); if (dir == null) { Program.Error(log, $"# Directory {path} does not exist anymore"); } else { dir = await dir.ChangeLayerAsync(tr, layer); Program.Success(log, $"# Directory {path} layer changed to {dir.Layer}"); } }, ct)); }
/// <summary>Creates a new directory</summary> public static async Task CreateDirectory(FdbPath path, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct) { if (log == null) { log = Console.Out; } string layer = extras.Count > 0 ? extras.Get <string>(0).Trim() : string.Empty; if (path.LayerId != layer) { path.WithLayer(layer); } log.WriteLine($"# Creating directory {path}"); (var prefix, var created) = await db.ReadWriteAsync(async tr => { var folder = await db.DirectoryLayer.TryOpenAsync(tr, path); if (folder != null) { return(folder.GetPrefix(), false); } folder = await db.DirectoryLayer.TryCreateAsync(tr, path); return(folder.Copy().GetPrefix(), true); }, ct); if (!created) { log.WriteLine($"- Directory {path} already exists at {FdbKey.Dump(prefix)} [{prefix.ToHexaString(' ')}]"); return; } log.WriteLine($"- Created under {FdbKey.Dump(prefix)} [{prefix.ToHexaString(' ')}]"); // look if there is already stuff under there var stuff = await db.ReadAsync(async tr => { var folder = await db.DirectoryLayer.TryOpenAsync(tr, path); return(await tr.GetRange(folder.ToRange()).FirstOrDefaultAsync()); }, ct); if (stuff.Key.IsPresent) { Program.Error(log, $"CAUTION: There is already some data under {path} !"); Program.Error(log, $" {FdbKey.Dump(stuff.Key)} = {stuff.Value:V}"); } }
private static FdbPath CombinePath(FdbPath parent, string children) { if (string.IsNullOrEmpty(children) || children == ".") { return(parent); } var p = FdbPath.Parse(children); if (!p.IsAbsolute) { p = parent[p]; } if (HasIndirection(p)) { p = RemoveIndirection(p); } return(p); }
public void Test_FdbPath_Basics() { { var path = FdbPath.Relative("Foo"); Assert.That(path.IsEmpty, Is.False, "[Foo].IsEmpty"); Assert.That(path.Count, Is.EqualTo(1), "[Foo].Count"); Assert.That(path.Name, Is.EqualTo("Foo"), "[Foo].Name"); Assert.That(path.ToString(), Is.EqualTo("Foo"), "[Foo].ToString()"); Assert.That(path[0].Name, Is.EqualTo("Foo"), "[Foo][0]"); Assert.That(path[0].LayerId, Is.EqualTo(string.Empty), "[Foo][0]"); Assert.That(path.GetParent(), Is.EqualTo(FdbPath.Empty), "[Foo].Name"); Assert.That(path, Is.EqualTo(path), "[Foo].Equals([Foo])"); #pragma warning disable CS1718 // Comparison made to same variable // ReSharper disable EqualExpressionComparison Assert.That(path == path, Is.True, "[Foo] == [Foo]"); Assert.That(path != path, Is.False, "[Foo] != [Foo]"); // ReSharper restore EqualExpressionComparison #pragma warning restore CS1718 // Comparison made to same variable Assert.That(path, Is.EqualTo(FdbPath.Relative("Foo")), "[Foo].Equals([Foo]')"); Assert.That(path, Is.EqualTo(FdbPath.Relative("Foo", "Bar").GetParent()), "[Foo].Equals([Foo/Bar].GetParent())"); Assert.That(path, Is.Not.EqualTo(FdbPath.Empty), "[Foo].Equals(Empty)"); Assert.That(path == FdbPath.Empty, Is.False, "[Foo] == Empty"); Assert.That(path != FdbPath.Empty, Is.True, "[Foo] != Empty"); } { var path1 = FdbPath.Relative("Foo", "Bar"); var path2 = FdbPath.Parse("Foo/Bar"); var path3 = new FdbPath(new[] { FdbPathSegment.Create("Foo"), FdbPathSegment.Create("Bar") }, false); Assert.That(path2, Is.EqualTo(path1), "path1 eq path2"); Assert.That(path3, Is.EqualTo(path1), "path1 eq path3"); Assert.That(path3, Is.EqualTo(path2), "path2 eq path3"); Assert.That(path2.GetHashCode(), Is.EqualTo(path1.GetHashCode()), "h(path1) == h(path2)"); Assert.That(path3.GetHashCode(), Is.EqualTo(path1.GetHashCode()), "h(path1) == h(path3)"); } }
public static async Task Get(FdbPath path, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct) { if (path.IsRoot) { Program.Error(log, "Cannot read keys of the Root Partition."); return; } if (extras.Count == 0) { Program.Error(log, "You must specify a key of range of keys!"); return; } (var v, bool pathNotFound) = await db.ReadAsync(async tr => { var folder = await db.DirectoryLayer.TryOpenAsync(tr, path); if (folder == null) { Program.Error(log, "The directory does not exist anymore"); return(default, false);
public void Test_FdbPath_Simple_Absolute() { var foo = FdbPath.Absolute("Foo"); Assert.That(foo.ToString(), Is.EqualTo("/Foo")); Assert.That(foo.IsAbsolute, Is.True); Assert.That(foo.IsEmpty, Is.False); Assert.That(foo.IsRoot, Is.False); Assert.That(foo.Count, Is.EqualTo(1)); Assert.That(foo[0].Name, Is.EqualTo("Foo")); Assert.That(foo[0].LayerId, Is.EqualTo(string.Empty)); Assert.That(foo.Name, Is.EqualTo("Foo")); Assert.That(foo.ToArray(), Is.EqualTo(new [] { FdbPathSegment.Create("Foo") })); Assert.That(foo.StartsWith(FdbPath.Root), Is.True); Assert.That(foo.IsChildOf(FdbPath.Root), Is.True); Assert.That(foo.EndsWith(FdbPath.Root), Is.False); Assert.That(foo.IsParentOf(FdbPath.Root), Is.False); var fooBar = foo["Bar"]; Assert.That(fooBar.ToString(), Is.EqualTo("/Foo/Bar")); Assert.That(fooBar.IsAbsolute, Is.True); Assert.That(fooBar.IsEmpty, Is.False); Assert.That(fooBar.IsRoot, Is.False); Assert.That(fooBar.Count, Is.EqualTo(2)); Assert.That(fooBar[0].Name, Is.EqualTo("Foo")); Assert.That(fooBar[0].LayerId, Is.EqualTo(string.Empty)); Assert.That(fooBar[1].Name, Is.EqualTo("Bar")); Assert.That(fooBar[1].LayerId, Is.EqualTo(string.Empty)); Assert.That(fooBar.Name, Is.EqualTo("Bar")); Assert.That(fooBar.ToArray(), Is.EqualTo(new [] { FdbPathSegment.Create("Foo"), FdbPathSegment.Create("Bar") })); Assert.That(fooBar.StartsWith(FdbPath.Root), Is.True); Assert.That(fooBar.IsChildOf(FdbPath.Root), Is.True); Assert.That(fooBar.IsParentOf(FdbPath.Root), Is.False); Assert.That(fooBar.EndsWith(FdbPath.Root), Is.False); Assert.That(fooBar.StartsWith(foo), Is.True); Assert.That(fooBar.IsChildOf(foo), Is.True); Assert.That(fooBar.IsParentOf(foo), Is.False); Assert.That(fooBar.EndsWith(foo), Is.False); }
public void Test_FdbPath_Empty() { var empty = FdbPath.Empty; Assert.That(empty.IsAbsolute, Is.False); Assert.That(empty.IsEmpty, Is.True); Assert.That(empty.IsRoot, Is.False); Assert.That(empty.Count, Is.EqualTo(0)); Assert.That(empty.ToString(), Is.EqualTo(string.Empty)); Assert.That(empty.Name, Is.EqualTo(string.Empty)); Assert.That(empty.Segments.Length, Is.EqualTo(0)); Assert.That(empty.ToArray(), Is.EqualTo(new string[0])); Assert.That(empty, Is.EqualTo(FdbPath.Empty)); Assert.That(empty == FdbPath.Empty, Is.True); Assert.That(empty != FdbPath.Empty, Is.False); Assert.That(empty, Is.Not.EqualTo(FdbPath.Root)); Assert.That(empty == FdbPath.Root, Is.False); Assert.That(empty != FdbPath.Root, Is.True); Assert.That(FdbPath.Parse("Hello").StartsWith(empty), Is.True); Assert.That(FdbPath.Parse("/Hello").StartsWith(empty), Is.False); }
/// <summary>Move/Rename a directory</summary> public static async Task MoveDirectory(FdbPath source, FdbPath destination, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct) { await db.WriteAsync(async tr => { var folder = await db.DirectoryLayer.TryOpenAsync(tr, source); if (folder == null) { Program.Error(log, $"# Source directory {source} does not exist!"); return; } folder = await db.DirectoryLayer.TryOpenAsync(tr, destination); if (folder != null) { Program.Error(log, $"# Destination directory {destination} already exists!"); return; } await db.DirectoryLayer.MoveAsync(tr, source, destination); }, ct); Program.Success(log, $"Moved {source} to {destination}"); }
public void Test_FdbPath_Root() { var root = FdbPath.Root; Assert.That(root.IsAbsolute, Is.True); Assert.That(root.IsEmpty, Is.False); Assert.That(root.IsRoot, Is.True); Assert.That(root.Count, Is.EqualTo(0)); Assert.That(root.ToString(), Is.EqualTo("/")); Assert.That(root.Name, Is.EqualTo(string.Empty)); Assert.That(root.Segments.Length, Is.EqualTo(0)); Assert.That(root.ToArray(), Is.EqualTo(new string[0])); Assert.That(root, Is.EqualTo(FdbPath.Root)); Assert.That(root == FdbPath.Root, Is.True); Assert.That(root != FdbPath.Root, Is.False); Assert.That(root, Is.Not.EqualTo(FdbPath.Empty)); Assert.That(root == FdbPath.Empty, Is.False); Assert.That(root != FdbPath.Empty, Is.True); Assert.That(FdbPath.Parse("Hello").StartsWith(root), Is.False); Assert.That(FdbPath.Parse("/Hello").StartsWith(root), Is.True); }
public static async Task ShowDirectoryLayer(FdbPath path, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct) { var dir = await db.ReadAsync(tr => TryOpenCurrentDirectoryAsync(tr, path), ct); if (dir == null) { Program.Error(log, $"# Directory {path} does not exist anymore"); } else { if (dir.Layer == FdbDirectoryPartition.LayerId) { log.WriteLine($"# Directory {path} is a partition"); } else if (!string.IsNullOrEmpty(dir.Layer)) { log.WriteLine($"# Directory {path} has layer '{dir.Layer}'"); } else { log.WriteLine($"# Directory {path} does not have a layer defined"); } } }
public static async Task <IFdbDirectory> TryOpenCurrentDirectoryAsync(IFdbReadOnlyTransaction tr, FdbPath path) { var location = new FdbDirectorySubspaceLocation(path); if (location.Path.Count != 0) { return(await location.Resolve(tr)); } else { return(location); } }
private static FdbDirectorySubspaceLocation ParsePath(string path) { return(Db.Root[FdbPath.Parse(path)]); //path = path.Replace("\\", "/").Trim(); //return path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); }
public void Test_FdbPath_Parse() { // Relative paths FdbPath Parse(string value) { Log($"\"{value}\":"); var path = FdbPath.Parse(value); if (path.IsEmpty) { Log("> <empty>"); } else if (path.IsRoot) { Log("> <root>"); } else { Log($"> Path='{path.ToString()}', Count={path.Count}, Name='{path.Name}', Absolute={path.IsAbsolute}"); } return(path); } { // Empty var path = Parse(""); Assert.That(path.IsAbsolute, Is.False, ".Absolute"); Assert.That(path.IsRoot, Is.False, ".IsRoot"); Assert.That(path.IsEmpty, Is.True, ".IsEmpty"); Assert.That(path.Count, Is.EqualTo(0), ".Count"); Assert.That(path.ToString(), Is.EqualTo("")); Assert.That(path.Name, Is.EqualTo(string.Empty)); } { // Foo var path = Parse("Foo"); Assert.That(path.IsAbsolute, Is.False, ".Absolute"); Assert.That(path.IsRoot, Is.False, ".IsRoot"); Assert.That(path.IsEmpty, Is.False, ".IsEmpty"); Assert.That(path.Count, Is.EqualTo(1), ".Count"); Assert.That(path[0].Name, Is.EqualTo("Foo")); Assert.That(path[0].LayerId, Is.EqualTo(string.Empty)); Assert.That(path.ToString(), Is.EqualTo("Foo")); Assert.That(path.Name, Is.EqualTo("Foo")); } { // Foo/Bar/Baz var path = Parse("Foo/Bar/Baz"); Assert.That(path.IsAbsolute, Is.False, ".Absolute"); Assert.That(path.IsRoot, Is.False, ".IsRoot"); Assert.That(path.IsEmpty, Is.False, ".IsEmpty"); Assert.That(path.Count, Is.EqualTo(3), ".Count"); Assert.That(path[0].Name, Is.EqualTo("Foo")); Assert.That(path[0].LayerId, Is.EqualTo(string.Empty)); Assert.That(path[1].Name, Is.EqualTo("Bar")); Assert.That(path[1].LayerId, Is.EqualTo(string.Empty)); Assert.That(path[2].Name, Is.EqualTo("Baz")); Assert.That(path[2].LayerId, Is.EqualTo(string.Empty)); Assert.That(path.ToString(), Is.EqualTo("Foo/Bar/Baz")); Assert.That(path.Name, Is.EqualTo("Baz")); } // Absolute path { // Root ("/") var path = Parse("/"); Assert.That(path.IsAbsolute, Is.True, ".Absolute"); Assert.That(path.IsEmpty, Is.False, ".IsEmpty"); Assert.That(path.IsRoot, Is.True, ".IsRoot"); Assert.That(path.Count, Is.EqualTo(0)); Assert.That(path.ToString(), Is.EqualTo("/")); Assert.That(path.Name, Is.EqualTo(string.Empty)); } { // /Foo var path = Parse("/Foo"); Assert.That(path.IsAbsolute, Is.True, ".Absolute"); Assert.That(path.IsEmpty, Is.False, ".IsEmpty"); Assert.That(path.IsRoot, Is.False, ".IsRoot"); Assert.That(path.Count, Is.EqualTo(1)); Assert.That(path[0].Name, Is.EqualTo("Foo")); Assert.That(path[0].LayerId, Is.EqualTo(string.Empty)); Assert.That(path.ToString(), Is.EqualTo("/Foo")); Assert.That(path.Name, Is.EqualTo("Foo")); } { // /Foo/Bar/Baz var path = Parse("/Foo/Bar/Baz"); Assert.That(path.IsAbsolute, Is.True, ".Absolute"); Assert.That(path.IsEmpty, Is.False, ".IsEmpty"); Assert.That(path.IsRoot, Is.False, ".IsRoot"); Assert.That(path.Count, Is.EqualTo(3)); Assert.That(path[0].Name, Is.EqualTo("Foo")); Assert.That(path[0].LayerId, Is.EqualTo(string.Empty)); Assert.That(path[1].Name, Is.EqualTo("Bar")); Assert.That(path[1].LayerId, Is.EqualTo(string.Empty)); Assert.That(path[2].Name, Is.EqualTo("Baz")); Assert.That(path[2].LayerId, Is.EqualTo(string.Empty)); Assert.That(path.ToString(), Is.EqualTo("/Foo/Bar/Baz")); Assert.That(path.Name, Is.EqualTo("Baz")); } { // /Foo\/Bar/Baz => { "Foo/Bar", "Baz" } var path = Parse(@"/Foo\/Bar/Baz"); Assert.That(path.IsAbsolute, Is.True, ".Absolute"); Assert.That(path.IsEmpty, Is.False, ".IsEmpty"); Assert.That(path.IsRoot, Is.False, ".IsRoot"); Assert.That(path.Count, Is.EqualTo(2)); Assert.That(path[0].Name, Is.EqualTo("Foo/Bar")); Assert.That(path[0].LayerId, Is.EqualTo(string.Empty)); Assert.That(path[1].Name, Is.EqualTo("Baz")); Assert.That(path[1].LayerId, Is.EqualTo(string.Empty)); Assert.That(path.ToString(), Is.EqualTo(@"/Foo\/Bar/Baz")); Assert.That(path.Name, Is.EqualTo("Baz")); } { // /Foo\\Bar/Baz => { @"Foo\Bar", "Baz" } var path = Parse(@"/Foo\\Bar/Baz"); Assert.That(path.IsAbsolute, Is.True, ".Absolute"); Assert.That(path.IsEmpty, Is.False, ".IsEmpty"); Assert.That(path.IsRoot, Is.False, ".IsRoot"); Assert.That(path.Count, Is.EqualTo(2)); Assert.That(path[0].Name, Is.EqualTo("Foo\\Bar")); Assert.That(path[0].LayerId, Is.EqualTo(string.Empty)); Assert.That(path[1].Name, Is.EqualTo("Baz")); Assert.That(path[1].LayerId, Is.EqualTo(string.Empty)); Assert.That(path.ToString(), Is.EqualTo(@"/Foo\\Bar/Baz")); Assert.That(path.Name, Is.EqualTo("Baz")); } { // /Foo[Bar]/Baz => { "Foo[Bar]", "Baz" } var path = Parse("/Foo\\[Bar]/Baz"); Assert.That(path.IsAbsolute, Is.True, ".Absolute"); Assert.That(path.IsEmpty, Is.False, ".IsEmpty"); Assert.That(path.IsRoot, Is.False, ".IsRoot"); Assert.That(path.Count, Is.EqualTo(2)); Assert.That(path[0].Name, Is.EqualTo("Foo[Bar]")); Assert.That(path[0].LayerId, Is.EqualTo(string.Empty)); Assert.That(path[1].Name, Is.EqualTo("Baz")); Assert.That(path[1].LayerId, Is.EqualTo(string.Empty)); Assert.That(path.ToString(), Is.EqualTo(@"/Foo\[Bar\]/Baz")); Assert.That(path.Name, Is.EqualTo("Baz")); } // Layers { // "/Foo[Test]" var path = Parse("/Foo[test]"); Assert.That(path.IsAbsolute, Is.True); Assert.That(path.ToString(), Is.EqualTo("/Foo[test]")); Assert.That(path.IsEmpty, Is.False); Assert.That(path.IsRoot, Is.False); Assert.That(path.Count, Is.EqualTo(1)); Assert.That(path[0].Name, Is.EqualTo("Foo")); Assert.That(path[0].LayerId, Is.EqualTo("test")); Assert.That(path.Name, Is.EqualTo("Foo")); Assert.That(path.LayerId, Is.EqualTo("test")); Assert.That(path.ToArray(), Is.EqualTo(new [] { FdbPathSegment.Create("Foo", "test") })); Assert.That(path.StartsWith(FdbPath.Root), Is.True); Assert.That(path.IsChildOf(FdbPath.Root), Is.True); Assert.That(path.EndsWith(FdbPath.Root), Is.False); Assert.That(path.IsParentOf(FdbPath.Root), Is.False); } // invalid paths { // "/Foo//Baz" => empty segment Assert.That(() => FdbPath.Parse("/Foo//Baz"), Throws.InstanceOf <FormatException>()); // "/Foo/Bar/" => last is empty Assert.That(() => FdbPath.Parse("/Foo/Bar/"), Throws.InstanceOf <FormatException>()); } }
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 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 }
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 async Task Dir(FdbPath path, IVarTuple extras, DirectoryBrowseOptions options, IFdbDatabase db, TextWriter log, CancellationToken ct) { if (log == null) { log = Console.Out; } Program.Comment(log, $"# Listing {path}:"); await db.ReadAsync(async tr => { var parent = await TryOpenCurrentDirectoryAsync(tr, path); if (parent == null) { Program.Error(log, "Directory not found."); return; } if (!string.IsNullOrEmpty(parent.Layer)) { log.WriteLine($"# Layer: {parent.Layer}"); } var folders = await Fdb.Directory.BrowseAsync(tr, parent); if (folders.Count > 0) { // to better align the names, we allow between 16 to 40 chars for the first column. // if there is a larger name, it will stick out! var maxLen = Math.Min(Math.Max(folders.Keys.Max(n => n.Length), 16), 40); foreach (var kvp in folders) { var name = kvp.Key; var subfolder = kvp.Value; if (subfolder != null) { if ((options & DirectoryBrowseOptions.ShowCount) != 0) { if (!(subfolder is FdbDirectoryPartition)) { long count = await Fdb.System.EstimateCountAsync(db, subfolder.ToRange(), ct); Program.StdOut(log, $" {name.PadRight(maxLen)} {FdbKey.Dump(subfolder.Copy().GetPrefix()),-12} {(string.IsNullOrEmpty(subfolder.Layer) ? "-" : ("[" + subfolder.Layer + "]")),-12} {count,9:N0}", ConsoleColor.White); } else { Program.StdOut(log, $" {name.PadRight(maxLen)} {FdbKey.Dump(subfolder.Copy().GetPrefix()),-12} {(string.IsNullOrEmpty(subfolder.Layer) ? "-" : ("[" + subfolder.Layer + "]")),-12} {"-",9}", ConsoleColor.White); } } else { Program.StdOut(log, $" {name.PadRight(maxLen)} {FdbKey.Dump(subfolder.Copy().GetPrefix()),-12} {(string.IsNullOrEmpty(subfolder.Layer) ? "-" : ("[" + subfolder.Layer + "]")),-12}", ConsoleColor.White); } } else { Program.Error(log, $" WARNING: {name} seems to be missing!"); } } log.WriteLine($" {folders.Count} sub-directories."); } else { //TODO: test if it contains data? log.WriteLine("No sub-directories."); } //TODO: check if there is at least one key? }, ct); }