/// <summary> /// This is the entry point for the sample application /// </summary> /// <param name="args">Command line arguments - you may pass a comma or space-separated list of hosts to be /// used (otherwise the application's default will be used)</param> static void NoviceMain(string[] args) { try { // Default hosts string hosts = "192.168.1.203,192.168.1.200"; // If arguments were given, assume it's a host list. I don't know if you space or comma separated them, // so I clean all that up if (args.Length > 0) { hosts = string.Join(",", string.Join(",", args).Split(' ', ',')); } // Initialize some variables for the process Random rand = new Random(); long phoneNumber = 0; sbyte contestantId = 0; int maximumAllowedVotesPerPhoneNumber = 3; // A little introduction message Console.WriteLine("Voter Benchmark (2 minutes)\r\n---------------------------------------------------" + "-------------------------------------------------"); // You create a connection by calling the VoltConnection.GetConnection static factory method. // You may pass a ConnectionSettings object or a connectionstring - the conversion is implicit and the // ConnectionSettings object is fully compatible with the standard ConnectionStringBuilder class from // which it actually derives. // Through action-chaining (Open, Drain, Close and ResetStatistics all return the acting instance // instead of 'void', allowing LINQ-like sequencing of actions), you can also immediately open the // connection after getting it, which we do here. VoltConnection voltDB = VoltConnection.Create("hosts=" + hosts + ";statistics=true") .Open(); // Create strongly-typed procedure wrappers for each procedure we will use. // - Voter will have a callback to track procedure results asynchronously. // - Initialize and Results don't because we will simply call them synchronously. var Vote = voltDB.Procedures.Wrap <long, long, sbyte, int>("Vote", VoterCallback); var Initialize = voltDB.Procedures.Wrap <long, int, string>("Initialize", null); var Results = voltDB.Procedures.Wrap <Table>("Results", null); // Initialize the catalog and request a random number of contestants to vote on. // Notice the result is strongly-typed, so we can access it directly! int numContestants = (int)Initialize.Execute( rand.Next(5, 10) , "Edwina Burnam,Tabatha Gehling,Kelly Clauss,Jessie Alloway,Alana Bregman,Jessie Eichman,Allie Rogalski,Nita Coster,Kurt Walser,Ericka Dieter,Loraine Nygren,Tania Mattioli" ).Result; // Print a startup message. Console.WriteLine( "Voting for {0} Contestants\r\nTracking Live Statistics (Connection Aggregates)\r\n" + "----------------------------------------------------------------------------------" + "------------------" , numContestants); // Start a display timer that will "tick" every 5 seconds to print live performance data. We don't // really need a context here, so we'll just use an anonymous delegate for the callback. Timer ticker = new Timer( delegate(object state) { Console.WriteLine("{0,24}" , string.Join( "\r\n" , (state as VoltConnection) .Statistics .GetLifetimeStatisticsByNode() .Select(r => r.Key.ToString() + " :: " + r.Value.ToString(StatisticsFormat.Short) ) .ToArray() ) ); } , voltDB // Pass the connection , 5000 // Start in 5 seconds , 5000 // Tick every 5 seconds ); // Run for 2 minutes. Use the environment's ticks to count time - not very precise but that's not // where it matters, and it's low-cost. int end = Environment.TickCount + 120000; while (Environment.TickCount < end) { // Get a random phone number. phoneNumber = 2000000000L + (long)(rand.NextDouble() * 9999999999L); contestantId = unchecked ((sbyte)rand.Next(0, numContestants)); // Randomly introduce some bad votes (0.1%) if (rand.Next(10000) < 10) { contestantId = 11; } // Randomly introduce vote abuse (0.05%) by calling with the same phone number more than the // maximum allowed. // Note how we call the BeginExecute method on our procedure wrapper - this is all it takes. Our // callback will be executed upon completion. // One final note: this could fail: not because of a failure on the server (this is the role of // exception-packaging in the response), but if you lost connectivity and your connection is now // closed! // This means you should use a try/catch block and adequate handling, or leverage the .TryExecute // & .TryExecuteAsync methods on your Procedure Wrapper. // Here we have a global try/catch block that's good enough for a sample app, but vastly inadequate // for a production client, of course! if (rand.Next(20000) < 10) { for (int i = 0; i < 5; i++) { Vote.BeginExecute( phoneNumber , unchecked ((sbyte)rand.Next(0, numContestants)) , maximumAllowedVotesPerPhoneNumber ); } } else { Vote.BeginExecute( phoneNumber , contestantId , maximumAllowedVotesPerPhoneNumber ); } } // Drain the connection until all the work is done. voltDB.Drain(); // Stop and dispose of the ticker - we're done here. ticker.Dispose(); // Get the vote results (who's the winner, etc...). Table result = Results.Execute().Result; // And close the connection. voltDB.Close(); // Enjoy the fully LINQ-compatible Table object: string resultDisplay = string.Join( "\r\n" , result.Rows .Select(r => string.Format( "{0,21} => {1,12:##,#} votes(s)" , r.GetValue <string>(0) , r.GetValue <long?>(2) ) ).ToArray() ) + string.Format( "\r\n\r\n {0,21} was the winner!\r\n" , result.Rows .OrderByDescending(r => r.GetValue <long?>(2)) .First() .GetValue <string>(0) ); // Print out the results, performance stats, etc. A fair bit of fancy LINQ there - not the easiest to // read, but it's good learning material :-) // You could of course do that with loops and 50 lines, but I prefer simple one-liners... Console.Write( ResultFormat , resultDisplay , VoteResults[0] , VoteResults[1] , VoteResults[2] , VoteResults[3] // Get the lifetime statistics for the connection. , string.Format("{0,21} :: {1}", "Connection" , voltDB.Statistics.GetLifetimeStatistics().ToString(StatisticsFormat.Short)) // Get lifetime statistics by node. , string.Join("\r\n" , voltDB.Statistics.GetLifetimeStatisticsByNode() .Select(p => string.Format("{0,21} :: {1}" , p.Key , p.Value.ToString(StatisticsFormat.Short) ) ) .ToArray() ) // Statistics by procedure, across all nodes. , string.Join("\r\n" , voltDB.Statistics.GetStatistics(StatisticsSnapshot.SnapshotOnly) .Select(p => string.Format("{0,21} :: {1}" , p.Key , p.Value.ToString(StatisticsFormat.Short) ) ) .ToArray() ) // And lifetime statistics again, but with the detailed latency information. , voltDB.Statistics.GetLifetimeStatistics().ToString(StatisticsFormat.Default) ); } catch (Exception x) { // You'll want to be more elaborate than having a global catch block! // Might happen if: failed to connect, lose connection during the test (wrap a try/catch around the // Vote.BeginExecute call, or use the Vote.TryExecuteAsync call to test the execution was launched // successfully! Console.WriteLine(x.ToString()); } }
// Application entry-point static void Main(string[] args) { try { // Read hosts from the command or use defaults string hosts = "192.168.1.203"; if (args.Length > 0) { hosts = string.Join(",", string.Join(",", args).Split(' ', ',')); } // Initialize some variables for the process Random rand = new Random(); long phoneNumber = 0; sbyte contestantId = 0; int maximumAllowedVotesPerPhoneNumber = 3; Console.WriteLine("Voter Benchmark (2 minutes)\r\n----------------------------------------------------------------------------------------------------"); // Create & open connection VoltConnection voltDB = VoltConnection.Create("hosts=" + hosts + ";statistics=true;").Open(); // Create strongly-typed procedure wrappers var Vote = voltDB.Procedures.Wrap <long, long, sbyte, int>("Vote", VoterCallback); var Initialize = voltDB.Procedures.Wrap <long, int, string>("Initialize", null); var Results = voltDB.Procedures.Wrap <Table>("Results", null); // Initialize application int numContestants = (int)Initialize.Execute(rand.Next(5, 10), "Edwina Burnam,Tabatha Gehling,Kelly Clauss,Jessie Alloway,Alana Bregman,Jessie Eichman,Allie Rogalski,Nita Coster,Kurt Walser,Ericka Dieter,Loraine Nygren,Tania Mattioli").Result; Console.WriteLine("Voting for {0} Contestants\r\nTracking Live Statistics (Connection Aggregates)\r\n----------------------------------------------------------------------------------------------------", numContestants); // Start display ticker for stats Timer ticker = new Timer(delegate(object state) { Console.WriteLine("{0,24}", string.Join("\r\n", (state as VoltConnection).Statistics.GetLifetimeStatisticsByNode().Select(r => r.Key.ToString() + " :: " + r.Value.ToString(StatisticsFormat.Short)).ToArray())); }, voltDB, 5000, 5000); /* * int workerThreads; * int completionPortThreads; * ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads); * ThreadPool.SetMaxThreads(workerThreads*2, completionPortThreads*2); */ // Run for 2 minutes. int end = Environment.TickCount + 120000; while (Environment.TickCount < end) { phoneNumber = 2000000000L + (long)(rand.NextDouble() * 9999999999L); contestantId = unchecked ((sbyte)rand.Next(0, numContestants)); if (rand.Next(10000) < 10) { contestantId = 11; } if (rand.Next(20000) < 10) { for (int i = 0; i < 5; i++) { Vote.BeginExecute(phoneNumber, unchecked ((sbyte)rand.Next(0, numContestants)), maximumAllowedVotesPerPhoneNumber); } } else { Vote.BeginExecute(phoneNumber, contestantId, maximumAllowedVotesPerPhoneNumber); } } // Finalize operations and get vote results voltDB.Drain(); ticker.Dispose(); // Something new compared to the "Novice" version: you don't have to constantly when accessing data: // use .GetValue<type>(columnIndex) - simply wrap your table into a strongly-typed accessor and things // become a lot easier! var resultData = Results.Execute().Result.Wrap <string, int?, long?>(); voltDB.Close(); // Compile results & print summary string resultDisplay = string.Join("\r\n", resultData.Rows.Select(r => string.Format("{0,21} => {1,12:##,#} votes(s)", r.Column1, r.Column3)).ToArray()) + string.Format("\r\n\r\n {0,21} was the winner!\r\n", resultData.Rows.OrderByDescending(r => r.Column3).First().Column1); Console.Write(ResultFormat, resultDisplay, VoteResults[0], VoteResults[1], VoteResults[2], VoteResults[3] , string.Format("{0,21} :: {1}", "Connection", voltDB.Statistics.GetLifetimeStatistics().ToString(StatisticsFormat.Short)) , string.Join("\r\n", voltDB.Statistics.GetLifetimeStatisticsByNode().Select(p => string.Format("{0,21} :: {1}", p.Key, p.Value.ToString(StatisticsFormat.Short))).ToArray()) , string.Join("\r\n", voltDB.Statistics.GetStatistics(StatisticsSnapshot.SnapshotOnly).Select(p => string.Format("{0,21} :: {1}", p.Key, p.Value.ToString(StatisticsFormat.Short))).ToArray()) , voltDB.Statistics.GetLifetimeStatistics().ToString(StatisticsFormat.Default) , line ); } catch (Exception x) { // You'll want to be more elaborate than having a global catch block! Console.WriteLine(x.ToString()); } }