Ejemplo n.º 1
0
 private void resetConnectionToolStripMenuItem_Click(object sender, EventArgs e)
 {
     // Force the user to enter the connection information the next time a Web Request is made.
     WebTransactionProtocol.IsUrlPrompted        = true;
     WebTransactionProtocol.IsCredentialPrompted = true;
     WebTransactionProtocol.OnCredentialsChanged();
 }
Ejemplo n.º 2
0
        static int Main(string[] args)
        {
            // If this flag is set during the processing of the file, the program will exit with an error code.
            bool hasErrors = false;

            try
            {
                // Defaults
                batchSize     = 100;
                assemblyName  = "External Service";
                nameSpaceName = "MarkThree.Quasar.External";

                // The command line parser is driven by different states that are triggered by the flags read.  Unless a flag has been
                // read, the command line parser assumes that it's reading the file name from the command line.
                argumentState = ArgumentState.FileName;

                // Parse the command line for arguments.
                foreach (string argument in args)
                {
                    // Decode the current argument into a state change (or some other action).
                    if (argument == "-a")
                    {
                        argumentState = ArgumentState.Assembly; continue;
                    }
                    if (argument == "-b")
                    {
                        argumentState = ArgumentState.BatchSize; continue;
                    }
                    if (argument == "-n")
                    {
                        argumentState = ArgumentState.NameSpace; continue;
                    }
                    if (argument == "-i")
                    {
                        argumentState = ArgumentState.FileName; continue;
                    }

                    // The parsing state will determine which variable is read next.
                    switch (argumentState)
                    {
                    case ArgumentState.Assembly:
                        assemblyName = argument;
                        break;

                    case ArgumentState.BatchSize:
                        batchSize = Convert.ToInt32(argument);
                        break;

                    case ArgumentState.FileName:
                        fileName = argument;
                        break;

                    case ArgumentState.NameSpace:
                        nameSpaceName = argument;
                        break;
                    }

                    // The default state is to look for the input file name on the command line.
                    argumentState = ArgumentState.FileName;
                }

                // Throw a usage message back at the user if no file name was given.
                if (fileName == null)
                {
                    throw new Exception("Usage: Loader.Algorithm -i <FileName>");
                }

                // Open up the file containing all the broker.
                BrokerReader brokerReader = new BrokerReader(fileName);

                // Loading the database involves creating a batch of commands and sending them off as a transaction.  This gives
                // the server a chance to pipeline a large chunk of processing, without completely locking up the server for the
                // entire set of data.  This will construct a header for the command batch which gives information about which
                // assembly contains the class that is used to load the data.
                Batch           batch           = new Batch();
                TransactionPlan transactionPlan = batch.Transactions.Add();
                AssemblyPlan    assemblyPlan    = batch.Assemblies.Add(assemblyName);
                TypePlan        typePlan        = assemblyPlan.Types.Add(string.Format("{0}.{1}", nameSpaceName, "Broker"));

                // Read the file until an EOF is reached.
                while (true)
                {
                    // This counter keeps track of the number of records sent.  When the batch is full, it's sent to the server to be
                    // executed as a single transaction.
                    int batchCounter = 0;

                    // Read the next broker from the input stream.  A 'null' is returned when we've read past the end of file.
                    Broker broker = brokerReader.ReadBroker();
                    if (broker != null)
                    {
                        // Create a new method from the type information and the name found in the XML file.
                        MethodPlan methodPlan = new MethodPlan("Load");

                        // Construct a call to the 'Load' method to populate the broker record.
                        methodPlan.Parameters.Add(new InputParameter("brokerId", broker.Symbol));
                        methodPlan.Parameters.Add(new InputParameter("name", broker.Name));
                        methodPlan.Parameters.Add(new InputParameter("symbol", broker.Symbol));

                        // Create a method from the XML data and add it to the transaction.
                        transactionPlan.Methods.Add(typePlan, methodPlan);
                    }

                    // This will check to see if it's time to send the batch.  A batch is sent when the 'batchSize' has been
                    // reached, or if the last record has just been converted into a command.
                    if (++batchCounter % batchSize == 0 || broker == null)
                    {
                        WebTransactionProtocol.Execute(batch);

                        batch           = new Batch();
                        transactionPlan = batch.Transactions.Add();
                        assemblyPlan    = batch.Assemblies.Add(assemblyName);
                        typePlan        = assemblyPlan.Types.Add(string.Format("{0}.{1}", nameSpaceName, "Broker"));
                    }

                    // If the end of file was reached, break out of the loop and exit the application.
                    if (broker == null)
                    {
                        break;
                    }
                }
            }
            catch (BatchException batchException)
            {
                foreach (Exception exception in batchException.Exceptions)
                {
                    Console.WriteLine(exception.Message);
                }
                hasErrors = true;
            }
            catch (Exception exception)
            {
                // Show the system error and exit with an error.
                Console.WriteLine(exception.Message);
                hasErrors = true;
            }

            // Any errors will cause an abnormal exit.
            if (hasErrors)
            {
                return(1);
            }

            // Write a status message when a the file is loaded successfully.
            Console.WriteLine(String.Format("{0} Data: Brokers, Loaded", DateTime.Now.ToString("u")));

            // If we reached here, the file was imported without issue.
            return(0);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Execute a command batch and synchronizes the client data model with the newer records from the server.
        /// </summary>
        public static void Execute(Batch batch)
        {
            // This 'try' block will insure that the mutual exclusion locks are released.
            try
            {
                // Make sure only one thread at a time tries to refresh the data model.
                ClientMarketData.clientDataMutex.WaitOne();

                // Switching credentials without exiting the application will force the data model to be cleared and the row
                // counting to begin at zero again.  That is, it effectively resets the client data model.
                if (ClientMarketData.isReset)
                {
                    ClientMarketData.isReset    = false;
                    ClientMarketData.rowVersion = 0;
                    ClientMarketData.Clear();
                }

                // IMPORTANT CONCEPT: The rowVersion keeps track of the state of the client in-memory database. The server
                // returns a value for us to use on the next cycle.
                long rowVersion = ClientMarketData.rowVersion;

                // IMPORTANT CONCEPT:  Executing the 'GetClientMarketData' with a rowVersion returns to the client a DataSet
                // with only records that are the same age or younger than the rowVersion. This reduces the traffic on the
                // network to include only the essential records.  We are also merging it with the current ClientMarketData,
                // which adds new records and records that were deleted by the server.
                AssemblyPlan    assembly            = batch.Assemblies.Add("Server Market Data");
                TypePlan        type                = assembly.Types.Add("MarkThree.Guardian.Server.ServerMarketData");
                TransactionPlan transaction         = batch.Transactions.Add();
                MethodPlan      method              = transaction.Methods.Add(type, "Reconcile");
                Parameter       rowVersionParameter = method.Parameters.Add(new InputParameter("rowVersion", rowVersion));

                // Execute the the command to get the incremental changes from the server.
                WebTransactionProtocol.Execute(batch);

                // This is the updated data model information returned from the server.
                ArrayList reconciledData = (ArrayList)method.Parameters.Return.Value;

                // Optimization: Don't merge the results if there's nothing to merge.
                if (reconciledData != null)
                {
                    // IMPORTANT CONCEPT: Since the results will still be on the server if the client misses a refresh
                    // cycle, we take the attitude that thBzis update process doesn't have to wait for locks. That is, if we
                    // can't get all the tables locked quickly, we'll just wait until the next refresh period to get the
                    // results. This effectively prevents deadlocking on the client. Make sure all the tables are locked
                    // before populating them.
                    foreach (TableLock tableLock in ClientMarketData.TableLocks)
                    {
                        tableLock.AcquireWriterLock(ClientTimeout.LockWait);
                    }

                    // IMPORTANT CONCEPT: This broadcast can be used to set up conditions for the data event handlers. Often,
                    // optimizing algorithms will be used to consolidate the results of a merge.  This will allow the event
                    // driven logic to clear previous results and set up initial states for handling the bulk update of data.
                    ClientMarketData.OnBeginMerge(typeof(ClientMarketData));

                    // IMPORANT CONCEPT:  Once all the write locks have been obtained, we can merge the results.  This will
                    // trigger the events associated with the tables for updated and deleted rows.  Note that this 'Merge'
                    // method has different characteristics than the original one provided by Microsoft (that is, this one
                    // works).
                    ClientMarketData.rowVersion = MarketData.Merge(reconciledData);

                    // IMPORTANT CONCEPT: When the merge is complete, this will broadcast an event which allows optimization code
                    // to consolidate the results, examine the changed values and update reports based on the changed data.
                    ClientMarketData.OnEndMerge(typeof(ClientMarketData));
                }
            }
            finally
            {
                // No matter what happens above, we need to release the locks acquired above.
                foreach (TableLock tableLock in ClientMarketData.TableLocks)
                {
                    if (tableLock.IsWriterLockHeld)
                    {
                        tableLock.ReleaseWriterLock();
                    }
                }

                // Other threads can now request a refresh of the data model.
                ClientMarketData.clientDataMutex.ReleaseMutex();
            }

            // Throw a specialized exception if the server returned any errors in the Batch structure.
            if (batch.HasExceptions)
            {
                throw new BatchException(batch);
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Sends a batch of commands to the server and processes the results.
 /// </summary>
 private void SendBatch(Batch batch)
 {
     WebTransactionProtocol.Execute(batch);
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Read, parse and load the stylesheet into the middle tier.
        /// </summary>
        public void Load()
        {
            // If this flag is set during the processing of the file, the program will exit with an error code.
            this.HasErrors = false;

            // If the user wants to specify a new URL and certificate, then prompt for the connection info the next time a
            // WebTransactionProtocol sends off a batch.
            if (this.ForceLogin)
            {
                WebTransactionProtocol.IsUrlPrompted        = true;
                WebTransactionProtocol.IsCredentialPrompted = true;
            }

            // Load up an XML document with the contents of the file specified on the command line.
            XmlDocument stylesheet = new XmlDocument();

            stylesheet.Load(this.FileName);

            // The XML document has several nodes that need to be read -- and then removed -- that contain attributes of the
            // stylesheet.  These nodes can be found easily using the XSL Path functions which need a namespace manager to sort out
            // the tag prefixes.
            XmlNamespaceManager namespaceManager = new XmlNamespaceManager(stylesheet.NameTable);

            namespaceManager.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform");
            namespaceManager.AddNamespace("mts", "urn:schemas-markthreesoftware-com:stylesheet");

            // The spreadhseet source has several nodes which contain information about how the data in the XML document should be
            // loaded into the server, such as the stylesheet identifier, the name and the stylesheet style.  They are found at
            // this node.  After these information nodes have been read, they are removed from the stylesheet source.
            XmlNode stylesheetNode = stylesheet.SelectSingleNode("xsl:stylesheet", namespaceManager);

            if (stylesheetNode == null)
            {
                throw new Exception("Syntax Error: missing stylesheet declaration.");
            }

            // Find the StylesheetId node.
            XmlNode StylesheetIdNode = stylesheetNode.SelectSingleNode("mts:stylesheetId", namespaceManager);

            if (StylesheetIdNode == null)
            {
                throw new Exception("Syntax Error: missing StylesheetId declaration.");
            }

            // Find the StylesheetStyle node.
            XmlNode stylesheetTypeCodeNode = stylesheetNode.SelectSingleNode("mts:stylesheetTypeCode", namespaceManager);

            if (stylesheetTypeCodeNode == null)
            {
                throw new Exception("Syntax Error: missing StylesheetStyle declaration.");
            }

            // Find the name node.
            XmlNode nameNode = stylesheetNode.SelectSingleNode("mts:name", namespaceManager);

            if (nameNode == null)
            {
                throw new Exception("Syntax Error: missing name declaration.");
            }

            // Extract the data from the XML nodes.
            this.StylesheetId       = StylesheetIdNode.InnerText;
            this.StylesheetTypeCode = stylesheetTypeCodeNode.InnerText;
            this.StylesheetName     = nameNode.InnerText;

            // Remove the stylesheet nodes from the XSL spreadsheet before loading it into the server.
            stylesheetNode.RemoveChild(StylesheetIdNode);
            stylesheetNode.RemoveChild(stylesheetTypeCodeNode);
            stylesheetNode.RemoveChild(nameNode);

            // Create a command to load the stylesheet from the data loaded from the file.
            Batch           batch       = new Batch();
            TransactionPlan transaction = batch.Transactions.Add();
            AssemblyPlan    assembly    = batch.Assemblies.Add(this.Assembly);
            TypePlan        type        = assembly.Types.Add(this.Type);
            MethodPlan      method      = transaction.Methods.Add(type, this.Method);

            method.Parameters.Add(new InputParameter("stylesheetId", this.StylesheetId));
            method.Parameters.Add(new InputParameter("stylesheetTypeCode", this.StylesheetTypeCode));
            method.Parameters.Add(new InputParameter("name", this.StylesheetName));
            method.Parameters.Add(new InputParameter("text", stylesheet.InnerXml));

            try
            {
                // Create a new web client that will serve as the connection point to the server and call the web services to execute
                // the command batch.
                WebTransactionProtocol.Execute(batch);
            }
            catch (BatchException)
            {
                foreach (MethodPlan batchMethod in transaction.Methods)
                {
                    foreach (Exception exception in batchMethod.Exceptions)
                    {
                        Console.WriteLine(String.Format("{0}: {1}", method.Parameters["StylesheetId"].Value, exception.Message));
                    }
                }

                this.HasErrors = true;
            }
        }