Example #1
0
        /// <summary>
        /// Parse a transaction out of the XML file.
        /// </summary>
        /// <param name="xmlNode">The node where the transaction has been found.</param>
        private void ParseTransaction(XmlNode xmlNode)
        {
            // Create an explicit transaction for the methods found at this node.
            this.transaction = this.batch.Transactions.Add();

            // The <Method> tag specifies the name assembly, type and method name for this operation.  The parameters to the method
            // call will be nested under this heading.
            foreach (XmlNode methodNode in xmlNode.SelectNodes("method"))
            {
                ParseMethod(methodNode);
            }
        }
Example #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);
        }
Example #3
0
        /// <summary>
        /// Begins the task of applying the changes in the form to the data model.
        /// </summary>
        private void PostThread(object parameter)
        {
            // Extract the parameters from the threads parameter.
            object[]    parameters  = (object[])parameter;
            bool        exitDialog  = (bool)parameters[0];
            SourceOrder sourceOrder = (SourceOrder)parameters[1];

            // This batch will collect the information needed to execute a complex transaction on the server.  The first part of
            // the batch sets up the transaction: the assembly where the types and methods are found.  It also sets up a
            // transaction for a complex operation. In this case, the transaction is not that complex, just a single method to be
            // executed.
            Batch           batch       = new Batch();
            AssemblyPlan    assembly    = batch.Assemblies.Add("Trading Service");
            TypePlan        type        = assembly.Types.Add("MarkThree.Guardian.Trading.SourceOrder");
            TransactionPlan transaction = batch.Transactions.Add();
            MethodPlan      methodPlan  = transaction.Methods.Add(type, "Insert");

            // These are the parameters used to create a Source Order.  The Working Order will be created implicitly.
            methodPlan.Parameters.Add(new InputParameter("blotterId", this.blotter.BlotterId));
            methodPlan.Parameters.Add(new InputParameter("isBrokerMatch", sourceOrder.IsBrokerMatch));
            methodPlan.Parameters.Add(new InputParameter("isHedgeMatch", sourceOrder.IsHedgeMatch));
            methodPlan.Parameters.Add(new InputParameter("isInstitutionMatch", sourceOrder.IsInstitutionMatch));
            methodPlan.Parameters.Add(new InputParameter("submissionTypeCode", SubmissionType.UsePeferences));
            if (sourceOrder.MaximumVolatility != DBNull.Value)
            {
                methodPlan.Parameters.Add(new InputParameter("maximumVolatility", sourceOrder.MaximumVolatility));
            }
            if (sourceOrder.NewsFreeTime != DBNull.Value)
            {
                methodPlan.Parameters.Add(new InputParameter("newsFreeTime", sourceOrder.NewsFreeTime));
            }
            methodPlan.Parameters.Add(new InputParameter("orderedQuantity", sourceOrder.Quantity));
            methodPlan.Parameters.Add(new InputParameter("orderTypeCode", sourceOrder.OrderTypeCode));
            methodPlan.Parameters.Add(new InputParameter("priceTypeCode", PriceType.Market));
            methodPlan.Parameters.Add(new InputParameter("securityId", sourceOrder.SecurityId));
            methodPlan.Parameters.Add(new InputParameter("settlementId", sourceOrder.SettlementId));
            if (sourceOrder.StartTime != DBNull.Value)
            {
                methodPlan.Parameters.Add(new InputParameter("startTime", sourceOrder.StartTime));
            }
            if (sourceOrder.StopTime != DBNull.Value)
            {
                methodPlan.Parameters.Add(new InputParameter("stopTime", sourceOrder.StopTime));
            }
            methodPlan.Parameters.Add(new InputParameter("timeInForceCode", TimeInForce.Day));

            // This will execute the command on the server and return any exceptions.
            BatchException batchException = null;

            try
            {
                // Execute the batch.
                ClientMarketData.Execute(batch);
            }
            catch (BatchException exception)
            {
                // Any exceptions will be captured here and passed on to the foreground.
                batchException = exception;
            }

            // Call the foreground thread with the results of executing the batch on the server.  Also, in some cases the dialog is
            // going to be dismissed when the server data model has finished updating successfully.  Pass on the flag to the
            // foreground that will indicate whether the form is closed once the results are processed.
            BeginInvoke(this.postEndDelegate, new object[] { exitDialog, batchException });
        }
Example #4
0
        private void DeclineTrade(object parameter)
        {
            bool       isBatchValid = true;
            Batch      batch        = new Batch();
            MethodPlan method       = null;

            try
            {
                // Lock the tables.
                System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked);
                ClientMarketData.MatchLock.AcquireReaderLock(ClientTimeout.LockWait);
                ClientMarketData.OrderTypeLock.AcquireReaderLock(ClientTimeout.LockWait);
                ClientMarketData.SecurityLock.AcquireReaderLock(ClientTimeout.LockWait);
                ClientMarketData.WorkingOrderLock.AcquireReaderLock(ClientTimeout.LockWait);

                // Find the Match record.
                ClientMarketData.MatchRow matchRow = ClientMarketData.Match.FindByMatchId(this.matchId);

                AssemblyPlan    assembly    = batch.Assemblies.Add("Core Service");
                TypePlan        type        = assembly.Types.Add("MarkThree.Guardian.Core.Negotiation");
                TransactionPlan transaction = batch.Transactions.Add();
                method = transaction.Methods.Add(type, "Insert");
                method.Parameters.Add(new InputParameter("matchId", matchId));
                method.Parameters.Add(new InputParameter("quantity", 0.0m));
                method.Parameters.Add(new InputParameter("statusCode", Status.Declined));
            }
            catch (Exception exception)
            {
                // Write the error and stack trace out to the debug listener
                EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace);

                // This indicates that the batch shouldn't be executed.
                isBatchValid = false;
            }
            finally
            {
                // Release the locks.
                if (ClientMarketData.MatchLock.IsReaderLockHeld)
                {
                    ClientMarketData.MatchLock.ReleaseReaderLock();
                }
                if (ClientMarketData.OrderTypeLock.IsReaderLockHeld)
                {
                    ClientMarketData.OrderTypeLock.ReleaseReaderLock();
                }
                if (ClientMarketData.SecurityLock.IsReaderLockHeld)
                {
                    ClientMarketData.SecurityLock.ReleaseReaderLock();
                }
                if (ClientMarketData.WorkingOrderLock.IsReaderLockHeld)
                {
                    ClientMarketData.WorkingOrderLock.ReleaseReaderLock();
                }
                System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked);
            }

            // If the command batch was built successfully, then execute it.  If any part of it should fail, cancel the edit and
            // display the server errors.
            if (isBatchValid)
            {
                try
                {
                    // Call the web server to rename the object on the database.  Note that this method must be called when there
                    // are no locks to prevent deadlocking.  That is why it appears in it's own 'try/catch' block.
                    ClientMarketData.Execute(batch);

                    this.negotiationId = (int)method.Parameters.Return.Value;
                }
                catch (BatchException batchException)
                {
                    // Display each error in the batch.
                    foreach (Exception exception in batchException.Exceptions)
                    {
                        Invoke(new MessageDelegate(ShowMessage), exception.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }
Example #5
0
        /// <summary>
        /// Moves a child object from one parent to another.
        /// </summary>
        /// <param name="parameter">An array consiting of the target parent, the current parent and the child to be moved.</param>
        private void MoveChild(object parameter)
        {
            // Extract the objects selected by the drag-and-drop operation.
            object[] parameters = (object[])parameter;
            MarkThree.Guardian.Object toObject    = (MarkThree.Guardian.Object)parameters[0];
            MarkThree.Guardian.Object fromObject  = (MarkThree.Guardian.Object)parameters[1];
            MarkThree.Guardian.Object childObject = (MarkThree.Guardian.Object)parameters[2];

            try
            {
                // Lock the tables needed for this operation.
                System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked);
                ClientMarketData.ObjectLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.ObjectTreeLock.AcquireReaderLock(CommonTimeout.LockWait);

                // It's critical that circular references aren't created, either by accident or design.  First, find the object
                // record associated with the destination node.
                ClientMarketData.ObjectRow parentRow = ClientMarketData.Object.FindByObjectId(toObject.ObjectId);
                if (parentRow == null)
                {
                    throw new Exception("This object has been deleted");
                }

                // This is the object that is being dragged.  Find the row
                ClientMarketData.ObjectRow childRow = ClientMarketData.Object.FindByObjectId(childObject.ObjectId);
                if (childRow == null)
                {
                    throw new Exception("This object has been deleted");
                }

                // This will remove the possibility of a circular relationship.
                if (MarkThree.Guardian.Relationship.IsChildObject(childRow, parentRow))
                {
                    Invoke(new MessageDelegate(ShowMessage), Properties.Resources.CircularReferenceError, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            catch (Exception exception)
            {
                // Write the error and stack trace out to the debug listener
                EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace);
            }
            finally
            {
                // Release table locks.
                if (ClientMarketData.ObjectLock.IsReaderLockHeld)
                {
                    ClientMarketData.ObjectLock.ReleaseReaderLock();
                }
                if (ClientMarketData.ObjectTreeLock.IsReaderLockHeld)
                {
                    ClientMarketData.ObjectTreeLock.ReleaseReaderLock();
                }
                System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked);
            }

            // Any commands created below will be constructed in this object and sent to the server for execution.
            bool  isBatchValid = true;
            Batch batch        = new Batch();

            // If we made it here, the drag-and-drop is interpreted as a command to move a child from one parent to another.
            try
            {
                // Lock the tables needed for this operation.
                System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked);
                ClientMarketData.ObjectLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.ObjectTreeLock.AcquireReaderLock(CommonTimeout.LockWait);

                // Extract the primary identifiers from the user interface nodes.
                // This is the object that is being dragged.  Find the row
                ClientMarketData.ObjectRow childRow = ClientMarketData.Object.FindByObjectId(childObject.ObjectId);
                if (childRow == null)
                {
                    throw new Exception("This object has been deleted");
                }

                // Find the object in the data model and make sure it still exists.
                ClientMarketData.ObjectTreeRow objectTreeRow = null;
                foreach (ClientMarketData.ObjectTreeRow innerObjectTreeRow in childRow.GetObjectTreeRowsByObjectObjectTreeChildId())
                {
                    if (innerObjectTreeRow.ParentId == fromObject.ObjectId)
                    {
                        objectTreeRow = innerObjectTreeRow;
                    }
                }
                if (objectTreeRow == null)
                {
                    throw new Exception("This relationship has been deleted by someone else.");
                }

                // Moving a child object from one parent to another must be accomplished as a transaction.  Otherwise, an
                // orhpan object will be created if the operation fails midway through.
                TransactionPlan transaction = batch.Transactions.Add();
                AssemblyPlan    assembly    = batch.Assemblies.Add("Core Service");
                TypePlan        type        = assembly.Types.Add("MarkThree.Guardian.Core.ObjectTree");

                // Construct a command delete the old parent relation.
                MethodPlan deleteObjectTree = transaction.Methods.Add(type, "Update");
                deleteObjectTree.Parameters.Add(new InputParameter("objectTreeId", objectTreeRow.ObjectTreeId));
                deleteObjectTree.Parameters.Add(new InputParameter("parentId", toObject.ObjectId));
                deleteObjectTree.Parameters.Add(new InputParameter("childId", childObject.ObjectId));
                deleteObjectTree.Parameters.Add(new InputParameter("rowVersion", objectTreeRow.RowVersion));
            }
            catch (Exception exception)
            {
                // Write the error and stack trace out to the debug listener
                EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace);

                // This indicates that the batch shouldn't be executed.
                isBatchValid = false;
            }
            finally
            {
                // Release table locks.
                if (ClientMarketData.ObjectLock.IsReaderLockHeld)
                {
                    ClientMarketData.ObjectLock.ReleaseReaderLock();
                }
                if (ClientMarketData.ObjectTreeLock.IsReaderLockHeld)
                {
                    ClientMarketData.ObjectTreeLock.ReleaseReaderLock();
                }
                System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked);
            }

            // If the command batch was built successfully, then execute it.
            if (isBatchValid)
            {
                try
                {
                    // Call the web server to rename the object on the database.  Note that this method must be called when there are
                    // no locks to prevent deadlocking.  That is why it appears in it's own 'try/catch' block.
                    ClientMarketData.Execute(batch);
                }
                catch (BatchException batchException)
                {
                    // Display each error in the batch.
                    foreach (Exception exception in batchException.Exceptions)
                    {
                        MessageBox.Show(exception.Message, "Guardian Error");
                    }
                }
            }
        }
Example #6
0
        /// <summary>
        /// Rename the object.
        /// </summary>
        /// <param name="parameters">The object to be renamed.</param>
        private void RenameObject(object parameter)
        {
            // Extract the thread arguments
            object[] parameters = (object[])parameter;
            TreeNode treeNode   = (TreeNode)parameters[0];
            string   name       = (string)parameters[1];

            // Extract the object that is associated with the TreeView node.
            MarkThree.Guardian.Object commonObject = (MarkThree.Guardian.Object)treeNode.Tag;

            // This command batch is constructed below and sent to the server for execution.  Note that the batch is designed to
            // live beyond the block of code that locks the data model.  This is to prevent the data model from being locked while
            // a relatively long server database operation is underway.
            bool  isBatchValid = true;
            Batch batch        = new Batch();

            try
            {
                // Lock the table
                System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked);
                ClientMarketData.ObjectLock.AcquireReaderLock(CommonTimeout.LockWait);

                // Find the object in the data model and make sure it still exists.
                ClientMarketData.ObjectRow objectRow = ClientMarketData.Object.FindByObjectId(commonObject.ObjectId);
                if (objectRow == null)
                {
                    throw new Exception("This object has been deleted.");
                }

                // Construct a command to rename the object.
                AssemblyPlan    assembly    = batch.Assemblies.Add("Core Service");
                TypePlan        type        = assembly.Types.Add("MarkThree.Guardian.Core.Object");
                TransactionPlan transaction = batch.Transactions.Add();
                MethodPlan      method      = transaction.Methods.Add(type, "Update");
                method.Parameters.Add(new InputParameter("rowVersion", objectRow.RowVersion));
                method.Parameters.Add(new InputParameter("objectId", objectRow.ObjectId));
                method.Parameters.Add(new InputParameter("name", name));
            }
            catch (Exception exception)
            {
                // This serves as an indication that the batch couldn't be constructed.
                isBatchValid = false;

                // Write the error and stack trace out to the debug listener
                EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace);
            }
            finally
            {
                // Release table locks.
                if (ClientMarketData.ObjectLock.IsReaderLockHeld)
                {
                    ClientMarketData.ObjectLock.ReleaseReaderLock();
                }
                System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked);
            }

            // If the command batch was built successfully, then execute it.  If any part of it should fail, cancel the edit and
            // display the server errors.
            if (isBatchValid)
            {
                try
                {
                    // Call the web server to rename the object on the database.  Note that this method must be called when there
                    // are no locks to prevent deadlocking.  That is why it appears in it's own 'try/catch' block.
                    ClientMarketData.Execute(batch);
                }
                catch (BatchException batchException)
                {
                    // Display each error in the batch.
                    foreach (Exception exception in batchException.Exceptions)
                    {
                        Invoke(new MessageDelegate(ShowMessage), exception.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }
Example #7
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);
            }
        }
Example #8
0
        /// <summary>
        /// Load the XML script.
        /// </summary>
        public void Load()
        {
            // This flag is set when an error occurs anywhere in the processing of the XML file.
            this.HasErrors = false;

            // Read the XML data from the specified file.
            XmlDocument xmlDocument = new XmlDocument();

            xmlDocument.Load(this.FileName);

            // Sending records to the server is state driven.  This loop will collect a batch of commands until a new table is
            // found in the XML stream, or until the limit of a batch is reached, or until the end of the file is read.  The idea
            // is to allow several tables of data to exist in a single file.
            XmlNode rootNode = xmlDocument.DocumentElement;

            // The script name is stored in the root node.  The name is used in status and debugging messages.
            this.ScriptName = rootNode.Attributes["name"] == null ? "Unnamed Batch" : rootNode.Attributes["name"].Value;

            // 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;
            }

            // Create a batch to hold the transactions.
            this.batch = new Batch();

            // As methods are parsed, they're added to this transaction.  The organization of the transaction is determined by the
            // input file.  Explicit transaction will create their own transactions when they appear in the file.  Implicit
            // transactions are created when an unaffiliated method element is parsed out of the XML file.
            this.transaction = null;

            // The batch is sent when this flag is set.
            bool sendBatch = false;

            // Cycle through all of the children of the root node.  The methods in this file will either be affiliated with an
            // explicit transaction, or be unaffiliated.  The 'free' methods will be packed together in an implicit transaction and
            // sent to the server when the transaction reaches a predetermined size.  This will search the file for both kinds of
            // records.
            foreach (XmlNode xmlNode in rootNode)
            {
                // A 'transaction' element is a command for an explicit transaction.  A 'method' element declares a method for an
                // implicit (internally created) transaction.
                switch (xmlNode.Name)
                {
                case "transaction":

                    // Parse the methods out of the node and send the batch off to the server for execution.
                    ParseTransaction(xmlNode);
                    break;

                case "send":

                    // Transactions can be grouped together in a file.  They are not sent to the Web Transaction handler until
                    // either the end of the file, or an explicit 'send' node.
                    sendBatch = true;;
                    break;

                case "method":

                    // For an implicit method execution, a transaction will be created automatically.  When the batch is sent, this
                    // value will be cleared again.
                    if (this.transaction == null)
                    {
                        this.transaction = this.batch.Transactions.Add();
                    }

                    // Parse the method out of the XML node.
                    ParseMethod(xmlNode);

                    // If the size of the transaction has reached the predetermined limit, then the batch can be sent.
                    if (this.transaction.Methods.Count == this.TransactionSize)
                    {
                        sendBatch = true;
                    }

                    break;
                }

                // If the parser has determined that the batch is large enough, then it is sent to the server.
                if (sendBatch)
                {
                    // Send the batch to the server.
                    SendBatch(batch);

                    // Prepare a brand new batch for the records remaining to be parsed.
                    this.batch       = new Batch();
                    this.transaction = null;
                    sendBatch        = false;
                }
            }

            // If a transaction has been initialized but not sent, then send the batch.
            if (batch.Transactions.Count != 0)
            {
                SendBatch(batch);
            }

            // Wait here until all the IO requests have completed.
            this.requestCompleted.WaitOne();
        }
Example #9
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;
            }
        }
Example #10
0
        /// <summary>
        /// Marshals the data needed refuse a chance to negotiate a trade.
        /// </summary>
        /// <param name="parameter">The thread initialization data.</param>
        private void DeclineNegotiationThread(object parameter)
        {
            // Extract the thread parameters
            int matchId = (int)parameter;

            // This batch, if succesfully constructed, will be sent to the server to deline the negotiation.
            Batch batch = new Batch();

            try
            {
                // Lock the tables.
                System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked);
                ClientMarketData.MatchLock.AcquireReaderLock(ClientTimeout.LockWait);
                ClientMarketData.OrderTypeLock.AcquireReaderLock(ClientTimeout.LockWait);
                ClientMarketData.SecurityLock.AcquireReaderLock(ClientTimeout.LockWait);
                ClientMarketData.WorkingOrderLock.AcquireReaderLock(ClientTimeout.LockWait);

                // Find the Match record.
                ClientMarketData.MatchRow matchRow = ClientMarketData.Match.FindByMatchId(matchId);

                // Construct a command decline the negotiation.
                AssemblyPlan    assembly    = batch.Assemblies.Add("Core Service");
                TypePlan        type        = assembly.Types.Add("MarkThree.Guardian.Core.Negotiation");
                TransactionPlan transaction = batch.Transactions.Add();
                MethodPlan      method      = transaction.Methods.Add(type, "Insert");
                method.Parameters.Add(new InputParameter("matchId", matchId));
                method.Parameters.Add(new InputParameter("quantity", 0.0m));
                method.Parameters.Add(new InputParameter("statusCode", Status.Declined));
            }
            catch (Exception exception)
            {
                // Write the error and stack trace out to the debug listener
                EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace);

                // This indicates that the batch shouldn't be executed.
                batch = null;
            }
            finally
            {
                // Release the locks.
                if (ClientMarketData.MatchLock.IsReaderLockHeld)
                {
                    ClientMarketData.MatchLock.ReleaseReaderLock();
                }
                if (ClientMarketData.OrderTypeLock.IsReaderLockHeld)
                {
                    ClientMarketData.OrderTypeLock.ReleaseReaderLock();
                }
                if (ClientMarketData.SecurityLock.IsReaderLockHeld)
                {
                    ClientMarketData.SecurityLock.ReleaseReaderLock();
                }
                if (ClientMarketData.WorkingOrderLock.IsReaderLockHeld)
                {
                    ClientMarketData.WorkingOrderLock.ReleaseReaderLock();
                }
                System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked);
            }

            // If the command batch was built successfully, then execute it.
            if (batch != null)
            {
                try
                {
                    // Call the web server to rename the object on the database.  Note that this method must be called when there
                    // are no locks to prevent deadlocking.  That is why it appears in it's own 'try/catch' block.
                    ClientMarketData.Execute(batch);
                }
                catch (BatchException batchException)
                {
                    // Write any server generated error messages to the event log.
                    foreach (Exception exception in batchException.Exceptions)
                    {
                        EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace);
                    }
                }
            }
        }