Example #1
0
        public static void IoTest(PerformanceTestRequest request)
        {
            var tester = new DiskPerformanceTester(request, Console.WriteLine);

            tester.DescribeTestParameters();
            tester.TestDiskIO();
            var result = tester.Result;

            var hasReads  = request.OperationType == OperationType.Read || request.OperationType == OperationType.Mix;
            var hasWrites = request.OperationType == OperationType.Write || request.OperationType == OperationType.Mix;

            if (hasReads)
            {
                var sb = new StringBuilder();
                sb.AppendLine(string.Format("Total read: {0}", SizeHelper.Humane(result.TotalRead)));
                sb.AppendLine(string.Format("Average read: {0}/s", SizeHelper.Humane(result.TotalRead / request.TimeToRunInSeconds)));
                sb.AppendLine("Read latency");
                sb.AppendLine(string.Format("\tMin:   {0:#,#.##;;0}", result.ReadLatency.Min));
                sb.AppendLine(string.Format("\tMean:  {0:#,#.##;;0}", result.ReadLatency.Mean));
                sb.AppendLine(string.Format("\tMax:   {0:#,#.##;;0}", result.ReadLatency.Max));
                sb.AppendLine(string.Format("\tStdev: {0:#,#.##;;0}", result.ReadLatency.Stdev));

                sb.AppendLine("Read latency percentiles");
                foreach (var percentile in result.ReadLatency.Percentiles)
                {
                    sb.AppendLine(string.Format("\t{0}: {1:#,#.##;;0}", percentile.Key, percentile.Value));
                }

                sb.AppendLine();
                Console.WriteLine(sb.ToString());
            }
            if (hasWrites)
            {
                var sb = new StringBuilder();
                sb.AppendLine(string.Format("Total write: {0}", SizeHelper.Humane(result.TotalWrite)));
                sb.AppendLine(string.Format("Average write: {0}/s", SizeHelper.Humane(result.TotalWrite / request.TimeToRunInSeconds)));
                sb.AppendLine("Write latency");
                sb.AppendLine(string.Format("\tMin:   {0:#,#.##;;0}", result.WriteLatency.Min));
                sb.AppendLine(string.Format("\tMean:  {0:#,#.##;;0}", result.WriteLatency.Mean));
                sb.AppendLine(string.Format("\tMax:   {0:#,#.##;;0}", result.WriteLatency.Max));
                sb.AppendLine(string.Format("\tStdev: {0:#,#.##;;0}", result.WriteLatency.Stdev));

                sb.AppendLine("Write latency percentiles");
                foreach (var percentile in result.WriteLatency.Percentiles)
                {
                    sb.AppendLine(string.Format("\t{0}: {1:#,#.##;;0}", percentile.Key, percentile.Value));
                }

                sb.AppendLine();
                Console.WriteLine(sb.ToString());
            }
        }
        public DiskPerformanceTester(PerformanceTestRequest testRequest, Action<string> onInfo, CancellationToken taskKillToken = default(CancellationToken))
        {
            this.testRequest = testRequest;
            this.onInfo = onInfo;
            this.taskKillToken = taskKillToken;
            testTimerCts = new CancellationTokenSource();
            linkedCts = CancellationTokenSource.CreateLinkedTokenSource(taskKillToken, testTimerCts.Token);
            threads = new List<Thread>(testRequest.ThreadCount);
            dataStorage = new DiskPerformanceStorage();
            perThreadRandom = Enumerable.Range(1, testRequest.ThreadCount)
                .Select(i => testRequest.RandomSeed.HasValue ? new Random(testRequest.RandomSeed.Value) : new Random()).ToList();

            if (testRequest.Sequential && testRequest.OperationType == OperationType.Mix)
            {
                onInfo("Sequential test with mixed read/write mode is not supported. Changing to random access");
                testRequest.Sequential = false;
            }
        }
Example #3
0
        public void TestRandomWrite()
        {
            var performanceRequest = new PerformanceTestRequest
            {
                FileSize = (long)128 * 1024,
                OperationType = OperationType.Write,
                Path = Path.Combine(Path.GetTempPath(), "data.ravendb-io-test"),
                Sequential = false,
                ThreadCount = 4,
                TimeToRunInSeconds = 5,
                ChunkSize = 4 * 1024
            };

            var tester = new DiskPerformanceTester(performanceRequest, s => { });
            tester.TestDiskIO();
            var result = tester.Result;
            Assert.Equal(0, result.TotalRead);
            Assert.True(result.TotalWrite > 0);
        }
Example #4
0
        public void TestRandomRead()
        {
            var performanceRequest = new PerformanceTestRequest
            {
                FileSize           = (long)128 * 1024,
                OperationType      = OperationType.Read,
                Path               = Path.Combine(Path.GetTempPath(), "data.ravendb-io-test"),
                Sequential         = false,
                ThreadCount        = 4,
                TimeToRunInSeconds = 5,
                ChunkSize          = 4 * 1024
            };

            var tester = new DiskPerformanceTester(performanceRequest, s => { });

            tester.TestDiskIO();
            var result = tester.Result;

            Assert.Equal(0, result.TotalWrite);
            Assert.True(result.TotalRead > 0);
        }
Example #5
0
        public void TestCanCancelPerformanceTest()
        {
            var cts = new CancellationTokenSource();

            cts.CancelAfter(TimeSpan.FromSeconds(5));

            var performanceRequest = new PerformanceTestRequest
            {
                FileSize           = (long)128 * 1024,
                OperationType      = OperationType.Mix,
                Path               = Path.Combine(Path.GetTempPath(), "data.ravendb-io-test"),
                Sequential         = false,
                ThreadCount        = 4,
                TimeToRunInSeconds = 30,
                ChunkSize          = 4 * 1024
            };

            var tester = new DiskPerformanceTester(performanceRequest, s => { }, cts.Token);

            Assert.Throws <OperationCanceledException>(() => tester.TestDiskIO());
        }
Example #6
0
		private static void Main(string[] args)
		{
            var performanceRequest = new PerformanceTestRequest
            {
                FileSize = (long) 1024 * 1024 * 1024,
                OperationType = OperationType.Read,
                BufferingType = BufferingType.ReadAndWrite,
                Path = "c:\\temp\\data.ravendb-io-test",
                Sequential = true,
                ThreadCount = 4,
                TimeToRunInSeconds = 100,
                ChunkSize = 4 * 1024
            };

            var tester = new DiskPerformanceTester(performanceRequest, Console.WriteLine, CancellationToken.None);
            tester.TestDiskIO();

		    var r = tester.Result;

            Console.WriteLine(RavenJObject.FromObject(r));
		    Console.ReadKey();
		}
Example #7
0
        private static void Main(string[] args)
        {
            var performanceRequest = new PerformanceTestRequest
            {
                FileSize           = (long)1024 * 1024 * 1024,
                OperationType      = OperationType.Read,
                BufferingType      = BufferingType.ReadAndWrite,
                Path               = "c:\\temp\\data.ravendb-io-test",
                Sequential         = true,
                ThreadCount        = 4,
                TimeToRunInSeconds = 100,
                ChunkSize          = 4 * 1024
            };

            var tester = new DiskPerformanceTester(performanceRequest, Console.WriteLine, CancellationToken.None);

            tester.TestDiskIO();

            var r = tester.Result;

            Console.WriteLine(RavenJObject.FromObject(r));
            Console.ReadKey();
        }
Example #8
0
        public void TestCanCancelPerformanceTest()
        {
            var cts = new CancellationTokenSource();
            cts.CancelAfter(TimeSpan.FromSeconds(5));

            var performanceRequest = new PerformanceTestRequest
            {
                FileSize = (long)128 * 1024,
                OperationType = OperationType.Mix,
                Path = Path.Combine(Path.GetTempPath(), "data.ravendb-io-test"),
                Sequential = false,
                ThreadCount = 4,
                TimeToRunInSeconds = 30,
                ChunkSize = 4 * 1024
            };

            var tester = new DiskPerformanceTester(performanceRequest, s => { }, cts.Token);
            Assert.Throws<OperationCanceledException>(() => tester.TestDiskIO());
        }
Example #9
0
        public static void IoTest(PerformanceTestRequest request)
        {
            var tester = new DiskPerformanceTester(request, Console.WriteLine);
            tester.DescribeTestParameters();
            tester.TestDiskIO();
            var result = tester.Result;

            var hasReads = request.OperationType == OperationType.Read || request.OperationType == OperationType.Mix;
            var hasWrites = request.OperationType == OperationType.Write || request.OperationType == OperationType.Mix;

            if (hasReads)
            {
                var sb = new StringBuilder();
                sb.AppendLine(string.Format("Total read: {0}", SizeHelper.Humane(result.TotalRead)));
                sb.AppendLine(string.Format("Average read: {0}/s", SizeHelper.Humane(result.TotalRead / request.TimeToRunInSeconds)));
                sb.AppendLine("Read latency");
                sb.AppendLine(string.Format("\tMin:   {0:#,#.##;;0}", result.ReadLatency.Min));
                sb.AppendLine(string.Format("\tMean:  {0:#,#.##;;0}", result.ReadLatency.Mean));
                sb.AppendLine(string.Format("\tMax:   {0:#,#.##;;0}", result.ReadLatency.Max));
                sb.AppendLine(string.Format("\tStdev: {0:#,#.##;;0}", result.ReadLatency.Stdev));

                sb.AppendLine("Read latency percentiles");
                foreach (var percentile in result.ReadLatency.Percentiles)
                {
                    sb.AppendLine(string.Format("\t{0}: {1:#,#.##;;0}", percentile.Key, percentile.Value));
                }

                sb.AppendLine();
                Console.WriteLine(sb.ToString());
            }
            if (hasWrites)
            {
                var sb = new StringBuilder();
                sb.AppendLine(string.Format("Total write: {0}", SizeHelper.Humane(result.TotalWrite)));
                sb.AppendLine(string.Format("Average write: {0}/s", SizeHelper.Humane(result.TotalWrite / request.TimeToRunInSeconds)));
                sb.AppendLine("Write latency");
                sb.AppendLine(string.Format("\tMin:   {0:#,#.##;;0}", result.WriteLatency.Min));
                sb.AppendLine(string.Format("\tMean:  {0:#,#.##;;0}", result.WriteLatency.Mean));
                sb.AppendLine(string.Format("\tMax:   {0:#,#.##;;0}", result.WriteLatency.Max));
                sb.AppendLine(string.Format("\tStdev: {0:#,#.##;;0}", result.WriteLatency.Stdev));

                sb.AppendLine("Write latency percentiles");
                foreach (var percentile in result.WriteLatency.Percentiles)
                {
                    sb.AppendLine(string.Format("\t{0}: {1:#,#.##;;0}", percentile.Key, percentile.Value));
                }

                sb.AppendLine();
                Console.WriteLine(sb.ToString());
            }

        }
Example #10
0
		private static void InteractiveRun(string[] args)
		{
		    var ioTestRequest = new PerformanceTestRequest();

			string backupLocation = null;
			string restoreLocation = null;
			string restoreDatabaseName = null;
		    string restoreFilesystemName = null;
			bool defrag = false;
            var requiresRestoreAction = new HashSet<string>();
		    bool isRestoreAction = false;
		    var requiresIoTestAction = new HashSet<string>();
		    bool isIoTestAction = false;
			Action actionToTake = null;
			bool launchBrowser = false;
			bool noLog = false;
			var ravenConfiguration = new RavenConfiguration();
		    bool waitForRestore = true;
		    int? restoreStartTimeout = 15;

			OptionSet optionSet = null;
			optionSet = new OptionSet
			{
				{"set={==}", "The configuration {0:option} to set to the specified {1:value}" , (key, value) =>
				{
					ravenConfiguration.Settings[key] = value;
					ravenConfiguration.Initialize();
				}},
				{"nolog", "Don't use the default log", s => noLog=true},
				{"config=", "The config {0:file} to use", ravenConfiguration.LoadFrom},
				{"install", "Installs the RavenDB service", key => actionToTake= () => AdminRequired(InstallAndStart)},
				{"allow-blank-password-use", "Allow to log on by using a Windows account that has a blank password", key => actionToTake = () => AdminRequired(() => SetLimitBlankPasswordUseRegValue(0))},
				{"deny-blank-password-use", "Deny to log on by using a Windows account that has a blank password", key => actionToTake = () =>  AdminRequired(() => SetLimitBlankPasswordUseRegValue(1))},
				{"service-name=", "The {0:service name} to use when installing or uninstalling the service, default to RavenDB", name => ProjectInstaller.SERVICE_NAME = name},
				{"uninstall", "Uninstalls the RavenDB service", key => actionToTake= () => AdminRequired(EnsureStoppedAndUninstall)},
				{"start", "Starts the RavenDB service", key => actionToTake= () => AdminRequired(StartService)},
				{"restart", "Restarts the RavenDB service", key => actionToTake= () => AdminRequired(RestartService)},
				{"stop", "Stops the RavenDB service", key => actionToTake= () => AdminRequired(StopService)},
				{"ram", "Run RavenDB in RAM only", key =>
				{
					ravenConfiguration.Settings["Raven/RunInMemory"] = "true";
					ravenConfiguration.RunInMemory = true;
					ravenConfiguration.Initialize();
					actionToTake = () => RunInDebugMode(AnonymousUserAccessMode.Admin, ravenConfiguration, launchBrowser, noLog);		
				}},
				{"debug", "Runs RavenDB in debug mode", key => actionToTake = () => RunInDebugMode(null, ravenConfiguration, launchBrowser, noLog)},
				{"browser|launchbrowser", "After the server starts, launches the browser", key => launchBrowser = true},
				{"help", "Help about the command line interface", key =>
				{
					actionToTake = () => PrintUsage(optionSet);
				}},
				{"config-help", "Help about configuration databaseOptions", key=>
				{
					actionToTake = () => PrintConfig(ravenConfiguration.GetConfigOptionsDocs());
				}},
				{"restore", "[Obsolete] Use --restore-system-database or --restore-database",
					key =>
					{
					    actionToTake = () =>
					    {
					        throw new OptionException("This method is obsolete, use --restore-system-database or --restore-database", "restore");
					    };
					    isRestoreAction = true;
					}
				},
				{"restore-system-database", "Restores a SYSTEM database from backup.",
					key =>
					{
					    actionToTake = () =>
					    {
					        if (backupLocation == null || restoreLocation == null)
					        {
					            throw new OptionException("when using --restore-system-database, --restore-source and --restore-destination must be specified", "restore-system-database");
					        }
					        RunSystemDatabaseRestoreOperation(backupLocation, restoreLocation, defrag);
					    };
					    isRestoreAction = true;
					}
				},
				{"restore-database=", "Starts a restore operation from a backup on a REMOTE server found under specified {0:url}.", 
					url =>
					{
					    actionToTake = () =>
					    {
					        if (backupLocation == null)
					        {
					            throw new OptionException("when using --restore-database, --restore-source must be specified", "restore-database");
					        }

					        Uri uri;
					        if (Uri.TryCreate(url, UriKind.Absolute, out uri) == false)
					        {
					            throw new OptionException("specified destination server url is not valid", "restore-database");
					        }

					        RunRemoteDatabaseRestoreOperation(backupLocation, restoreLocation, restoreDatabaseName, defrag, uri, waitForRestore, restoreStartTimeout);
					        Environment.Exit(0);
					    };
					    isRestoreAction = true;
					}
				},
                {"restore-filesystem=", "Starts a restore operation from a backup on a REMOTE server found under specified {0:url}.",
                    url =>
                    {
                        actionToTake = () =>
                        {
                            if (backupLocation == null)
                            {
                                throw new OptionException("when using --restore-filesystem, --restore-source must be specified", "restore-filesystem");
                            }

                            Uri uri;
                            if (Uri.TryCreate(url, UriKind.Absolute, out uri) == false)
                            {
                                throw new OptionException("specified destination server url is not valid", "restore-database");
                            }

                            RunRemoteFilesystemRestoreOperation(backupLocation, restoreLocation, restoreFilesystemName, defrag, uri, waitForRestore, restoreStartTimeout);
                            Environment.Exit(0);
                        };
                        isRestoreAction = true;
                    }
                },
				{
				    "restore-no-wait", "Return immediately without waiting for a restore to complete", value =>
				    {
				        waitForRestore = false;
				        requiresRestoreAction.Add("restore-no-wait");
				    }
				},
                { "restore-start-timeout=", "The maximum {0:timeout} in seconds to wait for another restore to complete. Default: 15 seconds.", value =>
                {
                    int timeout;
                    if (int.TryParse(value, out timeout) == false)
                    {
                        throw new OptionException("specified restore start timeout is not valid", "restore-start-timeout");
                    }
                    restoreStartTimeout = timeout;
                    requiresRestoreAction.Add("restore-start-timeout");
                }},
				{"restore-defrag", 
					"Applicable only during restore, execute defrag after the restore is completed", key =>
					{
						defrag = true;
					    requiresRestoreAction.Add("restore-defrag");
					}},
				{"restore-destination=", "The {0:path} of the new database. If not specified it will be located in default data directory", value =>
				{
				    restoreLocation = value;
				    requiresRestoreAction.Add("restore-destination");
				}},
				{"restore-source=", "The {0:path} of the backup", value =>
				{
				    backupLocation = value;
				    requiresRestoreAction.Add("restore-source");
				}},
				{"restore-database-name=", "The {0:name} of the new database. If not specified, it will be extracted from backup. Only applicable during REMOTE restore", value =>
				{
				    restoreDatabaseName = value;
				    requiresRestoreAction.Add("restore-database-name");
				}},
                {"restore-filesystem-name", "The {0:name} of the new filesystem. If not specified, it will be extracted from backup.", value =>
                {
                    restoreFilesystemName = value;
                    requiresRestoreAction.Add("restore-filesystem-name");
                }},
                {"io-test=", "Performs disk io test using {0:path} as temporary file path", path =>
                {
                    ioTestRequest.Path = path;
                    actionToTake = () => IoTest(ioTestRequest);
                    isIoTestAction = true;
                }},
			    {
			        "io-test-file-size=", "The {0:size} of test file for io test in MB (default: 1024MB)", value =>
			        {
                        int fileSize;
                        if (int.TryParse(value, out fileSize) == false)
                        {
                            throw new OptionException("specified test file size is not valid", "io-test-file-size");
                        }
			            ioTestRequest.FileSize = fileSize*1024*1024;
			            requiresIoTestAction.Add("io-test-file-size");
			        }
			    },
                 {
			        "io-test-threads=", "The {0:number} of threads to use during test", value =>
			        {
                        int threads;
                        if (int.TryParse(value, out threads) == false)
                        {
                            throw new OptionException("specified amount of threads is not valid", "io-test-threads");
                        }
			            ioTestRequest.ThreadCount = threads;
			            requiresIoTestAction.Add("io-test-threads");
			        }
			    },
                {
			        "io-test-time=", "The {0:number} of seconds to run the test (default: 30)", value =>
			        {
                        int testTime;
                        if (int.TryParse(value, out testTime) == false)
                        {
                            throw new OptionException("specified test time is not valid", "io-test-time");
                        }
                        ioTestRequest.TimeToRunInSeconds = testTime;
			            requiresIoTestAction.Add("io-test-time");
			        }
			    },
                 {
			        "io-test-seed=", "The {0:seed} for random generator", value =>
			        {
                        int seed;
                        if (int.TryParse(value, out seed) == false)
                        {
                            throw new OptionException("specified random seed is not valid", "io-test-seed");
                        }
                        ioTestRequest.RandomSeed = seed;
			            requiresIoTestAction.Add("io-test-seed");
			        }
			    },
                {
			        "io-test-mode=", "The operation {0:mode} (read,write,mix) (default: write)", value =>
			        {
                        OperationType opType;
                        if (Enum.TryParse(value, true, out opType) == false)
                        {
                            throw new OptionException("specified test mode is not valid", "io-test-mode");
                        }
                        ioTestRequest.OperationType = opType;
                        requiresIoTestAction.Add("io-test-mode");
			        }
			    },
                {
			        "io-test-chunk-size=", "The {0:value} for chunk size in KB (default: 4 KB)", value =>
			        {
                        int chunkSize;
                        if (int.TryParse(value, out chunkSize) == false)
                        {
                            throw new OptionException("specified test chunk size is not valid", "io-test-chunk-size");
                        }
                        ioTestRequest.ChunkSize = chunkSize * 1024;
                        requiresIoTestAction.Add("io-test-chunk-size");
			        }
			    },
			    {
			        "io-test-sequential", "Perform sequential read/write (default: random)", value =>
			        {
			            ioTestRequest.Sequential = true;
			            requiresIoTestAction.Add("io-test-sequential");
			        }
			    },
                {
			        "io-test-buffering-type", "Buffering type (None,Read, ReadAndWrite) (default: None)", value =>
			        {
                          BufferingType bufferingType;
                          if (Enum.TryParse(value, true, out bufferingType) == false)
                        {
                            throw new OptionException("specified buffering type is not valid", "io-test-buffering-type");
                        }
                        ioTestRequest.BufferingType = bufferingType;
                        requiresIoTestAction.Add("io-test-buffering-type");
			        }
			    },
				{"encrypt-self-config", "Encrypt the RavenDB configuration file", file =>
						{
							actionToTake = () => ProtectConfiguration(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
						}},
				{"encrypt-config=", "Encrypt the specified {0:configuration file}", file =>
						{
							actionToTake = () => ProtectConfiguration(file);
						}},
				{"decrypt-self-config", "Decrypt the RavenDB configuration file", file =>
						{
							actionToTake = () => UnprotectConfiguration(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
						}},
				{"decrypt-config=", "Decrypt the specified {0:configuration file}", file =>
						{
							actionToTake = () => UnprotectConfiguration(file);
						}},
				{"installSSL={==}", "Bind X509 certificate specified in {0:option} with optional password from {1:option} with 'Raven/Port'.", (sslCertificateFile, sslCertificatePassword) =>
						{
							actionToTake = () => InstallSsl(sslCertificateFile, sslCertificatePassword, ravenConfiguration);
						}},
				{"uninstallSSL={==}", "Unbind X509 certificate specified in {0:option} with optional password from {2:option} from 'Raven/Port'.", (sslCertificateFile, sslCertificatePassword) =>
						{
							actionToTake = () => UninstallSsl(sslCertificateFile, sslCertificatePassword, ravenConfiguration);
						}},
                {"update-version=", "Updates the specified {0:databaseName} to newest version", dbName =>
                    {
                        actionToTake = () => UpdateVersion(dbName);
                    }}
			};


			try
			{
				if (args.Length == 0) // we default to executing in debug mode 
					args = new[] { "--debug" };

				optionSet.Parse(args);
			}
			catch (Exception e)
			{
				Console.WriteLine(e.Message);
				PrintUsage(optionSet);
				return;
			}

            if (!isRestoreAction && requiresRestoreAction.Any())
            {
                var joinedActions = string.Join(", ", requiresRestoreAction);
                throw new OptionException(string.Format("when using {0}, --restore-source must be specified", joinedActions), joinedActions);
            }

            if (!isIoTestAction && requiresIoTestAction.Any())
            {
                var joinedActions = string.Join(", ", requiresRestoreAction);
                throw new OptionException(string.Format("when using {0}, --io-test must be specified", joinedActions), joinedActions);
            }

			if (actionToTake == null)
				actionToTake = () => RunInDebugMode(null, ravenConfiguration, launchBrowser, noLog);

			actionToTake();

		}
Example #11
0
        private static void InteractiveRun(string[] args)
        {
            var ioTestRequest = new PerformanceTestRequest();

            string backupLocation        = null;
            string restoreLocation       = null;
            string restoreDatabaseName   = null;
            string restoreFilesystemName = null;
            bool   defrag = false;
            var    requiresRestoreAction = new HashSet <string>();
            bool   isRestoreAction       = false;
            var    requiresIoTestAction  = new HashSet <string>();
            bool   isIoTestAction        = false;
            Action actionToTake          = null;
            bool   launchBrowser         = false;
            bool   noLog = false;
            var    ravenConfiguration  = new RavenConfiguration();
            bool   waitForRestore      = true;
            int?   restoreStartTimeout = 15;

            OptionSet optionSet = null;

            optionSet = new OptionSet
            {
                { "set={==}", "The configuration {0:option} to set to the specified {1:value}", (key, value) =>
                  {
                      ravenConfiguration.Settings[key] = value;
                      ravenConfiguration.Initialize();
                  } },
                { "nolog", "Don't use the default log", s => noLog = true },
                { "config=", "The config {0:file} to use", ravenConfiguration.LoadFrom },
                { "install", "Installs the RavenDB service", key => actionToTake = () => AdminRequired(InstallAndStart) },
                { "allow-blank-password-use", "Allow to log on by using a Windows account that has a blank password", key => actionToTake = () => AdminRequired(() => SetLimitBlankPasswordUseRegValue(0)) },
                { "deny-blank-password-use", "Deny to log on by using a Windows account that has a blank password", key => actionToTake = () => AdminRequired(() => SetLimitBlankPasswordUseRegValue(1)) },
                { "service-name=", "The {0:service name} to use when installing or uninstalling the service, default to RavenDB", name => ProjectInstaller.SERVICE_NAME = name },
                { "uninstall", "Uninstalls the RavenDB service", key => actionToTake = () => AdminRequired(EnsureStoppedAndUninstall) },
                { "start", "Starts the RavenDB service", key => actionToTake = () => AdminRequired(StartService) },
                { "restart", "Restarts the RavenDB service", key => actionToTake = () => AdminRequired(RestartService) },
                { "stop", "Stops the RavenDB service", key => actionToTake = () => AdminRequired(StopService) },
                { "ram", "Run RavenDB in RAM only", key =>
                  {
                      ravenConfiguration.Settings["Raven/RunInMemory"] = "true";
                      ravenConfiguration.RunInMemory = true;
                      ravenConfiguration.Initialize();
                      actionToTake = () => RunInDebugMode(AnonymousUserAccessMode.Admin, ravenConfiguration, launchBrowser, noLog);
                  } },
                { "debug", "Runs RavenDB in debug mode", key => actionToTake = () => RunInDebugMode(null, ravenConfiguration, launchBrowser, noLog) },
                { "browser|launchbrowser", "After the server starts, launches the browser", key => launchBrowser = true },
                { "help", "Help about the command line interface", key =>
                  {
                      actionToTake = () => PrintUsage(optionSet);
                  } },
                { "config-help", "Help about configuration databaseOptions", key =>
                  {
                      actionToTake = () => PrintConfig(ravenConfiguration.GetConfigOptionsDocs());
                  } },
                { "restore", "[Obsolete] Use --restore-system-database or --restore-database",
                  key =>
                  {
                      actionToTake = () =>
                      {
                          throw new OptionException("This method is obsolete, use --restore-system-database or --restore-database", "restore");
                      };
                      isRestoreAction = true;
                  } },
                { "restore-system-database", "Restores a SYSTEM database from backup.",
                  key =>
                  {
                      actionToTake = () =>
                      {
                          if (backupLocation == null || restoreLocation == null)
                          {
                              throw new OptionException("when using --restore-system-database, --restore-source and --restore-destination must be specified", "restore-system-database");
                          }
                          RunSystemDatabaseRestoreOperation(backupLocation, restoreLocation, defrag);
                      };
                      isRestoreAction = true;
                  } },
                { "restore-database=", "Starts a restore operation from a backup on a REMOTE server found under specified {0:url}.",
                  url =>
                  {
                      actionToTake = () =>
                      {
                          if (backupLocation == null)
                          {
                              throw new OptionException("when using --restore-database, --restore-source must be specified", "restore-database");
                          }

                          Uri uri;
                          if (Uri.TryCreate(url, UriKind.Absolute, out uri) == false)
                          {
                              throw new OptionException("specified destination server url is not valid", "restore-database");
                          }

                          RunRemoteDatabaseRestoreOperation(backupLocation, restoreLocation, restoreDatabaseName, defrag, uri, waitForRestore, restoreStartTimeout);
                          Environment.Exit(0);
                      };
                      isRestoreAction = true;
                  } },
                { "restore-filesystem=", "Starts a restore operation from a backup on a REMOTE server found under specified {0:url}.",
                  url =>
                  {
                      actionToTake = () =>
                      {
                          if (backupLocation == null)
                          {
                              throw new OptionException("when using --restore-filesystem, --restore-source must be specified", "restore-filesystem");
                          }

                          Uri uri;
                          if (Uri.TryCreate(url, UriKind.Absolute, out uri) == false)
                          {
                              throw new OptionException("specified destination server url is not valid", "restore-database");
                          }

                          RunRemoteFilesystemRestoreOperation(backupLocation, restoreLocation, restoreFilesystemName, defrag, uri, waitForRestore, restoreStartTimeout);
                          Environment.Exit(0);
                      };
                      isRestoreAction = true;
                  } },
                {
                    "restore-no-wait", "Return immediately without waiting for a restore to complete", value =>
                    {
                        waitForRestore = false;
                        requiresRestoreAction.Add("restore-no-wait");
                    }
                },
                { "restore-start-timeout=", "The maximum {0:timeout} in seconds to wait for another restore to complete. Default: 15 seconds.", value =>
                  {
                      int timeout;
                      if (int.TryParse(value, out timeout) == false)
                      {
                          throw new OptionException("specified restore start timeout is not valid", "restore-start-timeout");
                      }
                      restoreStartTimeout = timeout;
                      requiresRestoreAction.Add("restore-start-timeout");
                  } },
                { "restore-defrag",
                  "Applicable only during restore, execute defrag after the restore is completed", key =>
                  {
                      defrag = true;
                      requiresRestoreAction.Add("restore-defrag");
                  } },
                { "restore-destination=", "The {0:path} of the new database. If not specified it will be located in default data directory", value =>
                  {
                      restoreLocation = value;
                      requiresRestoreAction.Add("restore-destination");
                  } },
                { "restore-source=", "The {0:path} of the backup", value =>
                  {
                      backupLocation = value;
                      requiresRestoreAction.Add("restore-source");
                  } },
                { "restore-database-name=", "The {0:name} of the new database. If not specified, it will be extracted from backup. Only applicable during REMOTE restore", value =>
                  {
                      restoreDatabaseName = value;
                      requiresRestoreAction.Add("restore-database-name");
                  } },
                { "restore-filesystem-name", "The {0:name} of the new filesystem. If not specified, it will be extracted from backup.", value =>
                  {
                      restoreFilesystemName = value;
                      requiresRestoreAction.Add("restore-filesystem-name");
                  } },
                { "io-test=", "Performs disk io test using {0:path} as temporary file path", path =>
                  {
                      ioTestRequest.Path = path;
                      actionToTake       = () => IoTest(ioTestRequest);
                      isIoTestAction     = true;
                  } },
                {
                    "io-test-file-size=", "The {0:size} of test file for io test in MB (default: 1024MB)", value =>
                    {
                        int fileSize;
                        if (int.TryParse(value, out fileSize) == false)
                        {
                            throw new OptionException("specified test file size is not valid", "io-test-file-size");
                        }
                        ioTestRequest.FileSize = fileSize * 1024 * 1024;
                        requiresIoTestAction.Add("io-test-file-size");
                    }
                },
                {
                    "io-test-threads=", "The {0:number} of threads to use during test", value =>
                    {
                        int threads;
                        if (int.TryParse(value, out threads) == false)
                        {
                            throw new OptionException("specified amount of threads is not valid", "io-test-threads");
                        }
                        ioTestRequest.ThreadCount = threads;
                        requiresIoTestAction.Add("io-test-threads");
                    }
                },
                {
                    "io-test-time=", "The {0:number} of seconds to run the test (default: 30)", value =>
                    {
                        int testTime;
                        if (int.TryParse(value, out testTime) == false)
                        {
                            throw new OptionException("specified test time is not valid", "io-test-time");
                        }
                        ioTestRequest.TimeToRunInSeconds = testTime;
                        requiresIoTestAction.Add("io-test-time");
                    }
                },
                {
                    "io-test-seed=", "The {0:seed} for random generator", value =>
                    {
                        int seed;
                        if (int.TryParse(value, out seed) == false)
                        {
                            throw new OptionException("specified random seed is not valid", "io-test-seed");
                        }
                        ioTestRequest.RandomSeed = seed;
                        requiresIoTestAction.Add("io-test-seed");
                    }
                },
                {
                    "io-test-mode=", "The operation {0:mode} (read,write,mix) (default: write)", value =>
                    {
                        OperationType opType;
                        if (Enum.TryParse(value, true, out opType) == false)
                        {
                            throw new OptionException("specified test mode is not valid", "io-test-mode");
                        }
                        ioTestRequest.OperationType = opType;
                        requiresIoTestAction.Add("io-test-mode");
                    }
                },
                {
                    "io-test-chunk-size=", "The {0:value} for chunk size in KB (default: 4 KB)", value =>
                    {
                        int chunkSize;
                        if (int.TryParse(value, out chunkSize) == false)
                        {
                            throw new OptionException("specified test chunk size is not valid", "io-test-chunk-size");
                        }
                        ioTestRequest.ChunkSize = chunkSize * 1024;
                        requiresIoTestAction.Add("io-test-chunk-size");
                    }
                },
                {
                    "io-test-sequential", "Perform sequential read/write (default: random)", value =>
                    {
                        ioTestRequest.Sequential = true;
                        requiresIoTestAction.Add("io-test-sequential");
                    }
                },
                {
                    "io-test-buffering-type", "Buffering type (None,Read, ReadAndWrite) (default: None)", value =>
                    {
                        BufferingType bufferingType;
                        if (Enum.TryParse(value, true, out bufferingType) == false)
                        {
                            throw new OptionException("specified buffering type is not valid", "io-test-buffering-type");
                        }
                        ioTestRequest.BufferingType = bufferingType;
                        requiresIoTestAction.Add("io-test-buffering-type");
                    }
                },
                { "encrypt-self-config", "Encrypt the RavenDB configuration file", file =>
                  {
                      actionToTake = () => ProtectConfiguration(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
                  } },
                { "encrypt-config=", "Encrypt the specified {0:configuration file}", file =>
                  {
                      actionToTake = () => ProtectConfiguration(file);
                  } },
                { "decrypt-self-config", "Decrypt the RavenDB configuration file", file =>
                  {
                      actionToTake = () => UnprotectConfiguration(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
                  } },
                { "decrypt-config=", "Decrypt the specified {0:configuration file}", file =>
                  {
                      actionToTake = () => UnprotectConfiguration(file);
                  } },
                { "installSSL={==}", "Bind X509 certificate specified in {0:option} with optional password from {1:option} with 'Raven/Port'.", (sslCertificateFile, sslCertificatePassword) =>
                  {
                      actionToTake = () => InstallSsl(sslCertificateFile, sslCertificatePassword, ravenConfiguration);
                  } },
                { "uninstallSSL={==}", "Unbind X509 certificate specified in {0:option} with optional password from {2:option} from 'Raven/Port'.", (sslCertificateFile, sslCertificatePassword) =>
                  {
                      actionToTake = () => UninstallSsl(sslCertificateFile, sslCertificatePassword, ravenConfiguration);
                  } },
                { "update-version=", "Updates the specified {0:databaseName} to newest version", dbName =>
                  {
                      actionToTake = () => UpdateVersion(dbName);
                  } }
            };


            try
            {
                if (args.Length == 0)                 // we default to executing in debug mode
                {
                    args = new[] { "--debug" }
                }
                ;

                optionSet.Parse(args);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                PrintUsage(optionSet);
                return;
            }

            if (!isRestoreAction && requiresRestoreAction.Any())
            {
                var joinedActions = string.Join(", ", requiresRestoreAction);
                throw new OptionException(string.Format("when using {0}, --restore-source must be specified", joinedActions), joinedActions);
            }

            if (!isIoTestAction && requiresIoTestAction.Any())
            {
                var joinedActions = string.Join(", ", requiresRestoreAction);
                throw new OptionException(string.Format("when using {0}, --io-test must be specified", joinedActions), joinedActions);
            }

            if (actionToTake == null)
            {
                actionToTake = () => RunInDebugMode(null, ravenConfiguration, launchBrowser, noLog);
            }

            actionToTake();
        }