Login| Sign Up| Help| Contact|

Patent Searching and Data


Title:
LOG BASED DATA ARCHITECTURE FOR A TRANSACTIONAL MESSAGE QUEUING SYSTEM
Document Type and Number:
WIPO Patent Application WO/1998/021654
Kind Code:
A1
Abstract:
A message queuing system is provided that saves and stores messages and their state in an efficient single file on a single disk to enable rapid recovery from server failures. The single disk, single file storage system into which messages and their states are stored eliminates writes to three different disks, the data disk, the index structure disk and the log disk. The single disk, single file storage is made possible by clustering all information together in a contiguous space on the same disk. The result is that all writes are contained in one sweeping motion of the write head in which the write head moves only in one direction and only once to find the area where it needs to start writing messages and their states are stored. In order to keep track of the clustered information, a unique Queue Entry Map Table (100) is used which includes control information (100), message blocks (102) and log records (104) in conjunction with single file disk storage that allows the write head never to have to back-up to traverse saved data when writing new records. The system also permits locating damaged files without the requirement of scanning entire log files.

Inventors:
WONG DAVID W H
SCHWENKE DEREK L
Application Number:
PCT/US1997/020561
Publication Date:
May 22, 1998
Filing Date:
November 11, 1997
Export Citation:
Click for automatic bibliography generation   Help
Assignee:
MITSUBISHI ELECTRIC INF TECH (US)
International Classes:
G06F12/00; G06F9/46; G06F9/54; G06F15/16; H04L29/06; G06F11/14; (IPC1-7): G06F11/00; G06F12/00
Foreign References:
US5465328A1995-11-07
US5555388A1996-09-10
Other References:
See also references of EP 1015973A4
Attorney, Agent or Firm:
Tendler, Robert K. (Boston, MA, US)
Download PDF:
Claims:
WHAT IS CLAIMED IS:
1. A message queuing system, comprising: means for transmitting a transactional message having an associated message queue including the state of the queue, message queue data and log records; and, means at a recipient site for storing said transactional message on a single disk in a single file utilizing a combined on disk file structure for said message queue data and said log records.
2. The system of Claim 1, and further including a read/write head for accessing said single disk and means for driving said head in a single forward direction during a write operation.
3. The system of Claim 1, and further including a queue entry management table placed on said disk at preselected locations, said table having a control information block, at least one message block and at least one log record.
4. The system of Claim 3, wherein said preselected locations correspond to a fixed offset from the beginning of said file, thus to permit rapid identification of the most recent state of the message queue data.
5. The system of Claim 4 and further including means at said recipient site for recovering said message queue upon interruption of said transmission responsive to the most recent queue entry management table prior to said information, whereby the last valid information received and stored is located from information contained in said most recent queue entry management table.
6. The system of Claim 5, wherein said file is divided into sectors, and wherein said offset places a queue entry management table at the beginning of a sector such that said table constitutes a checkpoint for the location of a sector having valid information, whereby the last valid information prior to said interruption may be rapidly located through the identification of the sector containing said most recent table.
7. The system of Claim 2, wherein said management queue table is written in contiguous blocks, the result of a single file, forward write direction and contiguous message queue data block system being minimization of seek time, increase in throughout and rapid recovery from a transmission interruption.
Description:
LOG BASED DATA ARCHITECTURE FOR A TRANSACTIONAL MESSAGE QUEUING SYSTEM.

FIELD OF INVENTION This invention relates to message queuing, and more particularly to a fast, reliable message queuing system for both client-server and mobile agent applications.

CROSS-REFERENCE TO RELATED APPLICATIONS A claim of priority is made to U.S. Provisional Patent Application Serial No. 60/030,905, filed November 14, 1996, entitled LOG BASED DATA ARCHITECTURE FOR A TRANSACTIONAL MESSAGE QUEUING SYSTEM.

BACKGROUND OF THE INVENTION Message queuing is the most fundamental paradigm for communication between applications on different computer systems due to its inherent flexibility in allowing both synchronous and asynchronous processing. The message queuing middleware infrastructure is a very flexible framework for a number of application domains in both general client-server as well as mobile agent computing arenas, to wit work flow computing, object messaging, transactional messaging and data replication services.

It will be appreciated that in many transactional messaging scenarios data is oftentimes lost during the transmission. This is no more catastrophic than in the banking industry in which banking records transmitted from one location to another can be lost due to server failures, transmission line failures or other artifacts. It is incumbent upon the system managers to be able to quickly locate the fact that an error has occurred and to be able to reconstruct the data from a known point where the data was valid.

Establishing that point at which an error has occurred has in the past been accomplished by systems which scan an entire so- called log file to reconstruct the up-to-date state of the system before the crash. Log files are routinely utilized with their associated time stamps to identify messages and the data they contain. However, the scanning of entire log files to ascertain the up-to-date state can require scanning as many as 1,000 log records.

Not only is the scanning of the overall log record an inefficient way to ascertain where an error occurred and to be able to reconstruct files from that point, systems in the past have required two disk files, one serving as a data file, and the other serving as a log file.

Moreover, the correlation between the log entries and the data files or sectors is complicated by the fact that in the past, sectors were stored in some indiscriminant order, leaving the mapping between the log file and the sectors a somewhat time consuming process.

By way of further background, it will be appreciated that message queuing is used in general to be able to provide a fail- safe storage for data records which are transmitted from one point to another. If, for instance, an error occurs and data is lost at one location, it can be reconstructed at a second location due to the storage inherent in message queuing.

As an example, it is desirable, especially in stock market trades, that any interruption in trading to be minimized to minutes as opposed to hours. On occasion, however, when system servers go down, recovery can take from two to eight hours depending on the number of trades in the system at that time. There is thus a need to minimize down time and expense of locating and reconstructing damaged files.

Note that as used herein, the term queue file refers to the physical storage of messages that are in transmission. Queue files may also be viewed as holding cells for uncompleted operations.

Basically, what this means is that if the receiver is not there to receive a given message, the message is held in the queue file and is deliverable at a later time. As a result, the queue files offer reliability in the retention of information that is transmitted.

Moreover, in traditional systems, the recovery data is not provided by the queue file itself. Thus, queue files have not been utilized to identify the state of the file when an error or lost data has occurred, and have thus not been used to reconstruct the data file from data which is previously uncorrupted. In a traditional system, the recovery data is not provided by the queue file itself.

Another example of how message queuing is applied to a real- world application involves how a message queuing infrastructure may support real-time on-line transaction processing using mobile agents. In this example, the customer, for instance, is a bank with geographically dispersed branches. Customer accounts are created and kept at the local branches where the account was opened. For illustrative purposes, this is called the home branch of the account. A copy of each account is also kept at the main office. A read operation on an account can be made from either the local branch or the main office. An update to an account, however, will require that both the home branch copy and the main office copy be updated in a coordinated fashion.

If the update request occurred at the home branch, the local copy must then be updated. This update can trigger an agent which then automatically submits an enqueue request to the queue manager or queue server. This queue manager in turn dequeues the request across a wide area network to another queue manager, which in turn, dequeues the update request to the database server for the mirror office accounts.

A message queue in this example provides asynchronous and reliable processing. Asynchronous processing begins with the agent that is triggered by the database update at one location. The agent submits the update request to the message queue manager in an asynchronous manner, and need not wait around for a response. The message queue manager serves as holding cell for the request so that the requester can continue processing without the need to wait for a response. The message queue manager also provides reliability in this example in that it maintains a copy of the update request in its queue until the recipient of this update request has acknowledged its receipt via a well-known handshaking protocol called the Two Phase Commit protocol, known in the industry as transactional message queuing.

While these types of message queuing systems have operated reliably in the past, they have relied on a data architecture that uses separate queue data and log record files to store the messages that are appended to a message queue. This architecture prevents rapid repair at the time of a serve crash and requires two storage disks, one for data and one for the log records. Moreover, traditional message queuing architectures are generally not optimized for write operations without requiring extra hardware to work efficiently, and are not appropriate for high throughput systems with low message residence times. The separate queue data and log files mentioned above also introduce an extra level of unreliability since there exists two points of potential file corruption and media failure. Additionally, there is usually no means for the message queuing systems administrator to predefine the amount of work needed to do recovery a priori.

Note, the above systems are commercially available as Digital Equipment Corporation's DECmessageQ, IBM's MQ Series, and Transarc's Encina RQS.

SUMMARY OF INVENTION In order to solve the above noted problems with traditional message queuing, a message queuing system is provided that saves and stores messages and their state in an efficient single file on a single disk to enable rapid recovery from server failures. The single disk, single file storage system into which messages and their states are stored eliminates writes to three different disks, the data disk, the index structure disk and the log disk. The single disk, single file storage is made possible by clustering all information together in a contiguous space on the same disk. The result is that all writes are contained in one sweeping motion of the write head in which the write head moves only in one direction and only once to find the area where it needs to start writing messages and their states are stored. In order to keep track of the clustered information, a unique Queue Entry Map Table is used which includes control information, message blocks and log records in conjunction with single file disk storage that allows the write head never to have to back-up to traverse saved data when writing new records. The system also permits locating damaged files without the requirement of scanning entire log files.

In order to find the most recent valid data, a control check point interval system is utilized to find the most recent uncorrupted data. Scanning to find the most recent check point interval permits rapid identification of the last queue. Subsequent scanning of log records after the checkpoint establishes the most up-to-date state of all messages. The above system permits data recovery in an order of magnitude less time than previous systems, while at the same time establishing an efficient forward writing mechanism to prevent the need for searching through unordered sectors.

In one embodiment, a circular wrap around buffering system is used in which a modification of a previous sector is made by appending a new record at the last sector to indicate that the state of a file has changed, thus to reuse previous blocks that have been freed and no longer hold valid messages and/or log records.

The present invention thus provides a log-based data architecture for transactional message queuing systems which utilizes a combined on-disk file structure for the message queue data and log records. It is the combined queue data/log record file, in one embodiment, on a single disk, which improves write operation performance and reliability, while at the same time reducing the number of disks used. As mentioned above, system crash recovery is accelerated through the use of a Queue Entry Map Table which does not require searching though all of the log records to ascertain where the error occurred. The use of the Queue Entry Map Table also permits a priori assigning the number of requirements on a queue data file that results in extensibility and flexibility to system administrators.

Also as mentioned above, the subject system utilizes a circular queue that implies that there is potential wrap around of the queue data file for storage reuse. This requires that a reservation table or free space heap be maintained to ensure that when the queue wraps around, subsequent write operations do not overwrite queue data and/or log records that might still be valid.

In one embodiment, the queue data storage architecture consists of a single flat file that is created when a queue manager is first initialized based on a fixed size for the queue. The initial queue creation is based on the system administrator's feel for the peak load on the message queuing system, e.g., the maximum number of expected entries in message queue at any given point in time. Each message in the queue data file contains a Message Header and a Message Body. The Message Body, which contains the message content, is stored on disk in subsequent contiguous blocks that follow the message header.

In the above embodiment, the queue data file is partitioned into a predefined number of logical segments or sectors which can be extended at run time. Each segment contains a copy of the Queue Entry Map Table or QEMT for short, which is stored at the beginning of each segment. The QEMT contains control information for the queue entries and log record information stored in the entire queue file. Message headers, message bodies, and log records are stored after the QEMT with potential mixing of message data and log record blocks.

As will be appreciated, the QEMT size depends on some expected maximum number of queue entries defined by the user at queue creation time. Since the log record takes up some deterministic number of bytes, the queue data file will consist of mixed data types of log records, message headers, message bodies, and QEMTs.

When a new segment is reached in the queue data file, a new QEM Table is written to disk at the beginning of the new segment, with the message and log records following the QEM Table. Since the smallest on-disk data type is the log record, a segment in the queue data file is defined to consist of blocks, where one block is the size of the log record. This implementation enhancement simplifies development of search algorithms.

The state of a transactional message queuing system is captured by the control information contained in a QEMT. The QEMT is defined as a static data structure that multiple threads can operate on, rather than each thread maintaining its own copy.

As a result of the log-based data architecture, the subject invention provides a number of improvements over existing transactional message queuing data architectures. It improves on the performance of the write operation over existing message queuing architectures, which makes message queuing systems based on this invention highly appropriate for high throughput systems with low message residence times such as high speed banking applications. The subject system is also applicable to the underlying reliable messaging infrastructure for the transport of agents over unreliable networks and/or networks with different bandwidths.

Moreover, message data and log record write operations always proceed in the forward direction and both can be stored on the same disk file.

This system also improves the reliability of transactional message queuing systems. In this log-based data architecture, there exists a single place where file corruption can occur versus two potential file corruption scenarios with separate queue data and log record files. Reliability is also improved since fewer disk files are used. A combined queue data/log record file adheres to the Atomicity, Consistency, and Isolation properties of the well-known ACID properties. Also, as will be seen, one can utilize existing RAID technology to do transparent duplicate writes.

The subject system allows the resulting message queuing system to support any method of message data access including First In First Out, Last In First Out or priority-based message data access, while at the same time reducing the amount of time needed for recovery from system crashes. Instead of scanning all data in an entire file for log records in traditional approaches, the subject system only requires that one test a few Queue Entry Map Tables first to determine the most recent checkpoint, and then proceed to scan the log records within that segment.

Moreover, the subject system provides extensibility and flexibility to message queuing systems administration since the invention allows the administrator to control how much work they want to do on system recovery by a priori predefining the number of segments on a queue data file, and subsequently the number of checkpoint intervals, again determined a priori. System administrators can thus pay the overhead cost of writing the checkpoints up front to avoid paying the heavier cost of doing extensive log record scans upon recovery. This tradeoff can be adjusted and fine-tuned to suit the application requirements and domains.

The above advantages flow from the use of a pre-allocated on- disk queue buffer containing queue control information, message data, and transactional log records of message operations. The on-disk queue buffer consists of a number of segments or sectors.

Each segment consists of the same predefined number of blocks. At the beginning of each segment is the aforementioned Queue Entry Map Table, which contains control information data regarding the state of the individual queue entries, and pointer offsets to where on disk the messages are physically stored. The Queue Entry Map Table serves as a fixed checkpoint interval for the entire message queuing system. Messages and transactional log records of message operations are stored on the blocks in the segment such that message blocks and log record blocks can be intertwined. Moreover, there is no requirement that the log record for a particular message be stored contiguously to the message.

As a feature of the subject invention, a message data write operation always proceeds in a forward manner for the disk head.

Additionally, a message is stored contiguously on disk with no need for pointer traversal. Further, a log record write operation always proceeds in a forward manner for the disk head. Log records are written for change of state in a message operation that follows the Two Phase Commit protocol. Therefore, log records can be written for Prepare, Prepared, Commit, Abort, Acknowledge messages from a remote queue manager.

As an another unique feature, the entire queue can be scanned in a single pass. Moreover, on-disk garbage collection is always a linear process. Additionally, there exists a number of Queue Entry Map Tables on the same file, with the unique sequence number of the most recent table being stored on disk on a graceful shutdown of the queue manager.

Importantly, the read operation can follow the First In First Out, Last In First Out, or Priority-based policy such that no special provision is needed to implement any of the three policies.

Moreover, the recovery procedure is accelerated by searching only the Queue Entry Map Tables timestamp. This is because, the most recent Queue Entry Map Table serves as the starting state for the recovery process. Log records following this table are then read sequentially and changes are then made to the in-memory copy of this most recent Queue Entry Map Table to reflect changes made after the last known checkpoint.

BRIEF DESCRIPTION OF THE DRAWINGS These and other features of the Subject Invention will be better understood with reference to the Detailed Description taken in conjunction with the Drawings, of which: Figure 1 is a block diagram of a typical banking application utilizing the subject system in which messages flow from the main office to subsidiary branches; Figure 2 is a diagrammatic representation of a two file system in which data is recorded at one file, whereas logs are recorded on a separate file, with the data stored at non- consecutive sectors and with the requirement that the entire log file be scanned in order to reconstruct an up-to-date state, the recovery process involving both the data file and log file to obtain the complete state of all messages in the system; Figure 3 is a diagrammatic representation of the subject system in which a single file is utilized to store the data and QEMT mapping table to permit rapid recovery of lost data with a minimum amount of hardware and with reduced scanning time required for data recovery; Figure 4 is a diagrammatic illustration of the storage of blocks of data within the file of Figure 3, indicating a circular file with a single write direction; Figure 5 is a diagrammatic illustration of the possible QEMT control blocks at various well known positions or offsets within the file indicating that through the utilization of these QEMT control blocks, the position and/or location of valid data can be easily ascertained; Figure 6 is a diagrammatic illustration showing the interdispersion of state change log records with the message data blocks to enable the forward writing of the file; Figure 7 is a table illustrating the QEMT structure, including the QEMT sequence number which serves as a time stamp and which contains the incremental check point information required to restore the system; Figure 8 is a table providing information to permit the restoration of individual message states; Figure 9 is a diagrammatic illustration of the forward directional flow of data in a wrap around system in which a circular queue is implemented; Figure 10 is a table illustrating the information stored in the incremental log record with the log entries of Figure 6; Figure 11 is a flow chart illustrating the procedure for fetching a message from the queue; Figure 12 is a flow chart illustrating a procedure for writing a message in the queue; and, Figure 13 is a flow chart illustrating the recovery process in which the most recent QEMT is identified by an initial scan, with subsequent reading of the log records following the identification of the most recent QEMT resulting in a completely restored state.

DETAILED DESCRIPTION Referring now to Figure 1, a message queuing system 10 is provided between branch offices of banks 12 and a main office 14 for the purpose of transmitting updated account information from the branches to the main office. In order to accomplish this, data is entered at terminals 16, 18 and 20 respectively at different branch offices of the bank. This data is stored in local database servers 22, 24 and 26 of the respective branches, with each database server having its own local storage, here designated by reference character 28.

The output the database server is coupled to a series of message queuing servers 30, 32 and 34 respectively, each having their own storage units, here labeled by reference character 36.

The outputs of the message queuing servers are applied to a wide area network 40 which couples the outputs to a message queuing server 42 at the main office, with this server having associated respective storage units 44 as illustrated. The message queuing servers 30, 32, and 34 communicate with a wide to a database server 50 having its associated units 52 as illustrated. The output of the message queuing server 42 is coupled to a database server 50 having its associated units 52 as illustrated. The information in this database is viewable at terminals 54 at the main office.

It is the purpose of the message queuing system to be able to reliably transmit updated account information from the branches so that it will reside at the main office. It is also important that the transaction at the branches can proceed without regard to direct connection to the central office.

Referring now to Figure 2, in the past messages and headers such as illustrated at 60 and 62 were stored on data disks 64 in sectors 66, 68, 70 and 72, with the message and accompanying header being randomly placed within the sectors.

At the same time, message state information was stored on a log disk 80 which included records about each message stored in the data disk, including the order of arrival and its location on the data disk. Moreover, the state of the transaction was logged into log disk 80 for each of the messages and corresponding headers.

In the case of an interrupted transmission as indicated by 8X" 82, in the past was a requirement that the entire log file, here illustrated at 84, be scanned to be able to reconstruct the up-to-date state of the data disk file just prior to the interruption of the transmission. As mentioned hereinbefore, this is a time-consuming process in which the entire log file must be scanned in order to be able to reconstruct the state of the system just prior to the crash. The situation is made even more complicated due to the storage of the message and header information at nonsequential sectors on the data disk, requiring the interaction of the log file and the data file in order to locate those messages which are uncorrupted at the time of the interruption of the transmission.

Referring now to Figure 3, in the subject system message data 60 and message header information 62 are stored on a single disk storage 90 in sequential sectors, here illustrated at 92, 94, 96 and 98. It is a feature of the subject invention that the message and header information is stored in an order which is accessible through the utilization of a queue entry management table, which locates message data through a checkpoint system to be described.

It will be appreciated that the message data is not stored across all of the sectors, but rather is stored in the above- mentioned sequential manner.

In order to be able to access the data stored in file 90, the queue entry management table, or QEMT, contains sector information which includes entries for control information 100, message blocks 102 and log records 104 all of which are designed to uniquely specify the sector in which relevant data and headers can be found.

The QEMT therefore specifies the state of the system in so doing.

As will be seen in connection with Figures 4, 5 and 6 the Queue Entry Management Table is stored in file 90 interspersed between message data and header information.

Referring now to Figure 4, in one embodiment, file 90 is arranged such that contiguous sectors have blocks of information, here illustrated at 106, with the blocks of information entering from the left as illustrated by arrow 108 and traversing the file from left to right as illustrated by block number 1 entering from the left and block number 13 exiting from the right. It will be understood that the contiguous of blocks and the flow through the file creates a so-called write direction which does not change.

Referring now to Figure 5, it will be seen that the aforementioned QEMT control blocks 100 can be interspersed between other contiguous blocks 106 so that the position of the QEMT control information blocks 100 specify check points at well-known offsets throughout file 90.

The purpose of interspersing the QEMT control blocks at regular intervals is to be able to quickly locate a complete system state containing specific message data and header information by merely specifying the checkpoint number or checkpoint interval, as the case may be. The result is that it is possible to have message data and log record blocks to either side of a control QEMT control block, such that upon identification of a check point interval as being the last to have valid information, the contiguous blocks written after the QEMT block specifies where valid data may be found as well as its identity and location.

As an alternative explanation, the QEMT control blocks provide the recovery process with well-known locations to examine the state of the system.

Referring now to Figure 6, it will be seen that blocks 106 can be utilized as message data blocks as illustrated at 110 or incremental log blocks as illustrated at 112, with blocks 112 corresponding to log record 104 of Figure 3. These log records record state changes to messages in contiguous downstream blocks.

Note, the control block provides only some known point for the beginning of the examination of the file, whereas the log records provide information concerning individual messages in the file.

Referring back to Figure 3, it will be appreciated that log record 104 is but one of a number of sequential log records relating to the data having its start point indicated by the QEMT control block. These log records record changes to information in the preceding message block so that a complete history of changes to that particular message block are annotated.

Referring back to Figure 6, it is noted that a given number of message blocks are bounded by QEMT control blocks which specify additional message data blocks that have occurred after the check point. Within this sector are transactional log records 112. It will be seen that log record T1 can describe a change in any one of the message blocks. As can be seen from arrow 114, the information flow is from left to right. This being the case, transactional log record T1 can describe the state change for any message in the system, which could be an acknowledgment that the message has been received and is no longer needed to be kept, or that a message has been sent and has not been received or acknowledged, the above reflecting the two pass handshaking technique for the transmission of the secure messages in this type of system.

For instance, transactional log record T1 could indicate that a new message has been added to the file at that particular point.

It will be appreciated that the position of the log record is determined by the write head when the log record is created. Thus, when the log record is created at a time T1 the write head is at a particular point in the file. However, the log record can refer to transactions and messages anywhere within the whole file structure.

Likewise, transactional log records T2, T3 and T4 reflect that these messages have changed state, with these log records being posted sequentially in time.

It will be appreciated that since the QEMT blocks and the log record blocks are insertable into the single file structure and since the single file structure in one embodiment has a information flow in one direction, it is possible to completely eliminate the two-file structure of the prior art. Moreover, the utilization of the QEMT blocks and the transactional log record blocks permits rapid diagnose of the effect of information interruption, with a way of specifying uniquely those messages which are uncorrupted, while thereafter permitting rapid recovery of the state of the system after failure.

Referring now to Figure 7, the organization of the Queue Entry Management Table header is illustrated at 120. As can be seen, in one embodiment, the header includes the number of segments in a queue file 122, the segment size 124, the QEMT sequence number or timestamp 126, the sequence number of the last log record in the previous segment 128, the current segment number 130, the queue head pointer 132, the queue tail pointer 134, the next available block in the current segment 136, the list of QEMT entries 138, the reservation table of disk blocks 140, the pending transaction list acting as coordinator 142 and the pending transaction list acting as participant 144.

It will be appreciated that the information contained in the header is supporting information for the recovery process.

Referring now to Figure 8, each QEMT entry 138 includes a sequence number 146, a message ID 148, a message operational mode 150, which is either Qput or Qget, the message recipient's node name 152, the message recipient's server name 154, the transaction state 156, which is either "active", "pending", "abort" or "commit", the participant 2 PC vote 158 which is the last known response that was received by the receiver, a set of additional flags 160 and a pointer on-disk location of message 162.

Thus the Queue Entry Management Table provides exact information as to the state of the file and more particularly any queue entry.

Referring now to Figure 9, what will be appreciated is that since a single message is stored in contiguous blocks, the reprocess involves reading contiguous blocks back. As a result, this cuts down on the head movement during a read operation.

In summary, in the prior art doing a read might require the read head to traverse noncontiguous blocks, and therefore take a considerable amount of time. In the subject system since the message are stored in contiguous blocks, only traversing these contiguous blocks is necessary in the read operation. Likewise, for a sequential write operation, the head traverses only a limited amount of the file.

In short, because there is a forward directional flow and wrap around on subsequent writes, the data is arranged in contiguous blocks and the above advantages flow therefrom.

Referring now to Figure 10, the transactional log record 112 of Figure 6 includes a special log record marker 162 in one embodiment. In this embodiment, a sequence number 164 is provided along with a message operational mode 166 which refers to either a Qget or Qput operation. Also included is a message ID 168, a set of operational flags 170, the transactional state 172 which includes "active", "pending", "abort" or "commit" states, the participant 2 PC vote 174 mentioned above and a pointer 176 to on-disk location of message in queue file.

Referring now to Figure 11, what is shown is a flow chart for the write or Qput operation. In this flow chart, upon having started as illustrated at 180, a block queue head pointer 182 effectively puts a lock on the head of the list so that no other user can access the head entry. Thereafter, the system increments the queue head pointer and sets the transaction state to "active read". This indicates the beginning of the handshaking process.

As illustrated at 186, the system then unlocks the queue head pointer and then, as illustrated at 188, reads the messages from the on-disk queue file. Thereafter, the QEM Table is locked as illustrated at 190, whereafter the log record is written as illustrated at 192 and the QEM Table is unlocked as illustrated at 194. The output of the unlock QEM Table step is referred to a decision block 196 which ascertains if the message transmission is transactional. If so, as illustrated at 198, the system runs a two-phase "commit" protocol to permit handshaking. This completes the Qput or write operation.

Referring now to Figure 12, a Qget or read operation is described. As can be seen, upon starting as illustrated at 200, the queue tail pointer is locked as illustrated at 202 and a new QEM entry is created with the queue tail pointer being incremented as illustrated at 204. Thereafter, as illustrated at 206, the system fills in the QEM entry control information and sets the transaction state to "active control". Thereafter, as illustrated at 208, the queue tail pointer is unlocked and the QEM table is locked as illustrated at 210. Subsequently, as illustrated at 212, the system allocates on-disk blocks from the reservation table, with a block crossing a segment boundary being indicated at decision block 214. If the blocks cross segment boundaries, then as illustrated at 216, the system forces the QEMT check point write to disk. This refers to the fact of writing the in-memory copy to disk. It will be appreciated that block 206 updates the in-memory copy of the state of the QEM Table and thus the QEM entry.

After having forced the QEMT check point write to disk as illustrated at 218, the system writes the message data to disk and unlocks the QEM Table. Decision block 220 establishes whether or not the messages is a transactional one and if so, runs a two phase commit protocol as illustrated at 221 to facilitate the handshaking. The end of the write sequence is illustrated at 222.

It will be appreciated that block 220 refers to the receiver end running the handshaking protocol.

Referring now to Figure 13, a recovery sequence is illustrated in which, upon starting as illustrated at 230, the queue table pointers are locked as illustrated at 232 and the system thereafter restores global data structure as illustrated at 234. This initializes the state of the system as a whole.

Thereafter, as illustrated at 236 the system scans each QEMT in the queue file for the most recent QEMT. This establishes the most recent check point before communications interruption. Thereafter, as illustrated at 238, the system scans the log records in this segment for the log record with the latest QEMT. This means that the log records of the segment are applied to the messages referred to by the entries in the QEMT.

As illustrated at decision block 240, the system ascertains if there are more log records to scan. It will be appreciated that the QEMT specifies the most recent log record subsequent to the pointer associated with the QEMT in question. However, there may indeed be subsequent log records thereafter which need to be scanned. If this is the case, then the system contacts the participant about the transaction state of the message as illustrated at 242. In one instance, the receiver is queried as to whether it has received a message or not. Thereafter, the system invokes a two-phase "commit" protocol to resolve the transaction as illustrated at 244. This refers to the fact that the handshaking process is a two pass process. Thus, whatever state that one receives back from the receiver is used to restart the handshaking process at the point at which the system had failed.

As can be seen at 246, the system updates the state of the reservation table and determines a new file pointer position.

Thus, the entire section is scanned to update the state of reservation table 140, with the determination of the new file pointer position being established by the current segment number 130 and the next available block in the current segment 136.

As illustrated at 248, the system then writes out the new QEMT state to the disk at which point the recovery is complete as illustrated at 250.

As described hereinafter, the programming listing for one embodiment of the subject invention written in C follows: * Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

* UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT * LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE * IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION * OR DISCLOSURE.

* THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND * TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, * OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR * EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

* OpenMQ * Module: qmain.c * Author: David Wong 9/8/95 *=========================================================== ==== * Command Line Syntax: * C> qserv [-c] [-lq (name>] [-pq <name>] [-p <pathname>] \ * [-t <threads>] [-n <&num qentries>] [-e <&num qextents>] \ * [-s <4segments>] * where [] = Optional flag.

* -c = Create new queue file mode. Will overwrite * existing queue data and state files. If not * set, then it is a restart caes.

* -lq = Logical queue name.

* -pq = Physical queue server name.

* -p = Path of queue data and state files.

* -t = Number of queue server threads to allocate.

* -n = Number of queue entries to allocate for new queue.

* -e = Max number of additional extries that the queue * can be extended to; not supported currently.

* -s = Number of segments to allocate for new queue.

*======================================================== ======= // Include Files //#include <memory.h> #include "qlib. h" #include "qserv. h" #include "qadmin. h" lpQEMT MQEMT; lpQSTR MQstate; lpOPSTATS MQops; lpMTLIST Pending~TXNs = NULL; int BLOCKS PER SEG; int SEGMENT~SIZE; int TOT~MSG~BLOCKS; int QEMT~Size; int QEMT~Seq~No = 0; int LREC~Seq~No = 0; int NUM~SEGS; int MAX~ELMS; int shdn~flag=0; int holey~entries=0; unsigned long QEME~TS = 1; 1pLPG~TS~STR Last~Pending~Get; lpLRCLST Active~LREC~List; #define DefaultPath "C:\\Q\\QSERV" define DefaultLogQue "Ql" define DefaultPhyQue "QSl" #define Op~State $"~Op~State" #define DefaultElms 100 #define DefaultExt 0 #define DefaultSegs 10 #define DefaultThrs 1 4. define Format "C> qserv [-.c] [-lq <name>] [-pq <name>] [-p <pathname>] [-t <thr void Process~Msg( lpMSTR arg) HANDLE hQSHDN~Event; lpQHANDLE qhandle; lpTSTR thr~str; SMBUF ENQ; Diag("Queue Server Thread No. %d starting up. ",arg->thr~no); // Open the queue for getting if (!(qhandle = Qopen(arg->physical,GET~MODE,0,0,0,-1,0))) Fail("QServ~main: could not open queue server ts",arg->physical); thr str = (TSTR *)malloc(sizeof(TSTR)); while ((thr~str->Que~File~Handle=Open~Queue~File(arg->qname) ) == INVALID~HANDLEVALUE); while (!shdn~flag && (QSUCCESS == QlistenBeforeReply(qhandle,&ENQ.msgh,ENQ.mdata,MAXMSGDATA))) strcpy(thr~str->logical,arg->logical); strcpy(thr~str->physical,arg->physical); strcpy(thr~str->qname,arg->qname); strcpy(thr str->qstate,arg->qstate); thr~str->qhandle = qhandle; thr~str->lpsmbuf = &ENQ; Diag (""); Diag("Request Serviced by QS Thread No. td",arg->thr~no); switch(ENQ.msgh.mode) case PUT MODE: Diag("DiskQ(%s) Queue Server in PUT~MODE",arg->physical); QS~QPut(thr~str); break; case REQUEST~MODE: Diag("DiskQ(%s) Queue Server in GET~MODE",arg->physical); QS~QGet(thr~str); break; case ABORT~MODE: case COMMIT~MODE: if (ENQ.msgh.mode == ABORT~MODE) Diag("DiskQ(ks) Queue Server in ABORT~MODE",arg->physical); else Diag("DiskQ(ks) Queue Server in COMMIT~MODE",arg->physical); QS~QCommit(thr~str); break; case ADMINREQ~MODE: Diag("DiskQ(%s) Queue Server in ADMINREQ~MODE",arg->physical); QS~QAdmin(thr~str); if (shdn~flag) { QreplyAfterListen(qhandle,ADMINREP~MODE,SUB~MODE~OK,0,0,0); // Qclose (NULL,arg->physical); Qclose(&qhandle,0); hQSHDN~Event = OpenEvent(EVENT~MODIFY~STATE,TRUE,QSHDN~EVENT); if (!hQSHDN~Event) Diag("QS~Admin: Can't OpenEvent for QS Shutdown"); if (SetEvent(hQSHDN~Event) == FALSE) Diag("QS~Admin: Can't SetEvent for QS Shutdown"); return; break; default: Diag("DiskQ(%s). Unexpected Mode=%d",arg->physical,ENQ.msgh.mode); QreplyAfterListen(qhandle,ACK~MODE,SUB~MODE~BAD~REQ,0,0,0);& lt;BR> } /* Diag("head = %d, tail = %d, pgets = %d, pputs = %d, segment = %d, block = %d MQEMT->que~hd~ptr, MQEMT->que~tl~ptr, MQops->pending~gets, MQops->pending~puts, MQEMT->next~avail~block.segment, MQEMT->next~avail~block.block); print~RST(); print Active LogList(); <BR> print~QEME~txn~states(); */ // Sleep (3000); } void main( int argc, CHAR **argv) HANDLE Que File Handle; HANDLE Que~State~Handle; HANDLE hQHD, hQTL, hQEMT; HANDLE hQEME,hLPG; HANDLE hMQstate, hMQops; HANDLE hQSHDN,hQSHDN~Event; HANDLE hTSM[MAX QSERV THREADS]; DWORD idTSM[MAX~QSERV~THREADS]; DWORD dwPointer; DWORD dwBytesRead,dwBytesWritten; 1pMSTR thr~arg[MAX~QSERV~THREADS]; BOOL Return~Status; long temp~time; int seg~no; int i,status; int newq=0; CHAR logical[NAMESIZE]=DefaultLogQue; CHAR physical[NAMESIZE]=DefaultPhyQue; CHAR path[QUE FILE SIZE]=DefaultPath; CHAR quefile[QUE~FILE~SIZE]; CHAR qstate[QUE~FILE~SIZE]; CHAR buf[255]; int max~elms=DefaultElms; int ext~elms=DefaultExt; int num~segs=DefaultSegs; int num~threads=DefaultThrs; int max~txns~per~seg; i = 1; if ((argc > 1) && (!stromp(argv[i],"-c"))) newq = 1; i++; } while (i < argc) { if (!strcmp(argv[i] ,"-lq")) i++; if (argv[i][0] != strcpy(logical,argv[i]); else Diag("Ws",Format); } else if (!stromp(argv[i],"-pq")) { i++; if (argv[i] [0] != '-') stropy(physical,argv[i]); else Diag("ts",Format); else if (!stromp(argv[i],"-p")) 1++; if (argv[i][0] != strcpy(path,argv[i]); else Diag("%s",Format); else if (!strcmp(argv[i],"-t")) i++; if (argv[i][0] != num~threads = atoi(argv[i]); else Diag("%s",Format); } else if (!stromp(argv[i],"-n")) { i++; if (argv[i][0] != '-') max~elms = atoi(argv[i]); else Diag("%s",Format); } else if (!stromp(argv[i],"-n")) { i++; if (argv[i][0] != '-') ext~elms = atoi(argv[i]); else Diag("ts",Format); else if (!strcmp(argv[i],"-s")) i++; if (argv[i][0] != num~segs = atoi(argv[i]); else Diag("%s",Format); } i++; } sprintf(quefile,"%s\\%s.dat",path,physical) sprintf(qstate,"%s\\%s.sta",path,physical) // Check to see if QNETD is running.

if (!AttachSharedMemory()) Fail("Error: QNETD is not running."); // Create mutexes for protected data structures.

hQHD = CreateMutex(NULL,FALSE,QUE~HD~PTR~LOCK); if (!hQHD) Diag("CreateMutex for Que Head Pointer lock failed."); hQTL = CreateMutex(NULL,FALSE,QUE~TL~PTR~LOCK); if (!hQTL) Diag("CreateMutex for Que Head Pointer lock failed."); hQEME = CreateMutex(NULL,FALSE,QEME~TS~GEN~LOCK); if (!hQEME) Diag("CreateMutex for QEME~TS Lock failed."); hLPG = CreateMutex(NULL,FALSE,LPG TS~GEN~LOCK); if (!hLPG) Diag("CreateMutex for LPG~TS Lock failed."); hQEMT = CreateMutex(NULL,FALSE,QEMT~LOCK); if (!hQEMT) Diag("CreateMutex for QEM Table lock failed."); hMQstate = CreateMutex(NULL,FALSE,MQstate~LOCK); if (!hMQstate) Diag("CreateMutex for MQstate file lock failed."); hMQops = CreateMutex(NULL,FALSE,MQops~LOCK); if (!hMQops) Diag("CreateMutex for MQops stats lock failed."); hQSHDN = CreateMutex(NULL,FALSE,QSHDN~LOCK); if (!hQSHDN) Diag("CreateMutex for QShutdown lock failed."); hQSHDN~Event = CreateEvent(NULL,TRUE,FALSE,QSHDN~EVENT); if (!hQSHDN~Event) Diag("CreateEvent for QShutdown event failed."); // Allocate structure for queue shutdown // state and recovery statistics.

MQstate = (QSTR *)malloc(sizeof(QSTR)); // If new queue file get max~elms and num~segs // from command line, else find most recent // QEM table from disk. Policy is to delete // existing quefile and qstate file when the // -c flag is used.

if (newq) Que~File~Handle = Create~Queue~File(quefile,qstate, max~elms,num~segs); while (Que File Handle == INVALID HANDLE VALUE) <BR> <BR> <BR> <BR> sprintf(buf,"del ts",quefile); <BR> <BR> <BR> system(buf); <BR> <BR> <BR> sprintf(buf,"del ts",qstate); <BR> <BR> system(buf); Que~File~Handle = Create~Queue~File(quefile,qstate, max~elms,num~segs); MAX ELMS = max elms; NUM-SEGS = num segs; else Que-File-Handle = Open Queue File(quefile); status = Find~Latest~QEM(Que~File~Handle,&MQEMT,&segno); // print~QEMT(MQEMT,1); Return~Status = CloseHandle(Que~File~Handle); MAX ELMS = MQEMT->max~entries; NUM~SEGS = MQEMT~>num~segs; Update~QEME~TS(); Update~Globals(); Last~Pending~Get = (LPG~TS~STR *)malloc(sizeof(LG TS STR)); Last Pending Get->qeme no = NIL; Last~Pending~Get->timestamp = 1; // Theoretically possible to have MAX~ELMS // GET operations and txn termination log // records in same segment? max~txns~per~seg = MAX~ELMS; // max~txns~per~seg = 2*MAX~ELMS; // max~txns~per~seg = (int)ceil((double) (MAX~ELMS/NUM~SEGS)); Active~LREC~List = (LRCLST *)malloc(sizeof(LRCLST)); Active~LREC~List->max~txns~per~seg = max~txns~per~seg; Active~LREC~List->address = (int *)malloc(max txns per seg*sizeof(int)); // Reinitialize the active log record list.

Init~Active~LREC~List(); Que~State~Handle = Open~Queue~File(qstate); // If new queue file, or if a restart clear, // case, initialize global data structures // and create new initial QEM Table.

if (newq) status = Create~QEMT(&MQEMT,MAX~ELMS); status = Init~QEMT(MQEMT,MAX~ELMS,ext~elms,NUM~SEGS); status = Write~QEMT(Que~File~Handle,0,MQEMT); MQstate->svr~state = QUEUE~ACTIVE; MQstate->num~restarts = 0; MQstate->num~recov~tries = 0; temp time = time(&MQtate-sfirst start time); temp~time = time(&MQstate->last~restart~time); MQstate->last recov time = 0; else // Restart case.

// see if queue server shutdown cleanly last time dwPointer = SetFilePointer(Que~State~Handle, 0,NULL,FILE~BEGIN); Return~Status = ReadFile(Que~State~Handle, MQstate, sizeof (QSTR) &dwBytesRead,NULL); if ((Return~Status == FALSE) || (dwBytesRead != sizeof(QSTR))) { if ((Return~Status == FALSE) Diag("status = FALSE"); Fail("Main: Problem reading MQstate; BytesRead = %d",dwBytesRead); MQstate->num~restarts++; temp~time = time(&MQstate->last restart time); // If queue server did not shutdown cleanly // last time, then run the recovery module.

if (MQstate->svr state == QUEUE~ACTIVE) MQstate->num~recov~tries++; MQstate->last~recov~time = temp~time; dwPointer = SetFilePointer(Que~State~Handle, 0,NULL,FILE~BEGIN); Return~Status = WriteFile(Que~State~Handle, MQstate,sizeof(QSTR), &dwBytesWritten,NULL); if ((Return~Status == FALSE) I (dwBytesWritten != sizeof(QSTR))) if (Return~Status == FALSE) Diag("status = FALSE"); Fail("Main: Problem writing MQstate; BytesWrtten = td",dwBytesWritten); QRecov(Que~File~Handle,seg~no); MQstate->num~recov~tries = 0; MQstate->last~recov~time = 0; else // Clean shutdown last time; simple restart case.

MQstate->svr state = QUEUE~ACTIVE; MQEMT->qget~state = ENABLED; MQEMT->qput~state = ENABLED; if (!Reconstruct~RST()) Fail("Restart procedure failed: cannot reconstruct // update the queue server state file dwPointer = SetFilePointer(Que State~Handle, 0,NULL,FILE~BEGIN); Return~Status = WriteFile(Que State Handle, MQstate, sizeof (QSTR) &dwBytesWritten,NULL); if ((Return~Status == FALSE) || (dwBytesWritten != sizeof(QSTR))) if (Return~Status == FALSE) Diag("status = FALSE"); Fail("Main: Problem writing MQstate; BytesWrtten = Wd",dwBytesWritten); Return~Status = CloseHandle(Que~File~Handle); Return~Status = CloseHandle(Que~State~Handle); // initialize RT statistical counters MQops = (OPSTATS *)malloc(sizeof(OPSTATS)); MQops->num~gets = 0; MQops->numputs = 0; MQops->num~aborts = 0; MQops->num~commits = 0; MQops->pending~gets = 0; MQops->pendingputs = 0; // do initial close to clear stale buffers Qclose(NULL,physical); // spawn off worker threads i = O; while(i < num~threads) thr~arg[i] = (MSTR *)malloc(sizeof(MSTR)); strcpy(thrarg[i] ->logical, logical); stropy(thr~arg[i]->physical,physical); stropy(thr~arg[i]->qname,quefile); stropy(thr~arg[i]->qstate,qstate); thr~arg[i]->thr~no = i; hTSM[i] = CreateThread(NULL,0, (LPTHREAD~START~ROUTINE) Process~Msg, thr~arg[i],0,&idTSM[i]); i++; } // Wait for shutdown to be signalled by a worker thread.

// Add code later to check on status of worker threads.

hQSHDN Event = OpenEvent(SYNCHRONIZE,TRUE,QSHDN~EVENT); if ((status = WaitForSingleObject(hQSHDN Event,INFINITE)) != WAIT~OBJECT~0) Diag("QS~Main: Synch wait for QS Shutdown Event failed"); // Clear memory buffers held by worker threads.

// Need to wait for remaining replies to be sent // back before issuing Qclose.

Sleep(3000); Qclose(NULL,physical); */ // Fetch all locks first.

hQHD = OpenMutex(SYNCHRONIZE,FALSE,QUE~HD~PTR~LOCK); if (!hQHD) Diag("QS~Main: Can't OpenMutex for que head pointer lock if ((status = WaitForSingleObject(hQHD,QUE~LOCK TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~Main: Synch wait for que head pointer lock failed"); hQTL = OpenMutex(SYNCHRONIZE,FALSE,QUE~TL~PTR LOCK); if (!hQTL) Diag("QS~Main: Can't OpenMutex for que tail pointer lock"); if ((status = WaitForSingleObject(hQTL,QUE~LOCK~TIMEOUT)) != WAIT OBJECT~0) Diag("QS~Main: Synch wait for que tail pointer lock failed"); hQEME = OpenMutex(SYNCHRONIZE,FALSE,QEME~TS~GEN~LOCK); if (!hQEME) Diag("QS~Main: Can't OpenMutex for QEME~TS Lock"); if ((status = WaitForSingleObject(hQEME,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~Main: Synch wait for QEME~TS Lock failed"); hLPG = OpenMutex(SYNCHRONIZE,FALSE,LPG TS GEN LOCK); if (!hLPG) Diag("QS~Main: Can't OpenMutex for LPG~TS Lock"); if ((status = WaitForSingleObject(hLPG,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~Main: Synch wait for LPG~TS Lock failed"); hQEMT = OpenMutex(SYNCHRONIZE,FALSE,QEMT~LOCK); if (!hQEMT) Diag("QS~Main: Can't OpenMutex for QEM Table lock"); if ((status = WaitForSingleObject(hQEMT,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~Main: Synch wait for QEM Table lock failed"); hQSHDN = OpenMutex(SYNCHRONIZE,FALSE,QSHDN~LOCK); if (!hQSHDN) Diag("QS~Main: Can't OpenMutex for QSHDN lock"); if ((status = WaitForSingleObject(hQSHDN,QUE~LOCK~TIMEOUT)) != WAIT OBJECT~0) Diag("QS~Main: Synch wait for QSHDN lock failed"); hMQstate = OpenMutex(SYNCHRONIZE,FALSE,MQstate~LOCK); if (!hMQstate) Diag("QS~Main: Can't OpenMutex for MQstate lock"); if ((status = WaitForSingleObject(hMQstate,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~Main: Synch wait for MQstate lock failed"); // write out last QEM Table before shutting down Que~File~Handle = Open Queue File(quefile); status = Gen~QEM~Seq~No(&MQEMT->qem~sn); MQEMT->next~avail~block.segment = (MQEMT->next~avail~block.segment+l)WMQEMT->num~segs; MQEMT->next~avail~block.block = 0; status = Write~QEMT(Que~File~Handle, MQEMT->next~avail~block.segment, MQEMT); Return~Status = CloseHandle(Que~File~Handle); // Write out graceful shutdown state MQstate->svr~state = QUEUE~SHUTDOWN; Que~State~Handle = Open Queue File(qstate); dwPointer = SetFilePointer(Que~State~Handle, 0,NULL,FILE~BEGIN); Return~Status = WriteFile(Que~State~Handle, MQstate, sizeof (QSTR) &dwBytesWritten,NULL); if ((Return~Status == FALSE) || (dwBytesWritten != sizeof(QSTR))) if (Return~Status == FALSE) Diag("status = FALSE"); Fail("QS~Main: Problem writing MQstate; BytesWritten = dwBytesWritten); Return~Status = CloseHandle(Que State Handle); Say("Queue Server ts shuts down gracefully",physical); Sleep(3000); // print~QEMT(MQEMT,1); // keep the locks to avoid worker // threads from writing to queue /* ReleaseMutex(hMQstate); ReleaseMutex(hQSHDN); ReleaseMutex(hQEMT); ReleaseMutex(hLPG); ReleaseMutex(hQEME); ReleaseMutex(hQTL); ReleaseMutex(hQHD); User: root Host: bunny Class: bunny Job: stdin * Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

* UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT * LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE * IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION * OR DISCLOSURE.

* * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND * TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, * OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR * EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

* * OpenMQ * Module: qrecov.c * Author: David Wong 10/15/95 */ //Include Files #include "qlib.h" include "qserv.h' <BR> <BR> <BR> <BR> &num include "qadmin.h" extern lpQEMT MQEMT; extern lpQSTR MQstate; extern lpMTLIST Pending~TXNs; extern int BLOCKS~PER~SEG; extern int SEGMENT~SIZE; extern int TOT MSG BLOCKS; extern int QEMT~Size; extern int QEMT~Seq~No; extern int LREC~Seq~No; extern int NUM~SEGS; extern int MAX~ELMS; extern unsigned long QEME~TS; // Recovery module basic algorithm: // - lock queue table and head/tail ptrs // - restore global data structures // - fetch log records // - determine state // - contact client // - invoke (partial) 2PC protocol // - rollback bad cases // - commit good cases // - fix up reservation table // - determine file ptr position // - write new QEM Table out to disk void QRecov( HANDLE Que~File~Handle, int seq~no) HANDLE hQHD, hQTL, hQEMT; lpMTLIST This TXN; LREC log~rec; BOOL Return~Status; DWORD dwPointer; DWORD dwBytesRead; SN lrec~no; int i,status; hQHD = OpenMutex(SYNCHRONIZE,FALSE,QUE~HD~PTR~LOCK); if (!hQHD) Diag("QS~QRecov: Can't OpenMutex for queue head pointer lock"); if ((status = WaitForSingleObject(hQHD,QUE~LOCK~TIMEOUT)) != WAIT OBJECT~0) Diag("QS~QRecov: Synch wait for queue head pointer lock failed"); hQTL = OpenMutex(SYNCHRONIZE,FALSE,QUE~TL~PTR~LOCK); if (!hQTL) Diag("QS~QRecov: Can't OpenMutex for queue tail pointer lock"); if ((status = WaitForSingleObject(hQTL,QUE~LOCK~TIMEOUT)) != WAIT OBJECT~0) Diag("QS~QRecov: Synch wait for queue tail pointer lock failed hQEMT = OpenMutex(SYNCHRONIZE,FALSE,QUE~TL~PTR~LOCK); if (!hQEMT) Diag("QS~QRecov: Can't OpenMutex for QEM table lock"); if ((status = WaitForSingleObject(hQEMT,QUE LOCK TIMEOUT)) != WAIT~OBJECT~p Diag("QS~QRecov: Synch wait for QEM table lock failed"); // set file pointer to start of log records dwPointer = SetFilePointer(Que~File~Handle, seq~no*SEGMENT~SIZE, NULL,FILE~BEGIN); dwPointer = SetFilePointer(Que~File~Handle, QEMT~Size, NULL,FILE~CURRENT); // Initialize log record timestamp, which is recorded // in QEMT. Next, start reading the log records and // construct extended pending txn list based on one // fetched from QEMT.

i = O; lrec~no.timestamp = MQEMT->lrec~sn.timestamp; lrec~no.counter = MQEMT->lrec~sn.counter; while(i<BLOCKS~PER~SEG) Return~Status = ReadFile(Que~File~Handle, &logrec, sizeof (LREC), &dwBytesRead,NULL); i += LOG~REC~BLOCKS; if (log~rec.marker != LRMARK) dwPointer = SetFilePointer(Que File Handle, (MSG~BODY~BLOCKS+LOG~REC~BLOCKS)*BLOCK, NULL,FILE~CURRENT); i += (MSG BODY BLOCKS+LOG REC BLOCKS); else if (Bigger Seq~No(&log rec.seq no,&lrec~no)) // only need to be concern about log records // with increasing timestamps.

lrec~no.timestamp = log~rec.seq~no.timestamp; lrec~no.counter = logrec.seq~no.counter; // find txn in pending list Return~Status = Find~MTlist(Pending~TXNs,&This TXN,log rec.mid); switch (log~rec.txn~state) case PENDING: if (Return~Status == TRUE) Return~Status = Find~Tlist(This~TXN->ops,log~rec.qeme~no); if (Return~Status == FALSE) Add Tlist(&This~TXN->ops,log~rec.qeme~no); else Add MTlist(&Pending~TXNs,&This~TXN,log~rec.mid); Add~Tlist(&This~TXN->ops.log~rec.qeme~no); break; case ABORT: case COMMIT: if (Return~Status == TRUE) Return~Status = Del~MTlist(&Pending~TXNs,log~rec.mid); if (Return~Status == FALSE) Diag("QS~Recovery: Error deleting TID %d from Host %d", log~rec.mid.tid,log~rec.mid.host); break; case EMPTY: break; default: Diag("QRecov: No such txn state"); break; // now, resolve pending txns QR~Resolve~PTL(Que~File~Handle); // Flush out reconstructed QEMT to disk.

// No need to find last known QEME offset.

MQEMT->next~avail~block.segment = (MQEMT->next~avail~block.segment+1)%MQEMT-onum~segs; MQEMT->next~avail~block.block = 0; status = Gen~QEM~Seq~No(&MQEMT~>qem~sn); status = Write~QEMT(Que~File~Handle, MQEMT-snext~avail block.segment, MQEMT); // Reconstruct reservation table.

if (!Reconstruct~RST()) Diag("Recovery procedure failed: cannot reconstruct RST"); ReleaseMutex(hQEMT); ReleaseMutex(hQHD); ReleaseMutex(hQTL); return; MQEMT->qget~state = ENABLED; MQEMT->qput~state = ENABLED; ReleaseMutex(hQEMT); ReleaseMutex(hQHD); ReleaseMutex(hQTL); void QR~Resolve~PTL( HANDLE Que~File~Handle) lpQHANDLE qhandle; lpMTLIST This~TXN; lpTLIST This~TXN~ops; lpQEME lpqeme; MSGH msgh,msgh2; int status; This~TXN = Pending~TXNs; while(This~TXN != NULL) { This~TXN~ops = This TXN~>ops status = Cycle QEME(This~TXN ops->qeme~no,&lpqeme); status = Retrieve~Msg~Hdr(Que~File~Handle,lpqeme->offset,&msgh); // get buffer for communication with QNETD if (!(qhandle = QopenReply(0,&msgh,0, "QNETD",&status))) Fail("QS~QRecov: could not open connection to QNETD'); // check with Derek on proper use of inquiry msg if (QSUCCESS == QsendAndReceive (qhandle,ADMINREQ MODE,QNETD TRAN INQ, (QSUCCESS == QsendAll@Receive(qhandle,ADMINREQ~MOL<BR> 0,0,0,0,0,0,&msgh2)) while(This~TXN~ops != NULL) { if (msgh2.sub mode == Q~COMMIT) QR Resolve TXN~Op(This TXN ops->qeme no,COMMIT); else QR~Resolve~TXN~Op(This~TXN~ops->qeme~no,ABORT); This~TXN~ops = This~TXN~ops->next else Fail("QS~QRecov: no response from QNETD"); Fail("QS~QRecov: Queue Server ABORTs Transaction %d",This~TXN->mid.tid); while(This~TXN~ops != NULL) QR Resolve~TXN~Op(This TXN ops->qeme no,ABORT); THIS~TXN~ops - THIS~TXN~ops~@@@AL; This~TXN = This TXN->next void QR~Resolve~TXN~Op( int qeme~no, short mode) lpQEME lpqeme,lpqeme2; lpQEME hd~qeme,tl~qeme; int qeme~no2; int status; status = Cycle QEME(qeme~no,&lpqeme); lpqeme->txn~state = mode; lpqeme->vote = mode; // if txn is ABORTed, we need to rollback either // the queue head or tail pointer depending on // whether it's a GET/PUT op if (mode == COMMIT) if (lpqeme->mode == GET~MODE) lpqeme->txn~state = EMPTY; lpqeme->vote = EMPTY; else // mode == ABORT if (lpqeme->mode == PUT~MODE) lpqeme->txn~state = EMPTY; lpqeme->vote = EMPTY; if (qeme~no == MQEMT~>que~hd~ptr) if (MQEMT->que~hd~ptr == MQEMT->que~tl~ptr) MQEMT->que~hd~ptr = NIL; MQEMT->que~tl~ptr = NIL; else MQEMT->que~hd~ptr = (MQEMT->que~hd~ptr+1)%MQEMT->max~entries; else if (qeme~no == MQEMT->que~tl~ptr) qeme~no2 = qeme~no; lpqeme2 = lpqeme; while ((lpqeme2->txn~state == EMPTY) && (qeme~no2 != MQEMT->que~hd~ptr)) qeme~no2 = (MQEMT->max~entries+qeme~no2-l)tMQEMT->max~entries; status = Cycle~QEME(qeme~no2,&1pqeme2); if ((qeme~no2 == MQEMT->que~hd~ptr) && (lpqeme2->txn~state == EMPTY)) MQEMT->que~hd~ptr = NII MQEMT->que~tl~ptr = NIL; else MQEMT->que~tl~ptr = qeme~no2; else // failed GET operation // reset the op flag to a PUT lpqeme->mode = PUT MODE; lpqeme->txn~state = COMMIT; lpqeme->vote = COMMIT; if (MQEMT->que~hd~ptr == NIL) MQEMT->que~hd~ptr = qeme~no; MQEMT->que~tl~ptr = MQEMT->que~hd~ptr; else status = Cycle~QEME(MQEMT->que~hd~ptr,&hd qeme); status = Cycle~QEME(MQEMT->que~tl~ptr,&tl qeme); if (lpqeme->timestamp < hdqeme->timestamp) MQEMT->que~hd~ptr = qeme~no; else if (lpqeme->timestamp > tl~qeme->timestamp) MQEMT->que~tl~ptr = qeme~no; int Reconstruct~RST() lpRSTSEG lprstseg; lpQEME lpqeme; int *msg~block; int qeme~no; int i,j,status; // Initialize the reservation table first.

lprstseg = MQEMT->rst~ptr->seg~ptr; for (i=0; icNUM~SEGS; i++) msg~block = lprstseg-omsg~block; for (j=0; j<MQEMT->rst~ptr->msgs~per~seg; j++) *msg block = NIL; msg~block++; lprstseg++; // Then, reconstruct it based on current QEMT state.

qeme~no = MQEMT->que~hd~ptr; while (qeme~no != MQEMT->que~tl~ptr) { status = Cycle~QEME(qeme~no,&lpqeme); if (!Add~RST~Entry(lpqeme->offset.segment,lpqeme->offset. bloc Diag("RST reconstruction phase failed: too many msgs in a segments return(0); <BR> qeme~no = (qeme~no+1)%MQEMT->max~entries; } status = Cycle~QEME(qeme~no,&lpqeme); if (!Add~RST~Entry(lpqeme->offset.segment,lpqeme->offset. block)) Diag("RST reconstruction phase failed: too many msgs in a segment"); return(0); for (i=0; i<MQEMT->num~seqs; i++) Sort~RST~Entries(i); return(l); User: rco@ Host: bunny Class: bunny Job: stdin * Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

* UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT * LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE * IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION * OR DISCLOSURE.

* * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND * TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, * OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR * EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

* * OpenMQ * Module: qsadmin.c * Author: David Wong 10/15/95 */ //Include Files include "qlib.h" include "aserv.hl #include "qadmin.h" extern lpQEMT MQEMT; extern lpQSTR MQstate; extern lpOPSTATS MQops; extern lpMTLIST Pending~TXNs; extern int BLOCKS~PER~SEG; extern int SEGMENT~SIZE; extern int TOT~MSG~BLOCKS; extern int QEMT~Size; extern int QEMT~Seq~No; extern int LREC~Seq~No; extern int MAX~ELMS; extern int NUM~SEGS; extern int shdn flag; extern int holey~entries; extern unsigned long QEME~TS; toid QS QAdmin( lpTSTR thr~arg) HANDLE Que File Handle; HANDLE Que~State~Handle; HANDLE hQHD, hQTLThQEMT; HANDLE hMQstate, hMQops, hQSHDN; DWORD dwPointer; DWORD dwBytesRead; DWORD dwflyteswritten; MSGH msgh; lpQEME lpqeme; BLAD triad; CHAR buffer[MAXMSGDATA]; BOOL Return~Status; int done,found; int i,cnt,status; int qeme~no; int entry~num; time~t temp~time; CHAR *t0, *t1, *t2, *t3; int *int0, *int1, *int2; short *shO,*shl,*sh2; LONG Dist~to~Move; QMSG qmsg2; lpMID mid; lpQMSG qmsg; lpQADMSEL seldat; lpQADMSTATS lpstats; lpQADMCTLS ctls; lpCNTSTR cnt~ptr=NULL; lpMLIST ml=NULL,m2=NULL,m3=NULL; lpMID midstrl=NULL,midstr2=NULL; Que~File~Handle = thr~arg->Que~File~Handle; // Might have to fetched all locks if // we do not assume a quiescent state.

switch(thr~arg->lpsmbuf->msgh.sub~mode) case QADM~REQ~STATS: lpstats = (QADMSTATS *)malloc(sizeof(QADMSTATS)); strcpy(lpstats->logical qname,thr arg->logical); strcpy(lpstats->physical~qname,thr~arg->physical); if (thr~arg->qhandle != QUEUE~TEST~VALUE) strcpy(lpstats->node~name,SHAREDATA(hostname)); lpstats->node~address = SHAREDATA(hostip); lpstats->max-entries-limit = MQEMT->max~entries~limit; lpstats->max~entries = MQEMT->max~entries; lpstats->pending~puts = MQops->pending~puts; lpstats - >pendinggets = MQops->pending~gets; if (Check~Queue~Empty(MQEMT) == TRUE) lpstats->committed~entries = 0; lpstats->holey~entries = 0; lpstats->num~free~entries = MQEMT->max entries; lpstats->amt~free~dspace = BLOCKS~PER~SEG*NUM~SEGS*BLOCK; else status = Find Num~Entries(&cnt~ptr); lpstats->committed~entries = cnt~ptr->committed; if (holey~entries == 0) lpstats->holey~entries = cnt~ptr->holey else lpstats->holey~entries = holey~entries; lpstats->num~free~entries = MQEMT->max~entries- (Ipstats->committed entries+lpstats->pending gets+ lpstats->pending~puts+lpstats->holey~entries) Ipstats->amt free dspace = (int) (((float)lpstats->num~free~entries/(float)MQEMT->max~e ntries)* TOT~MSG~BLOCKS*BLOCK); lpstats->qget~state = MQEMT->qget~state; lpstats->qputstate = MQEMT->qput~state; lpstats->num~puts = MQops->num~puts; lpstats->num~gets = MQops-onum~gets; lpstats->num~aborts = MQops-onum~aborts; lpstats->num~commits = MQops->num commits; lpstats->num~restarts = MQstate->num~restarts; lpstats->first~start~time = MQstate->first~start~time; lpstats->last~restart~time = MQstate->last~restart~time; if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr~arg->qhandle,ADMINREP~MODE,SUB~MODE ~OK, (char *)lpstats,sizeof(QADMSTATS),0); free(lpstats); if (cnt~ptr != NULL) free(cnt~ptr); break; case QADM~SET~CONTROLS: ctls = (lpQADMCTLS)thr~arg->lpsmbuf->mdata // Enable/Disable QGETs and QPUTs hQEMT = OpenMutex(SYNCHRONIZE,FALSE,QEMT~LOCK); if (!hQEMT) Diag("QS~Admin: Can't OpenMutex for QEM Table lock"); if ((status = WaitForSingleObject(hQEMT,QUE LOCK TIMEOUT)) WAIT~OBJECT~0) Diag("QS~Admin: Synch wait for QEM Table lock failed"); if (ctls->enable~qputs~flag) MQEMT->qput~state = ENABLED; else MQEMT->qpùt~state = DISABLED; if (ctls->enable~qgetsflag) MQEMT->qget~state = ENABLED; else MQEMT->qget~state = DISABLED; ReleaseMutex(hQEMT); if (ctls->stats~reset~flag) hMQops = OpenMutex(SYNCHRONIZE,FALSE,MQops~LOCK); if (!hMQops) Diag("QS~Admin: Can't OpenMutex for MQops stats lock"); if ((status = WaitForSingleObject(hMQops,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT 0) Diag("QS~Admin: Synch wait for MQops stats lock failed"); MQops->num~puts = 0; MQops->num~gets = 0; MQops->num~aborts = 0; MQops->num~commits = 0; ReleaseMutex(hMQops); // full reset: clear stat counters and queue entries if (ctls->full~reset~flag) // Fetch all locks first.

hQHD = OpenMutex(SYNCHRONIZE,FALSE,QUE~HD~ PTR~ LOCK); if (!hQHD) Diag("QS~Admin: Can't OpenMutex for que head pointer lock"); if ((status = WaitForSingleObject(hQHD,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~Admin: Synch wait for que head pointer lock failed"); hQT = OpenMutex(SYNCHRONIZE,FALSE,QUE TL PTR LOCK); if (!hQTL) Diag("QS~Admin: Can't OpenMutex for que tail pointer lock"); if ((status = WaitForSingleObject(hQTL,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~Admin: Synch wait for que tail pointer lock failed"); hQEMT = OpenMutex(SYNCHRONIZE,FALSE,QEMT LOCK); if (!hQEMT) Diag("QS~Admin: Can't OpenMutex for QEM Table lock"); if ((status = WaitForSingleObject(hQEMT,QUE~LOCK~TIMEOUT)) != WAIT OBJECT~0) Diag("QS~Admin: Synch wait for QEM Table lock failed"); hQSHDN = OpenMutex(SYNCHRONIZE,FALSE,QSHDN~LOCK); if ('.hQSHDN) Diag("QS~Admin: Can't OpenMutex for QSHDN lock"); if ((status = WaitForSingleObject(hQSHDN,QUE~LOCK TIMEOUT)) WAIT~OBJECT~0) Diag("QS~Admin: Synch wait for QSHDN lock failed"); hMQstate = OpenMutex(SYNCHRONIZE,FALSE,MQstate~LOCK); if (!hMQstate) Diag("QS~Admin: Can't OpenMutex for MQstate lock"); if ((status = WaitForSingleObject(hMQstate,QUE~LOCK~TIMEOUT)) != WAIT OBJECT~0) Diag("QS~Admin: Synch wait for MQstate lock failed"), hMQops = OpenMutex (SYNCHRONIZE, FALSE,MQops~LOCK); if (!hMQops) Diag("QS~Admin: Can't OpenMutex for MQops stats lock"); if ((status = WaitForSingleObject(hMQops,QUE LOCK TIMEOUT)) WAIT~OBJECT~0) Diag("QS~Admin: Synch wait for MQops stats lock failed"); // Clear queue and pending txn list and // write out initialized QEM table.

Del MTlist~All(&Pending TXNs); Init~Active~LREC~List(); status = Init~QEMT(MQEMT,MQEMT->max~entries, MQEMT->max entries~limit, <BR> <BR> MQEMT->num~segs); status = Write~QEMT(Que~File~Handle,0,MQEMT); // Reset all stat counters.

MQops->num~puts = 0; MQops->numgets = 0; MQops->num~aborts = 0; MQops->num~commits. = 0; MQops->pending~puts = 0; MQops->pendinggets = 0; // Dump out queue state info.

MQstate->num~restarts = 0; MQstate->num~recov~tries = 0; temp~time = time(&MQstate->last~restart~time); MQstate->last~recov~time = 0; Que~State~Handle = Open Queue File(thr arg->qstate); dwPointer = SetFilePointer(Que~State~Handle, 0,NULL,FILE~BEGIN); Return~Status = WriteFile(Que~State~Handle, MQstate,sizeof(QSTR), &dwBytesWritten,NULL); if ((Return~Status == FALSE) || (dwBytesWritten != sizeof(QSTR)) printf("QS Admin: Problem writing out MQstate.\n"); printf("BytesWritten = %d\n",dwBytesWritten); if (Return~Status == FALSE) printf("status = FALSE\n"); Return~Status = CloseHandle(Que~State~Handle); QreplyAfterListen(thr~arg->qhandle,ADMINREP~MODE, SUB~MODE~OK,0,0,0); ReleaseMutex(hMQops); ReleaseMutex(hQMstate); ReleaseMutex(hQSHDN); ReleaseMutex(hQEMT); ReleaseMutex(hQTL); ReleaseMutex(hQHD); if (ctls->shutdown~flag) // Fetch all locks first.

hQHD = OpenMutex(SYNCHRONIZE,FALSE,QUE~HD~PTR~LOCK); if (!hQHD) Diag("QS~Admin: Can't OpenMutex for que head pointer lock"); if ((status = WaitForSingleObject(hQHD,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~Admin: Synch wait for que head pointer lock failed"); hQTL = OpenMutex(SYNCHRONIZE,FALSE,QUE~TL~PTR~LOCK); if (!hQTL) Diag("QS~Admin: Can't OpenMutex for que tail pointer lock"); if ((status = WaitForSingleObject(hQTL,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~Admin: Synch wait for que tail pointer lock failed"); hQEMT = OpenMutex(SYNCHRONIZE,FALSE,QEMT~LOCK); if (!hQEMT) Diag("QS~Admin: Can't OpenMutex for QEM Table lock"); if ((status = WaitForSingleObject(hQEMT,QUE LOCK~TIMEOUT)) WAIT~OBJECT 0) Diag("QS~Admin: Synch wait for QEM Table lock failed"); hQSHDN = OpenMutex(SYNCHRONIZE,FALSE,QSHDN~LOCK); if (!hQSHDN) Diag("QS~Admin: Can't OpenMutex for QSHDN lock"); if ((status = WaitForSingleObject(hQSHDN,QUE~LOCK~TIMEOUT)) WAIT OBJECT~0) Diag("QS~Admin: Synch wait for QSHDN lock failed"); // Disable GETs/PUTs and set shutdown flag.

MQEMT->qget~state = DISABLED; MQEMT->qput~state = DISABLED; shdnflag = 1; ReleaseMutex(hQSHDN); ReleaseMutex(hQEMT); ReleaseMutex(hQTL); ReleaseMutex(hQHD); break; case QADM~REQ~COM~DATA: // retrieve msg based on QEM entry case QADM~REQ~UNCOM~DATA: entry~num = (int)*thr~arg-lpsmbuf->mdata found = 0; if (Check~Queue~Empty(MQEMT) == FALSE) i = O; qeme~no =MQEMT->que~hd~ptr; status = CycleQEME(qeme~no,&lpqeme); done = 0; while (!done) if (((thr arg-slpsmbuf->msgh.sub mode == QADM REQ~COM~DATA) && (lpqeme->txn~state == COMMIT)) | - <BR> ((thr~arg->lpsmbuf->msgh.sub.mode == QADM~REQ~UNCOM~DATA) && ((lpqeme->txn state == ACTIVE) || (lpqeme->txn~state == PENDING)))) if (i == entry~num) done = 1; found = 1; else if (i > entry~num) done = 1; else if (i < entry~num) i++; } if (!done) { if (qeme no == MQEMT->que~tl~ptr) done = 1; else <BR> <BR> <BR> <BR> <BR> qeme no = (qeme no+l)MQEMT->max entries;<BR> <BR> <BR> status = Cycle~QEME(qeme~no,&lpqeme);<BR> } } } // end while } // end if Check~Queue~Empty() if (found) status = Retrieve~Msg~Hdr(Que~File~Handle,lpqeme->offset,&msgh); tblad.segment = lpqeme- >offset segment; tblad.block = lpqeme->offset.block+MSG~HDR~BLOCKS; status = Retrieve Msg Body(Que File Handle,tblad,msgh.size,buffer); QreplyAfterListen(thr~arg->qhandle,ADMINREP~MODE,SUB~MODE ~OK, buffer,msgh.size,&msgh); else // bad queue entry number Diag("QS~Admin: Queue Entry d is Invalid",entry~num); QreplyAfterListen(thr~arg->qhandle,ADMINREP~MODE,0,0,0,0) ; break; case QADM~REQ~SEL~DATA: // retrieve list of MIDs based on key search seldat = (QADMSEL *)thr~arg->lpsmbuf->mdata to = (CHAR *)malloc(sizeof(QMSG)); if (Check~Queue~Empty(MQEMT) == FALSE) qeme no = MQEMT->que~hd~ptr; status = Cycle~QEME(qeme~no,&lpqeme); ml = (MLIST *)malloc(sizeof(MLIST)); ml->next = NULL; ml->mid.host = 0; ml->mid.tid = 0; ml->mid.uid = 0; m2 = ml; done = 0; while (!done) found = 0; if ((seldat->search~type == SEARCH ALL ENT) ((seldat->search~type == SEARCH COM ENT) && (lpqeme->txn~state == COMMIT)) - ((seldat->searchtype == SEARCH UNCOM~ENT) && ((lpqeme->txn~state == ACTIVE) || (lpqeme->txn~state == PENDING)))) Conv Addr(&Dist to Move,&lpqeme->offset); dwPointer = SetFilePointer(Que~File~Handle, Dist to Move, NULL,FILE~BEGIN); Return~Status = ReadFile(Que~File~Handle, t0,sizeof(QMSG), &dwBytesRead,NULL); ti = tO; t1 += seldat->preds[0].offset; if (seldat->preds[0].pred~type == INT~SEARCH~TYPE) int0 = (int *)tl; else if ((seldat->preds[0].pred~type == SHORT~SEARCH~TYPE) shO = (short *)tl; if (seldat->num~preds > 1) t2 = t0; t2 += seldat->preds[1].offset; if (seldat->preds[1].pred~type == INT SEARCH~TYPE) int1 = (int *)t2; else if (seldat->preds[1].pred~type == SHORT~SEARCH~TYPE) shl = (short *)t2; if (seldat->numpreds > 2) t3 = t0; t3 += seldat->preds[2].offset; if (seldat->preds[2] pred~type == INT~SEARCH~TYPE) int2 = (int *)t3; else if (seldat->preds[2] pred~type == SHORT~SEARCH~TYPE) sh2 = (short *)t3; switch(seldat->num~preds) { case 1: if ((!seldat->preds[0].min~switch || (((seldat->preds[0].pred.type == INT~SEARCH~TYPE) &&<BR> (*int0 >= seldat->preds[0].min~int~val)) ||<BR> <BR> <BR> <BR> <BR> <BR> <BR> ((seldat->preds[0].pred.type == SHORT~SEARCH~TYPE)<BR> <BR> (*sh0 >= seldat->preds[0].min sh val)) || ((seldat->preds[0].pred.type == STR~SEARCH~TYPE) && (strncmp(t1,seldat->preds[0].min str val, seldat->preds[0].min~str~len,) >= 0)))) && (!seldat->preds[0].max~switch || (((seldat->preds[0].pred.type == INT~SEARCH~TYPE)<BR> <BR> (*intO <= = seldat->preds[0].max~int~val)) TI <BR> <BR> <BR> <BR> <BR> <BR> <BR> ((seldat->preds[0].pred.type == SHORT~SEARCH~TYPE)<BR> <BR> (*sh0 <= seldat->preds[0].max~sh~val)) || ((seldat->preds[0].pred~type == STR~SEARCH~TYPE) && (strncmp(t1,seldat->preds[0].max str val, seldat->preds[0].max~str~len) <= 0))))) found = 1; break; case 2: if ((!seldat->preds[0].min~switch || (((seldat->preds[0].pred.type == INT~SEARCH~TYPE) &&<BR> (*int0 >= seldat->preds[0].min~int~val)) ||<BR> <BR> <BR> <BR> <BR> <BR> <BR> ((seldat->preds[0].pred.type == SHORT~SEARCH~TYPE) &<BR> <BR> (*sh0 >= seldat->preds[0].min~sh~val)) || ((seldat->preds[0].pred.type == STR~SEARCH~TYPE) && (strncmp(t1,seldat->preds[0].min~str~val,<BR> seldat->preds[0].min~str~len) >= 0)))) (!seldat->preds[0].max switch || (((seldat->preds[0].pred.type == INT~SEARCH~TYPE) && (*intO <= = seldat->preds[0].max~int~val)) TI ((seldat->preds[0].pred.type == SHORT SEARCH TYPE) &&<BR> (*sh0 <= seldat->preds[0].max~sh~val)) II - ((seldat->preds[0].pred~type == STR~SEARCH~TYPE) && (strncmp(tl,seldat->preds[0].max~str~val, seldat->preds[0].max~str~len) <= 0)))) && (!seldat->preds[1].min~switch || (((seldat->preds[1].pred.type == INT~SEARCH~TYPE)<BR> <BR> (*intl >= = seldat->preds[1].min~int~val)) TI<BR> <BR> <BR> <BR> <BR> <BR> <BR> ((seldat->preds[1].pred.type == SHORT~SEARCH~TYPE) &<BR> <BR> (*sh1 >= seldat->preds[1].min~sh~val)) || ((seldat->preds[1].pred.type == STR~SEARCH~TYPE) && (strncmp(t2,seldat->preds[1].min~str~val, seldat->preds[1].min~str~len) >= 0)))) (!seldat->preds[1].max~switch || (((seldat->preds[1].pred.type == INT~SEARCH~TYPE) && (*int1 <= seldat->preds[1].max~int~val)) || ((seldat->preds[1].pred.type == SHORT~SEARCH~TYPE) && (*shl <= = seldat->preds[1].max~sh~val)) II ((seldat->preds[1].pred.type == STR~SEARCH~TYPE) &&<BR> (strncmp(t2,seldat->preds[1].max~str~val, seldat->preds[1].max~str~len) <= 0))) found = 1; break; case 3: if ((!seldat->preds[0].min~switch || (((seldat->preds[0].pred~type == INT~SEARCH~TYPE) && (*int0 >= seldat->preds[0].min~int~val)) || ((seldat->preds[0].pred~type == SHORT~SEARCH~TYPE) && (*sh0 >= seldat->preds[0].min~sh~val)) || ((seldat->preds[0].pred~type == STR~SEARCH~TYPE) && (strncmp(t1,seldat->preds[0].min~str~val, seldat->preds[0].min~str~len) >= 0)))) && (!seldat->preds[0].max~switch || <BR> <BR> (((seldat->preds[0].pred~type == INT~SEARCH~TYPE) &&<BR> <BR> <BR> <BR> (*int0 >= seldat->preds[0].max~int~val)) || ((seldat->preds[0].pred~type == SHORT~SEARCH~TYPE) && (*sh0 >= seldat->preds[0].max~sh~val)) || ((seldat->preds[0].pred~type == STR~SEARCH~TYPE) && (strncmp(t1,seldat->preds[0].max~str~val, seldat->preds[0].max~str~len) <= 0)))) && (!seldat->preds[1].min~switch || (((seldat->preds[1].pred~type == INT~SEARCH~TYPE) &&<BR> <BR> <BR> <BR> (*int1 >= seldat->preds[1].min~int~val)) || ((seldat->preds[1].pred~type == SHORT~SEARCH~TYPE) && (*sh1 >= seldat->preds[1].min~sh~val)) || ((seldat->preds[1].pred~type == STR~SEARCH~TYPE) && (strncp(t2,seldat->preds[1].min~str~val, seldat->preds[1].min~str~len) >= 0)))) && (!seldat->preds[1].max~switch || (((seldat->preds[1].pred~type == INT~SEARCH~TYPE) && (*intl <= seldat->preds[1].max~int~val)) T ((seldat->preds[1].pred~type == SHORT~SEARCH~TYPE) && (*sh1 <= seldat->preds[1].max~sh~val)) || ((seldat->preds[1].pred~type == STR~SEARCH~TYPE) && (strncmp(t2,seldat->prds[l] .max sr val,- seldat->preds[1].max str len) <= 0)))) && (!seldat->preds[2].min~switch II (((seldat->preds[2].pred~type == INT~SEARCH~TYPE) && (*int2 >= seldat->preds[2].min~int~val)) || ((seldat->preds[2].pred~type == SHORT~SEARCH~TYPE) && (*sh2 >= seldat->preds[2] min~sh~val)) II - ((seldat->preds[2].pred~type == STR~SEARCH~TYPE) && (strncmp(t3,seldat->preds[2].min~str~val, seldat->preds[2].min~str~len) >= 0)))) && (!seldat->preds[2].max~switch || (((seldat->preds[2].pred~type == INT SEARCH TYPE) && (*int2 <= seldat->preds[2].max~int~val)) TI ((seldat->preds[2].pred~type == SHORT SEARCH TYPE) && (*sh2 <= seldat->preds[2].max~sh~val)) || ((seldat->preds[2].pred~type == STR~SEARCH~TYPE) && (strncmp(t3,seldat->preds[2] max~str~val, seldat->preds[2].max~str~len) <= 0))))) found =,'l; break; default: break; } // end switch // endif if (found) m3 = (MLIST *)malloc(sizeof(MLIST)); m3->next = NULL; m2->next = m3; m2 = m3; qmsg = (QMSG *)tO; m3->mid.host = qmsq->Msg~Hdr.mid.host; m3->mid.tid = qmsq->Msg~Hdr.mid.tid; m3->mid.uid = qmsg->Msg~Hdr.mid.uid; if (qeme~no == MQEMT->que~tl~ptr) done = 1; else { qeme~no = (qeme~no+1)%MQEMT->max~entries; status = Cycle~QEME(qeme~no,&lpqeme);<BR> } } // end while { // end if Check Queue Empty() if (ml != NULL) m2 = ml; ml = ml->next m2->next = NULL; free(m2); if (ml == NULL) Diag("QS~Admin: No match on predicate QreplyAfterListen(thr~arg->qhandle,ACK~MODE,SUB~MODE~EMPT Y, 0,0,0); <BR> } else { cnt = 0; m2 = ml; while (m2 != NULL) cnt++; m2 = m2->next midstrl = (MID *)malloc(cnt*sizeof(MID)); m2 = m1; midstr2 = midstr1; while(m2 != NULL) midstr2->host = m2->mid.host; midstr2->tid = m2->mid.tid; midstr2->uid = m2->mid.uid; m2 = m2->next midstr2++; QreplyAfterListen(thr~arg->qhandle,ADMIN MODE,SUB MODE OK, (char *)midstrl,cnt*sizeof(MID),0); // free up memory to clean up memory leaks free(tO); if (midstrl != NULL) free(midstrl); while (ml != NULL) m2 = ml; ml = ml->next m2->next = NULL; free(m2); break; case QADM~REQ~MSG: // retrieve msg based on MID mid = (MID *)thr~arg->lpsmbuf->mdata status = Find QEME(mid,&qeme~no,&lpqeme); if (status == QSUCCESS) Conv~Addr(&Dist~to~Move,&lpqeme->offset) dwPointer = SetFilePointer(Que~File~Handle, Dist~to~Move, NULL,FILE~BEGIN); Return~Status = ReadFile(Que~File~Handle, &qmsg2,sizeof(QMSG), &dwBytesRead,NULL); QreplyAfterListen(thr arg->qhandle,ADMINREP~MODE,SUB~MODE OK, qmsg2.Msg~Body.text,qmsg2.Msg~Hdr.size, &qmsg2.Msg~Hdr); else Diag("QS~Admin: No msg with such MID"); QreplyAfterListen(thr~arg->qhandle,ACK~MODE,SUB~MODE~EMPT Y, 0,0,0); break; default: Diag("QS~Admin: Option %d Not Valid",thr~arg->lpsmbuf->msgh.sub~mode); * Copyright (C) 1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

* UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT * LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE * IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION * OR DISCLOSURE.

* * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND * TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, * OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR * EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

* * OpenMQ * Module: qscommit.c * Author: David Wong 9/8/95 */ // Include Files #include "qlib.h" #include "qserv.h" #include "qadmin.h" extern lpQEMT MQEMT; extern lpQSTR MQstate; extern lpOPSTATS MQops; extern lpMTLIST Pending~TXNs; extern int BLOCKS PER SEG; extern int SEGMENT SIZE; extern int TOT MSG~BLOCKS; extern int QEMT~Size; extern int QEMT~Seq~No; extern int LREC Seq~No; extern int NUM SEGS; extern int MAX~ELMS; void QS~QCommit( lpTSTR thr arg) HANDLE Que File Handle; HANDLE hQEMT,hMQops; BLAD tblad; BOOL Return~Status; lpMTLIST This~TXN; lpTLIST This~TXN~ops; lpSMBUF lpsmbuf; LREC log~rec; short mode; int status; int tgets=0,tputs=0; int count=0; Diag("DiskQ(ts): Termination for TID: %d from Host: Wx",thr~arg->qname, thr~arg->lpsmbuf->msgh.mid.tid,thr~arg->lpsmbuf-> ;msgh.mid.host); Diag (""); Diag("MID.host = %x",thr~arg->lpsmbuf->msgh.mid.host); Diag("MID.tid = %d",thr~arg->lpsmbuf->msgh.mid.tid); Diag("MID.uid = d",thrarg->lpsmbuf->msgh.mid.uid); Diag(""); print~PTList(); Diag(""); */ lpsmbuf = thr~arg->lpsmbuf if (lpsmbuf->msgh.mode == COMMIT~MODE) mode = COMMIT; else mode = ABORT; Return~Status = Find~MTlist(Pending~TXNs,&This~TXN,lpsmbuf->msgh.mid); if (Return~Status == FALSE) Diag("QS~Commit: TXN kd from Host %x does not exist", lpsmbuf->msgh.mid.tid,lpsmbuf->msgh.mid.host); if (thr arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr~arg->qhandle,ACK~MODE,SUB~MODE~INV~ TID, 0,0,0); else // first, update the entries in the // QEM Table for each op in txn This~TXN~ops = This~TXN->ops while (This~TXN~ops != NULL) QS~Resolve~TXN~Op(This~TXN~ops->qeme~no, &tgets,&tputs,mode); This TXN ops = This TXNops->next count++; // increment txn ops counter // delete TID op list from pending txn list Return~Status = Del~MTlist(&PendingTXNs,lpsmbuf->msgh.mid); if (Return~Status == FALSE) Diag("QS~Commit: error deleting TID %d from Host %d", log~rec.mid.tid,logrec.mid.host); // then, write ABORT/COMMIT log record Que~File~Handle = thr arg->Que~File~Handle; hQEMT = OpenMutex(SYNCHRONIZE,FALSE,QEMT~LOCK); if (!hQEMT) Diag("QS~QCommit: Can't OpenMutex for QEM Table lock"); if ((status = WaitForSingleObject(hQEMT,QUE LOCK TIMEOUT)) WAIT~OBJECT~0) Diag("QS~QCommit: Synch wait for QEM Table lock failed"); log~rec.marker = LRMARK; status = Gen~LREC~Seq~No(&log~rec.seq~no); log~rec.mode = mode; log~rec.flags = lpsmbuf->msgh.flags; log~rec.qeme~no = NIL; log~rec.txn~state = mode; log~rec.vote = mode; log~rec.mid.host = lpsmbuf->msgh.mid.host; log~rec.mid.tid = lpsmbuf->msgh.mid.tid; log~rec.mid.uid = lpsmbuf->msgh.mid.uid; log~rec.offset.segment = NIL; log~rec.offset.block = NIL; // Fetch next available on-disk slot for log write.

if (!Get Next BLAD(Que File Handle,LOG WRITE,&tblad)) // queue data file is full or too fragmented.

Diag("DiskQ(%s) is either full or too fragmented.",thr~arg->qname); if (thr arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr~arg->qhandle,ACK~MODE, SUB~MODE~FULL,0,0,0); ReleaseMutex(hQEMT); return; status = Write~Log~Rec(Que~File~Handle,tblad,&log~rec); ReleaseMutex(hQEMT); // send ACK msg back to client if (thr~arg->qhandle != QUEUE TEST VALUE) QreplyAfterListen(thrarg->qhandle,ACK~MODE,SUB~MODE~OK, 0,0,0); // update RT stastical counters hMQops = OpenMutex(SYNCHRONIZE,FALSE,MQops LOCK); if (!hMQops) Diag("QS~QCommit: Can't OpenMutex for MQops stats lock"); if ((status = WaitForSingleObject(hMQops,QUE LOCK TIMEOUT)) WAIT~OBJECT~0) Diag("QS~QCommit: Synch wait for MQops stats lock failed") if (mode == ABORT) MQops->num~aborts += count; else MQops->num~commits += count; MQops->pendinggets = MQops->pending~gets-tgets; MQops->pending~puts = MQops->pending~puts-tputs; ReleaseMutex(hMQops); void QS Resolve TXN Op ( int qemeno, int *tgets, int *tputs, short mode) lpQEME lpqeme; int status; status = Cycle~QEME(qeme~no,&lpqeme); // increment number of pending GET/PUT // to decrement from MQops counter.

if (lpqeme->mode == GET~MODE) (*tgets)++; else if (lpqeme->mode == PUT~MODE) (*tputs)++; lpqeme->txn state = mode; lpqeme->vote = mode; if (mode == COMMIT) { if (lpqeme->mode == GET~MODE) { lpqeme->txn~state = EMPTY; lpqeme->vote = EMPTY; if (!Del~RST~Entry(lpqeme->offset.segment,lpqeme->offset, block)) Diag("QS~QCommit: Problem with deleting entry from reservation table"; Sort RST Entries(lpeme->offset.segment) ; else // ABORTed txn.

if (lpqeme->mode == PUT~MODE) // aborted PUT operation // set QEM entry to be a hole lpqeme->txn~state = EMPTY; lpqeme->vote = EMPTY; if (!Del~RST~Entry(lpqeme->offset.segment,lpqeme->offset, block)) Diag("QS~QCommit: Problem with deleting entry from reservation table"); Sort~RST~Entries(lpqeme->offset.segment); Fix Qu Ptrs on Aborted Put(lpqeme,qeme~no); else // aborted GET operation // reset the op flag to a PUT lpqeme->mode = PUT~MODE; lpqeme->txn~state = COMMIT; lpqeme->vote = COMMIT; Fix~Que~Ptrs~on~Aborted Get(qeme~no); } } } User: root Host: bunny Class: bunny Job: stdin // // Common definitions used by OpenMQ Qservers // //////////////////////////////////////////////////////////// ///////////////// // Synch objects for Queue Pointers #define QEME~TS~GEN~LOCK "Q/QEME TS Gen" #define LPG~TS~GEN~LOCK "Q/LPG~TS~Gen" #define QUE~HD~PTR~LOCK "Q/QUE~Head~Ptr" #define QUE~TL~PTR~LOCK "Q/QUE~Tail~Ptr" define QEMT~LOCK - "Q/QEMTable" define MQstate LOCK "Q/MQstate" #define MQops~LOCK "Q/MQops" define QSHDN~LOCK "Q/QS Shutdown" #define QSHDN~EVENT "Q/QS~Shutdown~Event" // Queue server states #define QUEUE~ACTIVE OL #define QUEUE~SHUTDOWN 1L // Other queue server attributes define QUE~LOCK~TIMEOUT 10000 #define MAX~QSERV~THREADS 20 #define NIL -1L 4define FIFO OL #define QUEUE~TEST~VALUE (HANDLE)-111 // Log record attributes #define LOG~WRITE 0L #define MSG~WRITE 1L 4define LRMARK -999 #define QEMTMARK -111 // Queue element size - - disk block size is the larger of - - log record or half a msg header #define QUE~FILE~SIZE 50 #define QUE~EXTENT 0.0 // queue file extent percentage #define BLOCK 46 // size of a block on disk #define MSG~HDR~BLOCKS 2 // number of blocks for msg header #define MSG BODY BLOCKS 177 // ceil((8192-sizeof(MSGH))/BLOCK) // blocks for msg body #define LOG~REC~BLOCKS 1 // 1 block required for log record #define MSGHDR SIZE 2*BLOCK // msg header size define MSG~BODY~SIZE 177*BLOCK // msg body size on disk<BR> &num define MSG~ENTRY~BLOCKS (MSG~HDR~BLOCKS+MSG~BODY+LOG~REC~BLOCKS) #define GET~LOG~REC~BLOCKS LOG REC BLOCKS; // log record for GETs #define TERM LOG REC BLOCKS LOG~REC~BLOCKS; // ABORT/COMMOT log record // Queue entry transactional states #define INACTIVE 0L #define ACTIVE 1L #define INITIAL 2L #define PENDING 3L #define PREPARED 4L #define ABORT 5L #define COMMIT 6L #define EMPTY 7L // Queue server include files 4include <math.h> #include <string.h> // Queue server type defs typedef struct msgb I // Message body char text[MAXMSGDATA]; MSGB, *lpMSGB; typedef struct blad I // msg block address int segment; // segment number int block; // block offset in segment BLAD, *lpBLAD; typedef struct qeme ( // QEM Table entry int index; // QEM entry number unsigned long timestamp; // entry creation timestamp // needed to preserve order MID mid; // unique msg ID short mode; // QGET/QPUT type short priority; // currently unused short txn~state; // TXN state short vote; // participant 2PC vote int flags; // flags for TXN/NOTXN BLAD offset; // msg block offset on disk QEME, *lpQEME; typedef struct ptl { // pending TXN list on disk MID mid; // unique msg ID int qeme~no; // entry index in QEM Table PTLIST, *lpPTLIST; typedef struct sn ( // sequence number structure time~t timestamp; // timestamp based on time() call int counter; // counter that regenerates after each restart SN, *lpSN; typedef struct lrclst I // list of active log records in segment int max txns per seg; // max number of active txns per segment int *address; // pointer to log record block values ) LRCLST, *lpLRCLST; typedef struct rstseg ( // list msg block entry values in segment int seg~no; // segment number int *msg~block; // pointer to msg block entry values RSTSEG, *lpRSTSEG; typedef struct rst { // reservation table of msgs on disk int num~segs; // number of segments in queue data file int msgs~per~seg; // number of msgs in the segment lpRSTSEG seg~ptr; // pointer to buffer of segment entries RST, *lpRST; typedef struct qemt t // QEM Table int marker; // QEM Table marker SN qem~sn; // QEM sequence number SN lrec~sn; // beginning lrec timestamp in segment int num~segs; // number of segments in datafile int max~entries; // max number of entries on queue int max~entries~limit; // limit on max entries value int que hd ptr; // QEM Table head pointer int quetlptr; // QEM Table tail pointer short qget~state; // ENABLED/DISABLED switch for GETs short qput~state; // ENABLED/DISBLED switch for PUTs int num~pts; // number of pending txns BLAD next~avail~block; // next available block byte offset lpQEME qemeZptr; - // pointer to QEM Table entries lpRST rst~ptr; // pointer to reservation table lpPTLIST ptl~ptr; // pointer to list of pending txns QEMT, *lpQEMT; typedef struct opstats ( // RT operational statistics int pending~gets; // pending gets only int pending~puts; // pending puts only int num~gets; // committed gets only int num~puts; // committed puts only int num~aborts; int num~commits; OPSTATS, *lpOPSTATS; typedef struct qstr ( // used to record queue state short svr~state; // designate clean shutdown int num~restarts; // number of restarts int num~recov~tries; // number of recovery attempts time t first start time; // time of fresh startup time~t last = estart~time; // time of last restart time t last recov time; // time of last recovery attempt } QSTR, *1pQSTR; typedef struct msg { // Queue Msg Block on disk MSGH Msg~Hdr; // Msg Header MSGB Msg~Body; // Msg Body QMSG, *lpQMSG; typedef struct lrec ( // Log Record int marker; // log record marker SN seq~no; // increasing sequence number short mode; // QGET/QPUT flag short txn~state; // TXN state short vote; // participant 2PC vote short dummy~l; // not used at this time int flags; // Q~LOG|Q~TRAN flags int qeme~no; // QEM Table entry number MID mid; // unique msg ID BLAD offset; // msg block offset on disk LREC, *lpLREC; typedef struct drec ( // dummy structure for retrieving int field[ll]; // records from disk at recovery } DREC ,*1pDREC; typedef struct tstr CHAR -logical[NAMESIZE]; // logical queue name CHAR physical[NAMESIZE]; // physical queue server name CHAR qname[QUE~FILE~SIZE]; // queue data file name CHAR qstate [QUE~FILE~SIZE]; // queue state file name HANDLE Que~File~ Handle; // queue data file handle lpQHANDLE qhandle; // handle to SHM buffers lpSMBUF lpsmbuf; // pointer to SMBUF TSTR, *lpTSTR; typedef struct mstr ( // Structure for passing thread data CHAR logical[NAMESIZE]; // logical queue name CHAR physical[NAMESIZE]; // physical queue server name CHAR qname[QUE~FILE~SIZE]; // queue data file name CHAR qstate [QUE~FILE~SIZE]; // queue state file name int thr~no; // thread number MSTR, *lpMSTR; typedef struct tlist ( // list of ops for a TID struct tlist *next; // chain to next entry index int qeme~no; // entry index into QEM Table LIST, *lpTLIST; typedef struct mtlist ( // list of pending TIDs struct mtlist *next; // chain to next TID lpTLIST ops; // list of ops for txn MID mid; // MID for each txn MTLIST, *lpMTLIST; typedef struct cntstr int committed; int holey; } CNTSTR, *1pCNSTR; typedef struct lpg~ts ( int qeme~no; unsigned long timestamp; } LPG~TS~STR *1pLPG~TS~STR; // Function prototypes.

void QS QGet( lpTSTR thr~arg); void QS QPut( lpTSTR thr~arg); void QS QCommit( lpTSTR thr~arg); void QS~QAdmin( lpTSTR thr~arg); void QRecov( HANDLE Que~File~Handle, int seg~no); void QR~Resolve~PTL( HANDLE Que~File~Handle); void QR~Resolve~TXN~Op( int geme no, short mode); void QS~Resolve~TXN~Op( int qeme~no, int *tgets, int *tputs, Short mode); int Reconstruct~RST(); HANDLE Create~Queue~File( CHAR *FileName, CHAR *qstate, int Max~Elms, int Num~Segs); HANDLE Open~Queue~File( CHAR *FileName); BOOL Delete~Queue~File( CHAR *FileName); int Find Num Entries( lpCNTSTR *cnt~ptr); int Find~QEME( lpMID mid, int *qeme~no2, lpQEME *lpqeme2); int Cycle~QEME( int qeme~no, lpQEME *lpqeme2); void Find Last Pending Get( int *qeme~no); void Fix~Que~Ptrs~on~Aborted~Put( lpQEME lpqeme, int qeme~no); void Fix~Que~Ptrs~on~Aborted~Get( int qeme~no); void Update~QEME~TS(); int Find~Latest~QEM( HANDLE Que~File~Handle, lpQEMT *lpqemt2, int *seg~num); int Create~QEMT( lpQEMT *lpqemt, int max~elms); int Init~QEMT( lpQEMT lpqemt, int max~elms, int ext~elms, int num~segs); int Write~QEMT( HANDLE Que~File~Handle, int seg~no, lpQEMT lpqemt); int Retrieve QEMT( HANDLE Que~File~Handle, int seg~no, lpQEMT *lpqemt2); int Retrieve Msg~Hdr( HANDLE Que File Handle, BLAD Msg~Addr, lpMSGH Msg~Hdr); int Write~Msg~Hdr( HANDLE Que~File~Handle, BLAD Msg~Addr, lpMSGH Msg~Hdr); int Retrieve~Msg~Body( HANDLE Que~File~Handle, BLAD Msg~Addr, DWORD Msg~Length, CHAR *Msg~Body); int Write~Msg~Body( HANDLE Que~File~Handle, BLAD Msg~Addr, DWORD Msg~Length, CHAR *Msg~Body); int Retrieve Msg( HANDLE Que File Handle, BLAD Msg~Addr, lpQMSG Msg); int Retrieve~Log~Rec( HANDLE Que File Handle, BLAD LREC~Addr, lpLREC LREC~ptr); int Write~Log~Rec( HANDLE Que~File~Handle, BLAD LREC~Addr, lpLREC LREC~ptr); void Init~Active~LREC~List(); int msg~entry~comp( const void *argl, const void *arg2); void Sort~RST~Entries( int seg~no); int Add~RST~Entry( int seg~no, int entry~value); int Del~RST~Entry( int seg~no, int entry~value); int Entry~in~RST( int seg~no, int entry~value); int log~entry~comp( const void *argl, const void *arg2); void Sort~Log~Entries(); int Add~Log~Entry( int entry~value); int Del~Log~Entry( int entry~value); int Del~Log~Entry( int entry~value); int In~Log~Rec~List( int start, int end, int *hit) int Cycle~RST~Seg( int seg~no, lpRSTSEG *lprstseg); int Get~Next~BLAD( HANDLE Que~File~Handle, int type, BLAD *offset); BOOL Check~Queue~Full( lpQEMT lpqemt); BOOL Check Queue Empty( lpQEMT lpqemt); void Update~Globals(); void Conv~from~MTlist(); void Conv~to~ MTlist(); void Add~Tlist( lpTLIST *head, int qeme~no); void Add MTlist( lpMTLIST *head, lpMTLIST *tail, MID mid); BOOL Find MTlist( lpMTLIST head, lpMTLIST *pres, MID mid); BOOL Find Tlist( lpTLIST head, int qeme~no); void Del~MTlist~All( lpMTLIST *head); BOOL Del MTlist( lpMTLIST *head, MID mid); void Del~Tlist( lpTLIST *head); void Sub Addr LONG - *diff, BLAD *x, BLAD *y); void Conv~Addr LONG *diff, BLAD *x); int Gen~QEM~Seq~No( lpSN tSeq~No); int Gen~LREC~Seq~No( lpSN tSeq~No); int Gen~QEME~TS( unsigned long *tSeq~No); void test~qemt( CHAR *filename); void test~lrec( CHAR *filename); void test msgh( CHAR *filename); void test msgb( CHAR *filename); void test~QS~funcs( CHAR *logical, CHAR *physical, CHAR *qname); void test~QRecov( CHAR *qname); void print QEMT( lpQEMT - lpqemt, int mode); void print~QEME~txn~states(); void print LREC( lpLREC - lplrec); void print SMBUF( lpSMBUF lpsmbuf); void print MSGH( lpMSGH - lpmsgh); void print~MSGB( CHAR *lpmsgb); void print~RST(); void print Active Log List(); void print~PTList(); void print~QAdm~Stats(); BOOL Bigger~Seq~No ( 1pSN seq~no1, lpSN seq~no2); * Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

* UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT * LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE * IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION * OR DISCLOSURE.

* * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND * TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, * OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR * EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

* OpenMQ * Module: qsget.c * Author: David Wong 9/8/95 */ // Include Files #include "qlib.h" #include "qserv.h" &num include "qadmin.

extern lpQEMT MQEMT; extern lpQSTR MQstate; extern lpOPSTATS MQops; extern lpMTLIST Pending TXNs; extern int BLOCKS PER SEG; extern int SEGMENT~SIZE; extern int TOT~MSG~BLOCKS; extern int QEMT~Size; extern int QEMT~Seq~No; extern int LREC Seq~No; extern int NUM~SEGS; extern int MAX~ELMS; extern unsigned long QEME~TS; extern 1pLPG~TS~STR Last~Pending~Get; void QS~QGet( lpTSTR thr arg) HANDLE Que~File~Handle; HANDLE hQHD, hQTL, hLPG; HANDLE hQEMT,hMQops; BOOL Return Status; lpMTLIST This~TXN; lpSMBUF lpsmbuf; lpQEME lpqeme; LREC log~rec; BLAD tblad; int status; int qeme no; int new hd~ptr; int no~new~hd=0; int done=0; int found=0; lpsmbuf = (SMBUF *)malloc(sizeof(SMBUF)); Que~File~Handle = thr~arg->Que~File~Handle; // Check if GETs are disabled.

if (MQEMT->gget~state == DISABLED) Diag("GET Operations for DiskQ(%s) is DISABLED",thr~arg->qname); if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr~arg->qhandle,ACK~MODE, SUB~MODE~DISABLED,0,0,0); return; // Obtain locks on queue pointers.

// Protocol is to obtain hQHD first, // then hQTL.

hQHD = OpenMutex(SYNCHRONIZE,FALSE,QUE~HD~PTR~LOCK); if (!hQHD) Diag("QS~QGet: Can't OpenMutex for queue head pointer lock"); if ((status = WaitForSingleObject(hQHD,QUE LOCK TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~QGet: Synch wait for queue head pointer lock failed hQTL = OpenMutex(SYNCHRONIZE,FALSE,QUE~TL~PTR~LOCK); if (!hQTL) Diag("QS~QGet: Can't OpenMutex for queue tail pointer lock"); if ((status = WaitForSingleObject(hQTL,QUE LOCK TIMEOUT)) WAIT~OBJECT~0) Diag("QSQGet: Synch wait for queue tail pointer lock failed"); // Check if queue is EMPTY if (Check~Queue~Empty(MQEMT) == TRUE) Diag("DiskQ(%s): EMPTY",thr~arg->qname); if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr~arg->qhandle,ACK~MODE, SUB~MODE~EMPTY, 0,0,0); ReleaseMutex(hQHD); ReleaseMutex(hQTL); return; qeme~no = MQEMT->que~hd~ptr; status = Cycle~QEME(qemeno,&lpqeme); if (MQEMT->que~hd~ptr == MQEMT->que~tl~ptr) if ((lpqeme->mode == PUT MODE) && (lpqeme->txn~state == COMMIT)) MQEMT->que~hd~ptr = NIL; MQEMT->que~tl~ptr = NIL; else if (lpqeme->txn~state == EMPTY) MQEMT->que~hd~ptr = NIL; MQEMT->que~tlptr = NIL;<BR> } Diag("DiskQ(%s) : EMPTY", thr~arg->qname); if (thrarg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr~arg->qhandle, ACK~MODE, SUB~MODE~EMPTY,O,O,O); ReleaseMutex(hQTL); ReleaseMutex(hQHD); return; else // head != tail new~hd~ptr = MQEMT->que~hd~ptr; if ((lpqeme->mode == PUT MODE) && (lpqeme->txn~state == COMMIT)) MQEMT->que~hd~ptr = (MQEMT->que~hd~ptr+1) %MQEMT->max~entries; else // head entry is not yet committed; // find next one that is committed.

while (!done && found) if ((lpqeme->mode == PUT~MODE) && (lpqeme->txn~state == COMMIT)) done = 1; found = 1; } else { if ((lpqeme->mode == PUT~MODE) && (lpqeme->txn~state == PENDING) && (!no~new~hd)) new~hd~ptr = qeme~no; no~new~hd = 1; if (qeme~no == MQEMT->que~tl~ptr) done = 1; else { qeme~no = (qeme~no+1) %MQEMT->max~entries;<BR> status = Cycle = EME(qeme~no,&lpqeme); if (found) if ((qeme~no == MQEMT->que~tl~ptr) && (!no~new~hd)) { MQEMT->que~hd~ptr = NIL; MQEMT->que~tl~ptr = NIL; else MQEMT->que~hd~ptr = new~hd~ptr; else Diag("DiskQ(%s) : EMPTY", thr~arg->qname); if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr~arg->qhandle,ACK~MODE, SUB~MODE~EMPTY, 0, 0, 0); ReleaseMutex(hQTL); ReleaseMutex(hQHD); return; // Change state of QEM entry before // releasing queue pointer locks.

lpqeme->txn~state = ACTIVE; lpqeme->vote = INITIAL; ReleaseMutex(hQTL); ReleaseMutex(hQHD); status = Retrieve~Msg~Hdr(Que~File~Handle, lpqeme->offset, &lpsmbuf->msgh); lpqeme->mid.host = thrarg->lpsmbuf->msgh.mid.host; lpqeme->mid.tid = thr~arg->lpsmbuf->msgh.mid.tid; lpqeme->mid.uid = thr~arg->lpsmbuf->msgh.mid.uid; lpqeme->mode = GET MODE; lpqeme->flags = thr~arg->lpsmbuf->msgh.flags; lpqeme->priority = FIFO; tblad.segment = lpqeme->offset.segment; tblad.block = lpqeme->offset.block+MSG~HDR~BLOCKS; status = Retrieve~Msg~Body(Que~File~Handle, tblad, lpsmbuf->msgh.size, lpsmbuf->mdata); // Diag("DiskQ(%s): DEQUEs message - %s", thr~arg->qname, lpsmbuf->mdata); Diag ("DiskQ(%s): DEQUEs message", thr~arg->qname); // increment get ops counter hMQops = OpenMutex(SYNCHRONIZE,FALSE,MQops~LOCK); if (!hMQops) Diag("QS~QGet: Can't OpenMutex for MQops stats lock"); if ((status = WaitForSingleObject (hMQops, QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag ("QS~QGet: Synch wait for MQops stats lock failed"); MQops->num~gets++; hQEMT = OpenMutex(SYNCHRONIZE,FALSE,QEMT~LOCK); if (!hQEMT) Diag("QS~QGet: Can't OpenMutex for QEM Table lock"); if ((status = WaitForSingleObject(hQEMT,QUE LOCK TIMEOUT)) WAIT~OBJECT~0) Diag("QS~QGet: Synch wait for QEM Table lock failed"); // if transactional, then write PREPARED log record if (BITSET(Q TRAN,thr arg->lpsmbuf->msgh.flags)) log~rec.marker = LRMARK; status = Gen~LREC~Seq~No(&log~rec.seq~no); log~rec.mode = GET~MODE; log~rec.flags = thrarg->lpsmbuf->msgh.flags; log~rec.txn~state = PENDING; log~rec.vote = PREPARED; log~rec.qeme~no = qeme~no; log~rec.mid.host = thr~arg->lpsmbuf->msgh.mid.host; log~rec.mid.tid = thr~arg->lpsmbuf->msgh.mid.tid; log~rec.mid.uid = thr~arg->lpsmbuf->msgh.mid.uid; log~rec.offset.segment = lpqeme->offset.segment; log~rec.offset.block = lpqeme->offset.block; // Fetch next available on-disk slot for log write.

if (!Get~Next~BLAD(Que~Flle~Handle,LOG~WRITE,&tblad)) // queue data file is full or too fragmented.

Diag("DiskQ(%s) is either full or too fragmented.",thr~arg->qname); if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr~arg->qhandle,ACK~MODE, SUB~MODE~FULL, 0,0,0); ReleaseMutex(hQEMT); ReleaseMutex(hMQops); return; status = Write Log~Rec(Que File Handle,tblad,&log~rec); // return msg queue data and ACK msg to client if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr arg->handle,ACK MODE,SUB MODE OK, lpsmbuf->mdata, lpsmbuf->msgh.size, &lpsmbuf->msgh); // update QEM entry lpqeme->mode = GET~MODE; lpqeme->txn~state = PENDING; lpqeme->vote = PREPARED; // add txn and/or op to pending txn list Return~Status = Find MTlist(Pending~TXNs,&This TXN,lpqeme->mid); if (Return~Status == FALSE) Add MTlist(&Pending TXNs,&This TXN,lpqeme-mid); Add~Tlist(&This~TXN->ops,qeme~no); MQops- >pendinggets++; // update last pending GET timestamp hLPG = OpenMutex(SYNCHRONIZE,FALSE,LPG~TS~GEN~LOCK); if (!hLPG) Diag("QS~QGet: Can't OpenMutex for LPG~TS~GEN Lock"); if (status = WaitForSingleObject (hLPG, QUE~LOCK~TIMEOUT)) WAIT~OBJECT~0) Diag("QS~QGet: Synch wait for LPG~TS~GEN Lock failed"); if (lpqeme->tlmestamp > Last Pending Get->timestamp) Last Pending Get->qeme no = qeme~no; Last~Pending~Get->timestamp - lpqeme->timestamp ReleaseMutex(hLPG); else // return msg queue data and ACK msg to client if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr~arg->qhandle,ACK~MODE,SUB~MODE~OK, lpsmbuf->mdata,lpsmbuf->msgh.size, &lpsmbuf->msgh); // update QEM entry lpqeme->mode = GET~MODE; lpgeme->txn~state = EMPTY; lpqeme->vote = EMPTY; // increment commit counter MQops->num~commits++; // delete on-disk entry slot from reservation table if (!Del~RST~Entry(lpqeme->offset.segment, lpqeme->offset.block)) Diag("QS QGet: Problem with deleting entry from reservation table"); else Sort RST Entries(lpqeme->offset.segment); ReleaseMutex(hMQops); ReleaseMutex(hQEMT); free(lpsmbuf); Diag("TID = %d, UID = kd, index= td, offset.segment = d, offset.block = lpqeme->mid.tid, lpqeme->mid.uid, lpqeme->index, lpqeme->offset.segment,lpqeme->offset.block); * Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

* UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT * LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE * IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION * OR DISCLOSURE.

* THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND * TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, * OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR * EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

* * OpenMQ * Module: qsput.c * Author: David Wong 9/8/95 */ // Include Files &num include "qlib.h" #include "qserv.h" #include "qadmin.h" extern lpQEMT MQEMT; extern lpQSTR MQstate; extern lpOPSTATS MQops; extern lpMTLIST Pending~TXNs; extern int BLOCKS PER~SEG; extern int SEGMENT~SIZE; extern int TOT MSG~BLOCKS; extern int QEMT~Size; extern int QEMT Seq No; extern int LREC~Seq~No; extern int NUM~SEGS; extern int MAX~ELMS; extern unsigned long QEME~TS; extern lpLPG~TS~STR Last~Pending~Get; extern lpLRCLST Active LREC List; // Issue - create separate lock for obtaining space in reservation table.

void QS~QPut( lpTSTR thr~arg) HANDLE Que File~Handle; HANDLE hQHD,hQTL; HANDLE hQEME, hQEMT, hMQops; BOOL Return~Status; lpMTLIST This~TXN; lpSMBUF lpsmbuf; lpQEME lpqeme; LREC log~rec; BLAD temp~offset; int status; int qeme~no; int qeme~no2; int done=0; int found=0; lpsmbuf = thr~arg->lpsmbuf Que~File~Handle = thr~arg->Que~File~Handle; // Check if PUTs are disabled.

if (MQEMT->qput~state == DISABLED) Diag("PUT Operations for DiskQ(%s) is DISABLED",thr~arg->qname); if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen (thr~arg->qhandle,ACK~MODE, SUB~MODE~DISABLED, 0, 0, 0); return; // Obtain locks on queue pointers.

// Protocol is to obtain hQHD first, // then hQTL.

hQHD = OpenMutex(SYNCHRONIZE,FALSE,QUE~HD~PTR~LOCK); if (!hQHD) Diag("QS~QPUT: Can't OpenMutex for queue head pointer lock"); if ((status = WaitForSingleObject (hQHD, QUE~LOCK~TIMEOUT)) != WAIT OBJECT~0) Diag(egQS~QPut: Synch wait for queue head pointer lock failed"); hQTL = OpenMutex(SYNCHRONIZE,FALSE,QUE~TL~PTR~LOCK); if (!hQTL) Diag("QS~QPUT: Can't OpenMutex for queue tail pointer lock"); if ((status = WaitForSingleObject (hQTL, QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~QPut: Synch wait for queue tail pointer lock failed"); if (Check~Queue~Full(MQEMT) == TRUE) Diag("DiskQ(%s) is FULL", thr~arg->qname); if (thr~arg->qhandle != QUEUE~TEST~VALUE) <BR> <BR> QreplyAfterListen (thr~arg->qhandle,ACK~MODE, <BR> <BR> <BR> SUB~MODE~FULL,O,0,O); ReleaseMutex(hQTL); ReleaseMutex(hQHD); return; // Obtain lock on QEMT to fetch next available // entry in reservation table and disk writes.

hQEMT = OpenMutex(SYNCHRONIZE,FALSE,QEMT~LOCK); if (!hQEMT) Diag("QS~QPUT: Can't OpenMutex for QEM Table lock"); if ((status = WaitForSingleObject(hQEMT, QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~QPut: Synch wait for QEM Table lock failed"); if (MQEMT->que~hd~ptr == NIL) hMQops = OpenMutex(SYNCHRONIZE,FALSE,MQops~LOCK); if (!hMQops) Diag("QS~QCommit: Can't OpenMutex for MQops stats-lock"); if ((status = WaitForSingleObject(hMQops,QUE LOCK TIMEOUT)) != WAIT~OBJECT 0) Diag("QS~QCommit: Synch wait for MQops stats lock failed"); if (MQops->pendinggets == 0) // Fetch next available on-disk slot for msg.

if (!Get Next BLAD(Que Fle Handle,MSG WRITE,&temp~offset)) // queue data file is full or too fragmented.

Diag("DiskQ(%s) is too fragmented - PUT failed.",thr~arg->qname); if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen (thr~arg->qhandle,ACK~MODE,SUB~MODE FULL, 0, 0, 0); ReleaseMutex(hQEMT); ReleaseMutex(hQTL); ReleaseMutex(hQHD); return; MQEMT->que~hd~ptr = 0; MQEMT->que~tl~ptr = 0; status = Cycle~QEME (MQEMT->que~tl~ptr, &lpqeme); else qeme no = Last Pending~Get-sqeme no; if (qeme~no == NIL) Diag("DiskQ(%s) has faulty RT counters", thr~arg->qname); if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen (thr~arg->qhandle, ACK~MODE, SUB~MODE~FULL,O,0,0); ReleaseMutex(hMQops); ReleaseMutex(hQTL); ReleaseMutex(hQHD); return; qeme~no2 = qeme~no; qeme~no = (qeme~no+1) %MQEMT->max~entries; status = Cycle~QEME (qeme~no, &lpqeme); while (!done && found) if (lpqeme->txn~state == EMPTY) done = 1; found = 1; else qeme~no = (qeme no+l)%MQEMT->max entries; if (qeme~no == qeme~no2) done = 1; <BR> <BR> else status = Cycle~QEME(qemeno,&lpqeme); <BR> if (found) // Fetch next available on-disk slot for msg.

if (!Get Next BLAD(Que File Handle,MSG~WRITE,&temp~offset)) // queue data file is full or too fragmented.

Diag("DiskQ(%s) is too fragmented - PUT failed.",thr~arg->qname); if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen (thr~arg->qhandle,ACK~MODE,SUB~MODE~FULL, 0, 0, 0); ReleaseMutex(hQEMT); ReleaseMutex(hQTL); ReleaseMutex(hQHD); return; } MQEMT->que~hd~ptr = qeme~no; MQEMT->que~tl~ptr = qeme~no;<BR> } else { Diag("DiskQ(%s) has faulty que pointers", thr~arg->qname); if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen (thr~arg->qhandle,ACK~MODE, SUB~MODE~FULL,0,O,0); ReleaseMutex(hMQops); ReleaseMutex(hQTL); ReleaseMutex(hQHD); return; ReleaseMutex(hMQops); else if (!Get Next BLAD(Que File Handle,MSG WRITE,&temp~offset)) // queue data file is full or too fragmented.

Diag("DiskQ(%s) is too fragmented - PUT failed.",thr~arg->qname); if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen (thr~arg->qhandle,ACK~MODE,SUB~MODE~FULL, 0, 0, 0); ReleaseMutex(hQEMT); ReleaseMutex(hQTL); ReleaseMutex(hQHD); return; // This case is true only iff que head is EMPTY.

// Roll over both que head and tail pointers.

if (((MQEMT->que~tl~ptr+1) %MQEMT->max~entries) == MQEMT->que~hd~ptr) MQEMT->que~hd~ptr = (MQEMT->que~hd-ptr+1) %MQEMT->max~entries; MQEMT->que~tl~ptr = (MQEMT->que~tl-ptr+1) %MQEMT->max~entries; status = Cycle~QEME(MQEMT->que~tl~ptr, &lpqeme); // Change state of QEM entry before // releasing queue pointer locks.

lpqeme->txn~state = ACTIVE; lpqeme->vote = INITIAL; ReleaseMutex(hQTL); ReleaseMutex(hQHD); // Now assign storage location to QEM entry.

lpqeme->offset.segment = temp~offset.segment; lpqeme->offset.block = temp~offset.block; // Fetch QEM entry timestamp generator lock.

hQEME = OpenMutex(SYNCHRONIZE,FALSE,QEME~TS~GEN~LOCK); if (!hQEME) Diag("QS QPUT: Can't OpenMutex for QEME~TS Lock"); if ((status = WaitForSingleObject (hQEME, QUE~LOCK~TIMEOUT)) != WAIT~OBJECT 0) Diag("QSQPut: Synch wait for QEME~TS Lock failed status = Gen~QEME~TS(&lpqeme->timestamp); ReleaseMutex(hQEME); lpqeme->mid.host = lpsmbuf->msgh.mid.host; lpqeme->mid.tid = lpsmbuf->msgh.mid.tid; lpqeme->mid.uid = lpsmbuf->msgh.mid.uid; lpqeme->mode = PUT~MODE; lpqeme->flags = lpsmbuf->msgh. flags; lpqeme->priority = FIFO; // NoWait case on disk write of msg // send ACK msg to client immediately if ((!BITSET(Q~TRAN,lpsmbuf->msgh.flags)) && (!BITSET(Q~LOG,lpsmbuf->msgh.flags))) if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr~arg->qhandle,ACK~MODE,SUB~MODE~OK,0 , 0,0); status = Write~Msg~Hdr(Que~File~Handle, lpqeme->offset, &lpsmbuf->msgh); temp~offset.segment = lpqeme->offset.segment; tempoffset.block = lpqeme->offset.block+(MSG~HDR~BLOCKS); status = Write Msg Body(Que File Handle, temp offset, lpsmbuf->msgh.size, lpsmbuf->mdata); // Diag("DiskQ(ts): ENQUEs message - %s", thr~arg->qname,lpsmbuf->mdata); Diag("DiskQ(%s) . ENQUEs messages", thr~arg->qname); // increment put ops counter hMQops = OpenMutex(SYNCHRONIZE,FALSE,MQops~LOCK); if (!hMQops) Diag("QS~QPUT: Can't OpenMutex for MQops stats lock"); if ((status = WaitForSingleObject (hMQops,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~QPut: Synch wait for MQops stats lock failed"); MQops->num~puts++; // if transactional, then write log record if (BITSET(Q~TRAN,lpsmbuf->msgh.flags)) log~rec.marker = LRMARK; status = Gen~LREC~Seq~No(&log~rec.seq~no); log~rec.mode = PUT~MODE; log~rec.flags = lpsmbuf->msgh.flags; log~rec.txn~state = PENDING; log~rec.vote = PREPARED; log~rec.qeme~no = MQEMT->que~tl~ptr; log~rec.mid.host = lpqeme->mid.host; log~rec.mid.tid = lpqeme->mid.tid; log~rec.mid.uid = lpqeme->mid.uid; log~rec.offset.segment = lpqeme->offset.segment; log~rec.offset.block = lpqeme->offset.block; temp~offset.segment = lpqeme->offset.segment; temp~offset.block = lpqeme->offset.block + (MSG~HDR~BLOCKS+MSG~BODY~BLOCKS); status = Write Log Rec(Que File Handle,temp~offset,&log~rec); // send ACK msg back to client if (thr~arg->qhandle != QUEUE~TEST~VALUE) QreplyAfterListen(thr~arg->qhandle,ACK~MODE, SUB~MODE~OK, 0,0,0); // update QEM entry lpqeme->txn~state = PENDING; lpqeme->vote = PREPARED; // add txn and/or op to pending txn list Return~Status = Find~MTlist(Pending~TXNs,&This~TXN,lpsmbuf->msgh.mid); if (Return~Status == FALSE) Add~MTlist(&Pending~TXNs, &This~TXN, lpsmbuf->msgh.mid); Add Tlist(&This TXN->ops,MQEMT->que tl~ptr); <BR> <BR> <BR> <BR> <BR> <BR> MQops->pendingputs++; ReleaseMutex(hQEMT); else ReleaseMutex(hQEMT); // send ACK msg back to client if Q~LOG flag if ((BITSET(Q~LOG,lpsmbuf->msgh.flags) == Q~LOG) && (thr~arg->qhandle != QUEUE TEST VALUE)) QreplyAfterListen(thr~arg->qhandle,ACK~MODE,SUB~MODE~OK, 0,0,0); // update QEM entry lpqeme->txn~state = COMMIT; lpqeme->vote = COMMIT; // increment commit counter MQops->num~commits++; ReleaseMutex(hMQops); Diag("TID = %d, UID = %d, index = %d, offset.segment = %d, offset.block = lpqeme->mid.tid, lpqeme->mid.uid, lpqeme->index, lpqeme->offset.segment, lpqeme->offset.block); * Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

* UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT * LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE * IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION * OR DISCLOSURE.

* * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND * TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, * OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR * EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

* OpenMQ * Module: qtest.c * Author: David Wong 9/8/95 */ // Include Files #include "qlib.h" ((include "qserv.h" #include "qadmin.h" extern lpQEMT MQEMT; extern lpQSTR MQstate; extern lpMTLIST Pending~TXNs; extern int BLOCKS~PER~SEG; extern int SEGMENT~SIZE; extern int TOT~MSG~BLOCKS; extern int QEMT~Size; extern int QEMT Seq~No; extern int LREC SeqNo; extern int NUMSEGS; extern int MAX~ELMS; extern unsigned long QEME~TS; extern lpLRCLST Active LREC List; void test qemt( CHAR *filename) HANDLE Que File Handle; HANDLE hQHD, hQTL, hQEMT; BOOL Return~Status; lpQEMT lpqemt,lpqemt2; lpQEME lpqeme; int i,status; status = Create QEMT(&lpqemt,MAX~ELMS); status = Init QEMT(lpqemt,MAX ELMS,O,NUM~SEGS); hQHD = CreateMutex(NULL, // No security TRUE, // Get ownership of mutex QUE~HD~PTR~LOCK); // Name if (!hQHD) Diag("CreateMutex for Que Head Pointer lock failed."); hQTL = CreateMutex(NULL, // No security TRUE, // Get ownership of mutex QUE~TL~PTR~LOCK); // Name if (!hQTL) Diag("CreateMutex for Que Head Pointer lock failed."); hQEMT = CreateMutex(NULL, // No security TRUE, // Get ownership of mutex QUE~TL~PTR~LOCK); // Name if (!hQEMT) Diag("CreateMutex for Que Head Pointer lock failed."); lpqeme = lpqemt->qeme~ptr; for(i=l; i<=10; i++) lpqeme->mid.host = 11111; lpqeme->mid.tid = 22222; lpqeme->mode = PUT~MODE; lpqeme->flags = 0; lpqeme->priority = 0; lpqeme->txn~state = ACTIVE; lpqeme->vote = INACTIVE; lpqeme->offset.segment = 44444; lpqeme->offset.block = 55550+i; lpqeme++; Que~File Handle = Open Queue File(filename); if (Que~File~Handle == INVALID~HANDLE~VALUE) Diag("Problem opening queue file . ."); status = Gen QEM Seq~No(&MQEMT->qem~sn); status = Write~QEMT(Que~File~Handle,0,lpqemt); if (status == QFAIL) Diag("QEMT Write Failed ..."); status = Create~QEMT(&lpqemt2,MAX~ELMS); status = Retrieve~QEMT(Que~File~Handle,1,&lpqemt2); if (status == QFAIL) Diag("QEMT Read Failed ..."); Return~Status = CloseHandle(Que File Handle); if (Return~Status == FALSE) Diag("Could not close queue file handle") print~QEMT(lpqemt2,1); void test~lrec( CHAR *filename) HANDLE Que~File~Handle; BOOL Return~Status; lpLREC lplrec; lpLREC lplrec2; BLAD LREC~Addr; int status; Que~File~Handle = Open Queue File(filename); LREC~Addr.segment = 1; LREC~Addr.block = 1; lplrec = (LREC *)malloc(sizeof(LREC)); lplrec->marker = LRMARK; status = Gen~LREC~Seq~No(&lplrec->seq~no); lplrec->mode = PUT MODE; lplrec->qeme~no = 999; lplrec->txn~state = ACTIVE; lplrec->vote = INACTIVE; lplrec->mid.host = 11111; lplrec->mid.tid = 22222; lplrec->offset.segment = 1; lplrec->offset.block = 1; print~LREC(lplrec); status = Write Log Rec(nue~File Handle,LREC Addr,lplrec); if (status == QFAIL) Diag("Log Write Failure .

lplrec2 = (LREC *)malloc(sizeof(LREC)); status = Retrieve~Log~Rec(Que~File~Handle,LREC~Addr,lplrec2); if (status == QFAIL) Diag("Log Read Failure .

print~LREC(lplrec2); Return~Status = CloseHandle(Que~File~Handle); if (Return~Status == FALSE) Diag("Could not close queue file handle"); void test~msgh( CHAR *filename) HANDLE Que~File~Handle; BOOL Return~Status; lpMSGH lpmsgh; lpMSGH lpmsgh2; BLAD MSGH~Addr; int status; Que~File~Handle = OpenQueue~File(filename); MSGH~Addr.segment = 1; MSGH~Addr.block = 1; lpmsgh = (MSGH *)malloc(sizeof(MSGH)); lpmsgh->type~coding = 999999; lpmsgh->mode = 1; lpmsgh->sub~mode = 2; lpmsgh->flags = Q~TRAN; lpmsgh->mid.host = 11111; lpmsgh->mid.tid = 22222; lpmsgh->time = 33333; lpmsgh->to~node = 12345; lpmsgh->to~port = 23456; lpmsgh->to~smbuf = 44444; strcpy(lpmsgh->to server.,"aue Server 1"); strcpy(lpmsgh->to~logical,"Que~Service~1"); lpmsgh->from~smbuf = 45677; lpmsgh->reply~smbuf = 34567; lpmsgh->size = 888; print~MSGH(lpmsgh); status = Write~Msg~Hdr(Que~File~Handle,MSGH~Addr,lpmsgh); if (status == QFAIL) Diag("Msg Header Write Failure lpmsgh2 = (MSGH *)malloc(sizeof(MSGH)); status = Retrieve Msg Hdr(Que File Handle,MSGH Addr,lpmsgh2); if (status == QFAIL) Diag("Msg Header Read Failure ...

print~MSGH(lpmsgh2); Return~Status = CloseHandle(Que File Handle); if (Return~Status == FALSE) <BR> <BR> <BR> <BR> <BR> Diag("Could not close queue file handle");<BR> } void test~msgb( CHAR *filename) HANDLE Que~File~Handle; BOOL Return~Status; BLAD MSGB~Addr; CHAR stringl[41]; CHAR string2[41]; int status; Que~File~Handle = Open Queue~File(filename); MSGB~Addr.segment = 1; MSGB~Addr.block = 1; strcpy(stringl,"The quick brown fox jumps over the fence."); print~MSGB(stringl); status = Write Msg Body(Que File Handle,MSGB~Addr,41,stringl); if (status == QFAIL) Diag("Msg Body Write Failure ... "); status = Retrieve~Msg~Body(Que~File~Handle,MSGB~Addr,41,string2); if (status == QFAIL) Diag("Msg Body Read Failure .

print~MSGB(string2); Return~Status = CloseHandle(Que~File~Handle); if (Return Status == FALSE) Diag("Could not close queue file handle"); void test~QS~funcs( CHAR *logical, CHAR *physical, CHAR *qname) lpSMBUF lpsmbuf; lpTSTR thr~arg; lpsmbuf = (SMBUF *)malloc(sizeof(SMBUF)); strcpy(lpsmbuf->mdata,"This is a very small message"); strcpy(lpsmbuf->name,"Tem~Buffer~1"); lpsmbuf->status = 0; lpsmbuf->sub~status = 0; lpsmbuf->msgh.typecoding = 1; lpsmbuf->msgh.mode = PUT~MODE; lpsmbuf->msgh.sub~mode = O; // lpsmbuf - >msgh. flags = Q~TRAN; lpsmbuf->msgh.time = 33333; lpsmbuf->msgh.to~node = 1234567; lpsmbuf->msgh.to~port = 2345678; lpsmbuf->msgh.to~smbuf = 2345678; strcpy(lpsmbuf->msgh.to~server,"barny"); strcpy(lpsmbuf->msgh.to~logical,"barny/Q1"); lpsmbuf->msgh.from~smbuf = 4567890; lpsmbuf->msgh.reply~smbuf. = 3456789; lpsmbuf->msgh.size = strlen(lpsmbuf->mdata); thr~arg = (TSTR *)malloc(sizeof(TSTR)); strcpy(thr~arg->logical,logical); strcpy(thr~arg->physical,physical); strcpy(thr~arg->qname,qname); thr~arg->qhandle = QUEUE~TEST~VALUE; thr~arg->lpsmbuf = lpsmbuf; lpsmbuf-omsgh.flags = Q~LOG; lpsmbuf->msgh.mid.host = 33333; lpsmbuf->msgh.mid.tid = 1; QS~QPut(thr~arg); lpsmbuf->msgh.mode = ADMINREQ~MODE; lpsmbuf->msgh.sub~mode = QADM REQ STATS; QS~QAdmin(thr~arg); lpsmbuf->msgh.flags = Q~TRAN; lpsmbuf->msgh.mid.host = 214; lpsmbuf->msgh.mid.tid = 2; QS~QPut(thr~arg); lpsmbuf->msgh.flags = Q~TRAN; lpsmbuf->msgh.mid.host = 214; lpsmbuf->msgh.mid.tid = 2; QS~QGet(thr~arg); lpsmbuf-omsgh.mode = ADMINREQ MODE; lpsmbuf->msgh.sub~mode = QADM~REQ~STATS; QS~QAdmin(thr~arg); lpsmbuf->msgh.mode = ABORT~MODE; lpsmbuf->msgh.mid.host = 214; lpsmbuf->msgh.mid.tid = 2; QS~QCommit(thr~arg); lpsmbuf->msgh.mode = ADMINREQ~MODE; lpsmbuf->msgh.sub~mode = QADM~REQ~STATS; QS~QAdmin(thr~arg); /* lpsmbuf->msgh.mid.host = 216; lpsmbuf->msgh.mid.tid = 3; QS~QPut(thr~arg); lpsmbuf->msgh.mid.host = 217; lpsmbuf->msgh.mid.tid = 4; QS~QPut(thr~arg); print~QEMT(MQEMT,1); lpsmbuf->msgh.mid.host = 218; lpsmbuf->msgh.mid.tid = 5; QS~QPut(thr~arg); lpsmbuf->msgh.mid.host = 219; lpsmbuf->msgh.mid.tid = 6; QS~QPut(thr~arg); lpsmbuf->msgh.mid.host = 219; lpsmbuf->msgh.mid.tid = 6; QS~QPut(thr~arg); lpsmbuf->msgh.mid.host = 12345; lpsmbuf->msgh.mid.tid = 678; QS~QPut(thr~arg); lpsmbuf->msgh.mid.host = 12345; lpsmbuf->msgh.mid.tid = 678; QS~QPut(thr~arg); print~QEMT(MQEMT,1); lpsmbuf->msgh.mode = COMMIT~MODE; lpsmbuf->msgh.mid.host = 214; lpsmbuf->msgh.mid.tid = 2; QS~QCommit(thr~arg); lpsmbuf->msgh.mid.host = 33333; lpsmbuf->msgh.mid.tid = 111; QS~QGet(thr~arg); print~PTList(); lpsmbuf->msgh.mode = COMMIT~MODE; lpsmbuf->msgh.mid.host = 33333; lpsmbuf->msgh.mid.tid = 111; QS~QCommit(thr~arg); print~PTList () lpsmbuf->msgh.mode = ABORT~MODE; lpsmbuf->msgh.mode = COMMIT~MODE; QS~QGet(thr~arg); lpsmbuf-omsgh.mode = ADMINREQ MODE; lpsmbuf->msgh.sub~mode = QADM REQ STATS; QS~QAdmin(thr~arg); <BR> <BR> <BR> print~QEMT(MQEMT,1);<BR> */ } void test~QRecov( CHAR *qname) HANDLE Que~File~Handle; BOOL Return~Status; lpQEMT lpqemt; int seg~no; int status; Que~File~Handle = Open~Queue~File(qname); status = Find~Latest~QEM(Que~File~Handle,&lpqemt,&seg~no) print~QEMT(lpqemt,1); Return~Status = CloseHandle(Que File Handle); void print QEMT( lpQEMT lpqemt, int mode) lpQEME lpqeme; lpPTLIST ptl~ptr; int Diag (""); Diag("QEMT->marker = %d",lpqemt->marker); Diag("QEMT->qem~sn.timestamp = \t%s",ctime(&lpqemt->qem~sn.timestamp)); Diag("QEMT->qem~sn.counter = %d",lpqemt->qem~sn.counter); Diag("QEMT->num~segs = %d",lpqemt->num~segs); Diag("QEMT->max~entries = %d",lpqemt->max~entries); Diag("QEMT->max~entries~limit = 'd",lpqemt->max~entries~limit); Diag("QEMT->que~hd~ptr = %d",lpqemt->que~hd~ptr); Diag("QEMT->que~tl~ptr = %d",lpqemt->que~tl~ptr); Diag("QEMT->qget~state = %d",lpqemt->qget~state); Diag("QEMT->qput~state = %d",lpqemt->qput~state); Diag("QEMT->num~pts = %d",lpqemt->num~pts); Diag("QEMT->next~avail~block.segment = %d", Ipqemt-snext avail block.segment); Diag("QEMT->next~avail~block.block = %d" lpqemt->next~avail~block.block); if (mode == 1) lpqeme = lpqemt->qeme~ptr; for(i=0;iclpqemt->max~entries;i++) Diag (""); Diag("index = %d",lpqeme->index); Diag("timestamp = %d", lpqeme->timestamp); Diag("MID.host = %d", lpqeme->mid.host); Diag("MID.tid = %d", lpqeme->mid.tid); Diag("mode = %d", lpqeme->mode); Diag("flags = %d",lpqeme->flags); Diag("priority = %d",lpqeme->priority); Diag("txn~state = %d",lpqeme->txn~state); Diag("vote = %d", lpqeme->vote); Diag("offset.segment = %d", lpqeme->offset.segment); Diag("offset.block = %d", lpqeme->offset.block); lpqeme++; ptl~ptr = lpqemt->ptl~ptr; for(i=0si<lpqemt-,num~pts;i++) <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> Diag("") Diag("MID.host = %d", ptl~ptr->mid.host); Diag("MID.tid = %d", ptl~ptr->mid.tid); Diag("qeme~no = %d", ptl~ptr->qeme~no); ptl~ptr++; void print QEME txn states() lpQEME lpqeme; char buf[10]; int i; <BR> <BR> <BR> <BR> <BR> Diag <BR> <BR> <BR> Diag("qeme~no\t txn~state"); Diag ("-------\t ---------"); lpqeme = MQEMT->qeme~ptr; for(i=0;i<MQEMT->max-entries;i++) { switch(lpqeme->txn~state) { case INACTIVE: strcpy(buf,"INACTIVE"); break; case ACTIVE: strcpy(buf,"ACTIVE"); break; case INITIAL: strcpy(buf,"INITIAL"); break; case PENDING: strcpy(buf,"PENDING"); break; case PREPARED: strcpy(buf,"PREPARED"); break; case ABORT: strcpy(buf, "ABORT"); break; case COMMIT: strcpy(buf,"COMMIT"); break; case EMPTY: strcpy(buf,"EMPTY"); break; <BR> <BR> default: strcpy(buf,"GARBAGE");<BR> } Diag(" %d\t %s",i,buf); lpqeme++; Diag (""); void print~LREC( lpLREC lplrec) Diag("LREC->marker = %d",lplrec->marker); Diag("LREC->seq~no.timestamp = \t%s",ctime(&lplrec->seq~no.timestamp)); Diag("LREC->seq~no.counter = %d",lplrec->seq~no.counter); Diag("LREC->mode = %d",lplrec->mode); Diag("LREC->qeme~no = %d",lplrec->qeme~no); Diag("LREC->txn~state = %d",lplrec->txn~state); Diag("LREC->vote = %d",lplrec->vote); Diag("LREC->mid.host = %d",lplrec->mid.host); Diag("LREC->mid.tid = %d",lplrec->mid.tid); Diag("LREC->offset.segment = %d",lplrec->offset.segment); Diag("LREC->offset.block = %d",lplrec->offset.block); void print SMBUF( lpSMBUF lpsmbuf) Diag("SMBUF->name = %s",lpsmbuf->name); Diag("SMBUF->status = %d",lpsmbuf->status); Diag("SMBUF->sub~status = %d",lpsmbuf->sub~status); Diag("SMBUF->MSGH.type~coding = %d",lpsmbuf->msgh.type~coding); Diag("SMBUF->MSGH.mode = %d",lpsmbuf->msgh.mode); Diag("SMBUF->MSGH.sub~mode = %d",lpsmbuf->msgh.sub~mode); Diag("SMBUF->MSGH.flags = %d",lpsmbuf->msgh.flags); Diag("SMBUF->MSGH.mid.host = %d",lpsmbuf->msgh.mid.host); Diag("SMBUF->MSGH.mid.tid = %d",lpsmbuf->msgh.mid.tid); Diag("SMBUF->MSGH.time = %d",lpsmbuf->msgh.time); Diag("SMBUF->MSGH.to~node = %d",lpsmbuf->msgh.to~node); Diag("SMBUF->MSGH.to~port = %d",lpsmbuf->msgh.to~port); Diag("SMBUF->MSGH.to~smbuf = %d",lpsmbuf->msgh.to~smbuf); Diag("SMBUF->MSGH.to~server = %s",lpsmbuf->msgh.to~server); Diag("SMBUF->MSGH.to~logical = %s",lpsmbuf->msgh.to~logical); Diag("SMBUF->MSGH.from~smbuf = %d",lpsmbuf->msgh.from~smbuf); Diag("SMBUF->MSGH.reply~smbuf = %d",lpsmbuf->msgh.reply~smbuf); Diag("SMBUF->MSGH.size = %d",lpsmbuf->msgh.size); Diag("SMBUF->mdata:"); Diag("%s",lpsmbuf->mdata); void print MSGH( lpMSGH lpmsgh) Diag("MSGH->type~coding = %d",lpmsgh->.type~coding); Diag("MSGH->mode = %d",lpmsgh->mode); Diag("MSGH->sub~mode = %d",lpmsgh->sub~mode); Diag("MSGH->flags = %d",lpmsgh->flags); Diag("MSGH->mid.host = %d",lpmsgh->mid.host); Diag("MSGH->mid.tid = %d",lpmsgh->mid.tid); Diag("MSGH->time = Sd",lpmsgh->time); Diag("MSGH->to~node = %d",lpmsgh->to~node); Diag("MSGH->to~port = %d",lpmsgh->to~port); Diag("MSGH->to~smbuf = %d",lpmsgh->to~smbuf); Diag("MSGH->to~server = %s",lpmsgh->to~server); Diag("MSGH->to~logical = %s",lpmsgh->to~logical); Diag("MSGH->from~smbuf = %d",lpmsgh->from~smbuf); Diag ("MSGH->reply~smbuf = %d", lpmsgh->reply~smbuf); Diag ("MSGH->size = %d", lpmsgh->size); void print~MSGB( CHAR *lpmsgb) Diag ("MSGB text:"); Diag ("%s",lpmsgb); void print~RST() lpRSTSEG lprstseg; CHAR seg~str[255]; int *msg~block; int i,j; lprstseg = MQEMT->rst~ptr->seg~ptr; Diag("Reservation Table"); for (i=0; i<MQEMT->rst~ptr->num~segs; i++) sprintf(seg~str,"Segment %d: ",lprstseg->seg~no); msg~block = lprstseg->msg~block; for (j=O; jcMQEMT->rst~ptr->msgs~per~seg; j++) sprintf(seg~str,"%s %d",seg~str,*msg~block); msg~block++; lprstseg++; Diag("%s",seg~str); Diag(""); void print Active Log List() CHAR seg~str[255]; int *address; int i; Diag("Active Log List:"); sprintf (seg str,"") address = Active~LREC~List->address for (i=O; i<Active~LREC~List->max~txns~per~seg; i++) if ((i != 0) && ((i%10) == 0)) { Diag("%s",seg~str); sprintf(seg~str,"");<BR> } sprintf(seg~str,"%s %d",seg~str,*address); address++; Diag("%s",seg~str); Diag(""); void print~Globals() Diag("NUM~SEGS = %d", NUM~SEGS); Diag("MAX ELMS = %d", MAX~ELMS); Diag("BLOCKS~PER~SEG = %d", BLOCKS~PER~SEG); Diag("SEGMENT~SIZE = %d", SEGMENT~SIZE); Diag("QEMT~Size = %d", QEMT~Size); void print~PTList() lpMTLIST ptl~ptr; lpTLIST tlist; ptl~ptr = Pending~TXNs; Diag(""); while (ptl~ptr != NULL) tlist = ptl~ptr->ops Diag (""); Diag("mid.host = %x",pt1~ptr->mid.host); Diag("mid.tid = %d",ptl~ptr->mid.tid); while (tlist != NULL) Diag("qeme~no = %d",tlist->qeme~no); tlist = tlist->next ptl~ptr = ptl~ptr->next } void print~QAdm~Stats( lpQADMSTATS lpstats) { Diag (""); Diag("logical~qname = %s",lpstats->logical~qname); Diag("max~entries~limit = %d",lpstats->max~entries~limit); Diag("max~entries = %d",lpstats->max~entries); Diag("committed~entries = %d",lpstats->committed~entries); Diag("pending~gets = %d",lpstats->pending~gets); Diag("pending~puts = %d",lpstats->pending~puts); Diag("holey~entries = %d",lpstats->holey~entries); Diag("num~free~entries = %d",lpstats->num~free~entries); Diag("amt~free~dspace = %d",lpstats->amt~free~dspace); Diag("qget~state = %d",lpstats->qget~state); Diag("qput~state = %d",lpstats->qput~state); Diag("nume~puts = %d",lpstats->num~puts); Diag("num~gets = %d",lpstats->num~gets); Diag("num~commits = %d",lpstats->num~commits); Diag("num~aborts = %d",lpstats->num~aborts); Diag("num~restarts = %d",lpstats->num~restarts); Diag("first~start~time = \t%s",ctime(&lpstats->first~start~time)); Diag("last~restart~time = \t%s",ctime(&lpstats->last~restart~time)); Diag (""); * Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

* UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT * LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE * IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION * OR DISCLOSURE.

* THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND * TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, * OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR * EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

* OpenMQ * Module: qutil.c * Author: David Wong 9/8/95 */ // Include Files #include "qlib.h" &num include "qserv.h" include "qadmin.h" extern lpQEMT MQEMT; extern lpQSTR MQstate; extern lpMTLIST Pending~TXNs; extern int BLOCKS PER SEG; extern int SEGMENT SIZE; extern int TOT~MSG~BLOCKS; extern int QEMT~Size; extern int QEMT~Seq~No; extern int LREC~Seq~No; extern int NUM~SEGS; extern int MAX~ELMS; extern int holey~entries; extern unsigned long QEME~TS; extern lpLRCLST Active~LREC~List; // Routine for creating queue file HANDLE Create~Queue~File( CHAR *FileName, CHAR *qstate, int Max~Elms, int Num Segs) HANDLE Que~File~Handle; HANDLE Que~State~Handle; BOOL Return~Status; DWORD dwBytesWritten; DWORD pointer; QSTR que~state; // number of segments should divide // evenly among total block size NUM~SEGS = Num~Segs; MAX~ELMS = Max~Elms; Update~Globals(); if (INVALID~HANDLE~VALUE == (Que File Handle = CreateFile(FileName, GENERIC~READ GENERIC~WRITE FILE~SHARE~READ FILE~SHARE~WRITE, NULL, CREATE NEW, FILE ATTRIBUTE NORMAL, NULL))) return(Que~ile~Handle); pointer = SetFilePointer(Que~File~Handle, SEGMENT SIZE*NUM SEGS, NULL,FILE~BEGIN); SetEndOfFile(Que~File~Handle); que~state.svr~state = QUEUE~SHUTDOWN; que~state.num~restarts = 0; que~state.num~recov~tries = 0; time(hque state.first start time); que~state.last~restart~time = 0; questate.last~recov time = 0; <BR> <BR> <BR> <BR> if (INVALID~HANDLE~VALUE == (Que State Handle = CreateFile(qstate,<BR> <BR> <BR> GENERIC~READ GENERIC~WRITE, FILE~SHARE~READ FILE~SHARE~WRITE, <BR> <BR> NULL,CREATE NEW, <BR> <BR> <BR> FILE ATTRIBUTE~NORMAL, NULL))) return(Que~File~Handle); Return~Status = WriteFile(Que~State~Handle, &que~state, sizeof (QSTR), &dwBytesWritten, NULL); Return~Status = CloseHandle(Que~State~Handle); return(Que File Handle); // Routine to update global data structures.

void Update~Globals() int elems~per~seg; int temp; elems~per~seg = (int)ceil((double)(MAX~ELMS/NUM~SEGS)); // Size of QEMT; refer to qutil.h // Subject to change.

QEMT Size = sizeof(QEMT) + (MAX~ELMS*sizeof(QEME)) + sizeof(RST) + (NUM~SEGS*sizeof(RSTSEG)) + (NUM~SEGS*elems~per seg*sizeof(int)) + + (MAX~ELMS*sizeof(PTLIST)); // Total number of msg blocks in queue data file.

TOT~MSG~BLOCKS = (MAX~ELMS*sizeof(QMSG))/BLOCK; // Total msg blocks consists of msg header, msg // body, and 1 log record for recording PENDING // state for each operation in a segment.

BLOCKS~PER~SEG = elemsger~seg*MSG ENTRY BLOCKS; // Include enough extra blocks to record PENDING state // of transactional GETs and transaction ABORT/COMMIT // records. Set this to theorectical max of MAX~ELMS // for each log record type within a single segment.

temp = GET LOG REC BLOCKS+TERM LOG REC BLOCKS; BLOCKS~PER~SEG += (MAX~ELMS*temp); // Total number of bytes in each segment.

// Currently does not include an extent factor // for over-capacity. This will be handled // by sysadmin interface later.

SEGMENT~SIZE = (BLOCKS PER SEG*BLOCK)+QEMT Size; return; // Routine for opening an existing queue file HANDLE Open Queue File( CHAR *FileName) HANDLE Que~File~Handle; if (INVALID~HANDLE~VALUE == (Que File Handle = CreateFile(FileName, GENERIC READ(GENERIC WRITE, FILE~SHARE READIFILESSHARE~WRITE, <BR> <BR> NULL,OPEN~EXISTING, <BR> <BR> <BR> FILE ATTRIBUTE~NORMAL, NULL))) Fail("Open~Queue~File: could not open file 5 - Error = FileName,GetLastError()); return(Que File Handle); // Routine for deleting an existing queue file BOOL Delete~Queue~File( CHAR *FileName) { return (DeleteFile(FileName)); } int Find~Num~Entries( lpCNTSTR *cnt~ptr) lpCNTSTR cptr; lpQEME lpqeme; int qeme~no; int status; cptr = (CNTSTR *)malloc(sizeof(CNTSTR)); cptr->committed = 0; cptr->holey = 0; qeme~no = MQEMT->que~hd~ptr; while (qeme~no != MQEMT->que~tl~ptr) status = Cycle~QEME(qeme~no,&lpqeme); switch(lpqeme->txn~state) case COMMIT: cptr- >committed++; break; case EMPTY: cptr- >holey++; break; case ACTIVE: case PENDING: break; qeme~no = (qeme~no+1)%MQEMT->max~entries; Status = Cycle~QEME(qemeno,&lpqeme); switch(lpqeme->txn~state) case COMMIT: cptr- >committed++; break; case EMPTY: cptr->holey++; break; case ACTIVE: case PENDING: break; *cnt~ptr = cptr; return(QSUCCESS); // Find QEM entry based on MID int Find~QEME( lpMID mid, int *qeme~no2, lpQEME *lpqeme2) lpQEME lpqeme; int qeme~no; int valid = 1; int found = 0; int status; if (Check~Queue~Empty(MQEMT) == FALSE) { qeme~no = MQEMT->que~hd~ptr; status = Cycle~QEME(qeme~no,&lpqeme); while (valid && found) if ((lpqeme->mid.host == mid->host) && (lpqeme->mid.tid == mid->tid) && (lpqeme->mid.uid == mid->uid)) *qeme~no2 = qeme~no; *lpqeme2 = lpqeme; found = 1; else if (qeme no == MQEMT->que~tl~ptr) valid = 0; else qeme~no = (qeme~no+1)%MQEMT->max~entries; status = Cycle~QEME(qeme~no,&lpqeme); if (found) return(QSUCCESS); else return(QFAIL); int Cycle~QEME( int qeme~no, lpQEME *lpqeme2) lpQEME lpqeme; int i; lpqeme = MQEMT->qeme~ptr; for (i=O; i<qeme~no; i++) lpqeme++; *lpqeme2 = lpqeme; return (QSUCCESS); // Routine for determining next valid // QEM entry for a PUT given that some // entries have pending GETs.

// // Not currently used since it is expensive. Currently keeping // track of the timestamp of last // pending get operation.

// void Find~Last~Pending~Get( int *qeme~no) unsigned long latest~ts=0; lpQEME lpqeme; int latest~qeme=NIL; int qeme~no2; int status; for (qeme~no2=0; qeme~no2<MQEMT->max~entries; qeme~no2++) status = Cycle~QEME(qeme~no2,&lpqeme) if ((lpqeme->txn~state == PENDING) && (lpqeme->timestamp > latest~ts)) latest~ts = lpqeme->timestamp latest~qeme = qeme~no2; *qeme~no = latest qeme; // Routine fixes queue ptrs after aborts.

// Issues; - - might need to handle deadlock void Fix~Que~Ptrs~on~Aborted~Put ( lpQEME lpqeme, int qeme~no) HANDLE hQHD,hQTL; lpQEME lpqeme2; int qeme~no2; int status; // Protocol is to obtain hQHD first, // then hQTL.

hQHD = OpenMutex(SYNCHRONIZE,FALSE,QUE HD PTR~LOCK); if (!hQHD) Diag("QSQCommit: Can't OpenMutex for queue head pointer lock"); if ((status = WaitForSingleObject(hQHD,QUE~LOCK~TIMEOUT)) WAIT~OBJECT~0) Diag("QS~QCommit: Synch wait for queue head pointer lock failed"); hQTL = OpenMutex(SYNCHRONIZE,FALSE,QUE TL PTR LOCK); if (!hQTL) Diag("QS~QCommit: Can't OpenMutex for queue tail pointer lock"); if ((status = WaitForSingleObject(hQTL,QUE~LOCK TIMEOUT)) WAIT~OBJECT~0) Diag("QS~QCommit: Synch wait for queue tail pointer lock failled"); if (qeme~no == MQEMT->que~hd~ptr) if (MQEMT->que~hd~ptr == MQEMT->que~tl~ptr) MQEMT->que~hd~ptr = NIL; MQEMT->que~tl~ptr = NIL; else MQEMT->que~hd~ptr = (MQEMT->que~hd~ptr+1)%MQEMT->max~entries; else if (qeme no == MQEMT->que~tl~ptr) qeme~no2 = qeme~no; lpqeme2 = lpqeme; while ((lpqeme2->txn~state == EMPTY) && (qeme~no2 != MQEMT->quehdptr)) qeme~no2 = (MQEMT->max~entries+qeme~no2-1)%MQEMT->max~entries; status = Cycle~QEME(qeme~no2,&1pqeme2); if ((qeme~no2 == MQEMT->que~hd~ptr) && (lpqeme2->txn~state == EMPTY))<BR> { MQEMT->que~hd~ptr = NIL; MQEMT->que~tl~ptr = NIL;<BR> } else MQEMT->que~tl~ptr = qeme~no2; ReleaseMutex(hQTL); ReleaseMutex(hQHD); /* */ <BR> <BR> Diag("Fix~on~Aborted~Put: qeme~no = %d, head = %d, tail =<BR> <BR> qeme~no,MQEMT->que~hd~ptr,MQEMT->que~tl~ptr);<BR> ; } // Routine fixes queue ptrs after aborts.

// Use QEME timestamps for comparison.

// Issues: - - might need to handle deadlock void Fix~Que~Ptrs~on~Aborted~Get( int qeme~no) HANDLE hQHD,hQTL; lpQEME lpqeme,hd~qeme,tl~qeme; int status; hQHD = OpenMutex(SYNCHRONIZE,FALSE,QUE HD PTR LOCK); if (!hQHD) Diag("QS~QCommit: Can't OpenMutex for queue head pointer lock"); if ((status = WaitForSingleObject(hQHD,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~QCommit: Synch wait for queue head pointer lock failed"); hQTL = OpenMutex(SYNCHRONIZE,FALSE,QUE TL PTR LOCK); if (!hQTL) Diag("QS QCommit: Can't OpenMutex for queue tail pointer lock"); if ((status = WaitForSingleObject(hQTL,QUE~LOCK~TIMEOUT)) != WAIT~OBJECT~0) Diag("QS~QCommit: Synch wait for queue tail pointer lock failed"); if (MQEMT->que~hd~ptr == NIL) MQEMT->que~hd~ptr = qeme~no; <BR> MQEMT->que~tl~ptr = qeme~no;<BR> } else status = Cycle~QEME(qeme~no,&lpqeme); status = CycleZQEME(MQEMT-sque hd~ptr,&hd qeme); status = Cycle~QEME(MQEMT-sque-tl~ptr,&tl-qeme); if (lpqeme->timestamp < hd~qeme->timestamp) MQEMT->que~hd~ptr = qeme~no; else if (lpqeme->timestamp > tlqeme->timestamp) MQEMT->que~tl~ptr = qeme~no; ReleaseMutex(hQTL); ReleaseMutex(hQHD); /* */ Diag("Fix~on~Aborted~Get: qeme~no = %d, head = %d, tail = qeme~no,MQEMT->que~hd~ptr,MQEMT->que~tl~ptr); // Routine for fetching next // valid GET QEM entry slot.

// Not currently used.

int Fetch~Next~Get~Slot( int *qeme~no) lpQEME lpqeme; int done=0; int found=0; int qeme~no2; int status; qeme~no2 = MQEMT->que~hd~ptr; while (!done && found) status = Cycle~QEME(qeme~no2,&lpqeme) if ((lpqeme->mode == PUT MODE) && (lpqeme->txn~state == COMMIT)) *qeme no = qeme~no2; found = 1; else if (qeme~no2 == MQEMT->que~tl~ptr) done = 1; else qeme~no2 = (qeme~no2+1)%MQEMT->max~entries; if (found) return(QSUCCESS); else return(QFAIL); // Routine for fetching next // valid PUT QEM entry slot.

// Not currently used.

int Fetch~Next~Put~Slot( int *qeme~no) lpQEME lpqeme; int done=0; int found=0; int qeme~no2; int status; qeme~no2 = MQEMT->que~tl~ptr; while (!done) { status = Cycle~QEME(qeme~no2,&lpqeme); if (lpqeme->txn~state == EMPTY) *qeme~no = qeme~no2; found = 1; else if (qeme~no2 == MQEMT->que~hd~ptr) done = 1; else qeme~no2 = (qeme~no2+1)WMQEMT->max~entries; if (found) return(QSUCCESS); else return(QFAIL); // Routine for resetting QEME timestamps // starting from 1 after after recovery or // at queue server shutdown. Point is to // guide against timestamp ever exceeding // the max of an unsigned long.

void Update~QEME~TS() HANDLE hQEME; lpQEME lpqeme; int status; int qeme~no; int done=0; hQEME = OpenMutex(SYNCHRONIZE,FALSE,QEME TS GEN LOCK); if (!hQEME) Diag("Update~QEME TS: Can't OpenMutex for QEME~TS Lock"); if ((status = WaitForSingleObject(hQEME,QUE~LOCK~TIMEOUT)) != WAIT OBJECT~0) Diag("Update~QEME~TS: Synch wait for QEME~TS Lock failed"); QEME~TS = 1; qeme~no = MQEMT->que~hd~ptr; while (!done) status = Cycle~QEME(qeme~no,&lpqeme); lpqeme->timestamp = QEME~TS++; if(qeme~no == MQEMT->que~tl~ptr) done = 1; else qeme~no = (qeme~no+1)%MQEMT->max~entries; ReleaseMutex(hQEME); // Routine for finding most current // QEM Table in queue data file.

int Find~Latest~QEM( HANDLE Que~File~Handle, lpQEMT *lpqemt2, int *seg~num) lpQEMT lpqemt; lpQEME lpqeme; lpRST lprst; lpRSTSEG lprstseg; lpPTLIST ptl~ptr; BOOL Return~Status; DWORD dwPointer; DWORD dwBytesRead; SN curr~qem~sn; SN prev~qem~sn; int tseq~no=0; int done=0,i; int elems~per~seg; curr~qem~sn.timestamp = 0; curr~qem~sn.counter = 0; prev~oem~sn.timestamp = 0; prev~qem~sn.counter = 0; lpqemt = (QEMT *)malloc(sizeof(QEMT)); dwPointer = SetFilePointer(Que~File~Handle, O,NULL,FILE~BEGIN); if (!(Return~Status = ReadFile(Que File Handle,lpqemt, sizeof(QEMT),&dwBytesRead,NULL))) Fail("Find~Latest~QEM: could not read QEMT buffer - Error = GetLastError()); curr~qem~sn.timestamp = lpqemt->qem~sn. timestamp; curr~qem~sn.counter = lpqemt->qem~sn.counter; NUM~SEGS = lpqemt->num~segs; MAX~ELMS = lpqemt->max~entries; tseq~no++; elems~per~seg = (int)ceil((double)(MAX~ELMS/NUM~SEGS)); Update~Globals(); lpqeme = (QEME *)malloc(MAX~ELMS*sizeof(QEME)); lprst = (RST *)malloc(sizeof(RST)); lprstseg = (RSTSEG *)malloc(NUM SEGS*sizeof(RSTSEG)); lprst->num~segs = NUM~SEGS; lprst->msgs~per~seg = elems~per~seg; lprst->seg~ptr = lprstseg; for (i=O; i<NUM~SEGS; i++) lprstseg->seg~no = i; lprstseg->msg~block= (int *)malloc(elems~per~seg*sizeof(int)); lprstseg++; ptl~ptr = (PTLIST *)malloc(MAX~ELMS*sizeof(PTLIST)); while (!done) { dwPointer = SetFilePointer(Que~File~Handle, tseq~no*SEGMENT~SIZE, NULL, FILE~BEGIN) if (!(Return~Status = ReadFile(Que File Handle,lpqemt, sizeof(QEMT),&dwBytesRead,NULL))) Fail("Find~Latest~QEM: could not read QEMT buffer - Error = GetLastError ()); if ((lpqemt->marker == QEMTMARK) && Bigger Seq~No(&lpqemt->qem~sn,&curr qem sn)) prev~qem~sn.timestamp = curr~qem~sn.timestamp; prev~qem~sn.counter = curr~qem~sn.counter; curr~qem~sn.timestamp = lpqemt->qem~sn.timestamp; curr~qem~sn.counter = lpqemt->qem~sn.counter; tseq~no = (tseq~no+1)%NUM~SEGS; else done = 1; tseq~no = (NUM~SEGS+tseq no-1)%NUM SEGS; pointer = SetFilePointer(Que File Handle, tseqno*SEGMENT SIZE, NULL,FILE~BEGIN); if (!(Return~Status = ReadFile(Que~File~Handle,lpqemt, sizeof(QEMT),&dwBytesRead,NULL))) Fail("Find~Latest~QEM: could not read QEMT buffer - Error = GetLastError()); if (!(Return~Status = ReadFile(Que~File Handle,lpqeme, MAX~ELMS*sizeof(QEME), &dwBytesRead,NULL))) Fail("Find~Latest~QEM: could not read QEME buffer - Error = GetLastError()); if (!(Return Status = ReadFile(Que~File Handle,lprst, sizeof(RST),&dwBytesRead,NULL))) Fail("Find~Latest~QEM: could not read in RST structure - Error = GetLastError()); lprstseg = lprst->seg ptr; for (i=0; i<lprst->num~segs; i++) if (!(Return~Status = ReadFile(Que File~Handle, lprstseg,sizeof(RSTSEG) &dwBytesRead,NULL))) Fail("Find~Latest~QEM: could not read in RSTSEG structure - Error = GetLastError()); if (!(Return~Status = ReadFile(Que~File~Handle, lprstseg- >msgblock, <BR> <BR> <BR> <BR> lprst->msgs~per~seg*sizeof(int), &dwBytesRead,NULL))) Fail("Find~Latest~QEM: could not read in msg~block entries - Error GetLastError()); lprstseg++; if (!(Return~Status = ReadFile(Que~File~Handle,ptl~ptr, MAX~ELMS*sizeof(PTLIST), &dwBytesRead,NULL))) Fail("Find~Latest~QEM: could not read PTLIST buffer - Error = GetLastError()); lpqemt->qeme~ptr = lpqeme; lpqemt->rst~ptr = lprst; lpqemt->ptl~ptr = ptl~ptr; *lpqemt2 = lpqemt; *seg~num = tseq~no; return(QSUCCESS); int Create~QEMT( lpQEMT *lpqemt, int max~elms) { lpQEMT lpqemt2; lpRSTSEG lprstseg; int i,elems~per~seg; elems~per~seg = (int)ceil((double)(MAX~ELMS/NUM~SEGS)); lpqemt2 = (QEMT *)malloc(sizeof(QEMT)); lpqemt2->qemeptr = (QEME *)malloc(max~elms*sizeof(QEME)); lpqemt2->rst~ptr = (RST *)malloc(sizeof(RST)); lpqemt2->rst~ptr->seg~ptr = (RSTSEG *)malloc(NUM~SEGS*sizeof(RSTSEG)); lpqemt2->rst~ptr->num~segs = NUM~SEGS; lpqemt2->rst~ptr->msgs~per~seg = elems~per~seg; lprstseg = lpqemt2->rst~ptr->seg~ptr; for (i=0; i<NUM~SEGS; i++) lprstseg->seg~no = i; lprstseg->msg~block = (int *)malloc(elems per seg*sizeof(int)); lprstseg++; lpqemt2->ptl~ptr = (PTLIST *)malloc(max~elms*sizeof(PTLIST)); *lpqemt = lpqemt2; return(QSUCCESS); int Init~QEMT( lpQEMT lpqemt, int max elms, int ext~elms, int num~segs) lpQEMT lpqemt2; lpQEME lpqeme; lpPTLIST ptl~ptr; lpRSTSEG lprstseg; int *msg~block; int i,j; lpqemt2 = lpqemt; Gen QEM Seq No(&lpqemt2-sqem sn); lpqemt2->marker = QEMTMARK; lpqemt2->num~segs = num~segs; lpqemt2->max~entries = max elms; lpqemt2->max~entries limit = max~elms+ext~elms; lpqemt2->next avail block.segment = 0; Ipqemt2->next-avail-block.block = 0; lpqemt2->que~hd~ptr = NIL; lpqemt2->que~tl~ptr = NIL; lpqemt2->qget~state = ENABLED; lpqemt2->qput~state = ENABLED; lpqeme = lpqemt2->qeme~ptr; for (i=0; i<lpqemt2->max~entries; i++) lpqeme->index = i; lpqeme->timestamp = 0; lpqeme->mid.host = 0; lpqeme->mid.tid = 0; lpqeme->mid.uid = 0; lpqeme->mode = 0; lpqeme->flags = 0; lpqeme->priority = 0; lpqeme->txn~state = EMPTY; lpqeme->vote = 0; lpqeme->offset.segment = 0; lpqeme->offset.block = 0; lpqeme++; lprstseg = lpqemt2->rst~ptr->seg~ptr; for (i=0; i<NUM~SEGS; i++) { msg~block = lprstseg->msg~block; for (j=O; j<lpqemt2->rst~ptr->msgs~per~seg; j++) *msg~block = NIL; msg~block++; lprstseg++; lpqemt2->num~pts = 0; ptl~ptr = lpqemt2->ptl~ptr; for (i=O; i<lpqemt2->max~entries; i++) ptl~ptr->mid.host = 0; ptl~ptr->mid.tid = 0; ptl~ptr->qeme~no = NIL; ptl~ptr++; return(QSUCCESS); int Write~QEMT( HANDLE Que File Handle, int seg~no, lpQEMT lpqemt) lpRSTSEG lprstseg; BOOL Return~Status; DWORD dwPointer; DWORD dwBytesWritten; int status; int i; status = Gen~LREC~Seq~No (&lpqemt->lrec~sn); Conv from MTlist(); dwPointer = SetFilePointer(Que~File~Handle, (LONG)(seg no*SEGMENT SIZE), NULL,FILE~BEGIN); if (!(Return~Status = WriteFile(Que~File~Handle,lpqemt,sizeof(QEMT), &dwByteswritten,NULL))) Fail("Write~QEMT: could not write out QEM Table - Error = GetLastError()); if (!(Return~Status = WriteFile(Que~File~Handle,lpqemt->qeme~ptr, lpqemt->max~entries*sizeof(QEME), &dwBytesWritten,NULL))) Fail("Write~QEMT: could not write out QEM entries - Error = GetLastError()); if (!(Return~Status = WriteFile(Que~File~Handle, lpqemt->rst~ptr, sizeof (RST) &dwBytesWritten,NULL))) Fail("Write~QEMT: could not write out RST structure - Error = GetLastError ()); lprstseg = lpqemt->rst~ptr->seg~ptr; for (i=O; i<lpqemt->rst~ptr->num~segs; i++) if (!(Return~Status = WriteFile(Que~File~Handle, lprstseg, sizeof (RSTSEG) &dwBytesWritten,NULL))) Fail("Write~QEMT: could not write out RSTSEG-structure - Error = GetLastError()); if (!(Return~Status = WriteFile(Que~File~Handle, lprstseg- >msgblock, lpqemt->rst~ptr->msgs~per~seg*sizeof(int) &dwBytesWritten,NULL))) Fail("Write~QEMT: could not write out msg block entries - Error = GetLastError ()); lprstseg++; if (!(Return~Status = WriteFile(Que~File~Handle, lpqemt->ptl~ptr,lpqemt->num~pts*sizeof(PTLIST), &dwBytesWritten,NULL))) Fail("Write~QEMT: could not write out PT list - Error = %d", GetLastError()); // Now, write out the most current log record timestamp.

return(QSUCCESS); int Retrieve~QEMT( HANDLE Que~File~Handle, int seg~no, lpQEMT *lpqemt2) lpQEMT lpqemt; lpQEME lpqeme; lpRST lprst; lpRSTSEG lprstseg; lpPTLIST ptl~ptr; BOOL Return~Status; DWORD dwPointer; DWORD dwBytesRead; int elems~per~seg; int i; elems~per~seg = (int)ceil((double)(MAX~ELMS/NUM SEGS)); lpqemt = (QEMT *)malloc(sizeof(QEMT)); lpqeme = (QEME *)malloc(MAX ELMS*sizeof(QEME)); lprst = (RST *)malloc(sizeof(RST)); lprstseg = (RSTSEG *)malloc(NUM~SEGS*sizeof(RSTSEG)); lprst->num~segs = NUM~SEGS; lprst->msgs~per~seg = elems~per~seg; lprstseg = lprst->segptr for (i=O; i<NUM~SEGS; i++) lprstseg->seg~no = i; lprstseg->msg~block = (int *)malloc(elems~per seg*sizeof(int)); lprstseg++; ptlptr = (PTLIST *)malloc(MAX~ELMS*sizeof(PTLIST)); pointer = SetFilePointer(Que~File~Handle, (LONG) (seg~no*SEGMENT~SIZE), NULL,FILE~BEGIN); if (!(Return~Status = ReadFile(Que~File~Handle,lpqemt, sizeof(QEMT),&dwBytesRead,NULL))) Fail("Retrieve~QEMT: could not read QEMT Table - Error = GetLastError ()) if (!(Return Status = ReadFile(Que~File~Handle,lpqeme, lpqemt->max~entries*sizeof(QEME), &dwBytesRead,NULL))) Fail("Retrieve~QEMT: could not read QEME entries - Error = GetLastError()); if (!(Return~Status = ReadFile(Que~File~Handle,lprst, sizeof(RST),&dwBytesRead,NULL))) Fail("Write~QEMT: could not write out RST structure - Error = GetLastError()); lprstseg = lprst->segptr for (i=0; i<lprst->num~segs; i++) if (!(Return~Status = ReadFile(Que~File~Handle, lprstseg, sizeof (RSTSEG), &dwBytesRead,NULL))) Fail("Write~QEMT: could not write out RSTSEG structure - Error = GetLastError()); if (!(Return~Status = ReadFile(Que~File~Handle, lprstseg->msg~block, <BR> Iprst->msgs per seg*sizeof(int), <BR> <BR> <BR> <BR> <BR> &dwBytesRead,NULL))) Fail("Write~QEMT: could not write out msg~block entries - Error = GetLastError()); lprstseg++; if (!(Return~Status = ReadFile(Que~File~Handle,ptl~ptr, lpqemt->num~pts*sizeof(PTLIST), &dwBytesRead,NULL))) Fail("Retrieve~QEMT: could not read PT list - Error = GetLastError()); lpqemt->qeme~ptr = lpqeme; lpqemt->rstptr = lprst; lpqemt->ptl~ptr = ptl~ptr; *lpqemt2 = lpqemt; // Conv~to~MTlist(); return(QSUCCESS); int Retrieve~Msg~Hdr( HANDLE Que File Handle, BLAD Msg~Addr, lpMSGH Msg~Hdr) BOOL Return~Status; DWORD dwBytesRead; DWORD dwPointer; LONG Dist to Move; Conv~Addr(&Dist~to~Move,&Msg~Addr); dwPointer = SetFilePointer(Que~File~Handle, Dist to Move, NULL, FILE~BEGIN); Return~Status = ReadFile(Que~File~Handle, Msg~Hdr, MSG~HDR~SIZE, &dwBytesRead, NULL); if ((Return~Status == TRUE) && (dwBytesRead == MSG~HDR~SIZE)) return(QSUCCESS); else return(QFAIL); int Write~Msg~Hdr( HANDLE Que File Handle, BLAD Msg~Addr, lpMSGH Msg~Hdr) BOOL Return~Status; DWORD dwBytesWritten; DWORD pointer; LONG Dist~to~Move; Conv~Addr(&Dist~to~Move,&Msg~Addr); dwPointer = SetFilePointer(Que~File~Handle, Dist~to~Move, NULL, FILE~BEGIN); Return~Status = WriteFile(Que~File~Handle, Msg~Hdr, MSG~HDR~SIZE, &dwBytesWritten, NULL); if ((Return~Status == TRUE) && (dwBytesWritten == ==- MSG~HDR~SIZE)) return(QSUCCESS); else return(QFAIL); int Retrieve~Msg~Body( HANDLE Que~File~Handle, BLAD Msg~Addr, DWORD Msg~Length, CHAR *Msg~Body) BOOL Return~Status; LONG Dist~to~Move; DWORD dwBytesRead; DWORD dwPointer; Conv~Addr(&Dist~to~Move,&Msg~Addr); pointer = SetFilePointer(Que~File~Handle, Dist~to~Move, NULL, FILE~BEGIN); Return~Status = ReadFile(Que~File~Handle, Msg~Body, Msg~Length, &dwBytesRead, NULL); if ((Return~Status == TRUE) && (dwBytesRead == Msg~Length)) return(QSUCCESS); else return(QFAIL); int Write~Msg~Body( HANDLE Que~File~Handle, BLAD Msg~Addr, DWORD Msg~Length, CHAR *Msg~Body) BOOL Return~Status; LONG Dist~to~Move; DWORD dwBytesWritten; DWORD dwPointer; Conv~Addr(&Dist~to~Move,&Msg~Addr); pointer = SetFilePointer(Que File Handle, Dist~to~Move, NULL, FILE~BEGIN); Return Status = WriteFile(Que~File~Handle, Msg~Body, Msg~Length, &dwBytesWritten, NULL); if ((Return~Status == TRUE) && (dwBytesWritten == Msg~Length)) return(QSUCCESS); else return(QFAIL); int Retrieve Msg( HANDLE Que~File~Handle, BLAD Msg~Addr, lpQMSG qmsg) BOOL Return~Status; LONG Dist~to~Move; DWORD dwBytesRead; DWORD dwPointer; Conv~Addr(&Dist~to~Move,&Msg~Addr); pointer = SetFilepointer(Que File Handle, Dist to Move, NULL,FILE~BEGIN); Return~Status = ReadFile(Que~File~Handle, qmsg, sizeof (QMSG), &dwBytesRead,NULL); if ((Return~Status == TRUE) && (dwBytesRead == sizeof(QMSG))) return(QSUCCESS); else return(QFAIL); int Retrieve~Log~Rec( HANDLE Que File Handle, BLAD LREC~Addr, lpLREC LREC~ptr) BOOL Return~Status; DWORD dwBytesRead; LONG Dist~to~Move; DWORD dwPointer; Conv~Addr(&Dist~to~Move,&LREC~Addr); pointer = SetFilePointer(Que~File~Handle, Dist~to~Move, NULL, FILE~BEGIN); Return~Status = ReadFile(Que File Handle, LREC~ptr, LOG~REC~BLOCKS*BLOCK, &dwBytesRead, NULL); if ((Return~Status == TRUE) && (dwBytesRead == (LOG~REC~BLOCKS*BLOCK))) return(QSUCCESS); else return(QFAIL); int Write~Log~Rec( HANDLE Que~File~Handle, BLAD LREC~Addr, lpLREC LREC~ptr) BOOL Return~Status; DWORD dwBytesWritten; DWORD dwPointer; LONG Dist~to~Move; Conv~Addr(&Dist~to~Move,&LREC~Addr); dwPointer = SetFilePointer(Que~File~Handle, Dist to Move, NULL, FILE~BEGIN); Return~Status = WriteFile(Que~File~Handle, LREC~ptr, LOG~REC~BLOCKS*BLOCK, &dwBytesWritten, NULL); if (Return~Status == FALSE) Diag("Error Code = %d",GetLastError()); if ((Return~Status == TRUE) && (dwBytesWritten == (LOG~REC~BLOCKS*BLOCK))) return(QSUCCESS); else return(QFAIL); void Init~Active~LREC~List() { int i; int *address; address = Active~LREC~List->address for (i=O; i<Active~LREC~List->max~txns~per~seg; i++) *address = NIL; address++; int msg~entry~comp( const void *argl, const void *arg2) if (*(int*)argl < *(int*)arg2) return(-1); else if (*(int*)argl == *(int*)arg2) return(0); else if (*(int*)argl > *(int*)arg2) return(l); void Sort~RST~Entries( int seg~no) lpRSTSEG lprstseg; int i; lprstseg = MQEMT->rst~ptr->seg~ptr; for (i=0; i<seg~no; i++) lprstseg++; qsort((void *)lprstseg->msg~block, (size~t)MQEMT->rst~ptr->msgs~per~seg, sizeof(int),msg~entry~comp); int Add~RST~Entry( int seg~no, int entryvalue) lpRSTSEG lprstseg; int found=0; int i=O; int *msg~block; lprstseg = MQEMT->rst~ptr->seg~ptr; for (i=O; i<seg~no; i++) lprstseg++; msg~block = lprstseg->msg~block; while (!found && (i < MQEMT->rst~ptr->msgs~per~seg)) { if (*msg~block == NIL) found = 1; else { i++; msg~block++; } if (found) *msg~block = entry~value; return(found); int Del~RST~Entry( int seg~no, int entry~value) lpRSTSEG lprstseg; int found=0; int i; int *msg~block; lprstseg = MQEMT->rst~ptr->seg~ptr; for (i=0; i<seg~no; i++) lprstseg++;<BR> i = 0; msg~block = lprstseg->msgblock while (!found && (i < MQEMT->rst~ptr->msgs~per~seg)) { if (*msg~block == entry~value) found = 1; else <BR> <BR> <BR> <BR> <BR> <BR> {. <BR> <BR> <BR> <P> msg~block++; if (found) *msg~block = NIL; return(found); int Entry~in~RST( int seg~no, int entry~value) lpRSTSEG lprstseg; int found=0; int i=O; int *msg~block; lprstseg = MQEMT->rst~ptr->seg~ptr; for (i=O; icseg~no; i++) lprstseg++; msg~block = lprstseg->msg~block; while (!found && (i < MQEMT->rst~ptr->msgs~per~seg)) if (*msg~block == entry~value) found = 1; else ( i++; msg block++; return(found); int log~entry~comp( const void *argl, const void *arg2) { if (*(int*)arg1 < *(int*)arg2; return(1); else if (*(int*)argl == *(int*)arg2) return(0); else if (*(int*)argl > *(int*)arg2) return(-1); } void Sort~Log~Entries() { qsort((void *)Active~LREC~List->address, (size~t) Active~LREC~List->max~txns~per~seg, sizeof(int),log~entry~comp);<BR> } int Add~Log~Entry( int entry~value) int found=0; int i=O; int *address; address = Active~LREC~List->address while (!found && (i<Active LREC List->max txns~per~seg)) if (*address == NIL) found = 1; else i++; address++; if (found) *address = entry~value; return(found); int Del~Log~Entry( int entry~value) int found=0; int i=0; int *address; address = Active~LREC~List->address while (!found && (i<Active LREC List->max txns~per seg)) if (*address == entry~value) found = 1; else i++; address++; if (found) *address = NIL; return(found); int In~Log~Rec~List( int start, int end, int *hit) int found=0; int i=O; int *address; address = Active~LREC~List->address while (!found && (i<Active~LREC List->max txns~per~seg) && (*address != NIL)) if ((*address >= start) && (*address <= end)) *hit = *address; found = 1; else { i++; address++; } return(found); int Cycle~RST~Seg( int seg~no, lpRSTSEG *lprstseg2) lpRSTSEG lprstseg; int i; lprstseg = MQEMT->rst~ptr->seg~ptr; for (i=O; ieseg~no; i++) lprstseg++; *lprstseg2 = lprstseg; return (QSUCCESS); int Get~Next~BLAD( HANDLE Que~File~Handle, int type, BLAD *offset) { lpRSTSEG lprstseg; int end=0; int found=0; int notfull=1; int moved=0; int cycled=0; int start=l; int holes=0; int status; int conflict; int *msg~block,*msg~block2; int msg~num; int curr~block; int orig~seg, curr~seg; int blocks~needed; if (type == MSG~WRITE) blocks~needed = MSG~ENTRY~BLOCKS; else blocks~needed - LOG~REC~BLOCKS; orig~seg = MQEMT->next~avail~block.segment; curr~seg = MQEMT->next avail block.segment; curr~block = MQEMT->next~avail~block.block; status = Cycle~RST~Seg(curr~seg,&lprstseg); msg~num = 0; msg~block = lprstseg->msg~block; msg~block2 = msg~block; msg~block2++; while (notfull && found) while ((msg~num < MQEMT->rst~ptr->msgs~per~seg) && (*msg~block == NIL)) msg~num++; msg~block++; holes++; } <BR> <BR> <BR> /*<BR> Diag("segment = %d, curr~block = %d, msg~block = %d, msg~block2 = %d, msg~n<BR> <BR> <BR> */ if (msg~num == MQEMT->rst~ptr~>msgs~per~seg) { if (moved) curr~block = 0; if ((curr~block+blocks~needed) > BLOCKS~PER~SEG) end = 1; else while (!found && ((curr~block+blocks~needed) <= BLOCKS~PER~SEG)) if (!In Log Rec List(curr block, curr~block+blocks~needed, &conflict)) found = 1; else curr block = conflict+l; if (!found) end = 1; if (msg~num == (MQEMT->rst~ptr->msgs~per~seg-1)) if (moved) curr~block = 0; while (!found && ((curr~block+blocks~needed) <= *msg~block)) if (!In~Log~Rec List(curr block, - currrblock+blocks~needed, &conflict)) found = 1; else curr block = conflict+l; if (!found) curr~block = *msg~block+MSG~ENTRY~BLOCKS; while (!found && ((curr~block+blocks~needed) <= BLOCKS~PER~SEG)) if (!In~Log Rec List(curr block, curr~block+blocks~needed, <BR> <BR> <BR> <BR> &conflict)) found = 1; else curr~block = conflict+1; if (!found) end = 1; if (msg~num < (MQEMT->rst~ptr->msgs~per~seg-l)) if (moved) curr~block = 0; msg~block2 = msg~block; msg~block2++; while (!found && (msg~num < (MQEMT->rst~ptr->msgs~per~seg-1))) if (moved && start) while (!found && ((curr~block+blocks~needed) <= *msg~block)) { if (!In~Log~Rec~List(curr~block, <BR> <BR> curr~block+blocks~needed, <BR> <BR> <BR> <BR> &conflict)) found = 1; else curr~block = conflict+l; start = 0; if (!found) curr~block = *msg~block+MSG~ENTRY~BLOCKS; while (!found && ((curr~block+blocks~needed) <= *msg~block2)) if (!In~Log~Rec List(curr block, curr~block+blocks~needed, &conflict)) found = 1; else curr block = conflict+l; if (!found) msg~num++; msg~block++; if (msg~num < (MQEMT->rst~ptr->msgs~per~seg-1)) msg~block2 = msg~block; msg~block2++; else curr~block = *msg~block+MSG~ENTRY~BLOCKS; while (!found && ((curr~block+blocks~needed) <= BLOCKS~PER~SEG)) if (!In~Log~Rec~List(curr block, curr~block+blocks~needed, &conflict)) found = 1; else curr~blo#k = conflict+l; // end while if (!found) end = 1; if (end) moved = 1; start = 1; if (cycled) notfull = 0; else curr~seg = (curr~seg+1)%MQEMT->num~segs; if (!cycled) if (curr~seg == orig~seg) cycled = 1; // Flush out QEMT and zero out // active log record list.

MQEMT->next avail block.segment = (MQEMT->next~avail~block.segment+1)%MQEMT->num~segs; curr~block = 0; MQEMT->next avail block block = 0.

MQEMT->next~avail~block.block = 0; status = Gen~QEM~Seq~No(&(MQEMT->qem~sn)); status = Write~QEMT(Que~File~Handle, MQEMT->next~avail~block.segment, MQEMT); Init~Active~LREC~List(); status = Cycle~RST~Seg(curr~seg,&lprstseg); msg~num = 0; msg~block = lprstseg->msg~block; msg~block2 = msg~block; msg~block2++; end = 0; ) // end if (end) } // while (notfull && found) if (found) { /* Diag("Allocated Space: segment = %d, block = %d", curr~seg, curr~block); */ offset->segment = MQEMT->next~avail~block.segment; offset->block = curr~block; MQEMT->next~avail~block.block = curr~block + blocks~needed; holey~entries = 0; if (type == MSG~WRITE) if (!Add~RST~Entry(offset->segment,offset->block)) notfull = 0; else Sort RST Entries(offset-ssegment); else if (type == LOG~WRITE) if (!Add~Log~Entry(offset->block)) <BR> <BR> <BR> notfull = 0;<BR> else Sort~Log~Entries(offset->segment); else { holey~entries = holes; offset->segment = NIL; offset->block = NIL; return(notfull); BOOL Check~Queue~Full( lpQEMT lpqemt) lpQEME lpqeme; BOOL Full=TRUE; int status; int cnt; if (lpqemt->que~hd~ptr == NIL) Full = FALSE; else if (((lpqemt->que~tl~ptr+1)%lpqemt->max~entries) == lpqemt->que~hd~ptr) status = Cycle~QEME(lpqemt->que~hd~ptr,&lpqeme); if (lpqeme->txn~state == EMPTY) Full = FALSE; } else { lpqeme = lpqemt->qeme~ptr; cnt = 0; while (Full && (cnt < lpqemt->max~entries)) if (lpqeme->txn~state == EMPTY) Full = FALSE; else cnt++; <BR> <BR> lpqeme++; <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> return(Full); BOOL Check Queue Empty( lpQEMT lpqemt) if (lpqemt->que~hd~ptr == NIL) return(TRUE); else return(FALSE); void Conv from MTlist() lpPTLIST pl,p2; lpTLIST tl; lpMTLIST ml; int cnt = 0; pl = (PTLIST *)malloc(MQEMT->max~entries*sizeof(PTLIST)); ml = Pending~TXNs; p2 = pl; while (ml != NULL) { tl = ml->ops while (tl != NULL) p2->mid = ml->mid p2->qeme~no = tl->qemeno cnt++; p2++; tl = tl->next ml = ml->next MQEMT->ptl~ptr = p1; MQEMT->num~pts = cnt; void Conv to MTlist() lpPTLIST pl; lpMTLIST ml; lpTLIST tl; MID tmid; int cnt; Pending~TXNs = NULL; pl = MQEMT->ptl~ptr; cnt = 1; while (cnt <= MQEMT->num~pts) tmid = pl->mid Add MTlist(&Pending TXNs,&ml,pl->mid); tl = ml->ops while ((cnt <= MQEMT->num~pts) && (pl->mid.host == tmid.host) && (pl->mid.tid == tmid.tid)) Add~Tlist(&tl,pl->qeme~no); pl++; cnt++; ml->ops = tl; Pending~TXNs = ml; void Add~Tlist( lpTLIST *head, int qeme~no) {<BR> lpTLIST curr,prev; lpTLIST new.

lpTLIST new; new = (TLIST *)malloc(sizeof(TLIST)); new->qeme~no = qeme~no; new->next = NULL; curr = *head; prev = curr; while (curr != NULL) { prev = curr; curr = curr->next curr = curr->next if (prev == NULL) <BR> <BR> *head = new;<BR> else prev->next = new; void Add MTlist( lpMTLIST *head, lpMTLIST *tail, MID mid) lpMTLIST curr,prev; lpMTLIST new; new = (MTLIST *)malloc(sizeof(MTLIST)); new->mid = mid; new->ops = NULL; new->next = NULL; *tail = new; curr = *head; prev = curr; while (curr != NULL) prev = curr; curr = curr->next if (prev == NULL) *head = new; else prev->next = new; BOOL Find MTlist( lpMTLIST head, lpMTLIST *pres, MID mid) lpMTLIST curr; int found = 0; curr = head; while ((curr != NULL) && !found) { if ((curr->mid.host == mid.host) && (curr->mid.tid == mid.tid)) found = 1; else curr = curr->next if (found) *pres = curr; return (TRUE); else *pres = NULL; return(FALSE); BOOL Find~Tlist( lpTLIST head, int qeme~no) lpTLIST curr; int found = 0; curr = head; while ((curr != NULL) && found) if (curr->qeme~no == qeme~no) found = 1; else curr = curr->next if (found) return (TRUE); else return(FALSE); void Del~MTlist~All( lpMTLIST *head) lpMTLIST curr, prev; BOOL Return~Status; curr = *head; *head = NULL; while (curr != NULL) { prev = curr; curr = curr->next prev->next = NULL; Del~Tlist(&prev->ops); free (prev) if (Return~Status == FALSE) Diag("Del~MTlist~All: Problem with freeing memory."); BOOL Del~MTlist( lpMTLIST *head, MID mid) lpMTLIST curr, prev; int found = 0; BOOL Return~Status; curr = *head; prev = curr; while ((curr != NULL) && found) if ((curr->mid.host == mid.host) && (curr->mid.tid == mid.tid)) found = 1; else prev = curr; curr = curr->next if (found) Del~Tlist (&curr->ops); if (curr == prev) *head = curr->next else if (curr->next == NULL) prev->next = NULL; else prev->next = curr->next curr->next = NULL; free(curr) if (Return Status == FALSE) Diag("DeT~MTlist: Problem with freeing memory..."); return (TRUE); else return(FALSE); void Del~Tlist( lpTLIST *head) lpTLIST curr,prev; BOOL Return~Status; curr = *head; while (curr != NULL) prev = curr; curr = curr->next prev->next = NULL; free (prev) if (Return~Status == FALSE) <BR> <BR> Diag("Del Tlist: Problem with freeing memory. <BR> <P> *head = NULL; void Sub~Addr LONG *diff, BLAD *x, BLAD *y) *diff = (LONG) (((y->segment-x->segment)*SEGMENT~SIZE)+ QEMT Size+(y->block-x->block)*BLOCK) ; void Conv Addr LONG - *diff, BLAD *x) <BR> <BR> <BR> <BR> {<BR> *diff = (LONG) ( (x->segment*SEGMENT~SIZE)+QEMT~Size+(x->block*BLOCK)); <BR> }<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> int Gen~QEM~Seq~No( lpSN tSeq~No) long temp; // Generate unique QEMT sequence // number based on system time // and unique counter.

temp = time(&tSeq~No->timestamp); tSeq~No->counter = QEMTSeq~No++; return(QSUCCESS); int Gen~LREC~Seq~No( lpSN tSeq~No) long temp; // Generate unique LREC sequence // number based on date and time.

temp = time(&tSeq~No->timestamp); tSeq~No->counter = LREC~Seq~No++; return(QSUCCESS); int Gen~QEME~TS( unsigned long *tSeq~No) // Generate unique QEMT sequence // number based on date and time.

*tSeq~No = QEME~TS++; return (QSUCCESS) BOOL Bigger~Seq~No( lpSN seq~no1, lpSN seq~no2) if ((seq~no1->timestamp > seq~no2->timestamp) || ((sec~no1->timestamp == seq~no2->timestamp) && (seq~nol->counter > seq~no2->counter))) return (TRUE); else return(FALSE); ** Copyright (C) 1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: qnetd.c ** Author: Derek Schwenke 9/8/95 ** */ #include "qlib.h" #include "qnetd.h" // This thread listens on each Buffer that QNETD owns.

// Resurve a buffer // Wait For READY // Read the message void QnetdAdminRequest(lpSMBUF buf) char *p = buf->mdata int i; switch (buf->msgh. submode) case QNETD~TRAN~INQ: buf->msgh.sub~mode = ResolveTran(&buf->msgh.mid); break; case QNETD~RT~BROADCAST: Warn("QnetdAdminRequest: RT Broadcast not implemented"); break; case QNETD~BUF~STATUS: sprintf(p,"QNETD status for %p\n",SHAREDATA(hostip)); p = p + strlen(p); for(i=0;i<SHAREDATA(nsbuf);i++) lpSMBUF b = SMBUFADDR(i); sprintf (p, "%d: %d %s\n",i,b->status,b->name); p = p + strlen(p); break; default: Warn("QnetdAdminRequest: undefined sub~type of request (%d)", buf->msgh.sub~mode); DWORD ListenSMBuff() lpSMBUF buf; int stat,pass,bnum,rtn; SMOBJS sync; define MAXPASS 1 /* 1 Attempt to send on the socket */ Sleep(1000); // Wait for others to init, no real reason // Reserve a buffer Diag("ListenSMBuff[-]: Calling ReserveSharedBuffer"); bnum = ReserveSharedBuffer(0,"QNETD",SMBUF~EMPTY,&sync); buf = SMBUFADDR(bnum); while (1) stat = 0; // Wait for a message Diag("ListenSMBuff[%d]: Waiting for buffer ready",bnum); if ((rtn = WaitForSingleObject(sync.readyh,INFINITE)) == WAIT~FAILED Fail("ListenSMBuff[%d]. Failed while waiting for the buffer ready %d 4% // Sanity check the buffer if (buf->status != SMBUF SEND~MESS) { Warn("ListenSMBuff[%d]: Buffer status was wrong! %d",bnum,buf->status); // Read the message Diag("ListenSMBuff[%d]: got:%s", bnum,buf->mdata); pass = 0; if (SHAREDATA(hostip) != buf->msgh.to~node){ // Not local while(pass++ < MAXPASS ) I // Make N trys to send the message if (SendRemoteMess(buf,0)) { if (buf->msgh.mode != ADMINREQ~MODE) // Admin req's may fail Warn("ListenSMBuff[%d]: SendRemoteMess failed",bnum); else // send was ok now wait for the ACK/NACK if ((rtn = WaitForSingleObject(sync.ackh,22000)) == WAIT~OBJECT~0 if (buf->msgh.mode == NACK~MODE) pass = 100; Diag("ListenSMBuff[%d]: got an ack/nack",bnum); break; else if (rtn == WAIT TIMEOUT) Warn("ListenSMBuff[%d]: No ack Timed out after 22 sec",bnum,rt else Warn("ListenSMBuff[%d]: No ack WaitForSingleObject=%d",bnum,rt else I // Local message for QNETD Say("ListenSMBuff[%d] : GOT LOCAL MESSAGE",bnum); if (buf->msgh.mode == ADMINREQMODE) QnetdAdminRequest(buf); else Warn("ListenSMBuff[%d]: Qnetd drops non-admin request",bnum); pass = MAXPASS + 2; if (pass < MAXPASS + 1) buf->status = SMBUF~RETURN~MESS; else buf->status = SMBUF RETURN FAIL; // Notify the sender "Your message was read" Diag("ListenSMBuff[%d]: releases DONE status = %d",bnum,buf->status); if (!ReleaseSemaphore(sync.doneh,l,0)) Warn("ListenSMBuff[%d]: ReleaseSemaphore done #%d",bnum,GetLastError()) //loop Say("ListenSMBuff[%d] Aborts",bnum); return(0); // // Common routines and definitions used by OpenMQ // //////////////////////////////////////////////////////////// ///////////////// #include "qlib.h" #include "qnetd.h" // Routines //////////////////////////////////////////////////////////// //////// void ReadParms(int *nsbuf) I // *nsbuf is Optional char line[LINESIZE]; char parm[LINESIZE]; char value[LINESIZE]; FILE *fp = fopen(PARMNAME,"r"); if (sm~base) ( // If we have shared memory, then set defaults.

SHAREDATA(diag) = 1; SHAREDATA(time~out) = 20000; if ( ! fp Fail("Cant open the parameters file %s",PARMNAME); while (fgets(line,LINESIZE,fp)) *parm = *value = 0; if ( 2 != sscanf(line,"%s = %s",parm,value)) *parm = 0; else if (!strcmp(parm,"nsbuf") if (nsbuf) sscanf(value,"%d",nsbuf); if (*nsbuf > MAXNSMBUF) Warn("parameter: nsbuf %d exceeds 5 maximum",*nsbuf,MAXNS *nsbuf = MAXNSMBUF; else if (sm~base && !strcmp(parm,"diag")) sscanf(value,"%d",&SHAREDATE(diag)); else if (sm~base && !strcmp(parm,"time~out")) sscanf(value,"%d",&SHAREDATA(time~out)); else if (sm~base) Say("ReadParms: Ignoring: %s",line);<BR> if (ferror(fp))( Fail(tread error in parameters file %s",PARMNAME); clearerr(fp); fclose(fp); ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: qnetd.c ** Author: Derek Schwenke 9/8/95 ** */ #include "qlib.h" #include "qnetd.h" #include "rt.h" main(int argc, char **argv) HANDLE hSMT, hTCPT, hDOG; DWORD idSMT,idTCPT, idDOG; WSADATA WSAData; int nsbuf = 0; // DLL Init if (WSAStartup(0x0101, &WSAData)) Fail("WSAStartup() failed"); // Read only nsbuf.

ReadParms(&nsbuf); SharedMemInit(nsbuf); // Read and set all other shared memory parameters ReadParms(0); // Load routing table into shared memory ReadRT(); // Create Threads - listen for connections from other qnetd's //AfxBeginThread?? hSMT = CreateThread(NULL,O,(LPTHREAD START ROUTINE) ListenConn, O,0,&idTCPT // Create Threads - listen for shared memory buffer requests hTCPT = CreateThread(NULL,0, (LPTHREAD~START~ROUTINE) ListenSMBuff,0,0,&idSMT) // Create Background watchdog thread hDOG = CreateThread(NULL,0, (LPTHREAD~START~ROUTINE) WatchDog,0,0,&idDOG); Sleep(2000); Ask("QNETD All Done?"); return(0); ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: routab.c ** Author: Derek Schwenke 9/8/95 ** ** Routing table functions */ #include "qlib.h" #include "qnetd.h" 4include "rt.h" #include <string.h> #include <ctype.h> /* int Str2Port (char *str){ int port=0; if (sscanf (str, "%*[^\[1 [%d" , &port) ) Say("Str2Port Ws returns td",str,port); else Say("Str2Port 5 FAILED",str); return(port); } */ // Routing table entry,,,, to be deleted typedef struct rte int ip; char node[NAMESIZES]; // char ntype[NAMESIZE]; // char cs [NAMESIZE] ; int qnetd~port; // char serv~class[NAMESIZE];// char servers[4*NAMESIZE]; char physical[NAMESIZE]; ; // char logicals[4*NAMESIZE] ;// char serv~path[NAMESIZE]; //<BR> char serv~opts[NAMESIZE]; //<BR> <BR> <BR> } RTE, *lpRTE, static int is~ip(char *s) return( isdigit(s[0]) ) static int is stype(char *s) return( strlen(s) > 3 && strstr(&CLASSNAMES,s) ); // The table looks like this: //137.203.1.1 mars NT3.5 Server[100] // classO router c:/q/route -master // classl QSl[Ql,Q2,Q3] c:/q/qserv -threads 66 more opts // The node line is: <BR> <BR> // IP&num node node~name node~type Client~or~server[QNETD address] Preferred~servers,,, // The Services lines is: // type physical~name[logical~names,,,] path~to~executable options int parseRTnode( char *line, int line~no, int *ip, char *node, char *ntype, char *cs, int *port, char *servers) char ip~str[NAMESIZE]; char cs~str[LINESIZE]; strcpy(servers,","); if ( 4 > sscanf(line,"%s %s %s %s %s",ip str,node,ntype,cs str,cservers[l] Fail("Routing Table Line %d is not complete: %s",line~no,line); if (strlen(servers) > 1) strcat(servers,","); else strcpy(servers,""); if (!(*ip = Str2IP(ip~str))) Fail("Routing Table Line %d ip does not scan: %s",line~no,line); if (2 != sscanf(cs~str,"%[^\[][%d] ",cs,port)) Fail("Routing Table Line %d QNETD client/server does not scan: %s",line~no return(l); int parseRTservices(char *line, int line~no, char *clas, char *physical~name, char *logical~names, char *path, char *opts) char services[LINESIZE]; int len; strcpy(opts,""); if ( 3 > sscanf(line,"%s %s %s %[^]",clas,services,path,opts)) Fail("Routing Table: line %d is not complete: %s", line~no,line); strcpy(logical~names,","); sscanf(services,"%[^\[][%s]",physical~name,&logical~names[1] ); if((len = strlen(logical~names)) < 2) // No logical name sprintf(logical~names,",%s,",physical~name); else logical~names[--len] = ','; return(l); ** **char * NewStr(char * s) ** char * n = malloc(strlen(s)+l); ** if (!n) Fail("Malloc error in NewStr"); ** return(strcpy(n,s)); **) ** **void FreeNcopy(char ** o, char * s) ** char * n = malloc(strlen(s)+l); ** if (!n) Fail("Malloc error in FreeNcopy"); ** strcpy(n,s); ** free(*o); ** *0 = ** void SwapRT(lpRT RTl, lpRT RT2) lpRT P,R,PRTl=0,PRT2=0; Diag("SwapRT(%s,%s),RT~NODE(RT1),RT~NODE(RT2)); if (RTl == RT2) return; // Scan for the prel and pre2 nodes P = RTROOT; while (R = NextRT(P)) // Find both the previous nodes if (R == RTl) PRT1 = P; if (R == RT2) PRT2 = P; P = if (!(PRT1 && PRT2)) return; // Swap pointers PRTl->next~offset = RT2C(RT2) - RT2C(PRT1); if (RT2->next~offset) PRT2->next offset = RT2C(RT~NEXT(RT2)) - RT2C(PRT2); else - PRT2->next offset = 0; RT2->next~offset = RT2C(RT1) - RT2C(RT2); int fgetsh(char *line,int max,HANDLE rth) I // Aproximate fgets() // Read 1 char at a time until \n int rd=l,rdn=0; while ((rdn < max-1) && ReadFile(rth,line,l,&rd,0)) if (rd != 1) break; // Did not get one byte if (*line == '\n') break; line++; rdn++; if (*line = '\n') line--; if (rd) line++; *line = 0; return(rdn); HANDLE MakeRoutingTable() { // Only be called by QNETD.

int i,line~no = 0; PIN~ADDR pia; char line[LINESIZE]; HANDLE rth = CreateFile( ROUTNAME GENERIC WRITE, // GENERIC READ FILE~SHARE~WRITE, 0, // FILE SHARE READ OPEN~ALWAYS, FILE~ATTRIBUTE~NORMAL, 0); sprintf(line,"RT~VERSION 1\r\n"); WriteFile(rth,line,lstrlen(line), &i,0) sprintf(line,"#### Servers\r\n"); WriteFile(rth,line,lstrlen(line), &i,0); i = htonl( (u~long) SHAREDATA(hostip) ); // Back to network format pia = (PIN~ADDR) (&i); sprintf(line,"%s %-16s Win Server[4011]\r\n", inet~ntoa(*pia) WriteFile(rth,line,lstrlen(line), &i,0); sprintf(line,"# class1 QS1[QS1] c:\\q\\bin\\ramq -options\r\ WriteFile(rth,line,strlen(line), &i,0); sprintf(line,"#### Clients\r\n"); WriteFile(rth,line,lstrlen(line), &i,0); CloseHandle(rth); rth = Cr.eateFile( ROUTNAME GENERIC~READ, FILE SHARE READ, 0, OPEN~EXISTING, FILE ATTRIBUTE NORMAL, 0); if (rth == INVALID HANDLE VALUE ) Fail("Cant create the default routing table file %s",&ROUTNAME); return(rth); void ReadRT() { // Only be called by QNETD.

int line no = 0; char line[LINESIZE]; char first[LINESIZE]; char preferred[LINESIZE]; // must be readlwrite so that on second open we dont fail.

HANDLE rth = CreateFile( ROUTNAME GENERIC WRITEIGENERIC READ, // not FILE~SHARE~SHARE~WRITE|FILE~SHARE~READ, 0, // not OPEN~EXISTING, // not OPEN~ALWAYS FILE ATTRIBUTE NORMAL, 0); RTE rte; // Current RTE lpRT rt,rts; char *cp; SHAREDATA(rt~ver) = 0; if (SHAREDATA(rt~pingpong)) // Not the active RT rts = rt = (lpRT) sm~base->RT[0]; else rts = rt = (lpRT) sm~base->RT[1]; memset(rt,O,MAXRTSIZE); // Clear routing table (not required) cp = rt->s + 1; // 1st node is always nop rt->ntype~index = cp++ - (char *) rt->s // 1st node is always nop rt->appsindex = cp++ - (char *) rt->s // 1st node is always nop strcpy(preferred,""); if (rth == INVALID~HANDLE~VALUE ) ( // No routing table existed so makeon rth = MakeRoutingTable(); while (fgetsh(line,LINESIZE-l,rth)) line~no++; sscanf(line,"%s",first); if (*first == '#') { line no = line no; else Tf (is~ip(first)) ( // New node // // Perhaps we can filter other clinets out here to save space // parseRTnode(line,line no,&rte.ip,rte.node, rte.ntype,rte.cs, &rte.qnetd~port,rte.servers); // Start a new node in the RT RT~NOFFSET(rt) = ++cp - RT2C(rt); rt = NextRT(rt); // Build RT in shared memory RT~IP(rt) = rte.ip; // IP number RT~PORT(rt) = rte.qnetd~port; // Port number RT~NOFFSET(rt) = 0; // End of the chain strcpy(RT~NODE(rt),rte.node); // Node string rt->ntype~index = strlen(RT~NODE(rt)) + 1; strcpy(RT~NTYPE(rt),rte.ntype); rt->apps index = strlen(RT~NTYPE(rt)) + 1 + rt->ntype~index; cp = RT~APPS(rt); *cp = 0; if (Istrcmp(SHAREDATA(hostnatne) ,RT~NODE(rt))) strcpy(preferred,rte.servers); SHAREDATA(hostip) = RT~IP(rt); Diag("ParseRT this node is ts ip=tp",SHAREDATA(hostname),SHAREDATA(h else if (is~stype(first)) { // New service // parseRTservices(line,line no,rte.serv class, rte.physical,rte.logicals, rte.serv~path,rte.serv~opts); // format: [QS1],Q1,Q2, [QS2],Q4, sprintf(cp,"[%s]%s",rte,physical,rte.logicals) cp = strchr(cp,0); // Advance the pointer } else if(!strcmp(first,"RT~VERSION")) { sscanf(line,"%*s,%d",&SHAREDATE(rt~ver)); } // if (ferror(rth))( // Fail("ParseRT read error on %s.\n",&ROUTNAME); // clearerr(rth); // } CloseHandle(rth); // Sort this list according to the preferred servers PrintRT(rts,"Before sorting"); if (strlen(preferred) > 2) lpRT rtf,rtp = NextRT(rts); char *e,*p = preferred + 1; Diag("ReadRT: Sorting preferred servers:%s",preferred); // Swap entries to achive the right order while (rtp && ((strlen(p) > 2))) if (e = strchr(p,',')) *e = 0; rtf = rts; while (rtf = NextRT(rtf)) if (!strcmp(RT~NODE(rtf),p)) break; if (!rtf) Say("ReadRT: Cant find preferred server Ws",p); break; SwapRT(rtp,rtf); rtp = NextRT(rtp); if (e) p = e + 1; else break; PrintRT(rts,"After sorting"); // Ping Pong the RT tables, make this one active if (SHAREDATA(rt~pingpong)) SHAREDATA (rtgingpong) = 0; else <BR> <BR> SHAREDATA(rt~pingpong) = 1; <BR> <BR> SHAREDATA(rt~rev)++; // Every handle will re-load from new RT.

// We must find some way to set the IP addr, and the RT is the only way to <BR> <BR> if(!SHAREDATA(hostip))<BR> Warn("ReadRT: could not find host %s in the file ks",SHAREDATA(hostname),& //{{NO~DEPENDENCIES}} // Microsoft Visual C++ generated include file.

// Used by qnetd.rc #define ICON1 2 // Next default values for new objects #ifdef APSTUDIO~INVOKED #ifndef APSTUDIO~READONLY~SYMBOLS #define ~APS~NEXT~RESOURCE~VALUE 102 #define ~APS~NEXT~COMMAND~VALUE 40001 define APS NEXT CONTROL VALUE 1000 #define ~APS~NEXT~SYMED~VALUE 101 #endif endif ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: shm~init.c ** Author: Derek Schwenke 9/8/95 ** #include "qlib.h" // Global data - for qnetd only // QNETD keeps an open handle for each sync object so that they are // never deleted by the OS, until QNETD exits, then all bets are off.

// QNETD will not call closeHandle() so they will stay active.

// static int sharmeminit~done = 0; // sharmeminit done flag.

static HANDLE SMT; // Handle for access to SM table.

SMOBJS SYNC[MAXNSMBUF]; // Handles for all sync objects // ShareMemInit should be called once only once by QNETD.

LPVOID SharedMemInit(int nsbuf) HANDLE hMap; // Shared memory mapping lpSMBUFH lpBUFH; // Pointer to base of shared Memory PHOSTENT lpent; int i,sm~size,CFM~error; char * //Say("SharedMemInit: starts %d buffers.",nsbuf); if ( 0 ) I // must think of a better test... see if shared mem aleady exists a a lock would just say if another qnet had the shared mem. not anything abo Warn("ShareMemInit was already done!!!!"); else if (!nsbuf) Fail("nsbuf can not be '0' "); // Make Qopen() lock if (!CreateMutex( NULL, FALSE, MUTQOPEN )) Fail("ShareMemInit cant create mutex %s",&MUTQOPEN); // Make shared memory update lock if(!(SMT = CreateMutex(NULL, TRUE, SMEMTABLE))) Fail("ShareMemInit cant create mutex %s",&SMEMTABLE); // Calculate the size of shared memory sm~size = MAXSMSIZE(nsbuf); //Say("Shared memory will be d bytes\n",sm~size); // Create the shared memory hMap = CreateFileMapping( (HANDLE)0xFFFFFFFF, // Do not use a real disk file NULL, // No security PAGE~READWRITE, // Page protection 0, sm~size, // File size SMEMNAME); // Name CFM~error = GetLastError(); if ( ! hMap Fail("CreateFileMapping returned null"); // Map the shared memory into my address space lpBUFH = sm~base = MapViewOfFile( hMap, // object HANDLE FILE~MAP~WRITE, // Access 0,0, // Address into the file o ) ; // Size (Full file) if ( ! sm~base Fail("MapViewOfFile returned null"); if (CFM~error == ERROR~ALREADY~EXISTS) Fail("Shared memory already in use."); // Code should also check clcok to see if QNET is running ForcedBufferReset(i,0,0); for (i = 0 ; i < nsbuf ; i++ ForcedBufferReset(i,0,0); ) else // Initialize the buffers data for (i = 0 ; i < nsbuf ; i++ lpSMBUF b = SMBUFADDR(i); strcpy(b->name, "empty"); b->status = SMBUF~EMPTY; b->sub~status = 0; // Create all syncronization objects free,ready,done.

for (i = 0 ; i < nsbuf ; i++ char freename[NAMESIZE], readyname[NAMESIZE], donename[NAMESIZE], ackna sprintf(freename,MUTFREFMT,i); sprintf(readyname,SEMRDYFMT,i); sprintf(donename,SEMDONFMT,i); sprintf(ackname,SEMACKFMT,i); // sync QNETD tcp lister with buffer list if ( ! (SYNC[i].freeh = CreateMutex(NULL,FALSE,freename) Fail("Cant create mutex ts",freename); if ( ! (SYNC[i].readyh = CreateSemaphore(NULL,0,l,readyname) ) Fail("Cant create semaphore %s",readyname); if ( ! (SYNC[i].doneh = CreateSemaphore(NULL,0,1,donename) ) Fail("Cant create semaphore Ws",donename); if ( ! (SYNC[i].ackh = CreateSemaphore(NULL,0,l,ackname) ) Fail ("Cant create semaphore ks",ackname); // Get this host name if (gethostname(SHAREDATA(hostname), sizeof (SHAREDATA(hostname)))) Warn("ReadParms: gethostname failed WSAGetLastError()=%d",WSAGetLast // Get host ip from the hostent table if (!(lpent = gethostbyname(SHAREDATA(hostname))) Warn ( "Readparms: gethostbyname failed WSAGetLastError() =%d",WSAGetLastE i = *((int*) lpent->h addr); SHAREDATA(hostip) = htonl(i); // Get rid of the domain extention "bob.meitca.com9 if (strchr(SHAREDATA(hostname),'.')) { Say("Truncating host name %s",SHAREDATA(hostname)); *strchr(SHAREDATA(hostname),'.') = 0; SHAREDATA(nsbuf) = nsbuf; ReleaseMutex(SMT); //Say("ShareMemInit returns %d bytes at %p",sm~size,sm~base); return(sm~base); User: root Host: bunny Class: bunny Job: stdin ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: tcp.c ** Author: Derek Schwenke 9/8/95 ** */ #include "qlib.h" #include "qnetd.h" #include "rt.h" #include "netadmin.h" extern SMOBJS SYNC[MAXNSMBUF]; int SAY WSAERROR TEXT() int rc = WSAGetLastError(); #define ERROR~BUF~LEN (1000) char pszError[ERROR~BUF~LEN]; wsprintf(pszError, WinSock error hd: ", rc); switch (rc) case WSAEINTR: lstrcat(pszError, "Interrupted system call"); break; case WSAEBADF: lstrcat(pszError, "Bad file number"); break; case WSAEACCES: lstrcat(pszError, "Permission denied"); break; case WSAEFAULT: lstrcat(pszError, "Bad address"); break; case WSAEINVAL: lstrcat(pszError, "Invalid argument"); break; case WSAEMFILE: lstrcat(pszError, "Too many open files"); break; case WSAEWOULDBLOCK: lstrcat(pszError, "Operation would block"); break; case WSAEINPROGRESS: lstrcat(pszError, "Operation now in progress"); break case WSAEALREADY: lstrcat(pszError, "Operation already in progress"); b case WSAENOTSOCK: lstrcat(pszError, "Socket operation on non-socket"); case WSAEDESTADDRREQ: lstrcat(pszError, "Destination address required"); br case WSAEMSGSIZE: lstrcat(pszError, "Message too long"); break; case WSAEPROTOTYPE: lstrcat(pszError, "Protocol wrong type for socket"); case WSAENOPROTOOPT: lstrcat(pszError, "Protocol not available"); break; case WSAEPROTONOSUPPORT: lstrcat(pszError, "Protocol not supported"); break; case WSAESOCKTNOSUPPORT: lstrcat(pszError, "Socket type not supported"); bre case WSAEOPNOTSUPP: lstrcat(pszError, "Operation not supported on socket" case WSAEPFNOSUPPORT: lstrcat(pszError, "Protocol family not supported"); b case WSAEAFNOSUPPORT: lstrcat(pszError, "Address family not supported by pr case WSAEADDRINUSE: lstrcat(pszError, "Address already in use"); break; case WSAEADDRNOTAVAIL: lstrcat(pszError, "Can't assign requested address"); case WSAENETDOWN: lstrcat(pszError, "Network is down"); break; case WSAENETUNREACH: lstrcat(pszError, "Network is unreachable"); break;.

case WSAENETRESET: lstrcat(pszError, "Network dropped connection on rese case WSAECONNABORTED: lstrcat(pszError, "Software caused connection abort") case WSAECONNRESET: lstrcat,(pszError, "Connection reset by peer"); break; case WSAENOBUFS: lstrcat(pszError, "No buffer space available"); break case WSAEISCONN: lstrcat(pszError, "Socket is already connected"); bre case WSAENOTCONN: lstrcat(pszError, "Socket is not connected"); break; case WSAESHUTDOWN: lstrcat(pszError, "Can't send after socket shutdown") case WSAETOOMANYREFS: lstrcat(pszError, "Too many references: can't spli > case WSAETIMEDOUT: lstrcat(pszError, "Connection timed out"); break; case WSAECONNREFUSED: lstrcat(pszError, "Connection refused"); break; case WSAELOOP: lstrcat(pszError, "Too many levels of symbolic links" case WSAENAMETOOLONG: lstrcat(pszError, "File name too long"); break; case WSAEHOSTDOWN: lstrcat(pszError, "Host is down"); break; case WSAEHOSTUNREACH: lstrcat(pszError, "No route to host"); break; case WSAENOTEMPTY: lstrcat(pszError, "Directory not empty"); break; case WSAEPROCLIM: lstrcat(pszError, "Too many processes"); break; case WSAEUSERS: lstrcat(pszError, "Too many users"); break; case WSAEDQUOT: lstrcat(pszError, "Disc quota exceeded"); break; case WSAESTALE: lstrcat(pszError, "Stale NFS file handle"); break; case WSAEREMOTE: lstrcat(pszError, "Too many levels of remote in path case WSASYSNOTREADY: lstrcat(pszError, "Network sub-system is unusable"); case WSAVERNOTSUPPORTED: lstrcat(pszError, "WinSock DLL cannot support this case WSANOTINITIALISED: lstrcat(pszError, "WinSock not initialized"); break; case WSAHOST~NOT~FOUND: lstrcat(pszError, "Host not found"); break; case WSATRY AGAIN: lstrcat(pszError, "Non-authoritative host not found") case WSANO~RECOVERY: lstrcat(pszError, "Non-recoverable error"); break; case WSANO~DATA: lstrcat(pszError, "Valid name, no data record of requ #ifdef ~WIN32 case WSAEDISCON: lstrcat(pszError, "Disconnect"); break; endif default: lstrcpy(pszError, "Unknown WinSock error"); break; Say(pszError); return(rc); lpST STroot = NULL; lpST FindSocket (int ip) lpST stp = STroot; while(stp) if (stp->ip == ip) break; stp = stp->next } if (stp == NULL) Say("FindSocket: ip=%p not found.",ip); else Diag("FindSocket: ip=%p found.",ip); return(stp); int RemoveSocket (SOCKET s)( // This needs to be thread safe lpST stp = STroot; // Needs to kill the thread listening on this s .lpST stpp = NULL; while(stp) if (stp->s == s) break; stpp = stp; stp = stp->next if (stp) Diag("RemoveSocket: closesocket() ip=%p" , stp->ip); closesocket(s); if (stpp) stpp->next = stp->next else STroot = stp->next free(stp); return(l); } else if ((int) s Warn("RemoveSocket: s=%p NOT FOUND!!" ,s); return(0); DWORD ListenOnConn(lpST stab) { SOCKET s = stab->s int ip = stab->ip int port = stab->port SMBUF buf; // Buffer where messages will be held lpSMBUF abuf; // Buffer where ack data will be copied int rc; // recv code int i,bnum; // Buffer number to send ack QHANDLE q; // Psudo handle used to forward messages memset(&q,0,sizeof(QHANDLE)); Diag("ListenOnConn: PARAMETERS socket=%d ip=%s port=Wd",s,IP2Name(ip),port Diag("ListenOnConn(%s:%d): Waiting for some data",IP2Name(ip),s); while((rc = recv(s,(char *) &buf.msgh,MAXTXSIZE,0)) > 0) SHAREDATA(stat.rx)++; // Any communication received statistics if (rc == SOCKET ERROR) ( Warn("ListenOnConn(%s:%d): ends with SOCKET~ERROR=%d",IP2Name(ip),s,SAY break; if (rc < sizeof(MSGH)) ( // Safty check Warn("ListenOnConn(%s:%d): Dropping too small message",IP2Name(ip),s); continue; if (buf.msgh.size > MAXMSGDATA) { Warn("ListenOnConn(%s:%d): message %d:%d with too big size %d bytes", IP2Name(ip),s,buf.msgh.mode,buf.msgh.sub~mode,buf.msgh.size) ; // continue; Diag("ListenOnConn(%x:%d): Mode=%d:%d flag=%x %d bytes:%s",IP2Name(ip),s, buf.msgh.mode,buf.msgh.sub mode,buf.msgh.flags,rc,buf.mdata); switch(buf.msgh.mode) { case PUT~MODE: case REQUEST~MODE: case COMMIT~MODE: case ABORT~MODE: case ADMINREQ~MODE: // This could be optimized but for now: // (1) Fake a que handle // (2) Put data to the fake que // If the previous q handle was not for this server, fake the queue han if (0 == strcmp (buf.msgh.to~server, "")) { // No server name (see the rep lpSMBUF b = SMBUFADDR(buf.msgh.to~smbuf); if (strcmp (b->name, "empty")) strcpy(buf.msgh.to server,b->name); else Warn("ListenOnConn(%s:%d) : msg to 'empty' buffer %d",IP2Name(ip), if (strcmp(q.msgh:to server, buf.msgh.to~server)) //Construct que handle from messge header memcpy(&q.msgh,&buf.msgh,sizeof(MSGH)); q.base~flags = 0; q.time~out = SHAREDATA(time~out); if(!FindsMsuffers(&q,buf.msgh.to node,buf.msgh.to~server, -1)) Warn ("ListenOnConn (%s:%d): ERROR No local buffers found for %s",I strcpy(q.msgh.to~server,""); // So next time you remake the que buf.msgh.to~node = ip; // send back to orign buf.msgh.to~port = port; // send back to orign (port not used) buf.msgh.mode = NACK~MODE; // Perhaps Qsar() will set buf.msgh It Diag ("ListenOnConn (%s:%d): Sending NACK to %p [%s]", IP2Name (ip if (SendRemoteMess (&buf,0)) Warn ("ListenOnConn (%s:%d): Could not SendRemoteMess(NACK)",IP2 continue; else ( // re-use the existing handle, but update the message header Diag ("ListenOnConn (%s:%d): Reusing handle for %s", IP2Name (ip), s, buf.

memcpy(&q.msgh,&buf.msgh,sizeof(MSGH)); //q.msgh.mode = buf.msgh.mode; // Qsar() uses q.msgh.mode. Set recei if (buf.msgh.flags & Q~FAILOVER) // No Failover please buf.msgh.flags = buf.msgh.flags & (!Q~FAILOVER); // Put data into the local que and get any answer Diag("ListenonConn(%s:%d) : Before Qsar() MODE=%d ", IP2Name (ip), s, q.msgh // Last change: added last parameter of Qsar() the gotten mess header with if (QSUCCESS != QsendAndReceive (&q,0,0 /*buf.msgh.mode,buf.msgh.sub~mo MAXMSGDATA,buf.mdata,&buf.msgh.size,&buf.msgh)) { Warn ("ListenOnConn (%s:%d): Qsar error. Will make NACK~MODE", IP2Name ( buf.msgh.mode = NACK~MODE; // Perhaps Qsar() will set buf.msgh itsel else buf.msgh.mode = ACK~MODE; // Added 1/20/96 for recipts // Generate an ACK to the sending QNETD buffer Diag ("ListenOnConn (%s:%d): After Qsar() MODE ",IP2Name(ip),s,buf.msg buf.msgh.to~node = ip; // send back to orign buf.msgh.to~port = port; // send back to orign (port not used) Diag ("ListenOnConn (%s:%d): Sending n/ACK~MODE to %p [%s]", IP2Name (ip),s if (SendRemoteMess(&buf,0)) Warn ("ListenOnConn (%s:%d): Could not SendRemoteMess(ACK)",IP2Name(i break; case GET~MODE: Warn ("ListenOnConn (%s:%d): GET~MODE not supported",IP2Name(ip),s); break; case ACK MODE: case ADMTNREP~MODE: case QNETDREP~MODE: abuf = SMBUFADDR (bnum = buf.msgh.from~smbuf); // Target of ACK Diag ("ListenOnConn (%s:%d): Relaying ACK to buffer %d", IP2Name (ip),s,bnu memcpy (&abuf->msgh,&buf.msgh,rc); // Copy all bytes received to ACKs ta // Notify the sender if (!ReleaseSemaphore(SYNC[bnum] .ackh,l,O)) Warn("ListenOnConn(%s:%d) : ReleaseSemaphore ack %d &num %d",IP2Name(ip), break; case NACK~MODE: abuf = SMBUFADDR (bnum = buf.msgh.from~SMBUF); // Target of ACK Diag ("ListenOnConn (%s:%d): Relaying NACK to buffer %d", IP2Name (ip),s,bn memcpy (&abuf->msgh,&buf.msgh,rc); // Copy all bytes received to ACKs ta // Notify the sender if (!ReleaseSemaphore (SYNC [bnum].ackh,1,0)) Warn ("ListenOnConn (%s:%d): ReleaseSemaphore ack %d #%d", IP2Name (ip), break; case QNETDREQ~MODE: // Set up the reply message's data buf.msgh.mode = QNETDREP~MODE; // send back to orign buf.msgh.to~node = ip; // send back to orign buf.msgh.to~port = port; // send back to orign (port not used) if (buf.msgh.sub~mode == NETMAN~SMBUFH) Diag ("ListenOnConn (%s:%d): QNETDREQ~MODE sending SMBUFH=%d bytes", IP memcpy (&buf.mdata,sm~base, (sizeof (SMBUFH) - (2 * MAXRTSIZE) ) ); buf.msgh.size = (sizeof (SMBUFH) - (2 * MAXRTSIZE)); else if (buf.msgh.sub~mode == NETMAN~SMBUFS) lpBSA b = (lpBSA) &buf.mdata; b->nsbuf = SHAREDATA(nsbuf); for (i=O; i < SHAREDATA(nsbuf); i++) memcpy(&b->bs[i], SMBUFADDR(i) , sizeof(BS) ); buf.msgh.size = sizeof(BSA); else if (buf.msgh.sub~mode == NETMAN~SOCKETS) lpSSA b = (lpSSA) &buf.mdata; lpST stp = STroot; b->sockets = 0; while (stp) b->ss[b->sockets] .ip = stp->ip b->ss[b->sockets].port = stp->port stp = stp->next b->sockets++; b->ss[b->sockets].ip = 0; b->ss[b->sockets].port = 0; buf.msgh.size = sizeof(SSA); else if (buf.msgh.sub~mode == NETMAN~RT~READ) lpRTA b = (lpRTA) &buf.mdata; if(SHAREDATA(rt pingpong)) memcpy(&b->RT, &SHAREDATA(RT[1]) , MAXRTSIZE ); else memcpy(&b->RT, &SHAREDATA(RT[0]) , MAXRTSIZE ); <BR> <BR> <BR> <BR> buf.msgh.size = MAXRTSIZE;<BR> else if (buf.msgh.sub~mode == NETMAN~CLR~FOL) SHAREDATA(failed~servers) = 0; buf.msgh.size = 0; } else if (buf.msgh.sub~mode == NETMAN~RT~NEW) { /*BROADCAST */ FILE *RTFP = fopen(ROUTNAME,"w"); // Routing Table File<BR> Say("ListenOnConn(%s:%d): QNETDREQ~MODE NETMAN~RT~NEW! %s %d bytes"<BR> if (RTFP) if ( buf.msgh.size != (int) fwrite(&buf.mdata,sizeof( char ), buf Warn("ListenOnConn(%s:%d): QNETDREQ~MODE NETMAN~RT~NEW trouble fclose(RTFP); // ReadRT() is called by qnetd watchdog.c when file date changes else Warn("ListenOnConn(%s:%d): QNETDREQ~MODE NETMAN~RT~NEW can't open buf.msgh.size = 0; else if (buf.msgh.sub mode == NETMAN~RT~GET) FILE *RTFP = fopen(ROUTNAME,"r"); // Routing Table File Say("Listenonconn(%s:%d) : QNETDREQ MODE NETMAN~RT~GET ts",IP2Name(ip if (RTFP) buf.msgh.size = fread(&buf.mdata,sizeof( char ), MAXMSGDATA,RTFP) if (!buf.msgh.size) Warn("ListenOnConn(%s:%d): QNETDREQ~MODE NETMAN~RT~GET can't re fclose(RTFP); } else <BR> <BR> Warn("ListenOnConn(%s:%d): QNETDREQ~MODE NETMAN~RT~GET can't c<BR> } else if (buf.msgh.sub~mode == NETMAN~TRAN) {<BR> <BR> <BR> <BR> <BR> <BR> <BR> else <BR> Warn("ListenOnConn(%s:%d): QNETDREQ~MODE unknown submode td",IP2Name buf.msgh.size = 0; if (SendRemoteMess(&buf,0)) Warn("ListenOnConn(%s:%d): Could not SendRemoteMess(QNETDREP~MODE) break; default: Warn("ListenOnConn(%s:%d): Got a message I dont understand type=%d",IP2 } Diag("ListenOnConn(%s:%d): waits for another message",IP2Name(ip),s); Say("ListenOnConn(%s:%d): Done Reading socket Good Bye",IP2Name(ip),s); RemoveSocket(s); ExitThread(0) return(0); DWORD ListenConn() SOCKET sClient,sServe! = INVALID SOCKET; // SOCKADDR client; SOCKADDR~IN sas~in,sac~in; lpRT this~node; int sizeofsocket = sizeof(SOCKADDR); //char hostname[NAMESIZE]; Diag("ListenConn Thread"); //hostname now set by shm~init() //if (gethostname(hostname, sizeof (hostname))) // Fail("QNETDlistenConn: gethostname failed WSAGetLastError() =%d",WSAGetLa if (!(this node = RTByName(SHAREDATA(hostname)))) Fail("QNETDlistenConn: Could not find local node %s in %s",SHAREDATA(hostn Diag("QNETDlistenConn: host=%s listens~on=sd",SHAREDATA(hostname),this~node-, // (2) Establish a Socket if ((sServer = socket(AF~INET, SOCK~STREAM, 0)) == INVALID~SOCKET) Fail("QNETDlistenConn: Unable to open socket, WSAGetLastError() = WSAGetLastError()); // (3) Bind the socket // ~WNetGetHostAddress("bob, "wnetbnch", "tcp", &sa); sas~in.sin~family = AF~INET; sas~in.sin~port = htons( (short) this~node->qnetd~port); sas~in.sin~addr.s~addr = htonl(INADDR~ANY); if (bind(sServer, (LPSOCKADDR) &sas~in, sizeof (sas~in)) != 0) Fail("QNETDlisten: Unable to bind socket, WSAGetLastError() = SAY~WSAERROR~TEXT()); if (listen(sServer, 5)) // 5 is max number of mess to buffer Fail("QNETDlisten: Listen failed WSAGetLastError() = SAY WSAERROR TEXT()); while (TRUE) HANDLE thread~h; DWORD thread id; lpST stab; // Socket table entry pointer Diag("QNETDlisten: Waiting for client connections..."); sClient = accept(sServer,(LPSOCKADDR) &sac~in, &sizeofsocket); Diag("QNETDlisten: Got connected to a clinet"); Diag("QNETDlisten: Clinets ID in network format ip=%p port=%d", sac in.sin addr.s addr,sac in.sin~port); Diag("QNETDlisten: Clinets ID in regular format ip=');p port=Wd", ntohl(sac in.sin addr.s addr),ntohs(sac in.sin~port)); stab = AddSocketToTable(sClient,&sac~in); Diag("QNETDlisten: Creating thread"); thread~h = CreateThread(NULL,O,(LPTHREAD START~ROUTINE) ListenOnConn,stab,0,&thread~id); return(0) ;// This cant happen typedef struct lpar I // Message header SOCKET skt; // socket number SOCKADDR IN sac; // inet address of client } LPAR, *lpLAR; lpST FindOrMakeSocket (lpSMBUF buf) int trouble = 0; lpST stp; lpST stp~new; SOCKADDR~IN sas~in; HANDLE thread~h; DWORD thread~id; if ((stp = FindSocket(buf->msgh.to~node)) == NULL) Diag("FindOrMakeSocket(%p): Making new socket.",buf->msgh.to node); sty new = (lpST) malloc(sizeof(ST)); stp new->next = NULL; stp~new->ip = buf->msgh.to~node; stp~new->port = buf->msgh.to~port; // Not used if ((stp~new->s = socket(AF~INET, SOCK~STREAM, 0)) == INVALID~SOCKET) Warn("FindOrMakeSocket(%p): Unable to open socket, WSAGetLastError() = buf-smsgh.to~node,SAY WSAERROR TEXT()); free(stp~new); else // setsockopt(stp-as, IPPROTO~TCP, TCP~NODELAY, // (LPSTR) &bNoDelay, sizeof (BOOL)); sas~in.sin~family = AF~INET; sas~in.sin~port = htons( (short) buf->msgh.to~port); sas~in.sin~addr.s~addr = htonl(buf->msgh.to~node); if (connect(stpnew->s, (LPSOCKADDR) &sas~in, sizeof (sas~in)) != 0) Diag("FindOrMakeSocket(%p): connect() failed, WSAGetLastError() = buf->msgh.to~node,SAY~WSAERROR~TEXT()); free(stp~new); else ( - stp~new->port = ntohs(sas~in.sin~port); Diag("FindOrMakeSocket(%p): Connected to server on port %d",buf->msg Diag("FindOrMakeSocket: Starting new listening thread"); thread~h = CreateThread(NULL,0,(LPTHREAD~START~ROUTINE) ListenOnConn,stp~new,0,&thread~id); // Add to top of the chain stp~new->next = STroot; STroot = stp~new; stp = stp~new; // Sleep(500); // make sure args are copied before exit this routine return(stp); lpST AddSocketToTable(SOCKET sock,SOCKADDR~IN *sa) int ip = ntohl(sa-ssin addr.s addr); int port = ntohs(sa->sinport); lpST stp; Diag("AddSocketToTable: s=%d ip=%p",sock,ip); if (stp=FindSocket(ip)) { stp->s = sock; else stp = (lpST) malloc(sizeof(ST)); stp->s = sock; stp->ip = ip; stp->port = port; stp->next = STroot; // add to front of the list STroot = stp; return(stp); /* FAILOVER: First try the existing IP connection 2 times Then we will find a NEW IP and try that connection.

*/ int SendRemoteMess(lpSMBUF buf,int pass) { // Called from QNETD, TCP/ListenOnCon // Pass tells how many times we have been called.

lpsT skt; int sentsize; int msgsize = sizeof(MSGH) + buf->msgh.size; Diag("SendRemoteMess: About to FindOrMakeSocket mode=%d",buf->msgh.mode); if (!(skt = FindOrMakeSocket(buf))) Warn("SendRemoteMess: Could not FindOrMakeSocket for ip=%d",buf->msgh.to~n else Diag("SendRemoteMess: About to send mode=%d data:%s" ,buf->msgh.mode,buf->m sentsize = send(skt->s,(char *) &buf->msgh, msgsize, 0); if (sentsize == msgsize) ( // Send was good Diag("SendRemoteMess: send completed"); SHAREDATA(stat.tx)++; // Mess sent statistics return(0); // Good } else if (sentsize == -1) { // Send Error Warn("SendRemoteMess: send() error=%d",SAY~WSAERROR~TEXT()); RemoveSocket(skt->s); // Try to ReOpen the TCP Conn if (pass++ < 2) Warn("SendRemoteMess: Remaking the connection"); return(SendRemoteMess(buf,pass)); else { // sentsize != msgsize ; No error but not completed Warn("SendRemoteMess: did not send full message. sent %d of %d bytes", sentsize,buf->mdata); } return(l); // Bad ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.4' ** ** OpenMQ ** Module: qnetd.c ** Author: Derek Schwenke 9/8/95 ** */ #include "qlib.h" #include "qnetd.h" DWORD WatchDog() { int sec=0; BY~HANDLE~FILE~INFORMATION Info; FILETIME LastTime; HANDLE RTF = CreateFile( ROUTNAME GENERIC WRITEIGENERIC~READ, FILE SHARE WRITE(FILE~SHARE~READ, 0, OPEN ALWAYS, FILE~ATTRIBUTE~NORMAL, 0); while(l) Sleep(1000); // One second time(&SHAREDATA(time)); if (sec++ >= 15) sec = 0; if (RTF && GetFileInformationByHandle( RTF, &Info )) //Diag("WatchDog: RT file time = %d %d", Info.ftLastWriteTime.dwHig if (memcmp(&LastTime,&Info.ftLastWriteTime,sizeof(FILETIME))) { memcpy(&LastTime,&Info.ftLastWriteTime,sizeof(FILETIME)); Say("WatchDog: calls ReadRT"); ReadRT(); // file time differs // GetFileInformationByHandle } // 15 seconds } // forever CloseHandle(RTF); return(0); ** Copyright (C) 1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: ramq.c ** Author: Derek Schwenke 9/8/95 ** ** This is a single threaded ram queue */ // Each message could be an enq or a deq.

&num include "qlib.h" #define QSIZE 8 #define ENQ ramq[ramq~head] #define DEQ ramq[ramq~tail] #define ENTRIES ((( ramq~head + QSIZE ) - ramq~tail) % QSIZE) SMBUF ramq[QSIZE]; int ramq~head = 0; // points to empty space int ramq~tail = 0; // points to filled entry int main(int argc, char **argv) lpQHANDLE q; int status; char qname[NAMESIZE]; if(argc> 1) strcpy(qname,argv[l]); else strcpy(qname,"Q1"); Say("RAMQ(%s): About to Qopen",qname); if (!(q = Qopen(qname,GETTING))) Say("RAMQ(%s) Could not open the queue",qname); while (QSUCCESS == Qgnp~get(q,0,0,&ENQ.msgh,ENQ.mdata,MAXMSGDATA)) { Say("RAMQ(%s) Server Got :%s",qname,ENQ.mdata); if (ENQ.msgh.mode == PUTTING) Say("RAMQ(%s): ENQUEs message %s",qname,ENQ.mdata); ramq head = ++ramq~head % QSIZE; if (ramq~head == ramq~tail) Say("RAMQ(%s): OVERFLOW!",qname); Qgnp~put(q, ACK,0,0); } else if (ENQ.msgh.mode == REQUESTING) if (ramq~head == ramq~tail) Say("RAMQ(%s): EMPTY",qname); Qgnp put(q, EMPTY, 0,0); else T Say("RAMQ(%s): DEQUEs message %s",qname,DEQ.mdata); Qgnp~put(q, RETURN~DATA, DEQ.mdata, DEQ.msgh.size); ramq~tail = ++ramq~tail % QSIZE; } else { Say("RAMQ(%s): Unexpected Mode=%d",qname,ENQ.msgh.mode); Qgnp~put(q,NACK, 0, 0); Say("RAMQ(%s) has %d entries.",qname,ENTRIES); Ask("RAMQ(%s): all done ",qname); return(0); User: root Host: bunny Class: bunny Job: stdin ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: ramq.c ** Author: Derek Schwenke 9/8/95 ** ** This is a single threaded ram queue */ // Each message could be an enq or a deq.

#include "qlib.h" &include "qadmin.h" // Que entry states: #define INVALID 0 define VALID 1 #define PENDING PUT 2 #define PENDING-GET 3 #define MAXQSIZE 1001 define MAXRAMQDATA 100 define ENQ ramq[ramq~head] define DEQ ramq[ramq~tail] #define MES ramq[ramq~mess] #define MODE ENQ.msgh.mode &num define FLAGIS(X) BITSET(X,ENQ.msgh.flags) #define QINC(X) X = ++X % QSIZE #define QDEC(X) X = --X % QSIZE #define USEDSPACE ((( ramq~head + QSIZE ) - ramq~tail) % QSIZE) &num define ALLENTRIES (st.committed~entries + st.pending~gets + st.pending puts) typedef struct rqbuf ( //Ramq int status; MSGH msgh; char mdata[MAXRAMQDATA]; RQBUF, *lpRQBUF; QADMSTATS st; // Statistics RQBUF ramq[MAXQSIZE]; int QSIZE = MAXQSIZE; int ramq~head = 0; // points to empty space int ramq~tail = 0; // points to filled entry int ramq~mess = 0; // points to entry that was just filled char qname[NAMESIZE]; void PrintQ() char n[80]; int i; for ( i = 0 ; i < QSIZE ; i++ if (ramq[i].status == INVALID) // Clear entry just for display *ramq[i].mdata = ramq[i].msgh.mid.host = ramq[i].msgh.mid.tid = 0; strcpy(n,""); if (i == ramq~head) strcat(n," <- head"); if (i == ramq~tail) strcat(n," <- tail"); Say(" %d mid=%p:%d status=%d : ramq[i] .msgh.mid.host, ramq[i] .msgh.mid.tid, ramq[i].status, ramq[i].mdata,n); void StatReset(char *qname) st.amt~free~dspace = -1; st.num~puts = 0; st.num~gets = 0; st.num~commits = 0; st.num~aborts = 0; if (qname) strcpy(st.physical~qname,qname); if (qname) strcpy(st.logical~qname,'t"); st.max~entries~limit = MAXQSIZE - 1; void QueReset(char *qname) int i; for (i = 0; i < QSIZE ; i++) ram[i].status = 0; StatReset(qname); st.committed~entries = 0; st.pending~gets = 0; st.pending~puts = 0; ramq~head = ramq~tail = 0; st.num~restarts++; st.last~restart~time = SHAREDATA(time); st.node~address = SHAREDATA(hostip); strcpy(st.node~name,SHAREDATA(hostname)); void SetSize(int size) { // Resize the que size++; // Internaly it one lager QSIZE = size; QueReset(NULL); int FindNthMess(int nth, int mstatl, int mstat2) ( // Finds adm req data int p = ramq~tail; nth++; while ((nth) && (p != ramq~head)) ( if (ramq[p].status == mstatl || || ramq[p].status == mstat2 ) nth--; QINC(p); if (nth) return(-1); else return(QDEC(p)); void tran(action) ( // COMMIT or ABORT all parts of a transaction int p~gets = st.pending~gets, i; int p~puts = st.pending~puts; Diag("RAMQ-TRAN: %d mid=%p:%d", action,MES.msgh.mid.host,MES.msgh.mid.tid); for (i = 0 ; i < QSIZE ; i++) if (ramq[i].msgh.mid.tid == MES.msgh.mid.tid) if (ramq[i].msgh.mid.host == MES.msgh.mid.host) if (ramq[i].status == PENDING~PUT) { // Uncommitted PUT if (action) ramq[i] status = VALID; // Committed put st.num~puts++; st.committted~entries++; else ramq[i].status = INVALID; // Aborted put st.pending~puts--; } else if(ramq[i].status == PENDING~GET) { // Uncommitted GET if (action) ramq[i].status = INVALID; // Committed get st.num gets++; <BR> <BR> <BR> else ( - ramq[i].status = VALID; // Aborted get st.committed~entries++; st.pending~gets--; if ((gets == st.pending~gets) && (pputs == st.pending~puts)) Warn("tran(%d) did not commit or abort anything",action); //if (p gets = p~gets - st.pending~gets) Say("tran(%d) clears %d gets",actio //if (p~puts = p~puts - st.pending~puts) Say("tran(%d) clears %d puts",actio if(DEQ.status == 0 && ramq~head != ramq~tail) Diag("RAMQ-TRAN: Adjusting Tail while(DEQ.status == 0 && ramq~head != ramq~tail) //Adjust the tail QINC(ramq~tail); if(action) st.num~commits++; else st.num~aborts++; DWORD RQ () lpQHANDLE q; int char keys[MAXMSGDATA]; lpQADMCTLS pCTL; // Cast to ramq[] data lpQADMSEL pKEY; lpMID pMID; Say("RAMQ(%s): %d Entires",qname,QSIZE - 1); if (!(q = Qopen(qname,GET~MODE,0,0,0,0,0))) Say("RAMQ(%s) Could not open the logical queue",qname); st.num~restarts = -1; st.first~start~time = SHAREDATA(time); st.qget~state = 1; // enable puts st.qput~state = 1; // enable gets QueReset(qname); while (QSUCCESS == QlistenBeforeReply(q,&ENQ.msgh,ENQ.mdata,MAXMSGDATA)) { Diag("RAMQ(%s) Server Got md=%d mid:%p:%d :%s",qname,MODE,ENQ.msgh.mid.hos ramq~mess = ramq~head; // mess is where the last message went.

if (MODE == PUT MODE) if (!st.qput~state) { Say("RAMQ(%s) put is disabled!",qname); QreplyAfterListen(q,ACK~MODE,SUB MODE DISABLED, 0,0,0); else if (USEDSPACE >= QSIZE - 1) T - Say("RAMQ(%s) is FULL!",qname); QreplyAfterListen(q,ACK~MODE,SUB~MODE~FULL, 0,0,0); else Diag("RAMQ(ts): ENQUEs message %s",qname,ENQ.mdata); if (FLAGIS(Q~TRAN)) { ENQ.status = PENDING~PUT; st.pending~puts++; else I - ENQ.status = VALID; st.num~puts++; st.committed~entries++; QINC(ramq~head); QreplyAfterListen(q, ACK~MODE,SUB~MODE~OK, 0,0,0); else if (MODE == REQUEST~MODE) // Find next valid message int g = ramq~tail; while (ramq[g].status != VALID && g != ramq~head) QINC(g); if (!st.qget~state) Say("RAMQ(%s) get is disabled!",qname); QreplyAfterListen(q,ACK~MODE,SUB MODE DISABLED, 0,0,0); else if (g == ramq~head) { Diag("RAMQ(%s): is EMPTY!",qname); QreplyAfterListen(q, ACK~MODE,SUB~MODE~EMPTY, 0,0,0); else Diag("RAMQ(%s): DEQUEs message %s",qname,ramq[g] .mdata); QreplyAfterListen(q, ACK~MODE,SUB~MODE~OK, ramq[g].mdata, ramq[g].ms if (FLAGIS(Q~TRAN)) ramq[g].status = PENDING~GET; // Uncommtted get memcpy(&ramq[g].msgh.mid,&ENQ.msgh.mid,sizeof(MID)); // This MSG st.pending~gets++; else ramq[g].status = INVALID; // Committed get st.num~gets++; st.committed~entries--; while(ramq[ramq~tail].status == INVALID && ramq~head != ramqtail) QINC (ramq~tail); //Adjust the tail else if (MODE == ADMINREQ~MODE) I // Administrative messages switch(ENQ.msgh.sub~mode) { case QADM~REQ~STATS: st.max~entries = QSIZE - 1; st.holey~entries = USEDSPACE - ALLENTRIES st.num~free~entries = QSIZE - 1 USEDSPACE; QreplyAfterListen(q,ADMINREP~MODE,SUB~MODE~OK,(char *) &st, sizeof(s break; case QADM~REQ~COM~DATA: if (-1 != (x = FindNthMess((int) *ENQ.mdata,VALID,VALID))) QreplyAfterListen(q,ADMINREP~MODE,SUB~MODE~OK, ramq[x].mdata, 0,& else QreplyAfterListen(q,ADMINREP~MODE,0, 0, 0,0); break; case QADM~REQ~UNCOM~DATA: <BR> <BR> <BR> <BR> <BR> if (-1 !=(x = FindNthMess((int) *ENQ.mdata,PENDING~PUT,PENDING~GET)<BR> <BR> QreplyAfterListen(q,ADMINREP~MODE,SUB~MODE~OK, ramq[x].mdata, 0,&<BR> else QreplyAfterListen(q,ADMINREP~MODE,0, 0, 0,0); break; case QADM~SET CONTROLS: pCTL = (lpQADMCTLS) &ramq[ramq~mess] .mdata; st.qput~state = pCTL->enable~qputs~flag; st.qget~state = pCTL->enable~qgets~flag; Say("%d qput~state",st.qput~state); Say("%d qget~state",st.qget~state); if ( pCTL->stats~reset~flag ) StatReset(qname); if ( pCTL->full~reset~flag ) QueReset(qname); if ((pCTL->max~entries~value != QSIZE - 1) && (pCTL->max~entries~val<BR> SetSize(pCTL->max~entries~value); QreplyAfterListen(q,ADMINREP MODE,SUB MODE OK, 0, 0,0); if ( pCTL->shutdown~flag ) ( Qclose(&q,0); exit(0);} // PrintQ(); break; case QADM REQ MSG: ( int e = ramq~tail; pMID = (lpMID) &ramq[ramq~mess].mdata; Diag(*Finding mid %p %d %d",pMID->host,pMID->tid,pMID->uid);<BR> <BR> while(e != ramq~head) { if(0 == memcmp(&ramq[e].msgh.mid,&ramq[ramq~mess].mdata,sizeof e = QINC(e); } if ((e == ramq~head) || (ramq[e].status != VALID)) x = O; else x = ramq[e] .msgh.size; QreplyAfterListen(q,ADMINREP~MODE,SUB~MODE~OK, ramq[e].mdata, x break; case QADM~REQ~SEL~DATA: // KEY SEARCH pKEY =(lpQADMSEL) &ramq[ramq~mess].mdata; pMID = (lpMID) &keys if (pKEY->num~preds) int gt,lt, e = ramq~tail, p, p matches = 0; <BR> <BR> <BR> <BR> if (pKEY->search~type == SEARCH~UNCOM~ENT) gt = PENDING~PUT<BR> else if (pKEY->searchtype == SEARCH~ALL~ENT ) gt = VALID; lt =<BR> else - gt = lt = VALID; while (e != ramq~head) { // Scan the que looking for a match if ((ramq[e] status >= gt) && (ramq[e] status <= lt)<BR> <BR> matches = 0; for (p = 0; p < pKEY->num~preds; p++) if ((UINT) pKEY->preds[p].offset < (sizeof(MSGH) + ramq[ <BR> <BR> <BR> <BR> if (pKEY->preds[p] .pred~type == INT~SEARCH~TYPE)<BR> //int iv = *((int*) ((char *)&ramq[e].msgh + pKEY-><BR> <BR> <BR> <BR> <BR> <BR> <BR> if ((pKEY->preds[p] .min~switch == 0)<BR> (pKEY->preds[p].min~int~val <= *((int*)((char *)&ramq[e].msgh + pKEY->preds[p] p~matches++; <BR> <BR> <BR> <BR> if ((pKEY->preds[p] .max~switch == 0)<BR> <BR> (pKEY->preds[p].max~int~val >= *((int*)((char *)&ramq[e].msgh + pKEY->preds[p] p~matches++; <BR> <BR> <BR> <BR> <BR> } else if (pKEY->preds[p].pred~type == SHORT~SEARCH~T<BR> <BR> <BR> <BR> <BR> if ((pKEY->preds[p].min~switch == 0)<BR> <BR> <BR> (pKEY->preds[p].min~sh~val <= *((short*)((char *)&ramq[e].msgh + pKEY->preds[ p~matches++; <BR> <BR> <BR> <BR> if ((pKEY->preds[p].max~switch == 0)<BR> <BR> (pKEY->preds[p].max~sh~val >= *((short*)((char *)&ramq[e].msgh + pKEY->preds[ p~matches++; } else if(pKEY->preds[p].pred~type == STR~SEARCH~TYP if ((pKEY->preds[p].min~switch == 0)<BR> (0 >= strncmp(pKEY->preds[p].min~str~val, ((char *)&ramq[e].msgh + pKEY->preds[p].offset) p~matches++; <BR> <BR> <BR> <BR> <BR> if ((pKEY->preds[p].max~switch == 0)<BR> (0 <= strncmp(pKEY->preds[p].max~str~val, ((char *)&ramq[e].msgh + pKEY->preds[p].offset) p~matches++; } // offset within size } // for 3 predicates if (p~matches == 2 * pKEY->num~preds) memcpy(pMID,&ramq[e] .msgh.mid,sizeof(MID)); pMID = (lpMID) ((char *)pMID + sizeof(MID)); } // if Valid e = QINC(e); } // Scan que } // Predicates Diag("Matches = 'd", (x = (((char *)pMID - keys) / sizeof(MID)) )); QreplyAfterListen(q,ADMINREP MODE,SUB~MODE~OK, keys, ((char *)pMID break; default: Say("What?"); else if (MODE == COMMITMODE) tran(1) QreplyAfterListen(q,ACK~MODE,SUB~MODE~OK, 0, 0,0); else if (MODE == ABORT~MODE) tran(0); QreplyAfterListen(q,ACK~MODE,SUB~MODE~OK, 0, 0,0); else Warn("RAMQ(%s): Unexpected Mode=%d",qname,ENQ.msgh.mode); QreplyAfterListen(q,ACK~MODE,SUB~MODE~BAD~REQ, 0, 0,0); // Unexpected m if (FLAGIS(Q~TRAN~END)) tran(l); Diag("RAMQ(%s) has %d entries %d not commited.",qname, st.committed~entries,st.pending~puts + st.pending~gets); if (MODE != ADMINREQ MODE) if (SHAREDATA(diag)) PrintQ(); // Print the que Say("Bye",qname); return(0); int main(int argc, char **argv) HANDLE hRQ; DWORD idRQ; if(argc> 1) strcpy(qname,argv[1]); else strcpy(qname,"QSl"); if(argc> 2) sscanf (argv [2] , "%d",&QSIZE) ; QSIZE++; QSIZE=~min(MAXQSIZE,QSIZE); QSIZE=~max(2,QSIZE); hRQ = CreateThread(NULL,O, (LPTHREAD~START~ROUTINE) RQ, O,0,&idRQ); Ask("All done"); Qclose(NULL,qname); // Removes shared buffer so messages dont need to time-ou return(0); } ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: ramqcs.c ** Author: Derek Schwenke 9/8/95 ** ** ramq's client and server ** */ #include "qlib.h" #include "rt.h" #include "qadmin.h" void Help()( Say("O <name> - Open"); Say("P <data> - Put"); Say("G - Get"); Say("B - Begin tran"); Say("C - Commit tran"); Say("A - Abort tran"); Say("E - End tran on next op"); Say("S - Single tran op"); Say("N - No tran"); Say("L - List status"); Say("D - Diagnostics on/off"); Say("R - Reset all"); Say("T - Reset statistics"); Say("K - Shutdown"); Say("Q <put/get> - Enable/disable ops"); Say("H - Help"); Say("Z <numb> - Set size of que"); main(int argc, char **argv) int ret,i,flags=0,next~flag=0,sz; char qname[NAMESIZE]; MSGH mh; lpQHANDLE Q; lpQADMSTATS pSTA = (lpQADMSTATS) AskAnswer; // lpQADMCTLS pCTL = (lpQADMCTLS) AskAnswer; QADMCTLS ctl; memset(&ctl,0,sizeof(ctl)); ctl.enable~qputs~flag++; ctl.enable~qgets~flag++; if(argc==2) strcpy(qname,argv[1]); else strcpy(qname,"Ql"); // appl Say("RAMQCS: Server=%s",qname); // Open the queue for putting if (!(Q = Qopen(qname,PUT MODE,O,O,O,O,O))) Warn("RAMQCS: could not open the que %s",qname); // Put data into the que Say("Open Put Get Begin End Commit Abort Single List Kshutdown sTat siZe Rese while( strlen(Ask("ramqcs"))) #define SAR~WAS~OK(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10) QSUCCESS >= (ret = QsendAndR if (strchr("Pp", *AskAnswer) && AskAnswer[l] == ' ' && strlen(AskAnswer) > if (SAR~WAS~OK(Q,PUT~MODE,0, flags,strlen(AskAnswer),&AskAnswer[2], LINESIZE,AskAnswer,&sz,&mh)) if (ret == QSUCCESS FAILOVER) Say("RAMQCS: Failover successfull"); if (mh.mode == ACK~MODE && mh.sub~mode == SUB~MODE~OK) Say("RAMQCS: Succceded: (mode=Wd) ';s't,mh.mode,AskAnswer); else if (mh.sub~mode == SUB~MODE~FULL) Say("RAMQCS: que was FULL"); else Say("RAMQCS: Put failed %d",mh.sub~mode); else Say("RAMQCS: Qput comm error"); flags = next~flag; else if(strchr("Gg,*AskAnswer)) { // Get if (SAR~WAS~OK(Q,REQUEST~MODE,0, flags,strlen(AskAnswer)+1,AskAnswer, LINESIZE,AskAnswer,&sz,&mh)) { if (ret == QSUCCESS~FAILOVER) Say("RAMQCS: Failover successfull"); if (mh.mode == ACK~MODE && mh.sub~mode == SUB~MODE~OK) Say("RAMQCS: Succeded: (mode=%d) %d bytes %s",mh.mode,mh.size,As else if (mh.sub mode == SUB MODE EMPTY) Say("RAMQCS: que was EMPTY"); else Say("RAMQCS: Qget failed %d",mh.sub~mode); flags = next~flag; else if (strchr("Ll",*AskAnswer)) ( // List if (QSUCCESS >= QsendAndReceive (Q,ADMINREQ MODE, QADM~REQ~STATS, 0,0,0, sizeof(QADMSTATS),AskAnswer,&sz,&mh)) { int pg,pp,ce,he,fe,me; Say("\n\n%s:%s %s %x",pSTA->physical~qname,pSTA->logical~qname,pSTA- Say("7d committed~entries",ce = pSTA->committed~entries) Say ( "%7d pending~gets",pg = pSTA->pending~gets); Say("%7d pending~puts",pp = pSTA->pending~puts); Say("%7d holey~entries",he = pSTA->holey~entries); Say("%7d num~free~entries",fe = pSTA->num~free~entries); if (pSTA->amt~free~dspace != -1) Say("%7d amt~free~dspace",pSTA->amt~free~dspace); if (pSTA->max entries limit >= pSTA->max~entries Say("%7d max Used limit",me = pSTA->max~entries,pSTA->max~entrie else Say("%7d max ",me = pSTA->max~entries); Say ("%7d putstate %4d getstate", pSTA->qput~state, pSTA->qget~state); Say ("%7d puts %4d gets", pSTA->num~puts, pSTA->num~gets); Say("%7d committs %4d aborts %d restarts",pSTA->num~commits,pSTA- Say("\n\tFirst start time %s\tLast restart time %s", ctime (&pSTA->first~start~time), ctime (&pSTA->last~restart~time)); if (me - (ce + pg + pp + he + fe)) Warn("REPORTED ENTRIES OFF BY %d", me - (ce + pg + pp + he + *AskAnswer = i = 0; sz = 1; while(sz) *AskAnswer = if (QSUCCESS >= QsendAndReceive(Q,ADMINREQ~MODE,QADM~REQ~COM~DATA 0, sizeof (int), AskAnswer, LINESIZE, AskAnswer, &sz, &mh)) if (sz) Say("Wd %s", i, AskAnswer); <BR> <BR> <BR> <BR> <BR> <BR> <BR> *AskAnswer = i = 0; sz = 1; Say <BR> <BR> <BR> while (sz) *AskAnswer = if (QSUCCESS >= QsendAndReceive(Q,ADMINREQ~MODE,QADM~REQ~UNCOM~DA 0, sizeof (int), AskAnswer, LINESIZE, AskAnswer, &sz, &mh)) if (sz) Say ("%d submode=%d . %s", i, mh.sub~mode, AskAnswer); else if (strchr("Qq",*AskAnswer)) I // Shutdown if ('0' == AskAnswer [4]) ctl.enable~qputs~flag = 0; if ('1' == AskAnswer [4]) ctl.enable~qputs~flag = 1; if ('0' == AskAnswer [8]) ctl.enable qgets~flag = 0; if ('1' == AskAnswer [8]) ctl.enable~qgets~flag = 1; if 9QSUCCESS >=QsendAndReceive (Q,ADMINREQ~MODE,QADM~SET~CONTROLS, 0,sizeof (QADMCTLS), (char*) &ctl, 0, 0 &sz, &mh)) Say("puts %d gets %d",ctl.enable~qputs flag,ctl.enable qgets flag else if (strchr("Kk",*AskAnswer)) I // Shutdown ctl.shutdown~flag++; if (QSUCCESS >= QsendAndReceive (Q,ADMINREQ~MODE,QADM~SET~CONTROLS, 0, sizeof (QADMCTLS), (char*)&ctl, O,O,&sz,&mh)) Say("Shutdown"); ctl.shutdown~flag--; else if (strchr("Rr",*AskAnswer)) I // Reset ctl.full~reset~flag++; if (QSUCCESS >= QsendAndReceive(Q,ADMINREQMODE,QADM~SET-CONTROLS, 0, sizeof (QADMCTLS), (char*) &ctl, O,O,&sz,&mh)) Say("full Reset"); ctl.full~reset~flag--; else if (strchr("Zz",*AskAnswer) && (sscanf (AskAnswer, "%*s %d",&i))) if ((i) < 2) Say("Bad Size"); else { ctl.max~entries~value = if (QSUCCESS >= QsendAndReceive (Q,ADMINREQ~MODE,QADM~SET~CONTROLS 0, sizeof (QADMSTATS), (char*) &ctl, 0, 0, &sz, &mh)) Say ("Size=%d", i); ctl.max entries value = 0; else if (strchr("Tt",*AskAnswer)) ( // Kleer ctl.stats~reset~flag++; if (QSUCCESS >= QsendAndReceive (Q,ADMINREQ~MODE,QADM~SET~CONTROLS,<BR> <BR> O,sizeof(QADMCTLS) , (char*)&ctl, 0, 0, &sz, &mh)) Say("Stats reset")<BR> <BR> <BR> ctl.stats~reset~flag--;<BR> } /* else if (strchr ("x", *AskAnswer)) { // Broadcast BroadcastRT(); else if (strchr("X",*AskAnswer)) I // Get CopyRT(RT IP(RTByName(&AskAnswer[21)));<BR> else if (strchr("Hh",*AskAnswer)) Help(); else if (strchr("Bb",*AskAnswer)&&!(flags & Q~TRAN)) (flags = Q~TRAN~BEGIN else if (strchr("Cc",*AskAnswer)&&flags) Qcommit(COMMIT MODE);flags = nex<BR> <BR> <BR> else if (strchr("Aa",*AskAnswer)&&flags) {Qcommit (ABORT~MODE); flags = nex<BR> else if (strchr("Ee",*AskAnswer)) flags = Q~TRAN~END; next flag = 0;} <BR> else if (strchr("Ss",*AskAnswer)) flags = Q~TRAN~SINGLE; next flag = 0;} <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> else if (strchr("Nn",*AskAnswer)) flags = next~flag = 0;} else if (strchr("Dd",*AskAnswer)) SHAREDATA(diag) = (!SHAREDATA(diag));} else if (strchr("Oo",*AskAnswer) && AskAnswer[l] == ' ' && (strlen(AskAnsw int open~flags = 0; sscanf (AskAnswer, "%*s %s %1x", qname, &open~flags); Say("RAMQCS: Open %s flags=°sx",qname,open~flags); <BR> <BR> <BR> <BR> <BR> if (!(Q = Qopen(qname,PUT MODE,O,open flags,0,0,0))) <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> Fail("RAMQCS: could not open the que ss",qname); <BR> else <BR> Say ("Try again!"); if (flags) Diag("RAMQCS: flags %p", flags); Say("RAMQCS: ALL DONE"); return(0); ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** OpenMQ ** Module: ramqcs.c ** Author: Derek Schwenke 9/8/95 ** ** ramq's client and server ** */ #include "qlib.h" extern char AskAnswer[LINESIZE] main(int argc, char **argv) int status,sz; char qname[NAMESIZE]; MSGH mh; lpQHANDLE Q; ReadParms(); // Name that q if(argc==2) strcpy(qname,argv[1]); else strcpy(qname,"Ql"); // appl Say("Server=%s",qname); // Open the queue for putting if (!(Q = Qopen(qname,PUTTING))) Fail("APPC: could not open the que As",qname); // Ask the user to Put or Get while( strlen(Ask("RAMQS: Put Get Open?"))) if (*AskAnswer == 'p' | II *AskAnswer == 'P') Q->msgh.mode = PUTTING; if (strlen(Ask("RAMQS: Put messge"))) if (QSUCCESS == Qpng(Q,flags,strlen(AskAnswer)+l,AskAnswer, LINESIZE,AskAnsewer,&z,&mh)) Say("RAMQS: Succeded: (mode=%d) %s",mh.mode,AskAnswer); else Say("RAMQS: Qput failed"); else if (*AskAnswer == 'g' || *AskAnswer == 'G') Q->msgh.mode = REQUESTING; if (QSUCCESS == Qpng(Q,flags,strlen(AskAnswer)+1,AskAnswer, LINESIZE,AskAnswer,&sz,&mh)) Say("RAMQS: Succceded: (mode=%d) %d bytes s",mh.mode,mh.size,AskAns else Say("RAMQS: Qput failed"); else if (*AskAnswer == 'o' || *AskAnswer == '0' && strlen(AskAnswer) > 2) Say("RAMQS: Open") sscanf(AskAnswer,"%*s %s",qname); if (!(Q = Qopen(qname,PUTTING))) Fail("APPC: could not open the que %s",qname); Say("RAMQS: ALL DONE"); return(0); // // Common admin defs used by OpenMQ Qservers // //////////////////////////////////////////// #define DISABLED 0L #define ENABLED 1L #define QADM~REQ~STATS 2L #define QADM~REQ~SEL~DATA 3L #define QADM~REQ~MSG 7L #define QADM~REQ~COM~DATA 8L #define QADM~REQ~UNCOM~DATA 9L #define QADM~SET~CONTROLS 10L #define SHORT SEARCH TYPE OL #define INT~SEARCH~TYPE 1L #define STR~SEARCH~TYPE 2L #define SEARCH ALL ENT OL #define SEARCH~COM~ENT 1L define SEARCH UNCOM~ENT 2L #define KEY~STR~SIZE 50 typedef struct qadmstats CHAR logical~qname [NAMESIZE] ; // logical que name CHAR physical~qname[NAMESIZE]; // physical que server name <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> CHAR node~name [NAMESIZE] ; // node name of que server<BR> <BR> <BR> <BR> int node~address; // IP address of que server<BR> int max~entries~limit; // upper limit on max value<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> int max~entries; // current max value int committed~entries; // commited entries int pending gets; // pending GET entries <BR> <BR> int pending~puts; // pending PUT entries<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> int holey entries; // &num holes in the queue<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> int num~free~entries; // &num of free entries that can be used<BR> int amt~free~dspace; // amt of free~space left in queue<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> short qget~state; // gets~are~enabled <BR> <BR> <BR> short qput~state; // puts~are~enabled <BR> <BR> <BR> int num~puts; // committed puts only<BR> int num~gets; // committed gets int num~commits; // # of committed operations int num~aborts; // # of aborted operations int num~restarts; // # of server restarts time~t first start time; // time of fresh start time~t last restart time; // time of last restart<BR> // int num~recov~tries; <BR> <BR> <BR> <BR> <BR> // time t last recov~time; <BR> <BR> <BR> QADMSTATS, *lpQADMSTATS; <BR> typedef struct qadmctls int max entries value; // extends max entries; later...

// int clear all tran~flag; // cleans up stuck entries/compaction int full~reset~flag; int shutdown~flag; int stats~reset~flag; int enable~qputs~flag; int enable~qgets~flag; int halt flag; QADMCTLS, *lpQADMCTLS; typedef struct predstr int pred type; // predicate type int offset; // offset within QMSG structure short min~switch; // 1=ENABLED/DISABLED min switch short max~switch; // 1=ENABLED/DISABLED max switch short min~sh~val; // min short value short max~sh~val; // max short value int min~int~val; // min int value int max~int~val; // max int value char min~str~val[KEY~STR~SIZE]; // min string value char max~str~val[KEY~STR~SIZE]; // max string value int min~str~len; // min string length int max~str~len; // max string length PREDSTR, *lpPREDSTR; typedef struct qadmsel int num~preds; // number of predicates up to max of 3 int search type; // SEARCH~ALL~ENT, SEARCH~COM~ENT, SEARCH~UNCO PREDSTR preds[3]; // array of predicates QADMSEL, *lpQADMSEL; #define MAXSEL ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: qget.c ** Author: Derek Schwenke 9/8/95 ** ** ** Qget () is made from two calls: QlistenBeforeReply() // Get new data ** QreplyAfterListen() // Return ACK and maybe some data ** Both call must be made.

** */ #include "qlib.h" extern lpSMBUFH sm~base; int Qget( lpQHANDLE q, // Q handle returned by Qopen(); lpMSGH messh, // Pointer to message header to fill char *mess, // Pointer to message buffer to fill int maxsize)( // size of message buffer // Always return 1st error found // Always call reply after listen int status = QlistenBeforeReply(q,messh,mess,maxsize); if (status == QSUCCESS) status = QreplyAfterListen(q,0,0,0,0,0); else QreplyAfterListen(q,0,0,0,0,0); return(status); int QlistenBeforeReply(lpQHANDLE q, // Q handle returned by Qopen(); lpMSGH messh, // Pointer to message header to fill char *mess, // Pointer to message buffer to fill int max size)I // size of message buffer int objn, bnum, rtn, dsize, status = NOT~COMPLETE; lpSMBUF buf; if(q == NULL) Fail(Qlbr not passed handle"); if(max~size == 0) Fail("Qlbr not passed any message buffer"); // When your Qopen(GETTING) you reserve buffers, so we want // to wait on one becoming READY.

// When it is ready, we copy the data out.

Diag("Qlbr[-] . waiting for one of %d buffers to become ready ",q->num~bufs // Wait for a buffer rtn = WaitForMultipleObjects(q->num~bufs, q->readyh, FALSE,INFINITE); // objn = rtn - WAIT~OBJECT~0; if ((objn < 0) (objn > q->num~bufs)) Fail("Qlbr[-] : WaitForMultipleObjects fails [%d] ",rtn) bnum = q->bufs~found[objn]; Diag ("Qlbr[%d] . Wait ForMultipleObjects got object %d mode=%d",bnum,objn,q->ms buf = SMBUFADDR(bnum); // Read the message out of the buffer dsize = min(max~size, buf->msgh.size); memcpy(messh,&buf->msgh,sizeof(MSGH)); memcpy(mess,&buf->mdata,dsize); status = QSUCCESS; // Return without notifying the sender i.e. without releaing "done" // Qral will be called next to do that q->cur~objn = objn; // Save for Qral() to use.

Diag("Qlbr [%d]: returns",bnum); return(status); int QreplyAfterListen( lpQHANDLE q, // Handle returned by Qopen() int mode, // Optional type of message int sub~mode, // Optional User defined type of messa char *mess, // Reply message to send int size, // Size of reply messsage lpMSGH mh) ( // Optional message header int objn, bnum, status=QSUCCESS; lpSMBUF buf; if(!q) Fail("Qral: not passed handle"); if(q->curobjn == -1) Fail("Qral called out of order"); // Retrieve handels objn = q->cur~objn; bnum = q->bufs~found[objn]; buf = SMBUFADDR(bnum); q->cur~objn = -1; Diag("Qral[%d] object %d", bnum,objn); // Consturct the message header buf->msgh.size = size; if (mh) buf->msgh.mode = mh->mode buf->msgh.sub~mode = mh->sub~mode; // buf->msgh.size = mh->size // removed 12/27/95 by derek, passed size sho buf->msgh.reply~smbuf = mh->reply~smbuf; if (mode) buf->msgh.mode = mode; if (sub mode) buf->msgh.sub~mode = sub~mode; // Copy any message data if (buf->msgh.size = ~min(buf->msgh.size,MAXMSGDATA)) <BR> <BR> memcpy(&buf->mdata,mess,buf->msgh.size); <BR> <BR> <BR> <BR> else strcpy(buf->mdata,""); // Clear the whole buffer? Diag("Qral[%d]: releases done %d",bnum,objn); buf->status = SMBUF~RETURN~MESS; if (!ReleaseSemaphore(q->doneh[objn],1,0)) Warn("Qral : ReleaseSemaphore done #%d",bnum,GetLastError()); SHAREDATA(stat.gets)++; // Statistics Diag("Qral[%d]: returns(%d)",bnum,status); return(status); // Common routines and definitions used by OpenMQ // Size of shared memory #define LINESIZE 1024 &num define NAMESIZE 20 #define ROUTNAME "c:\\q\\routing.txt" #define PARMNAME "c:\\q\\parms.txt" #define MLOGNAME "c:\\q\\qlog1.txt" #define TLOGNAME "c:\\q\\tranlog.txt" #define SMEMNAME "Q/SHAREDMEMORY" #define SMEMTABLE "Q/SHAREDTABLE" &num define MUTQOPEN "Q/QOPEN" &num define MUTFREFMT "Q/SMB FREE %d" #define SEMRDYFMT "Q/SMB~READY~%d" #define SEMDONFMT "Q/SMB~DONE~%d" #define SEMACKFMT %Q/SMB~ACK~%d" #define CLASSNAMES "classO classl class2 class3" &num define SMBUFADDR(X) (lpSMBUF) ((int) sm~base + (X * sizeof(SMBUF)) + size 4define MAXSMSIZE(X) sizeof(SMBUFH) + X * sizeof(SMBUF); #define BITSET(X,Y) ((X & Y) == X) #define MAXMSGDATA (MAXTXSIZE - sizeof(MSGH)) #define SHAREDATA(X) (sm~base->X) #define MAXTXSIZE 8192 #define MAXNSMBUF 32 #define MAXRTSIZE ((MAXTXSIZE - sizeof(MSGH)) - 10) // bytes #define MAXFOLENT 8 #define FD SETSIZE 64 /* Number of sockets */ //#define RTROOT (lpRT) ((lpSMBUFH) sm~base)->RT #define RTROOT (lpRT) sm~base->RT[sm~base->rt~pingpong] // Return codes #define QSUCCESS~FAILOVER 1L *define QSUCCESS 2L #define NO~SUCH~QUEUE llL #define NO~MORE~SHARED~MEM 12L #define NOACK - 13L #define NOT~COMPLETE 14L #define WRONG~SMBUF~STATUS 15L #define QFAIL 16L #define QTOOBIGMESS 17L #define NO QNETD 18L #define QMODE~MISSMATCH 19L // Message Modes or message Types #define PUT MODE 2L #define GET~MODE 3L #define REQUEST~MODE 4L #define ACK MODE 8L #define NACK~MODE 9L #define COMMIT~MODE 10L #define ABORT~MODE 11L &num define ADMINREQ MODE 20L &num define ADMINREP MODE 21L &num define QNETDREQ~MODE 3CL #define QNETDREP~MODE 31L // Message sub~modes used by QNETD #define QNETD~TRAN~INQ 2L #define QNETD~RT~BROADCAST 3L #define QNETD~BUF~STATUS 4L // Message sub modes used by QUE servers #define SUB~MODE~OK 0L #define SUB~MODE~EMPTY 11L #define SUB~MODE~FULL 12L #define SUB~MODE~DISABLED 13L #define SUB~MODE~INV~INDX 14L // invalid que entry number #define SUB~MODE~INV~TID 15L // invalid TID for pending list search #define SUB~MODE~BAD~REQ 16L // Transactio inquiry msg modes #define Q~COMMIT COMMIT~MODE #define Q~ABORT ABORT~MODE define Q~INPROGRESS 12L *define Q~WRONGHOST 13L // Shared Memory Buffer Status Codes #define SMBUF~EMPTY 0L #define SMBUF~SEND~MESS 1L #define SMBUF~RETURN~MESS 2L #define SMBUF~RETURN~FAIL 5L #define SMBUF~GET~MESS 10L #define SMBUF~GOT~MESS 11L #define SMBUF~SEND~REMOTE 100L // Qopen & Qput & Qget flags #define Q~LOG (0x00000001L) // Log this message (not required if T #define Q~TRACE (0x00000002L) // Generate trace entries for this mes #define Q~ASYNC (0x00000004L) // Dont wait for the message to get to #define QFAILOVER (0x00000008L) // Enable failover (if its defined in #define Q~TRAN (0x00000010L) // Use two phase commit #define Q~TRAN~BEGIN (0x00000030L) // Start the tran #define Q~TRAN~END (0x00000050L) // End the tran (commit) #define Q~TRAN~SINGLE (0x000000FOL) // Both start and end // Includes //////////////////////////////////////////////////////////// //////// *include <stdlib.h> // for exit() call #include <malloc.h> // for malloc() call #include <studio.h> // for printf() call #include <windows.h> // HANDLE definition #include <time.h> // for mid time() //#include <windowsx.h> // ListBox~AddString // Structures //////////////////////////////////////////////////////////// ////// typedef struct mid ( // Message header int host; // IP of sender int tid; // incremnets on each tran. 0= not transactional int uid; // unique ID for each msg entry MID, *lpMID; typedef struct mlist I // List of MIDs struct mlist *next; MID mid; ) MLIST, *lpMLIST; typedef struct msgh ( // Message header int type~coding; // Header version, and machine coding format short mode; // Message type (Putting or Getting) short sub~mode; // User defined sub~mode int flags; // 32 bit message flags time~t time; // Time (set but not used) MID mid; // Last Unique message id (struct?) int to~node; // ip target int toport; // qnetd port on the target or sm buffer # int to~smbuf; // Shared memory buffer of receiver int from~smbuf; // Shared memory buffer of sender i.e. QNETD#1 int reply~smbuf; // Shared memory buffer for reply messages char to~server[NAMESIZE]; // Physical queue server name char to~logical [NAMESIZE] ; // Logical queue name int size; // size of the message MSGH, *lpMSGH; typedef struct qhandle ( // Que Handle struct qhandle *next; // Next handle if in chain MSGH msgh; // Prototype message header time~t open~time; // Time the open() was made int base~flags; // Flags to be used in all ops short cur bjn; // Current object (buff) number int time~out; // minimum time-out on this node short rt~rev; // Rev of the Routing Table that was used short num~bufs; // Number of buffers where service was found short bufs found [64]; // Buffers where the service was found HANDLE freeh[64]; // Handles for the "free" mutex for each buffer HANDLE readyh[64]; // ??notset? Handles for the "ready" semephore for ea HANDLE doneh[64]; // ??notset? Handles for the "done" semephore for eac HANDLE, *lpQHANDLE; typedef struct smobjs ( // Sync Obj for 1 Shared Memory Buffer HANDLE freeh; // Handle for the "free" mutex for each buffer HANDLE readyh; // Handle for the "ready" semephore for each buffer HANDLE doneh; // Handle for the "done" semephore for each buffer HANDLE ackh; // Handle for the "ack" semephore for each buffer SMOBJS, *lpSMOBJS; typedef struct smbuf ( // Shared memory buffers char name[NAMESIZE]; short status; short sub~status; // Currently not used! MSGH msgh; char mdata[MAXMSGDATA] ; SMBUF, *lpSMBUF; typedef struct aps { // any app specific shared data int app~num; // this is not accessed by OpenMQ int appdatl; int appdat2; int appdat3; j APS, *lpAPS; typedef struct stat int opens,openrep,closes; int puts,gets; int tx,rx; int commit,abort; int warn, fail; STAT, *lpSTAT; typedef struct fol char name [NAMESIZE] ; // Logical queue name int puts,gets; // Operations that fail int ip; // Addres to fail to } FOL, *lpFOL; /* typedef struct st { // QNETD Sockets Table struct st *next; int ip; int port; SOCKET s; // SOCKET def requires sock.lib } ST, *lpST; */ // Shared memory // ------------- typedef struct smbufh { // Shared memory header (global data area) int tran~id; // Current unique tran id for this node.

int unique~id; // Current unique message id for this node.

int hostip; // This nodes IP short diag; // Diagnostics On/Off short nsbuf; // Number of shared buffers int time~out; // minimal timeout on this node short failed~servers; // number of failures detected int time; - // now (watchdog's clock) int start~time; // time shared mem was initialized int rt~rev; // rev of last RT update (MINOR) int rt~ver; // version of last RT received (MAJOR) int rt~pingpong; // RT Buffer to use int tmpl; // not used int tmp2; // not used int tmp3; // not used APS ap; // not used (used by oentry) STAT stat; // Statistics char hostname [NAMESIZE]; // Hostname // int sockets // Number of active sockets // ST ST[MAXFOLENT]; // Socket table FOL FO[MAXFOLENT] // Fail over list char RT[2] [MAXRTSIZE]; // Routing table } SMBUFH, *lpSMBUFH; // Routing table typedef struct rt ( // Routing Table in shared memory int ip; int qnetd~port; // int next~offset; int ntype~index; // int apps~index; // char s[4]; // node\0ntype\0apps\0 «More than 4 char>> ) RT, *lpRT; // Global data ///////////////////////////////////////////////// // C++ does not allow 2nd define of variables.

*ifndef Q~LIB #define Q~LIB lpSMBUFH sm base; // Base address of shared memory segment // lpQHANDLE FLroot; // Linked list of (any) failed servers char AskAnswer[LINESIZE] ; // Defined in print.c *endif // Routines //////////////////////////////////////////////////////////// //////// Xifdef CPP extern "C" *endif void Say(); // Dont check any parameters void Fail(); // Dont check parameters void Warn(); // Dont check parameters void Diag(); // Dont check parameters char *Ask() ; // Dont check parameters //void Mlog(char *msg); // &num define Diag if (SHAREDATA(diag)) Say Made a call so "if" doesnt mess up int ReserveSharedBuffer( int seqno, char *bname, int bstatus, lpSMOBJS sync); int UnReserveSharedBuffer(int bnum); lpQHANDLE Qopen( char *que~name, // Queue name (logical) short mode, // Predefined Mode (PUT~MODE/GET~MODE) short sub~mode, // Userdefined sub~mode int flags, // Optional Flags (input) int *status, // Optional detailed failure code (out int buffers, // Optional number of buffers to make int index); // Optional index of server to be open lpQHANDLE QopenReply(lpQHANDLE q, // Optional existing q handle to be re lpMSGH mh, // Message to reply to int flags, // Optional Flags for Qopen() char *name, // Optional server name int *status); // Optional detailed status code int QreOpen( lpQHANDLE q); // Get new buffer and routing info int Qclose( lpQHANDLE *ppq, // Optional Queue handle OR char *bname); // Optional name must be specifed int Qput( lpQHANDLE q, // Q handle returned by Qopen(); short mode, // Optional mode for this put; short sub~mode, // Optional sub~mode for this put; int flags, // Optional Extra flags for this Put() int size, // Number of bytes to transfer char *buffer); // Optional Buffer that holds the mess int QsendAndReceive(lpQHANDLE q, // Q handle returned by Qopen(); int mode, // Optional Mode for this put int submode, // Optional SubMode for this put int putflags, // Optional flags for this Put; int putsize, // Number of bytes to transfer char *putbuf, // Optional Buffer that holds the mess int maxgetsize, // Optional size of get buffer char *getbuf, // Optional buffer fill with message d int *gotsize, // Optional number of bytes filled.

lpMSGH gothead); // Optional got message header.

int Qget( lpQHANDLE q, // Q handle returned by Qopen(); lpMSGH messh, // Pointer to message header to fil char *mess, // Pointer to message buffer to fill int maxsize) ; // size of message buffer int QlistenBeforeReply(lpQHANDLE q, // Q handle returned by Qopen(); lpMSGH messh, // Pointer to message header to fill char *mess, // Pointer to message buffer to fill int max~size); // size of message buffer int QreplyAfterListen( lpQHANDLE q, // Handle returned by Qopen() int mode, // Optional type of message int sub~mode, // Optional User defined type of messa char *mess, // Reply message to send int size, // Size of reply messsage lpMSGH mh); // Optional message header void Qcommit ( int action); // Commit or abort int FindSMBuffers( lpQHANDLE q, int targetsip, // Local or Remote IP char *physical~name, // Blank if not used int target~smbuf); // -1 if not used lpSMBUFH AttachSharedMemory(); // Used by graphic apps void SetWinPtr(HWND WinptrX); // Printing to GUI output void ForcedBufferReset(int bnum, // Optional Buffer number (-1 = not us lpQHANDLE q, // Optional Queue Handle int objn); // Optional objet number in Queue Hand *ifdef CPP #endif *ifdef QLIB // Routines that only QLIB uses (Not API) lpRT ServerByName2(lpRT rtp, char *name, int index, char *physical); void TLadd(lpQHANDLE q); // From tran.c void SetTID(lpMID m, int flags); lpRT RTByIP(int IP); void PrintRT(lpRT r,char * s); #endif //////////////////////////////////////////////////////////// ///////////////////<BR> // Qnetd.h //////////////////////////////////////////////////////////// /////////////////// #include winsock.h> // Structures /////////////////////////////////////////////// typedef struct st I // QNETD Sockets Table struct st *next; // int ip; int port; SOCKET s; // SOCKET def requires sock.lib ST, *lpST; // Routines //////////////////////////////////////////////////////////// //////// //void ReadRT(); // QLIB call move it to qnetd? LPVOID SharedMemInit(int nsbuf); DWORD ListenConn(); DWORD ListenSMBuff(); DWORD WatchDog(); int SendRemoteMess(lpSMBUF buf, int pass); lpST AddSocketToTable(SOCKET sock,SOCKADDR~IN *sa); lpRT RTByName(char *name); //QLIB call used by QNETD/tcp.c int ResolveTran(lpMID MID); //QLIB call used by QNETD to return admin messa void ReadParms(int *nsbuf); int Str2Port(char *str); ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: qopen.c ** Author: Derek Schwenke 9/8/95 ** Qopen?Qclose API calls */ #include "qlib.h" 4include "rt.h" extern lpSMBUFH sm~base; int FindSMBuffers( lpQHANDLE q, int targetsip, // Local or Remote IP char *physical name, // If local, name must be set int target~smbuf) t // -1 if not used int i = 0; int found = 0; char searchfor[NAMESIZE]; // Buffer name char freen[NAMESIZE]; // Syncronization object name char readyn[NAMESIZE]; // Syncronization object name char donen[NAMESIZE]; // Syncronization object name // This routine finds the buffers to use ON THE LOCAL NODE, to // communicate. If the targetsip is remote, then it returns // the buffers that QNETD will listen to.

// Messages can be sent to logical services // Reply messages are sent to specific smbuffers if (SHAREDATA(hostip) == targetsip) { // then its local strcpy(searchfor,physical~name); if (target smbuf != -1) i = target~smbuf; else ( // its not local Diag("The physical server of 5 is not local!",physical~name); strcpy(searchfor,"QNETD"); q->num~bufs = 0; while (i < SHAREDATA(nsbuf)) lpSMBUF bp = SMBUFADDR(i); if ((!strcmp(bp->name,searchfor)) II (i==target~smbuf)) I // Found a buffer // Get a handle for this buffer // Pack the handle into arrays so we can wait on any one of them.

sprintf (freen, MUTFREFMT, i); sprintf(readyn,SEMRDYFMT,i); sprintf(donen, SEMDONFMT, i); if (!(q->freeh[q->num~bufs] = OpenMutex( SYNCHRONIZE, FALSE, freen) Fail("Could not OpenMutex 5 Error=%d", freen, GetLastError()); if (!(q->readlyh [q->num~bufs] = OpenSemaphore (SEMAPHORE~MODIFY~STATE|SIN Fail("Could not OpenSemaphore 5 Error=%d", readyn, GetLastError()); if (!(q->doneh[q->num~bufs] = OpenSemaphore(SEMAPHORE~MODIFY STATEISYN Fail("Could not OpenSemaphore -"s Error=%d",donen,GetLastError()); q->bufs~found [q->num~bufs++] =i; Diag(" Buffer %d [-s] found ", q->num~bufs, searchfor); if (q->num~bufs == 64) continue; // Stop looking if (i++ == target~smbuf) i = SHAREDATA(nsbuf) ; // We are done with just o if(q->num~bufs) Diag ("Qopen [%s] found %d buffers", searchfor, q->num~bufs); else Warn ("Qopen [%s] No such server No buffers were found!",searchfor); return (q->num~bufs); lpQHANDLE Qopen ( char *que~name, // Queue name (logical) short mode, // Predefined Mode (PUT~MODE/GET~MODE) short sub~mode, // Userdefined sub mode int flags, // Optional Flags (input) int *status, // Optional detailed failure code ( int buffers, 7/ Optional number of buffers to make int index { // Optional index of server to be open // When called for PUT~MODE, just look for existing SMBUFers using this queue n // When called for GET~MODE, reserve a new set of buffers under the name int rtn, found = 0, stat = QSUCCESS; lpQHANDLE q = (lpQHANDLE) malloc(sizeof(QHANDLE)); lpRT rt=NULL; char physical~name[NAMESIZE]; HANDLE mutex; // Attach to shared memory <BR> <BR> if (!sm~base) {<BR> if('( sm~base = AttachSharedMemory()<BR> <BR> *status = NO~QNETD; return (0); } Diag ("Qopen (%s) opens mutex", que~name); if (!(mutex = OpenMutex(MUTEX~ALL~ACCESS, FALSE, MUTQOPEN))) // Ser <BR> <BR> <BR> <BR> <BR> Fail ("Qopen (%s): Cant OpenMutex %s %d", que~name, GetLastError ()); // Fails<BR> <BR> if ((rtn = WaitForSingleObject (mutex, INFINITE)) !=WAIT~OBJECT~0) Fail ("Qopen (%s): Failed while waiting for mutex 5 %d", que~name, &MUTQOPEN if (!q) Fail ("Qopen (%s) malloc error", que~name); // memset(q,0,sizeof(QHANDLE)); // Find this queue in the RT // If gettting look for servers on this node ,n if (mode == GET MODE) q->msgh.to~node = SHAREDATA(hostip); q->msgh.to~port = 0; strcpy(physical~name,que~name); // rt = ServerByName2 (RTByIP (SHAREDATA (hostip)), que~name, index, physical~na else ( // PUT~MODE rt = ServerByName2 (RTROOT, que~name, index,physical~name); if (|rt) // It's not in the routing table but check the local node anyway if (FindSMBuffers (q, SHAREDATA (hostip), que~name,-1)) { rt = RTByIP(SHAREDATA(hostip)); // Return- this node strcpy(physical~name,que~name); // Assign values from RT into handle if (rt || mode == GET MODE) if (rt) q->msgh.to~node = rt->ip q->msgh.to~port = rt->qnetd~port; strcpy(q->msgh.to~server,physical~name); q->msgh.type~coding = 1; q->msgh.flags = 0; q->msgh.mode = mode; q->msgh.sub~mode = sub~mode; q->msgh.mid.host = SHAREDATA(hostip); q->msgh.mid.tid = C; q->msgh.time = 0; q->msgh.to~smbuf = -1; strcpy (q->msgh.to~logical, que~name); q->msgh.from~smbuf = 0; q->msgh.size = °; q->base~flags = flags; // Flags used for all future access q->cur~objn = -1; // SMBUF number being used.

q->num~bufs = 0; // number of buffers found.

q->next = NULL; // Pointer to chain of handles q->open~time = SHAREDATA(time); //time (&q->open~time); if (mode == GET~MODE) q->time~out = INFINITE; // Ox7FFFFFFF; // 24 days else q->time~out = SHAREDATA (time~out); if (mode == PUT~MODE) { // Dont allocate, just find a list of existing buffers if ( ! FindSMBuffers (q,q->msgh.to~node,physical~name,-1)) stat = NO SUCH QUEUE; } else if (mode == GET~MODE) { // make a set of new buffers SMOBJS sync; int i,b, seqno = 0; int dontcheck = (buffers == -1); // Dont check for stale existing bufle // Reserve Shared buffers if (buffers == -1) seqno = 999; if (buffers < 1) buffers = 1; if (buffers > SHAREDATA(nsbuf) - 1) buffers = SHAREDATA(nsbuf) - 1; Diag("Qopen(%s) for GET~MODE: reserving 1;d buffers",que~name,buffers); for ( i = 0 ; i < buffers ; i++ )( if (-1 != (b = ReserveSharedBuffer( seqno++, physicalname, SMBUF~EMPTY, &sync) q->bufs~found[i] = q->num~bufs++; q->freeh[i] = sync.freeh; q->readyh[i] = sync.readyh; q->doneh[i] = sync.doneh; else Say("Qopen(9 s) for GET MODE: Failed, got %d of %d buffers",que~na if (i==0) stat = NO~MORE~SHARED~MEM; break; Diag("Qopen(ts) for GET~MODE: reserved %d buffers",que~name,buffers); // end of PUTTING or GETTING else ( // No rt route was found PrintRT(RTROOT,""); stat = NO~SUCH~QUEUE; Warn("Qopen(%s) NO-SUCH~QUEUE",que~name); if (stat != QSUCCESS) free(q); q = NULL; ReleaseMutex(mutex); // Mutex on all QOpen() calls if (status) *status = stat; return(q); int Qclose( lpQHANDLE *ppq, // Optional Queue handle OR char *bname)( // Optional name must be specifed lpQHANDLE qp; int i; // Attach to shared memory if(!sm~base){ if(!( sm~base = AttachSharedMemory() )) return(NO QNETD); if (bname){ Diag("Qclose(ks) by name",bname); for (i = 0; i < SHAREDATA(nsbuf) ; i++) // All buffers if (!strcmp((SMBUFADDR(i))->name,bname)) UnReserveSharedBuffer(i); } else if(ppq) if (qp = *ppq) if (qp->msgh.mode == GET~MODE) ( // Release any buffers .. perhaps num Diag("Qclose(%s) by handel",(SMBUFADDR(qp->bufs~found[0]))->name); for (i = 0; i < qp->num~bufs ; i++) if(UnReserveSharedBuffer(qp->bufs~found[i])) free(qp); *ppq = NULL; return(QSUCCESS); // Used for putting messages back to the sender (use if the sender is listeni lpQHANDLE QopenReply(lpQHANDLE q, // Optional existing q handle to be re lpMSGH mh, // Message to reply to int flags,// Optional Flags for Qopen() char *name, // Optional server name int *status) ( // Optional detailed status code int stat = QSUCCESS, bnum; if(!smbase)( // This cant happen. you must Qopen first.

if (! ( sm~base = AttachSharedMemory () )) if (status) *status = NO~QNETD; return(0); if (!q) { q = (lpQHANDLE) malloc(sizeof(QHANDLE)); if (!q) Fail("QopenReply Malloc error"); memset(q,0,sizeof(QHANDLE)); if (mh) // Construct que handle from messge header q->msgh.type~coding = 1; q->msgh.mode = PUT~MODE; q->msgh.sub~mode = 0; q->msgh.flags = flags; q->msgh.mid.host = SHAREDATA(hostip); q->msgh.mid.tid = o; q->msgh.time = 0; q->msgh.to~node = mh->mid.host; q->msgh.to~port = 0; q->msgh.to smbuf = mh->reply~smbuf; if (name) T strcpy(q->msgh.to~server,name); strcpy(q->msgh.to~logical,name); q->msgh.from~smbuf = 0; q->msgh.reply~smbuf = 0; q->msgh.size = 0; q->base~flags = flags; q->curobjn = -1; q->num~bufs = 0; q->next = NULL; // Pointer to chain of handles q->open~time = SHAREDATA(time); q->time~out = SHAREDATA(time~out); //time(&q->open~time); // Get a list of buffers for this service bnum = mh->reply~smbuf; if (name) if (!strcmp(name,"QNETD")) bnum = 0; if( ! FindSMBuffers(q,mh->mid.host,"",bnum)) stat = NO~SUCH~QUEUE; else Say("QopenReply() was not passed a message header"); stat = NO SUCH QUEUE; if (status) *status = stat; if (stat == QSUCCESS) return(q); free(q); return(0); int QreOpen( lpQHANDLE q){ // Existing q handle to be replaced lpRT rt=NULL; if (!q) return(NO~SUCH~QUEUE); if (q->msgh.mode == GET~MODE) return(QMODE~MISSMATCH); rt = RTByService(q); if (!rt) ( // Its not in the routing table but check the local node anyway if (SMByName(q->msgh.to~logical)) rt = RTByIP(SHAREDATA(hostip)); // Return this node strcpy(q->msgh.to~server,q->msgh.to~logical); // Assign values from RT into handle if (rt) q->msgh.to~node = rt->ip q->msgh.to~port = rt->qnetd~port; // Get a list of buffers for this service if( ! FindSMBuffers(q,q->msgh.to~node,q->msgh.to~server,-1)) // q->msgh.to.s return(NO~SUCH~QUEUE); return(0); int ApClose( lpQHANDLE ap )( free(ap); return (QSUCCESS) ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: qprint.c ** Author: Derek Schwenke 9/8/95 ** Printing routines used by OpenMQ */ #include "qlib.h" #include <windowsx.h> //&num define Diag(X) if(diag) (Say(X);) // Global Data //////////////////////////////////////////////////////////// ///// FILE *MLOG = NULL; // Message Log File // HANDLE *MLOG = NULL; // Message Log File HWND *LogWin; // Global data - Handle for printing to window int LogWinIndex=0; // Index of last lines written to the logwin // extern int diag; void SetWinStr(HWND WinStr)( LogWin = Winptr; <BR> <BR> ListBox ResetContent(LogWin); <BR> <BR> <BR> ListBox-SetCurSel(LogWin,LogWinIndex++); // Routines //////////////////////////////////////////////////////////// //////// void Mlog(char *msg) ( // Log to a file // int len,i,j; // char line[LINESIZE]; ((ifdef GUI //char line2[LINESIZE]; //TRACE(msg); // ListBox~InsertString <BR> <BR> ListBox AddString(LogWin,msg); <BR> <BR> <BR> ListBoxrSetCurSel(LogWin,LogWinlndex++); *endif if ( ! MLOG if ((MLOG = fopen(MLOGNAME,"a")) == NULL /* if if ( NULL == ( MLOG = CreateFile( MLOGNAME GENERIC WRITEIGENERICREAD, FILE~SHARE~WRITE|FILE~SHARE~READ,0, OPEN ALWAYS FILE~ATTRIBUTE~NORMAL,0))) //FILE~FLAG~WRITE~THROUGH */ printf("ERROR CAN NOT OPEN LOG FILE %s",&MLOGNAME); 000106 return; } fprintf(MLOG,"%s\n",msg); /* len = strlen(msg); // Make each \n into a \r\n for (i=j=0;i<leni++,j++){ if (msg[i] == line[j++] = line[j] = msg[i]; sprintf(line,"%s\r\n",msg); WriteFile(MLOG,line,strlen(line),&len,NULL) */ } void Sat( char *msg, void *al, void *a2, void, *a3, void *a4, void *a5, void *a6) char line[LINESIZE]; sprintf(line,msg,al,a2,a3,a4,a5,a6); #ifndef GUI printf("%s\n",line); endif Mlog(line); // char AskAnswer[LINESIZE]; char * Ask( char *msg, void *al, void *a2, void *a3, void *a4, void *a5, void *a6) char line[LINESIZE]; sprintf(line,msg,al,a2,a3,a4,a5,a6); strcat(line," >"); #ifndef GUI printf("%s,line); *endif Mlog(line); #ifndef GUI gets(AskAnswer); #endif Mlog(AskAnswer); return (AskAnswer) void Diag( char *msg, void *al, void *a2, void *a3, void *a4, void *aS, void *a6) if (SHAREDATA(diag)) Say(msg,al,a2,a3,a4,a5,a6); void Warn( char *msg, void *al, void *a2, void *a3, void *a4, void *a5, void *a6) char line[LINESIZE]; if(sm~base) SHAREDATA(stat.warn)++; sprintf(line,"\nWARNING: %s\n",msg); Say(line,a1,a2,a3,a4,a5,a6); void Fail( char *msg, void *al, void *a2, void *a3, void *a4, void *a5, void *a6) char line[LINESIZE]; char mbline[LINESIZE]; int r=O; if(sm~base) SHAREDATA(stat.fail)++; sprintf(line,"\nError: %s\n",msg); Say(line,al,a2,a3,a4,a5,a6); sprintf(line,"\nError: %s\nClick 'Retry' or 'Ignore' to continue",msg); sprintf(mbline,line,al,a2,a3,a4,a5,a6); r = MessageBox(NULL,mbline,"FATAL ERROR DETECTED",MB~ICONSTOP MB~ABORTRETRYIG if( r == IDABORT ) { Say("Bye\n",0,0,0,0,0,0); ExitThread(0); <BR> <BR> <BR> <BR> else Say("CONTINUES AFTER FATAL ERROR",0,0,0,0,0,0); /* Ask("Type any character to continue or return to exit",0,0,0,0,0,0); if (strlen(AskAnswer)) Say("CONTINUES AFTER FATAL ERROR",C,O,C,O,O,O); } else ( Say ("Bye\n",0,0,0,0,0,0); //4ifndef GUI // exit (0); ExitThread (0); // Try this //#endif ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** OpenMQ ** Module: qput.e ** Author: Derek Schwenke 9/8/95 */ #include "qlib.h" 'include "r=.h" extern lpSMBUFH sm base; //extern ipQHANDLE FLroot; //////////////////////////////////////////////////////////// //////////////////// int Qput ( lpQHANDLE q, // Q handle returned by Qopen(); short mode, // Optional mode for this put; short sub~mode, // Optional sub~mode for this put; int flags, // Extra flags for this Put(); int size, // Number of bytes to transfer char *buffer) ( // Buffer that holds the messages.

return(QsendAndReceive(q,mode,sub~mode,flags,size,buffer,O,0 ,0,O)); int QsendAndReceive(lpQHANDLE q, // Q handle returned by Qopen(); int mode, // Optional Mode for this put int sub~mode, // Optional SubMode for this put int putflags, // Optional flags for this Put; int putsize, // Number of bytes to transfer char *putbuf, // Buffer that holds the messages.

int maxgetsize, // Optional size of get buffer char *getbuf, // Optional buffer fill with message data int *gotsize, // Optional number of bytes filled.

lpMSGH gothead) ( // Optional got message header.

int objn, bnum, rtn, status = NOT~COMPLETE, maxpass, pass = 0,ms; lpSMBUF buf; if (q == NULL) Warn("Qsar[-] passed NULL handle"); return(NO SUCH QUEUE); if (q->num~bufs == 0) if (QreOpen(q) != 0) Warn("Qsar[-]: passed bad handle, no buffers after Qreopen()"); return(NO~SUCH QUEUE); if (putsize > MAXMSGDATA) Warn("Qsar[-] : Message data too big s d',putsize); return (QROOBIGMESS); q->msgh.flags = q->base~flags | putflags; if (q->msgh.flags & Q~FAILOVER) maxpass = 3; else maxpass = 1; while (pass < maxpass) ( // loop "contine" if error "break" if good if (pass) MarkFailedServer(q); if (q->rt~rev < SHAREDATA(rt~rev)) UpdateHandle(q); pass++; // Wait for a buffer Diag ("Qsar [-]: waiting for one of %d buffers to become free. .",q->num~buf if (putflags) Diag ("Qsar [-]: flags = %p", putflags); rtn = WaitForMultipleObjects (q->num~bufs, q->freeh, FALSE, q->time~out-500); objn = rtn - WAIT~OBJECT~0; if ((objn < 0) || (objn > q->num~bufs)) { int abn = rtn - WAIT ABANDONED~0; if (q->num~bufs == 0) Warn("Qsar[-] : Bad handle: has no buffers"); continue; else if (rtn == WAIT~TIMEOUT) Warn ("Qsar [-]: timeout"); continue; else if ( (abn >= 0 ) && (abn < q->num~bufs) Warn ("Qsar [-]: Waiting on abandoned obj %d", abn); continue; Fail("Qsar[-] : WaitForMultipleObjects fails [%d] on s d objects",rtn,q-> continue; // Should report some error here.

bnum = q->bufs~found[objn]; buf = SMBUFADDR(bnum); // Diag ("Qsar [%d=%s]: WaitForMultipleObjects got object %d",bnum,buf->name // Safty check the identy of the buffer if(*q->msgh.to~server) // if you know the name ("reply msgs only know the if(strcmp(q->msgh.to server,buf->name)) if( C != strncmp(buf->name,"QNETD",4)) Warn ("Qsar [%d=%s]: Stale handle. Wanted [%s] got [%s]", bnum, buf->name, q->msgh.to~server, buf->name); ForcedBufferReset (-1,q,objn); // Maybe re-open here? QreOpen(q); continue; // Transfer the data to the buffer memcpy(&buf->msgh,&q->msgh,sizeof(MSGH)) memcpy(&buf->mdata,putbuf,putsize); buf->msgh.size = putsize; // buf->msgh.flags = buf->msgh.flags | putflags; buf->status = SMBUF SEND MESS SetTID(&buf->msgh.mid,buf->msgh.flags); // Set uid and not time() buf-omsgh.time = SHAREDATA(time); if (mode) buf->msgh.mode = mode; // Else use default from Qope if (sub~mode) buf->msgh.sub~mode = sub~mode; // Else use default from Qope // Notify the reciver Diag ("Qsar [%d=%s] . ReleaseSemaphore ready object %d starts mode=%d", bnum,buf->name,objn,buf->msgh.mode); if (!ReleaseSemaphore (q->readyh [objn],1,NULL)) Warn ("Qsar [%d=%s] . ReleaseSemaphore ready failed handle %p &num ';d", bnum,buf->name,q->readyh [objn], GetLastError()) ForcedBufferReset(-1,q,objn); status = QFAIL; // How to recover here? // Wait for an answer if (buf->msgh.to~node == SHAREDATA(hostip)) //leave time for remote to ms = q->time~out; // Local should be faster else ms = q->time~out + (q->time~out)/4; // Remote is slower Diag ("Qsar [%d=%s]: Waiting for done object %d starts %d ms", bnum,buf->name, objn,ms); if ((rtn = WaitForSingleObject(q->doneh[objn],ms)) != WAIT~OBJECT~0) { if (rtn == WAIT~TIMEOUT) Warn ("Qsar [%d=%s]: WaitForSingleObject WAIT~TIMEOUT after %d ms",bnu else Warn ("Qsar [%d=%s]: WaitForSingleObject GetLastError = %d",bnum,buf-> status = QFAIL; // Add new desciptive status code here? ForceBufferReset )-1,q,objn); continue; // Check the answer if(buf->status != SMBUF~RETURN MESS) Warn ("Qsar [%d=%s]: GOT A BAD BUFFER STATUS [%d]",bnum,buf->name,buf->ct if (buf->status == SMBUF~RETURN~FAIL) status = QFAIL; else status = WRONG~SMBUF~STATUS; ForcedBufferReset(-l,q,objn); continue; if (pass == 1) status = QSUCCESS; else status = QSUCCESS~FAILOVER; // Get the reply's data if (getbuf && maxgetsize) int gotsz = min(maxgetsize,buf->msgh.size); if (gotsize) *gotsize = gotsz; memcpy(getbuf,&buf->mdata,gotsz); if (gothead) ( // if the caller wants to see the header, copy it.

memcpy(gothead,&buf->msgh,sizeof(MSGH)); // release the buffer if(!ReleaseMutex(q->freeh[objn])) Warn("Qsar[%d=%s]. . ReleaseMutex object %d failed &num %d", bnum,buf->name,objn,GetLastError()); // If it's transactional, add to the open transaction list // Perhaps the single tran case can be optimised not to reget the buffer? if(putflags & Q~TRAN) TLadd(q); // If it's the end of a transaction, then COMMIT if ((putflags & Q~TRAN END) == Q~TRAN~END) Qcommit(Q~COMMIT); // API call break; // We got this far, so it must have not failed.

// Loop 3 attempts to send if (status <= QSUCCESS) SHAREDATA(stat.puts)++; return(status); ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: routab.c ** Author: Derek Schwenke 9/8/95 ** ** Routing table functions */ &include "qlib.h" 4include "qnetd.h" &include "rt.h" ;(include <string.h> &include <ctype.h> int str2ip(char *str) int ip1,ip2,ip3,ip4; if (4 != sscanf(str,"%d.%d.%d.%d",&ip1,&ip2,&ipe3,&ip4)) // Perhaps inet~ad return(0); else return((ipl * 0x1000000) + (ip2 * 0x10000) + (ip3 * 0x100) + (ip4));} int str2port(char *str) { int port=0; if(sscanf(str,"%*[^\[][%d",&port)) say("str2port %s returns %d",str,port); else Say("str2port %s FAILED",str); return(port); // Routing table entry,,,, to be deleted typedef struct rte ( int ip; char node[NAMESIZE]; // char ntype [NAMESIZE] ; char cs[NAMESIZE] ; int qnetd~port; // char serv~class[NAMESIZE]; // char servers [4*NAMESIZE] ; char physical[NAMESIZE]; // char logicals[4*NAMESIZE];// char serv~path[NAMESIZE]; // char serv~opts[NAMESIZE]; // RTE, *lpRTE; static int is~ip (char *s) return( isdigit(s[0] ); static int is stype(char *s) return( strlen(s) > 3 && strstr(&CLASSNAMES,s) ); // The table looks like this: //137.203.1.1 mars NT3.5 Server[100] // classO router c:/q/route -master // class QS1[Ql,Q2,Q3] c:/q/qserv -threads 66 -more~opts // The node line is: // IP# node~name node~type Client~or~server[QNETD address] Preferred~servers,,, // The Services lines is: // type physical~name[logical~names,,,] path~to~executable options int parseRTnode( char *line, int line~no, int *ip, char *node, char *ntype, char *cs, int *port, char *servers) char ip~str[NAMESIZE]; char cs~str[LINESIZE]; strcpy(servers,","); if (4 > sscanf (line,"%s %s %s %s %s",ip~str,node,ntype,cs~str,&server[1])) Fail("Routing Table Line %d is not complete: %s",line~no,line); if (strlen(servers) > 1) strcat(servers,","); else strcpy(servers,""); if (!(*ip = str2ip(ip str))) Fail("Routing Table Line -',d ip does not scan: %s",line~no,line); if (2 != sscanf(cs~str,"%[^\[] [%d] ",cs,port)) Fail("Routing Table Line %d QNETD client/server does not scan: %s",line~no return(1); int parseRTservices(char *line, int line~no, char *class, char *physical~name, char *logical~names, char *path, char *opts) char services[LINESIZE]; int len; strcpy(opts,""); if ( 3 > sscanf(line,"'-s %s %s 5 %[^]",class,services,path,opts)) Fail("Routing Table: line %d is not complete: %s",line~no,line); strcpy(logical~names,","); sscanf(services,"%[^\[][%s]",physical~name,&logical~names[1] ); if((len = strlen(logical~names)) < 2) // No logical name sprintf(logical~names,",%s,",physical~name); else logical~names[--len] = ','; return(1); } /* ** **char * NewStr(char * s) ** char * n = malloc(strlen(s)+1); ** if (!n) Fail("Malloc error in NewStr"); ** return(strcpy(n,s)); **void FreeNcopy(char ** o, char * s) ** char * n = malloc(strlen(s)+1); ** if (!n) Fail("Malloc error in FreeNcopy"); ** strcpy(n,s); ** free(*o); ** *o = n; **} ** */ void SwapRT(lpRT RT1, lpRT RT2) lpRT P,R,PRT1=O,PRT2=C; Diag("SwapRT(%s,%s)",RT~NODE(RT1),RT~NODE(RT2)); if (RT1 == RT2) return; // Scan for the prel and pre2 nodes P = RTROOT; while (R = NextRT(P)) I // Find both the previous nodes if (R == RT1) PRT1 = P; if (R == RT2) PRT2 = P; P = if (!(PRT1 && PRT2)) return; // Swap pointers PRTI->next offset = RT2C(RT2) - RT2C(PRT1); if (RT2->next~offset) PRT2->next~offset = RT2C(RT~NEXT(RT2)) - RT2C(PRT2);<BR> else PRT2->next~offset = O; RT2->next offset = RT2C(RT1) - RT2C(RT2); int fgetsh(char *line,int max,HANDLE rth) { // Aproximate fgets() int rd=1,rdn=0; while ((rdn < max) && ReadFile(rth,line,i,&rd,O)) if (rd != 1) break; if (*line == '\n') break; line++; rdn++; if (*line = '\n') line--; if (rd) line++; *line = 0; return(rdn); void ReadRT() ( // Should only be called by QNETD.

int line no = 0; char line[LINESIZE]; char first[LINESIZE]; char preferred[LINESIZEi //FILE *fp = fopen(ROUTNAME,"r"); HANDLE rth = CreateFile( ROUTNAME GENERIC~WRITE|GENERIC~READ, FILE SHARE WRITEJFILE~SHARE~READ, C, OPEN~ALWAYS, FILE~ATTRIBUTE~NORMAL, 0); RTE rte; // Current RTE lpRT rt,rts; char *cp; if (SHAREDATA(rt~pingpong)) // Not the active RT rts = rt = (lpRT) sm~base->RT[O] else rts = rt = (lpRT( sm~base->RT[1]; memset(rt,O,MAXRTSIZE); // Clear routing table (not required) cp = rt->s + 1; // 1st node is always nop rt->ntype~index = cp++ - (char *) rt->s // 1st node is always nop rt->apps~index = cp++ - (char *) rt->s // 1st node is always nop strcpy(preferred,""); if (! rth Fail("Cant open the Routing Table %s",&ROUTNAME); while (fgetsh(line,LINESIZE-l,rth)) line~no++; sscanf(line,"%s",first); if (*first == line no = line no; else if (is~ip(first)) ( // New node // // Perhaps we can filter other clinets out here to save space // parseRTnode(line,line~no,&rte.ip,rte.node, rte.ntype,rte.cs, &rte.qnetd~port,rte.servers); // Start a new node in the RT RT~NOFFSET(rt) = ++cp - RT2C(rt); rt = NextRT(rt); // Build RT in shared memory RT~IP(rt) = rte.ip; // IP number RT PORT(rt) = rte.qnetd~port; // Port number RTNOFFSET(rt) = 0; // End of the chain strcpy(RT~NODE(rt),rte.node); // Node string rt->ntype~index = strlen(RT~NODE(rt)) + 1; strcpy(RT~NTYPE(rt),rte.ntype); <BR> <BR> <BR> <BR> rt->apps~index = strlen(RT~NTYPE(rt)) + 1 + rt->ntype~index;<BR> cp = RT~APPS(rt); *cp = 0; if (!strcmp(SHAREDATA(hostname),RT~NODE(rt))) { strcpy(preferred,rte.servers); SHAREDATA(hostip) = RT~IP(rt); Diag("ParseRT this node is %s ip=%p",SHAREDATA(hostname),SHAREDATA(h<BR> }<BR> } else if (is~stype(first)) { // New service // parseRTservices(line,line~no,rte.serv~class, rte.physical,rte.logicals, <BR> <BR> <BR> rte.serv~path,rte.serv~opts); // format: [QS1],Q1,Q2, [QS2],Q4, sprintf(cp,"[%s]%s",rte.physical,rte.logicals) cp = strchr(cp,0); // Advance the pointer else if (!strcmp(first,"RT VERSION")) sscanf(line,"%*s %d",&SHAREDATA(rt~ver)); // if (ferror(rth)){ // Fail("ParseRT read error on %s.\n",&ROUTNAME); // clearerr(rth); CloseHandle(rth); // Sort this list according to the preferred servers PrintRT(rts,Before sorting"); if (strlen(preferred) > 2) lpRT rtf,rtp = NextRT(rts); char *e,*p = preferred + 1; Diag("ReadRT: Sorting preferred servers:%s",preferred); // Swap entries to achive the right order while (rtp && ((strlen(p) > 2))) if (e = strchr(p,',',)) *e = 0; rtf = rts; while (rtf = NextRT(rtf)) if (!strcmp(RT~NODE(rtf),p)) break; if (!rtf) Say("ReadRT: Cant find preferred server %s",p); break; SwapRT(rtp,rtf); rtp = NextRT(rtp); if (e) p = e + 1; else break; PrintRT(rts,"After sorting"); // Ping Pong the RT tables, make this one active if (SHAREDATA (rt~pingpong)) SHAREDATA(rt~pingpong) = 0; else SHAREDATA(rt~pingpong) = 1; SHAREDATA(rt~rev)++; // Every handle will re-load from new RT.

// We must find some way to set the IP addr, and the RT is the only way to ge if(!SHAREDATA(hostip)) Warn("ReadRT: could not find host %s in the file %s",SHAREDATA(hostname),& ** Copyright (C) 1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** OpenMQ ** Module: routab.c ** Author: Derek Schwenke 9/8/95 ** ** Routing table functions */ #include "qlib.h" include "rt.h" *include "netadmin.h" 4include <string.h> #include <ctype.h> lpRT NextRT(lpRT rt) if (rt->next offset) return(RT~NEXT(rt)); return(0); void PrintRT(lpRT r,char * s) Diag("\n\n\t\tRouting Table %s\n",s); while(r = NextRT(r)) Diag("%8s %7s %p[%4d] %s",RT~NODE(r),RT~NTYPE(r), r->ip,r->qnetd~port,RT~APPS(r)); } Diag(""); lpRT ServerByNode(char *node) lpRT rt = RTROOT; while (rt = NextRT(rt)) if (!strcmp(RT~NODE(rt),node)) break; return(rt); lpRT RTByName(char *name) lpRT rt = RTROOT; while (rt = NextRT(rt)) if (!strcmp(RT~NODE(rt),name)) break; return(rt); lpRT RTByIP(int IP) lpRT rt = ROOT; while (rt = NextRT(rt)) if (IP == rt->ip) break; return(rt); int Str2IP(char *str)( int ipl,ip2,ip3,ip4; if ( 4 != sscanf(str,"%d.%d.%d.%d",&ip1,&ip2,&ip3,&ip4)) // Perhaps inet~ad return(0); else return((ipl * 0x1000000) + (ip2 * 0x10000) + (ip3 * 0x100) + (ip4)); int Name2IP(const char *name) lpRT rt; if (rt = RTByName((char *) name)) return(RT~IP(rt)); else return(Str2IP((char *) name)); char IP2NameStr[40]; char* IP2IPstr(int ip) unsigned long i = ip; sprintf(IP2NameStr,"%d.%d.%d.%d", ((i/0x01000000L) & 0x00FFL), ((i/0x00010000L) & 0x00FFL), ((i/0x00000100L) & 0x00FFL), (i & 0x00FFL)); return(IP2NameStr); char* IP2Name(int ip) lpRT rt = RTByIP(ip); if (rt) return(RT~NODE(rt)); else return(IP2IPstr(ip)); char* IP2NameOrNull(int ip) lpRT rt = RTByIP(ip); if (rt) return (RT~NODE(rt)); else return(0); // Called by Qopen lpRT RTByService(lpQHANDLE q) char sname[LINESIZE]; char *p; lpRT rtp = RTROOT; sprintf(sname,",%s,",q->msgh.to~logical); while (rtp) if (p = strstr(RTAPPS(rtp),sname)) if (!ServiceHasFailed(q->msgh.to logical,RT IP(rtp))) break; rtp = NextRT(rtp); if (rtp) { // Extract the physical server name while (*p != '[') p--; sscanf(p,"[%[^\]]",q->msgh.to~server); // physical server else { // Try the local node if (SMByName(q->msgh.to~logical)) rtp = RTByIP(SHAREDATA(hostip)); // Return this node strcpy(q-zmsgh.to server,q->msgh.to logical); // physical = logical return(rtp); // Null == failed // Called by Qopen lpRT ServerByName2(lpRT rtp, char *name, int index, char *physical) char sname[LINESIZE]; char *p; sprintf(sname,",%s,",name); while (rtp) if (p = strstr(RT~APPS(rtp),sname)) if (!(index--)) break; // Find the Nth entry rtp = NextRT(rtp); if (rtp && physical) I // Extract the physical server name while (*p != '[') p--; sscanf(p,"[%[^\]]",physical); return(rtp); // Null == failed lpRT GetRTroot()( // Used by GUI apps that want to find the RT if (!sm base) AttachSharedMemory(); return(RTROOT); #define TROUTNAME "c:\\q\\routing.tmp" int BroadcastRT() FILE* rtf = fopen(ROUTNAME,"r"); lpRT rt = RTROOT; lpQHANDLE qh = Qopen("QNETD" ,PUTMODE,O,0,C,O,0); SMBUF int sz; Diag ("BroadCastRT"); if (!qh || !rtf) return (0); memset (&b,0,sizeof (b)); qh->time~out = 1000; // One second strcpy(qh->msgh.to~logical,"QNETD"); <BR> <BR> <BR> strcpy(qh->msgh.to~server,"QNETD"); sz = fread(&b.mdata, sizeof( char ), MAXMSGDATA, rtf fclose( rtf while (rt = NextRT (rt)) { Say ("BroadCastRT Trying %d",RT~IP (rt)); if (RT~IP (rt) == SHAREDATA (hostip)) continue; // skip this n if (strstr (RT~NTYPE (rt),"NOBROADCAST")) continue; // skip this node qh-omsgh.to~node = RT~IP(rt); qh->msgh.toport = RT~PORT(rt); Qput (qh,QNETDREQ~MODE,NETMAN~RT~NEW 0,sz,b.mdata); return(1); int CopyRT(int ip) lpRT rt; lpQHANDLE qh = Qopen ("QNETD", PUT~MODE, 0, 0, 0, 0, 0,); SMBUF if (!qh) return(0); // qh->time~out = 1000; // One second strcpy (qh->msgh.to~logical,"QNETD"); strcpy (qh->msgh.to~server,"QNETD"); if (rt = RTByIP(ip)) Say("CpyRT Trying %d",ip); qh->msgh.to~node = RT~IP (rt); qh->msgh.to~port = RT~PORT (rt); QsendAndReceive (qh,QNETDREQ~MODE,NETMAN~RT~GET, 0,0,0, MAXMSGDATA,b.mdata, 0, &b.msgh); // Write to file if (b.msgh.size > 10) FILE * fp = fopen(ROUTNAME,"w"); Say("CpyRT saving copied table %d bytes %s",b.msgh.size,b.mdata); fwrite(b.mdata,sizeof( char ),b.msgh.size,fp); fclose(fp); // ReadRT(); called by watchdog.c when file time changes else return(0); return(1); ** Copyright (C) 1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: rt.h ** Author: Derek Schwenke, 10/8/95 ** **Routing table header */ // Routing table structure /* <BR> <BR> <BR> typedef struct rt { // Routing Table in shard memory<BR> <BR> int ip; int qnetd~port; // int next~offset; int ntype~index; // int apps~index; // char s[0]; // node\0ntype\0apps\0 <<More than 4 char>><BR> } RT, *lpRT; */ #define RT2C(rt) (char *)(rt) #define RT~NODE(rt) rt->s <BR> <BR> &num define RT IP(rt) rt->ip<BR> <BR> <BR> <BR> &num define RT~PORT(rt) rt->qnetd~port <BR> <BR> &num define RT~NOFFSET (rt) rt->next~offset<BR> <BR> <BR> <BR> <BR> &num define RT~APINDEX (rt) rt->apps~index<BR> <BR> <BR> &num define RT~NTINDEX(rt) rt->ntype index <BR> <BR> <BR> <BR> <BR> &num define RT~NEXT (rt) (lpRT) (RT2C(rt) + rt->next~offset)<BR> <BR> <BR> &num define RT~APPS (rt) &(rt->s[rt->apps~index])<BR> &num define RT~NTYPE (rt) &(rt->s[rt->ntype~index]) // From routtab.c #ifdef CPP extern "C" *endif int MarkFailedServer(lpQHANDLE q); void UpdateHandle(lpQHANDLE q); lpFOL ServiceHasFailed(char *name, int ip); lpRT RTByService(lpQHANDLE q); lpSMBUF SMByName(char *name); // move to qlib.h? char* IP2Name(int ip); int Name2IP(const char *name); void ReadRT(); lpRT NextRT(lpRT rt); void PrintRT(lpRT r,char * s); lpRT ServerByNode (char *node); //lpRT IPByName(char *name); lpRT RTByName(char *name); lpRT RTByIP(int IP); lpRT ServerByName2(lpRT rtp, char *name, int index, char *physical); lpRT GetRTroot(); // Used by GUI apps that want to find the RT // routtab.c - int BroadcastRT(); // used by netman int CopyRT(int ip); // used by netman *ifdef CPP #endif ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** OpenMQ ** Module: shm~acc.c ** Author: Derek Schwenke 9/8/95 ** ** */ #include "qlib.h" &num define TABLETIMEOUT 10000 void ForcedBufferReset(int bnum, // Optional Buffer number (-1 = not us lpQHANDLE q, // Optional Queue Handle (if set also int objn) f // Optional object number in Queue Han<BR> <BR> // This routine called only as repair after some failure.

SMOBJS sync; lpSMBUF buf = SMBUFADDR (bnum); int found,rtn,opened=0; char name[NAMESIZE]; if ((q) && (objn < 64)) sync.freeh = q->hreeh [objn]; sync.readyh = q->readyh [objn] sync.doneh = q->doneh[objn]; sync.ackh = 0; bnum = q->bufs~found [objn]; buf = SMBUFADDR (bnum); else if ( (bnum >= 0) && (bnum < SHAREDATA(nsbuf))) opened++; sprintf (name,MUTFREFMT,found); if (!(sync.freeh = OpenMutex (SYNCHRONIZE, FALSE, name))) Warn("ForcedBufferReset[%d=Ws]: OpenMutex 5 failed #%d", bnum, buf->name sprintf (name, SEMRDYFMT, found); if (! (sync.readyh = OpenSemaphore (SYNCHRONIZE, FALSE, name))) Warn ("ForcedBufferReset [%d=%s]: OpenSemaphore %s failed #%d",bnum,buf- sprintf (name,SEMDONFMT,found); if (! (sync.doneh = OpenSemaphore (SEMAPHORE~ALL~ACCESS, FALSE, name))) Warn ("ForcedBufferReset [%d=%s]: OpenSemaphore %s failed #%d",bnum,buf-> sprintf(name,SEMACKFMT,found); if (!(sync.ackh = OpenSemaphore (SEMAPHORE~ALL ACCESS, FALSE, name))) Warn("ForcedBufferReset[Wd=ts]: OpenSemaphore 5 failed *%d",bnum,but-> <BR> ) else sync.ackh = sync.doneh = sync.readyh = sync.freeh = NULL; Warn ("ForcedBufferReset Fails: bad args bnum=%d q=%p objn=%d", bnum, q, objn) // These Semephores have two states.

// To reset first release then reaquire them /* if (!ReleaseSemaphore (sync.readyh,1,NULL)) Warn("ForcedBufferReset[Wd=Ws]: ReleaseSemaphore ready readyh #%d",bnum if (!ReleaseSemaphore(sync.doneh,1,NULL)) Warn("ForcedBufferReset[Wd=ts]: ReleaseSemaphore ready doneh 4';d",bnum, if (!ReleaseSemaphore(sync.ackh,l,NULL)) Warn ("ForcedBufferReset [%d=%s]. ReleaseSemaphore ready ackh #%d",bnum,b */ if (sync.readyh) if ( (rtn = WaitForSingleObject(sync.readyh,l0)) != WAIT~TIMEOUT Warn("ForcedBufferReset[Wd=Ws]. WaitForSingleObject readyh was reset",b if (sync.doneh) if ( (rtn = WaitForSingleObject (sync.doneh,10)) !=WAIT~TIMEOUT) Warn ("ForcedBufferReset [%d=%s]: WaitForSingleObject doneh was reset",b if (sync.ackh) if ( (rtn = WaitForSingleObject(sync.ackh,l0)) != WAIT~TIMEOUT Warn("ForcedBufferReset[%d=%s] : WaitForSingleObject ackh was reset",bnu if (sync.freeh) if(!ReleaseMutex(sync.freeh)) Warn ("ForcedBufferReset (%d=%s): ReleaseMutex freeh fail GetLastError = bnum,buf->name,GetLastError()); if (opened) CloseHandle(sync.freeh); CloseHandle(sync.readyh); CloseHandle(sync.doneh); CloseHandle (sync.ackh); lpSMBUF SMByName(char *name) int i; for (i = C; i < SHAREDATA(nsbuf); i++) if (!strcmp(name,(SMBUFADDR(i))->name)) return(SMBUFADDR(i)); return(0); // This routine is called at startup by QNETD and QSERV.

// It's not done often so efficency is no issue here.

// This routine allocates 1 buffer and returns the buffer number or -1 on error.

// seqno specifes the number of existing buffers to expect already allocated.

int ReserveSharedBuffer(int seqno, char *bname, int bstatus, lpSMOBJS sync) int used,found,i,rtn; char name[NAMESIZE]; lpSMBUF BUF; HANDLE SMT = OpenMutex( SYNCHRONIZE, FALSE, SMEMTABLE ) Diag ("ReserveSharedBuffer (%s) starts...",bname); if (!SMT) // SMT control all changes to the shared memory buffers Fall ("ReserveSharedBuffer (%s): Cant OpenMutex for the table %d", bname, Ge if ((rtn = WaitForSingleObject (SMT,TABLETIMEOUT)) != WAIT~OBJECT 0) Fail(" Failed while waiting for the table %d",rtn); // Count the existing number of buffers registered under this name used = 0; // number of times we saw the name found = -1; // first empty buffer found for (i = 0; i c SHAREDATA(nsbuf) ; i++) BUF = SMBUFADDR(i) Diag("Checking buf Ws",BUF->name); <BR> <BR> <BR> <BR> <BR> <BR> if (!strcmp(BUF->name,bname)) <BR> <BR> if (used >= seqno) Say ("ReserveSharedBuffer (%s): FOUND STALE EXISTING BUFFER [%d] strcpy (BUF->name,"empty"); BUF->status = SMBUF~EMPTY; else Diag ("ReserveSharedBuffer (%s): found an existing buffer [%d] ",bna used++; }} } <BR> <BR> if ((found == -1) && (!strcmp (BUF->name,"empty"))) found = i;<BR> } if (found == -1) Warn("ReserveSharedBuffer(s) :Cant allocate a buffer - all %d currently return(found); // Get handles for free ready and done objects.

// All have previously been created by sharmeminit BUF = SMBUFADDR(found) sprintf(name,MUTFREFMT,found); if (!(sync->freeh = OpenMutex(SYNCHRONIZE, FALSE, name))) Fail ("ReserveSharedBuffer (%s): OpenMutex %s failed #%d",bname,name,GetLast if (sync->freeh) ReleaseMutex (sync->freeh): // I dont own this mutex, This ca GetLastError(); // clear this error out sprintf(name,SEMRDYFMT,found); if (!(sync->readyh = OpenSemaphore (SYNCHRONIZE, FALSE, name))) Fail (!ReserveSharedBuffer (%s): OpenSemaphore %s failed #%d",bname,name,Ge if (sync->readyh) WaitForSingleObject (sync->readyh,10); // Reset sprintf(name,SEMDONFMT,found); if (!(sync->doneh = OpenSemaphore (SEMAPHORE~ALL~ACCESS, FALSE, name))) Fail ("ReserveSharedBuffer (%s): OpenSemaphore %s failed #%d",bname,name,Get if (sync->doneh) WaitForSingleObject(sync->doneh,10); // Reset sprintf(name,SEMACKFMT,found); if (!(sync->ackh = OpenSemaphore(SEMAPHORE~ALL~ACCESS, FALSE, name))) Fail ("ReserveSharedBuffer (%s): OpenSemaphore %s failed #%d",bname,name,Get if (sync->ackh) WaitForSingleObject (sync->ackh,10); // Reset // Set name and status strcpy(BUF->name,bname); BUF->status = bstatus; ReleaseMutex(SMT); Diag("ReserveSharedBuffer(Ws) returns [Wd] addr %p",bname,found,BUF); return(found); int UnReserveSharedBuffer(int bnum) int rtn = 0; lpSMBUF BUF = SMBUFADDR(bnum); HANDLE SMT = OpenMutex( SYNCHRONIZE, FALSE, SMEMTABLE ); Diag ("UnReserveSharedBuffer (%s)", BUF->name); if (!SMT) Fail("UnReserveSharedBuffer(ts): Cant OpenMutex for the table %d", BUF->na if ((rtn = WaitForSingleObject (SMT,TABLETIMEOUT)) != WAIT OBJECT~0 ) Fail(" Failed while waiting for the table %d",rtn); strcpy(BUF->name,"empty"); BUF->status = SMBUF~EMPTY; ReleaseMutex(SMT); return(rtn); // This routine is called at startup by QNETD and QSERV.

// It's not done often so efficency is no issue here.

lpSMBUFH AttachSharedMemory() HANDLE hMap; // Shared memory mapping //Say("AttachSharedMemory \n"); // Open the shared memory object if ( ! (hMap = OpenFileMapping(FILE~MAP WRITE, FALSE, SMEMNAME))) Warn("OpenFileMapping returned null - QNETD is not running"); // Map the shared memory into my address space else if (! (sm base = (lpSMBUFH) MapViewOfFile( hMap, FILE~MAP~WRITE,0,0,0))) Warn ("MapViewOfFile returned null"); // Note: hMap is not returned because we dont expect anyone // to ever close this mapping once they have it.

Diag("AttachSharedMemory 5 returns %p", &SMEMNAME,sm~base); return(sm base); ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: tran.c ** Author: Derek Schwenke 9/8/95 ** Tran routines for single threaded clients, or well behaved ** multi threaded clients. There will be problems if 2 ** threads do different COMMITs So, this code is not thread safe.

*/ #include "qlib.h" //typedef struct tl ( // Message header // struct tl *next; // Next // QHANDLE q; // Header version, and machine coding format //) TL, *lpTL; lpQHANDLE TLroot = NULL; // Open transaction list int tran id = 1; // Transactional ID for this process int last~tran~id; // Last commited ID lpQHANDLE FindTL(lpQHANDLE q) lpQHANDLE tl = TLroot; while (tl) if (strcmp(tl->msgh.to logical,q->msgh.to logical) == 0 && strcmp(tl->msgh.to~server, q->msgh.toZserver) == 0) break; else tl = tl->next return(tl); void TLadd(lpQHANDLE q) lpQHANDLE n; if ( n = FindTL(q)) n->msgh.sub mode++; // Inc # of times used else n = (lpQHANDLE) malloc(sizeof(QHANDLE)); Diag ("TLadd: Starting for %s %s",q->msgh.to~logical,q->msgh.to~server); memcpy(n,q,sizeof(QHANDLE)); n->msgh.sub~mode = 1; // # of times used n->msgh.mid.tid = tran~id; // Save for acks n->next = TLroot; TLroot = } void TLdel() { lpQHANDLE nn,n = TLroot; while (nn = n) n = n->next free(nn); TLroot = NULL; char open~tran[1000]; char old~trans[1000]; FILE *TLOG = NULL; // Message Log File void LogTran(char *s)( if (!TLOG) if (!(TLOG = fopen(TLOGNAME,"w"))) Fail("ERROR CAN NOT OPEN LOG FILE %s",&TLOGNAME); fprintf(TLOG,"%s",s); void Qcommit(int action)( // Commit or abort // 1. Mark it commited on DISK // 2. Add to RAM list // 3. Send commit messages char transtr[80]; int trouble = 0; lpQHANDLE tl = TLroot; MSGH mh; Diag("Qcommit(%d)",action); // The Open Transaction List should have accumulated q's to commit if(!tl)( Diag("Attempt to commit with no outstanding messages Ignored"); else strcpy(old~trans,open~tran); sprintf(transtr,":%d=%d",TLroot->msgh.mid.tid,action); strcat(open tran,transtr); LogTran(opentran); // <-- This is the real commit Diag("Qcommit(%d) transtr=%s open~tran=%s",action,transtr,open tran); // Try to notify everyone about the commit or abort while(tl) mh.mode = 0; // Clear incase no full header is recived.

QsendAndReceive(tl,action,0,0, 0,0, 0,0,0,&mh); if(mh.mode == ACK~MODE) Diag("Qcommit: was acknoledged!"); else Diag("Qcommit: WAS NOT ACKNOLEDGED",trouble++); tl = tl->next TLdel(); // Clean up if(!trouble) I // Remove from the open tran list strcpy(open tran,old trans); if (*open~tran) LogTan(open tran); if (*open~tran) Say("Qcommit: open~tran=[%s]",open~tran); last tran id = tran id; int ResolveTran(lpMID MID)( int i, state = Q~ABORT; char *p,id[40]; sprintf(id,":%d,",MID->tid); if (p = strstr(old~trans,id)) // If this mid is on the old scanf(p,":%d=%d",i,state); // Read the tran state else if ( TLroot ) // If there's a inflight transaction if (TLroot->msgh.mid.tid == MID->tid) // And the msg# matches state = Q~INPROGRESS; // Return "inprogress" if (SHAREDATA(hostip) != MID->host) Warn("ResolveTran PASSED the wrong host"); state = Q~WRONGHOST; return(state); // This code is executed in each client's address space.

// But it should return a unique number void SetTID(lpMID m, int flags) if(flags & Q~TRAN) ( // It's transactional make a ID if(BITSET(Q~TRAN~BEGIN,flags) II (tran id == last~tran~id)) tran id = ++(SHAREDATA(tran~id)); // Generate new tran ID for this NODE Diag("SetTID id=%d",tran~id); m->tid = tran~id; // Always make a unique id for each message.

m->uid = ++(SHAREDATA(unique~id)); ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: copyrt.c ** Author: Derek Schwenke 11/20/95 ** ** Routing table broadcast funtions */ #include "qlib.h" include "qnetd.h" #include "rt.h" #define TROUTNAME "c:\\q\\routing.tmp" void BroadCastRT() FILE* rtf = fopen(ROUTNAME,"r"); FILE* trt = fopen(TROUTNAME,"w"); lpRT rt = RTROOT; lpQHANDLE qh = Qopen("QNETD",PUT~MODE,0,0,0,0,0); SMBUF int rd; Say("BroadCastRT"); if (!qh !rtf) return; memset(&b,0,sizeof(b)); qh->time out = 1000; // One second strcpy(qh->msgh.to~logical,"QNETD"); strcpy(qh->msgh.to~server, "QNETD"); rd = fread(&b.mdata, sizeof( char ), MAXMSGDATA, rtf ); Say("BroadCastRT read got tid bytes ",rd); fclose( rtf Say("BroadCastRT closed",b.mdata); rd = fwrite(&b.mdata, sizeof( char ), MAXMSGDATA, rtf); Say("BroadCastRT wrote %d ",rd); /* while (rt = RT~NEXT(rt)) { qh->msgh.to~node = RT~IP(rt); qh->msgh.to~port = RT~PORT(rt); QsendAndReceive (g 9,QNETDREQ MODE,NETMAN SMBUFI, 0,0,0, (sizeof(SMBUFH) - MAXRTSIZE),(char *) &g~smhead,0,0); int CopyRT(int IP) lpRT rt = RTROOT; lpQHANDLE qh = Qopen("QNETD",PUT~MODE,0,0,0,0,0); if (!qh) return(0); qh->time~out = 1000; // One second strcpy(qh->msgh.to~logical,"QNETD"); strcpy(qh->msgh.to~server,"QNETD"); /* while (rt = RT~NEXT(rt)) { qh->msgh.tonode = RT~IP(rt); qh->msgh.to~port = RT~PORT(rt); QsendAndReceive(g~q,QNETDREQ~MODE,NETMAN-SMBUFH, 0,0,0,<BR> <BR> (sizeof(SMBUFH) - MAXRTSIZE),(char *) &g~smhead,0,0);<BR> } */ return(1); ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: failover.c ** Author: Derek Schwenke 9/22/95 */ #include "qlib.h" // Make entry in the fail over list int MarkFailedServer(lpQHANDLE q) lpFOL fl = &(sm~base->FO[SHAREDATA(failed~servers)]); if (SHAREDATA(failed~servers) < MAXFOLENT - 1)( strcpy(fl->name,q->msgh.to~logical); fl->ip = q->msgh.to~node; SHAREDATA(failed~servers) ++; SHAREDATA(rt~rev)++; <BR> <BR> <BR> <BR> <BR> return(1) <BR> <BR> <BR> return(0) // Returns lpFOL if this server has failed lpFOL ServiceHasFailed(char *name, int ip) int i; for (i=O;i<SHAREDATA(failed~servers);i++) lpFOL fl = &(sm~base->FO[i]); if (!strcmp(name,fl->name) && fl->ip == ip) return(fl); return(0); void UpdateHandle(lpQHANDLE q){ q->rt rev = SHAREDATA(rt~rev); <BR> <BR> if ((Q FAILOVER & q->msgh.flags) && q->msgh.mode == PUT MODE)<BR> <BR> QreOpen(q); } } /* int markfailed( lpQHANDLE q, int pass) { lpQHANDLE failover; int rtn; // Note that this server has failed us, Find a new one Warn("markfailed(%s) server on p in pass looking for replacement" ,q->msgh failover = Qopen( q->msgh.to~logical, q->msgh.mode, q->msgh.sub~mode, q->base~flags, 0,0,pass); // Add to failed list if(failover) failover->next = FLroot; FLroot = failover; rtn = 1; // good } else { Say("markfailed(%s) no replacement found pass=%d",q->msgh.to~logical,pass) free (failover) rtn = 0; // bad return(rtn); lpQHANDLE findreplacement(lpQHANDLE q) { lpQHANDLE fop = FLroot; // List of all failed servers while(fop) I // Find first failover that matches if (!strcmp(fop->msgh.to~logical,q->msgh.to~logical))) break; fop = fop->next if (fop) Say("findreplacment(%s) Found a fail over",q->msgh.to~logical); q = fop; // We found a fail over for this service return(q); void flushfailedlist() lpQHANDLE pp, cp = FLroot; // List of all failed servers if (!cp) return; FLroot = NULL; //Sleep(60000); // Let any current transactions end while(pp=cp) cp = cp->next free(pp); User: root Host: bunny Class: bunny Job: stdin // QNETDREQ~MODE sub modes: #define NETMAN~SMBUFH 100 #define NETMAN~SMBUFS 101 #define NETMAN~SOCKETS 102 #define NETMAN~TRAN 103 #define NETMAN~RT~READ 104 // #define NETMAN~RT~BROAD 105 #define NETMAN RT NEW 106 #define NETMAN~RT~GET 107 #define NETMAN~CLR~FOL 110 // Shared Buffers Status // --------------------- typedef struct bs { // Shared memory buffers char name[NAMESIZE]; short status; short sub~status; MSGH msgh; } BS, *lpBS; typedef struct bsa { // Shared memory buffers int nsbuf; BS bs[MAXNSMBUF]; BSA, *lpBSA; // Socket Status // ------------- typedef struct ss { int ip; int port; 55, *lpSS; typedef struct ssa ( // Shared memory buffers int sockets; SS ss[FD~SETSIZE]; SSA, *lpSSA; // RT // ------------- typedef struct rta { // Shared memory buffers char RT[MAXRTSIZE]; } RTA, *lpRTA; // admindlg.cpp : implementation file &num include "stdafx.h" #include "qman.h" #include "admindlg.h" #define Q~LIB *include "qlib.h" *include "qadmin.h" &num include "rt.h" #define ADMTIMER 102 extern lpSMBUFH sm~base; extern QADMSTATS g~s[3]; extern CString g~que[3]; extern lpQHANDLE QS[3]; int IDC APICS[8] = {IDC~QNONE1,IDC~QDOWN1,IDC~QSTOP1,IDC QNOPUT1,IDC~QNOGET1,ID<BR> enum pics {QNONE,QDOWN,QSTOP,QNOPUT,QNOGET,QUP,QNOPG,QFULL}; extern int g~pic[3+3+3]; QADMCTLS g~ad; *ifdef DEBUG *undef THIS FILE static char BASED CODE THIS~FILE[] = FILE <BR> <BR> 4endif<BR> extern CFont g~text~font; int ALL~TEXT~A[] = {IDC~STATS,IDC~OGROUP,IDC~SGROUP, IDC~PUTC,ITC~GETC,IDC~HALTC,IDC~SRESETC,IDC~FRESETC,IDC~SHU IDC~MAXSIZE,IDC~LIMLAB,IDC~QSIZE, IDOK,IDC~SET,IDC~REFRESH,0}; //////////////////////////////////////////////////////////// //////////////// // CAdminDlg dialog CAdminDlg::CAdminDlg(CWnd* pParent /*=NULL*/) : CDialog(CAdminDlg::IDD, pParent) //( (AFXDATA~INIT(CAdminDlg) <BR> <BR> <BR> <BR> <BR> <BR> // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void CAdminDlg: : DoDataExchange (CDataExchange* pDX) CDialog::DoDataExchange(pDX);<BR> //{{AFX~DATA~MAP(CAdminDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN~MESSAGE~MAP(CAdminDlg, CDialog) //{{AFX~MSG~MAP(CAdminDlg) ON~BN~CLICKED(IDC~REFRESH, OnRefresh) ON~BN~CLICKED (IDC~SET, OnSet) ON~CBN EDITCHANGE(IDC QSIZE, OnEditchangeQsize) ON~WM~TIMER () ON () //}}AFX~MSG~MAP END~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// // CAdminDlg message handlers void CAdminDlg::SetDisplay(int init) String sp,sg,s,tl,t2; if (init) tl = g~que [m~id] + " Status"; t2 = g~que[m~id] + " Settings"; SetDlgItemText(IDC~OGROUP,tl); SetDlgItemText(IDC~SGROUP,t2); CListBox* lb = (CListBox*) GetDlgItem (IDC~STATS); lb->ResetContent ();<BR> s.Format ("%5d committed entries", g~s[m~id].committed~entries); lb->InsertStri s.Format ("%5d uncommitted puts", g~s[m~id].pending~puts); lb->InsertStri s.Format ("%5d uncommitted gets", g~s[m~id].pending~gets); lb->InsertStri s.Format ("%5d holes", g~s[m~id].holey~entries); lb->InsertStri s.Format ("%5d max entries", g~s[m~id].max~entries); lb->InsertStri sg = ctime(&g s[m id].first start time); sp = ctime (&g~s[m~id].last~restart~time); s.Format ("%5d restarts", g~s[m~id].num~restarts); lb->InsertString(-1, s.Format ("Last restart time %s", LPCTSTR (sg.Left (24))); lb->InsertString(-1, s.Format ("First restart time %s", LPCTSTR (sp.Left (24))); lb->InsertString(-1, if (init) s.Format("(%d limit)",g s[m id].max entries limit); SetDlgItemText (IDC~LIMLAB,LPCTSTR (s)); SetDlgItemInt (IDC~QSIZE,g~s[m~id].max~entries); // Select a icon // if (init) // for (int i=0; i<6 i++) // if (i != g~pic[m~id])<BR> <BR> <BR> // GetDlgItem~APICS[i])->ShowWindow(SW~ if ((g~pic[m~id] !=g~pic[m~id+3+3])) { GetDlgItem(IDC APICS[g~pic[m id]l)->ShowWindow(SW~SHOW); GetDlgItem (IDC~APICS [g~pic [m~id+3+3]])->ShowWindow (SW~HIDE); g~pic[m~id+3+3] = g~pic m~id];<BR> } // Set check box items if (init) ((CButton *) GetDlgItem(IDC~GETC))->SetCheck(g s[m id].qget state); ((CButton *) GetDlgItem(IDC~PUTC))->SetCheck(g-s[mid] .qput-state); ((CButton *) GetDlgItem(IDC~SRESETC))->SetCheck(g~ad.stats reset~flag); ((CButton *) GetDlgItem (IDC~FRESETC))->SetCheck (g~ad.full~reset~flag); ((CButton *) GetDlgItem(IDC-HALTC))->SetCheck(g ad.halt fag); - BOOL CAdminDlg::OnInitDialog() CDialog::OnInitDialog(); g~pic[m~id+3+3] = QNONE; // history is invalid for (int i=0;i<6i++) // Turn all pics off.

GetDlgItem (IDC~APICS[i])->ShowWindow (SW~HIDE); SetDisplay (1); SetTimer (ADMTIMER,1000,NULL); // 1 sec i = O; while (ALL~TEXT~A[i]) GetDlgItem (ALL~TEXT~A [i++])->SetFont (&g~text~font); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE void CAdminDlg: :OnRefresh() SetDisplay (1); DWORD SetCtl(LPVOID m~id) int id = (int)m~id; QsendAndReceive (QS[id], ADMINREQ~MODE, QADM~SET~CONTROLS, 0, sizeof (g~ad), (char g~ad.stats~reset~flag = 0; g~ad.full~reset~flag = 0; g~ad.shutdown flag = 0; g~ad.halt~flag = 0; return(0); void CAdminDlg::OnSet () memset(&g~ad,0,sizeof(g~ad)); if (IsDlgButtonChecked(IDC~PUTC)) g~ad.enable~qputs~flag++; if (IsDlgButtonChecked(IDC~GETC)) g~ad.enable~qgets~flag++; if (IsDlgButtonChecked(IDC-SRESETC)) g~ad.stats~reset~flag++; if (IsDlgButtonChecked(IDC~FRESETC)) g~ad.full~reset~flag++; if (IsDlgButtonChecked(IDC~SHUTDOWNC)) g~ad.shutdown~flag++; if (IsDlgButtonChecked (IDC-KALTC) ) g~ad.halt~flag++; int qs = GetDlgItemInt(IDC QSIZE,NULL,TRUE); if ((qs>0)&&(qs<=g~s[m~id].max~entries~limit)) g~ad.max~entries~value = qs; DWORD id; CreateThread(NULL,0,(LPTHREAD~START~ROUTINE) SetCtl,(LPVOID) m~id,0,&id); // QsendAndReceive (QS [m id],ADMINREQ~MODE, QADM~SET~CONTROLS, 0,sizeof(g~ad),( if (g~ad.shutdown~flag) { g~pic[m~id] = QSTOP; // QSTOP=Yellow (QDOWN=RED) we will hit a comm error // SetDisplay(0); // 0=refresh only.

//Sleep(1000); //SetDisplay(0); // O=refresh only.

//Sleep(1000); //if (g~ad.shutdown~flag) CDialog::OnOK(); // Exit CDialog::OnOK(); // Exit //g~ad.stats~reset~flag = 0; //g~ad.full~reset~flag = 0; //gad.shutdownf lag = 0; //g~ad.halt~flag = 0; //SetDisplay(1); // 1=init: set buttons void CAdminDlg::OnEditchangeQsize() int qs = GetDlgItemInt(IDC~QSIZE,NULL,TRUE); if (!((qs>O)&&(qs<=g s[m id].max~entries limit))) SetDlgItemText(IDC~QSIZE,""); void CAdminDlg::OnTimer(UINT nIDEvent) if (nIDEvent == ADMTIMER) SetDisplay(0); else CDialog::OnTimer(nIDEvent); void CAdminDlg::OnRButtonDown(UINT nFlags, CPoint point) GetParentFrame ()->SetMessageText (""); this->Invalidate(); CDialog::OnRButtonDown(nFlags, point); // admindlg.h header file <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> //////////////////////////////////////////////////////////// /////////////////<BR> <BR> // CAdminDlg dialog class CAdminDlg : public CDialog // Construction public: CAdminDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //( (AFX~DATA(CAdminDlg) enum { IDD = IDD~ADMINDIALOG ); // NOTE: the ClassWizard will add data members here //}}AFX~DATA int m~id; // Overrides // ClassWizard generated virtual function overrides // ( (AFX~VIRTUAL (CAdminDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL void SetDisplay(int i); // Implementation protected: // Generated message map functions //{{AFX~MSG(CAdminDlg) virtual BOOL OnInitDialog(); afx~msg void OnRefresh(); afx~msg void OnSet(); afx~msg void OnEditchangeQsize(); afx~msg void OnTimer(UINT nIDEvent); afx msg void OnRButtonDown(UINT nFlags, CPoint point); //)TAFX MSG DECLARE MESSAGE MAP() User: root Host: bunny Class: bunny Job: stdin // datadlg.cpp . implementation file *include "stdafx.h" #include "qman .

&num include "datadlg.h" *include "KeySearch.h" #define Q~LIB #include "qlib.h" #include "qadmin.h" &num include "rt.h" *include "orderfm.h" extern lpQHANDLE QS[3]; extern QADMSTATS g~s[3]; extern CString g~que[3]; *ifdef ~DEBUG *undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE~; *endif //////////////////////////////////////////////////////////// ///////////////// // CdataDlg dialog CdataDlg::CdataDlg(CWnd* pParent /*=NULL*/) CDialog(CdataDlg::IDD, pParent) //{{AFX DATA~INIT(CdataDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void CdataDlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(CdataDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN~MESSAGE MAP(CdataDlg, CDialog) //{{AFX~MSG~MAP(CdataDlg) ON~BN~CLICKED(IDREFRESHB, OnRefreshb) ON~BN~CLICKED(IDC~CMT, OnCmt) ON~BN~CLICKED(IDC~UNCMT, OnUncmt) ON~BN~CLICKED(IDR~SEARCHB, OnSearchb) //}}AFX~MSG~MAP END~MESSAGE~MAP() SMBUF m; void CdataDlg::ScreenInit() { CString s,ss; int i,gotsize; pOFORM po = (pOFORM) &m.mdata if (m sub mode == QADM~REQ~COM~DATA) s.Format ("%s %4d Commited %20d Uncommited entries", LPCTSTR (g~que[m~id] g~s [m~id].committed~entries, g~s[m~id].pending~gets + g~s[m~id].pen else s.Format("ts ';4d Uncommited %20d Commited entries",LPCTSTR(gque[m~id]), g~s]m~id].pending~gets + g~s[m~id].pending~puts, g~s[m~id].committed~ent SetDlgItenText(IDC~TITLE,LPCSTR(s)); CListBox* lb = (CListBox*) GetDlgItem(IDC~DATAL); lb->ResetContent(); for (i = 0; i < 200; i++) *m.mdata = i; if (QSUCCESS == QsendAndReceive(QS[m~id],ADMINREQ~MODE,m~sub~mode, 0,sizeof(int,m.mdata, sizeof(m.mdata),m.mdata,&gotsize,&m.msgh)) ss = "%3d\t%s\t%s\t%s"; if (gotsize == sizeof(OFORM)) s.Format(LPCTSTR(ss),i,po->cust,po->item,po->qty,0) ; lb->InsertString(-1,s); else if (gotsize) s.Format("%3d -\t%s",i,m.mdata); lb->InsertString(-1,s); else break; #define FORMATNAME "c:\\q\\formats.txt" char * IsAddr(char *c)( int off = 0; if (strstr(c,"msgh"))( if (strstr(c, "size")) return( (char *)m.msgh.size); } else if (strstr(c,"mdata")) sscanf(c,"t;*[^[]j[Wd",off); return((m.mdata + off)) return(0); typedef struct fmts ( // Thread parameters void* testa; int testv; char fmt[100]; void* a[10]; fmts* next; FMTS, *pFMTS; void clearfmt( pFMTS p)( p->testa = NULL; p->testv = 0; *p->fmt = 0; for (int i=0;i < 10;i++) p->a[i] = NULL; p->next = 0; FMTS fmts; void ParseFormats (){ char line[LINESIZE] char test[LINESIZE]; char format[LINESIZE]; char ops[LINESIZE]; char opl[LINESIZE]; char op2[LINESIZE]; char op[LINESIZE]; FILE *fp = fopen(FORMATNAME,"r"); if ( ! fp // Say("Cant open the data formats file ts",FORMATNAME); return; while (fgets(line,LINESIZE,fp)) <BR> <BR> <BR> <BR> if ( 3 == sscanf(line,"%[^;];%[^;]",test,format,ops))<BR> if (strchr(test,'&num ')) continue;<BR> <BR> <BR> if ( 3 != sscanf(test,"Ws %s ts",opl,op,op2)) continue; if (strstr(opl,"size")) fmts.testa = &m.msgh.size; sscanf(op2,"%d",&fmts.testv); strcpy(fmts.fmt,format); else ; //Say("ReadParms: Ignoring: ts",line); if (ferror(fp)) { // Fail("read error in parameters file ts",PARMNAME); clearerr(fp); fclose(fp); ///////////////////////////////////////////////////// // CdataDlg message handlers BOOL CdataDlg::OnInitDialog() CDialog::OnInitDialog(); m~sub~mode = QADM~REQ~COM~DATA; ((CButton *) GetDlgItem(IDC~CMT)->SetCheck(TRUE); ScreenInit(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE void CdataDlg: :OnRefreshb() ScreenInit(); void CdataDlg::OnCmt() m~sub~mode = QADM~REQ~COM~DATA; ScreenInit(); void CdataDlg::OnUncmt() m~sub~mode = QADM~REQ~UNCOM~DATA; ScreenInit(); void CdataDlg::OnSearchb() CKeySearch d; d.m~id = m id; d.DoModal(); // datadlg.h : header file //////////////////////////////////////////////////////////// ///////////////// // CdataDlg dialog class CdataDlg : public CDialog // Construction public: CdataDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX~DATA(CdataDlg) enum { IDD = IDD~DATADIALOG ); // NOTE: the ClassWizard will add data members here //}}AFX~DATA int m~id; int m~sub~mode; void ScreenInit(); // Overrides // ClassWizard generated virtual function overrides // ( (AFX~VIRTUAL (CdataDlg) protected: virtual void DoDataExchange (CDataExchange* pDX!; // DDX/DDV support //)}AFX~VIRTUAL // Implementation protected: // Generated message map functions //{{AFX~MSG(CdataDlg) virtual BOOL OnInitDialog(); afx~msg void OnRefreshb(); afxmsg void OnCmt(); afxmsg void OnUncmt(); afx msg void OnSearchb(); //}}AFX~MSG DECLARE~MESSAGE~MAP() // KeySearch.h : header file //////////////////////////////////////////////////////////// ///////////////// // CKeySearch dialog class CKeySearch : public CDialog // Construction public: CKeySearch(CWnd* pParent = NULL); // standard constructor //void CM switch(int mode); // Dialog Data //( (AFX DATA(CKeysearch) enum ( IDD = IDD~KEYSEARCH ); // NOTE: the ClassWizard will add data members here //}}AFX~DATA //int m min int,m~max int,m~at int; //CString m~min~str,m~max~str,m~at~str; int m~id; // 1-3 int m~preds; int m~pred~type[3]; int m~pic; int m~committed; int m~uncommitted; int m~total~entries; int m~search~type; void OnCompChange(int pred); void ChangePredView(int pred, int act); void CopyInput(int pred, int min, int max); // Overrides // ClassWizard generated virtual function overrides //((AFX VIRTUAL(CKeySearch) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //} VIRTUAL // Implementation protected: // Generated message map functions //((AFX~MSG(CKeySearch) virtual BOOL OnInitDialog(); afxmsg void OnSearchb(); afx~msg void OnAndl(); afx~msg void OnAnd2(); afx~msg void OnSelchangeCompCbl(); afx~msg void OnSelchangeCompCb2(); afx~msg void OnSelchangeCompCB3(); afx~msg void OnEditchangeMinCbl(); afx~msg void OnEditchangeMinCb2(); afx~msg void OnEditchangeMinCb3(); afxmsg void OnEditchangeMaxCbl(); afx~msg void OnEditchangeMaxCb2(); afx~msg void OnEditchangeMaxCb3(); afx~msg void OnTimer(UINT nIDEvent); afx~msg void OnAllR(); afxmsg void OnComR(), afx~msg void OnUncomR(); afx msg void OnRButtonDown(UINT nFlags, CPoint point); //}}AFX~MSG DECLARE~MESSAGE~MAP() // mainfrm.cpp implementation of the CMainFrame class #include "stdafx. h" #include "qman.h" #include "mainfrm.h" #ifdef DEBUG *undef THIS FILE <BR> <BR> static char BASED~CODE THIS~FILE[] = ~FILE~<BR> &num endif //////////////////////////////////////////////////////////// ///////////////// // CMainFrame IMPLEMENT~DYNCREATE(CMainFrame, CFrameWnd) BEGIN~MESSAGE~MAP(CMainFrame, CFrameWnd) //{{AFX~MSG~MAP(CMainFrame) // NOTE - the ClassWizard will add and remove mapping macros her<BR> <BR> <BR> <BR> // DO NOT EDIT what you see in these blocks of generated code ON WM CREATE() //T}AFX~MSG~MAP END~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// // arrays of IDs used to initialize control bars // toolbar buttons - IDs are command buttons static UINT BASED~CODE buttons[] = // same order as in the bitmap 'toolbar.bmp' ID~FILE~NEW, ID~FILE~OPEN, ID FILE~SAVE, ID~SEPARATOR, ID~EDIT~CUT, <BR> <BR> ID~EDIT~COPY, <BR> <BR> <BR> ID~EDIT~PASTE, ID~SEPARATOR, ID FILE PRINT, ID~APP~ABOUT, static UINT BASED~CODE indicators[] = ID SEPARATOR, // status line indicator ID~INDICATOR~CAPS, ID~INDICATOR~NUM, ID~INDICATOR~SCRL, }; ////////////////////////////////////// // CMainFrame construction/destruction CMainFrame::CMainFrame() { // TODO: add member initialization code here CMainFrame: : CMainFrame () int CMainFrame: :OnCreate (LPCREATESTRUCT lpCreateStruct) if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m~wndToolBar.Create(this) || !m~wndToolBar.LoadBitmap(IDR~MAINFRAME) || !m~wndToolBar.SetButtons(buttons, sizeof(buttons)/sizeof(UINT))) TRACEO("Failed to create toolbar\n"); return -1; // fail to create /* Derek's remove tool bar */ m~wndToolBar.ShowWindow(SW~HIDE); if (!m~wndStatusBar.Create(this) I !m~wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) TRACE0("Failed to create status bar\n"); return -1; // fail to create // TODO: Delete these three lines if you don't want the toolbar to // be dockable m~wndToolBar.EnableDocking(CBRS~ALIGN~ANY); EnableDocking(CBRS ALIGN ANY); - DockControlBar(&m~wndToolBar); // TODO: Remove this if you don't want tool tips m~wndToolBar.SetBarStyle(m~wndToolBar.GetBarStyle() | CBRS~TOOLTIPS | CBRS~FLYBY); return 0; //////////////////////////////////////////////////////////// ///////////////// // CMainFrame diagnostics #ifdef DEBUG void CMainFrame::AssertValid() const CFrameWnd::AssertValid(); void CMainFrame::Dump(CDumpContext& dc) consist CFrameWnd::Dump(dc); *endif //~DEBUG //////////////////////////////////////////////////////////// ///////////////// // CMainFrame message handlers // mainfrm.h : interface of the CMainFrame class //////////////////////////////////////////////////////////// ///////////////// class CMainFrame public CFrameWnd protected: // create from serialization only CMainFrame(); DECLARE DYNCREATE(CMainFrame) // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{ (AFX VIRTUAL(CMainFrame) //}}AFX~VIRTUAL // Implementation public: virtual ~CMainFrame(); #ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; ;)endif protected: // control bar embedded members CStatusBar m~wndStatusBar; CToolBar m~wndToolBar; // Generated message map functions protected: // ( (AFXMSG (CMainFrame) afx~msg int OnCreate(LPCREATESTRUCT lpCreateStruct); // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //}}AFX-MSG DECLARE~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// // KeySearch.cpp implementation file #include "stdafx.h" 4include "qman.h" #include "KeySearch.h" #define Q~LIB &num include "qlib.h" *include "qadmin.h" *include 2orderfm.h" #include "rt.h" #ifdef~DEBUG #define new DEBUG~NEW #undef THIS FILE static char THIS~FILE[] = ~FILE~ 4endif &num define KEYTIMER 106 extern lpQHANDLE QS[3]; extern QADMSTATS g~s[3]; extern CString g~que[3]; extern lpSMBUFH sm base; extern int g pic[3+3+3]; <BR> //////////////////////////////////////////////////////////// /////////////////<BR> <BR> &num define ID~OBJS 9<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> int IDC~KPICS[8] = {IDC~QNONE1,IDC~QDOWN1,IDC~QSTOP1,IDC~QNOPUT1,IDC~QNOGET@ @<BR> enum IDTYPE {COMP,MIN,AT,MAX,AND,OPA,OPB,OPC,OPD};<BR> <BR> <BR> <BR> <BR> <BR> int g~id[3][ID~OBJS] = {{IDC~COMP~CB1,IDC~MIN~CB1,IDC~AT~CB1,IDC~MAX~CB1,IDC~A<B R> <BR> <BR> <BR> <BR> {IDC~COMP~CB2,IDC~MIN~CB2,IDC~AT~CB2,IDC~MAX~CB2,IDC~A<BR > <BR> <BR> {IDC~COMP~CB3,IDC~MIN~CB3,IDC~AT~CB3,IDC~AT~CB3,IDC~MAX~CB3, IDC~A<BR> // List of items to get big fonts<BR> <BR> <BR> <BR> <BR> extern CFont gtext font; int ALL~TEXT~S[] = TIDCALL~R,IDC~COM~R,IDC~UNCOM~R,IDC~MODE,IDOK,IDSEARCHB,IDC~ //////////////////////////////////////////////////////////// ///////////////// // CKeySearch dialog CKeySearch::CKeySearch(CWnd* pParent /*=NULL*/) CDialog (CKeySearch: : IDD, pParent) //{{AFX~DATA~INIT(CKeySearch) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT } void CKeysearch::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(CkeySearch) //NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN~MESSAGE~MAP(CkeySearch, CDialog) //({AFX MSG MAP(CKeysearoh) ON~BN CLICKED(IDSEARCHB, OnSearchb) ON~BN~CLICKED(IDC~AND1, OnAndl) ON~BN~CLICKED(IDC~AND2, OnAnd2) ON C9N SELCHANGE(IDC COMP CB1, OnSelchangeCompCbl) ON-CBN-SELCHANGE(IDC-COMP-CB2, OnSelchangeCompCb2) ON-CBNSELCHANGE(IDC-COMP-CB3, OnSelchangeCompCb3) ON-CBNEDITCHANGE(IDC MIN-CB1, OnEditchangeMinCbl) ON-CBN-EDITCHANGE(IDC-MIN-CB2, OnEditchangeMinCb2) ON-CBN-EDITCHANGE(IDC-MIN-CB3, OnEditchangeMinCb3) ON~CBN~EDITCHANGE(IDC~MAX~CB1, OnEditchangeMaxCb1) ON CBN EDITCHANGE(IDC MAX CB2, OnEditchangeMaxCb2) ON~CBN~EDITCHANGE(IDC~MAX~CB3, OnEditchangeMaxCb3) ON~WM~TIMER() ON~BN~CLICKED(IDC~ALL~R, OnAllR) ON~BN~CLICKED(IDC~COM~R, OnComR) ON~BN~CLICKED(IDC~UNCOM~R, OnUncomR) ON WM //T)AFX~MSG~MAP END~MESSAGE~MAP() <BR> <BR> <BR> <BR> <BR> <BR> //////////////////////////////////////////////////////////// /////////////////<BR> <BR> <BR> // CKeySearch message handlers BOOL CKeySearch::OnInitDialog() CDialog::OnInitDialog(); int i,id; m~preds = 1; m~pred~type[0] = m~pred~type[1] = m~pred~type[2] = INT~SEARCH~TYPE; for (id = 1; id < OPA; id++) GetDlgItem(g~id[0][id])->EnableWindow(FALSE); m~pic = (g~pic[m~id] + 1) t 8; ((CButton *) GetDlgItem(IDC~ALL~R))->SetCheck(TRUE); m search type = SEARCH~ALL~ENT; m~committed = -1; m uncommitted = -1; m~total~entries = -1; SetDlgIteText(IDC MODE,"View " + g~que[m~id] + " Entries" ); SetTimer(KEYTIMER,1000,NULL); // 4 sec i = O; while (ALL~TEXT S[i]) GetDlgItem(ALL TEXT S[i++l)->SetFont(&g~text font); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE int String2Time(const char *s)( // Thu Nov 30 17:30:00 1995 char mon[80]; int mday,hr,mn,sc,yr,args; tm TM; // If it starts with a day skip it.

sscanf(s,"%s",mon); if (strstr("Mon Tue Wed Thu Fri Sat Sun",mon)) s = s + 4; args = sscanf(s,"%s td td:Wd:Wd %d",mon,&mday,&hr,&mn,&sc,&yr); if (!strcmp(mon,"Jan")) TM.tm~mon = 0; else if (!strcmp(mon,"Feb")) TM.tmmon = 1; else if (!strcmp(mon,"Mar")) TM.tm~mon = 2; else if (!strcmp(mon,"Apr")) TM.tm~mon = 3; else if (!strcmp(mon,"May")) TM.tm~mon = 4; else if (!strcmp(mon,"Jun")) TM.tm~mon = 5; else if (!strcmp(mon,"Jul")) TM.tm~mon = 6; else if (!strcmp(mon,"Aug")) TM.tm~mon = 7; else if (!strcmp(mon,"Sep")) TM.tm~mon = 8; else if (!strcmp(mon,"Oct")) TM.tm~mon = 9; else if (!strcmp(mon,"Nov")) TM.tm~mon = 10; else if (!strcmp(mon,"Dec")) TM.tm~mon = 11; else TM.tm~mon = 12; if ((args == 6) && (TM.tm~mon != 12)) TM.tm~sec = sc; TM.tm~min = mn; TM.tm~hour = hr; TM.tm~mday = mday; TM.tm~year = yr - 1900; TM.tm~isdst = -1; return(mktime(&TM)); } else return(-l); void Time2String(int time,char *s, int printday) if (printday) strcpy(s,ctime((time~t*)(&time))); else strcpy(s, (ctime((time t*)(&time)) + 4) ) ; // dont print day s[strlen(s) - 1] = 0; void CKeySearch::OnCompChange(int pred) CString type~str; GetDlgItemText(g~id[pred][COMP],type~str); int comptype = INT~SEARCH~TYPE; if type~str == "String") comptype = STR~SEARCH~TYPE; if type~str == "Short") comptype = SHORT~SEARCH~TYPE; m~pred~type[pred] = comptype; CComboBox * CBat = (CComboBox *) this->GetD1gItem(gid[pred] [AT]); CComboBox * CBmin = (CCombobox *) this->GetDlgItem(g~id[pred][MIN]); CComboBox * CBmax = (CCombobox *) this->GetDlgItem(g~id[pred][MAX]); <BR> <BR> <BR> <BR> CBat-sResetContent(); <BR> <BR> <BR> <BR> CBmin->ResetContent(); CBmax->ResetContent(); CBmin->AddString(""); CBmin->AddString(""); CBmin->AddString("ANY"); CBmax->AddString(""); CBmax->AddString(""); CBmax->AddString("ANY"); if (type~str == "Time") char tim[80]; Time2String(SHAREDATA(time) ,tim,O); CBat->AddString("TIME"); CBmin->SetCurSel(-1); CBmin->SetWindowText(tim); // CBmin->ReplaceSel(tim); CBmin->AddString(tim); // add to edit box too? CBmax->AddString(tim); // add to edit box too? else if (comptype == STR~SEARCH~TYPE) CBat->Addstring ("CUSTOMER"); <BR> <BR> <BR> <BR> CBat->Addstring("ITEM") <BR> <BR> <BR> CBat->Addstring("to server"); CBat->AddString("to~logical"); else if (comptype == INT~SEARCH~TYPE) CBat->AddString("UID"); CBat->AddString("TID"); CBat->AddString("HOST"); CBat->AddString("QUANTITY"); lpRT rt = ROOT; while (rt = NextRT(rt)) CBmin->AddString(RT NODE(rt)); <BR> <BR> <BR> <BR> CBmax->AddString(RT~NODE(rt)); else if (comptype == SHORT~SEARCH~TYPE) CBat->AddString("MODE"); CBat->AddString("SUB~MODE"); for (int id = 1; id < ID~OBJS; id++) GetDlgItem(g~id[pred][id]->EnableWindow(TRUE); GetDlgItem(IDSEARCHB)->EnableWindow(TRUE); // GetParentFrame()->SetMessageText(""); cedit SetDlgItemText(IDC~SERSTAT,""); ((CComboBox *) this->GetDlgItem(g~id[pred][AT]))->SetCursel(0); ((CComboBox *) this->GetDlgItem(g~id[pred][MAX]))->SetCursel(0); ((CComboBox *) this->GetDlgItem(g id[pred] [MIN]))-SetCurSel(O); void CKeySearch::OnSelchangeCompCb1() {OnCompChange(0);} void CKeySearch::OnSelchangeCompCb2() {OnCompChange(1);} void CKeySearch::OnSelchangeCompCb3() {OnCompChange(2);} void CKeySearch::ChangePredView(int pred, int act) int id; for (id = C; id < ID~OBJS; id++) GetDlgItem(g~id[pred][id])->ShowWindow(act); for (id = 1; id < OPA; id++) GetDlgItem(g~id[pred][id]->EnableWindow(FALSE); if (act == SW~HIDE) for (id = 0; id < AND; id++) ((CComboBox *) this->GetDlgItem(g~id[pred][id]))->SetCurSel(-1); if (act == SW~HIDE ) ( // Get rid of the ghost of the combo box MFC bug? this->Invalidate(); this->UpdateWindow(); void CkeySearch::OnAnd1() if (mpreds == 1) ChangePredView(l,SW~SHOW); <BR> m~preds = 2;<BR> else ChangePredView(l,SW~HIDE); ChangePredView(2,SW~HIDE); m~preds = 1; void CKeySearch: :DnAnd2() if (m~preds == 2) ChangepredView(2,SW~SHOW); <BR> <BR> <BR> <BR> <BR> <BR> <BR> m~preds = 3;<BR> else ChangePredView(2,SW~HIDE); m~preds = 2; void CKeySearch::CopyInput(int pred, int from, int to) CString s; int pos; GetDlgItemText(g~id[pred][from],s.GetBuffer(100),100); s.ReleseBuffer(); pos = ((CComboBox *) this->GetDlgItem(gid[pred] [to]))->GetCurSel(); ((CComboBox *) this->GetDlgItem(g~id[pred][to]))->DeleteString(0); ((CComboBox *) this->GetDlgItem(g~id[pred][to]))->InsertString(0,s); ((CComboBox *) this->GetDlgItem(g~id[pred][from]))->DeleteString(1); ((CComboBox *) this->GetDlgItem(g~id[pred][from]))->InsertString(1,s) if (pos == 0) ((CComboBox *) this->GetDlgItem(g~id[pred][to]))->SetCurSel(0);<BR > }<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> void CKeySearch::OnEditchangeMinCb1() {CopyInput(0,MIN,MAX);}<BR> <BR> <BR> <BR> <BR> <BR> void CKeySearch: :OnEditchangeMinCb2 () Copylnput (1,MIN,MAX); <BR> <BR> <BR> void CKeySearch::OnEditchangeMinCb3() {CopyInput(2,MIN,MAX); void CKeySearch::OnEditchangeMaxCb1() {CopyInput(0,MAX,MIN); void CKeySearch::OnEditchangeMaxCb2() {CopyInput(1,MAX,MIN); void CKeySearch::OnEditchangeMaxCb3() {CopyInput(2,MAX,MIN); void CKeySearch::OnSearchb() SMBUF b,B; QADMSEL key; OFORM order; CString ss,s,at~str,min~str, max~str; int i,at~int, sz, matches; GetDlgItem(IDSEARCHB)->EnableWindow(FALSE) CListBox* lb = (CListBox*) GetDlgItem(IDC SEARCH~LB); lb->ResetContent(); SetDlgItemText(IDC~SERSTAT,""); // lb->SetTabStops(100); key.num~preds = m~preds; key.search~type = m~search~type; //SEARCH~ALL~ENT for (int p = 0; p < m~preds; p++) { // Set min and max values min~str = max str = GetDlgItemText(gid[p] [MIN] ,min~str.GetBuffer(100) ,lCO) GetDlgItemText(g~id[p][MAX],max~str.GetBuffer(100),100); GetDlgItemText(gid[p] [AT] ,at~str.GetBuffer(lCO) ,10O) min~str.ReleaseBuffer(); max~str.ReleaseBuffer(); at~str.ReleaseBuffer(); at int = GetDlgItemInt(g~id[p] [AT],NULL,TRUE); strcpy(key.preds[p] .min str val,LPCTSTR(min str)); strcpy(key.preds[p].max~str~val,LPCTSTR(max~str)); key.preds[p] .min~int~val = GetDlgItemInt(gid[p] [MIN] ,NULL,TRUE); // min i key.preds[p].max~int~val = GetDlgltemlnt(gid[p] [MAX],NULL,TRUE); // max i key.preds[p].min~sh~val = key.preds.[p].min~int~val; // min short key.preds[p].max~sh~val = key.preds.[p].max~int~val; // max short if (min~str == "ANY") key.preds[p].min~switch = 0; key.preds[p].min~str~len = 0; else key.preds[p].min~switch = 1; key.preds[p].min~str~len = strlen(key.preds[p].min~str~val); if (max~str == "ANY") key.preds[p].max~switch = 0; key.preds[p].max~str~len = 0; else key.preds[p].max~switch = 1; key.preds[p].max~str~len = strlen(key.preds[p].max~str~val); if (at str == "TIME") //char tim(8O] if (max str == "NOW") key.preds[p].max~int~val = SHAREDATA(time); if ((i = String2Time(LPCTSTR(max~str))) != -1) key.preds[p].max~int~val = if (min str == "NOW") key.preds[p].min int val = SHAREDATA(time); if ((i = String2Time(LPCTSTR(min~str))) != -1) key.preds[p] .min~int~val = // Time2String(key.preds[p].min~int~val,tim,1); // s.Format("Time value:ts",tim); // SetDlgItemText(IDC~SERSTAT,s); if (at~str == "HOST") ( if (i = Name2IP(LPCTSTR(max~str))) key.preds[p].max~int~val = if (i = Name2IP(LPCTSTR(min~str))) key.preds[p].min~int~val = // Find the offset if (at~str == "TIME") at~int = ((char *) &b.msgh.time) - ((char *) &b.msgh); if (at~str == "MODE") at~int = ((char *) &b.msgh.mode) - ((char *) &b.msgh); if (at~str == "SUB MODE") at int = ((char *) &b.msgh.submode) - ((char *) &b.msgh); if (at~str == "UID") at~int = ((char *) &b.msgh.mid.uid) - ((char *) &b.rnsgh); if (at~str == "TID") at~int = ((char *) &b.msgh.mid.tid) - ((char *) &b.msgh); if (at~str == "HOST") at~int = ((char *) &b.msgh.mid.host) - ((char *) &b.msgh); if (at~str == "SIZE") at~int = ((char *) &b.msgh.size) - ((char *) &b.msgh); if (at~str == "to server") at~int = ((char *) &b.msgh.to~server) - ((char *) &b.msgh); if (at~str == "to logical") at~int = ((char *) &b.msgh.to~logical) - ((char *) &b.msgh); if (at~str == "CUSTOMER") at int = sizeof(MSGH) + ((char *) &order.cust) - ((char *) &order); if (at~str == "ITEM") at~int = sizeof(MSGH) + ((char *) &order.item) - ((char *) &order); if (at str == "QUANTITY") atint = sizeof(MSGH) + ((char *) &order.qty) - ((char *) &order); key.preds[p].offset = at~int; key.perds[p].pred~type = m~pred~type[p]; // Get the list of key matches if (QSUCCESS == QsendAndReceive(QS[m~id],ADMINREQ~MODE,QADM~REQ~SEL~DATA, 0,sizeof(key),(char *) &key, sizeof(b.mdata),b.mdata,&sz,&b.msgh)) lpMID md = (lpMID) b.mdata; matches = sz / sizeof(MID); if (matches > 0) // char * h = IP2Name(md->host); for (i = 0; i < matches ; i++) ss.Format("%s(%d,%d)", IP2Name(md->host),md->uid,md->tid); s.Format("%4d \t%s",i+1,ss ); lb->InsertString(-1,s); md = (lpMID) ((char *)md + sizeof(MID)); else lb->InsertString(-1,"No messages"); lb->UpdateWindow(); //Sleep(200); md = (lpMID) b.mdata; lpOFORM po = (lpOFORM)B.mdata; for (i = C; i < matches ; i++) memcpy(B.mdata,md,sizeof(MID)); // Copy one mid s.Format("%d Messages: Reading hd",matches/i); SetDlgItemText(IDC~SERSTAT,s); GetDlgItem(IDC~SERSTAT)->UpdateWindow(); if (QSUCCESS == QsendAndReceive(QS[m~id],ADMINREQ~MODE,QADM~REQ~MSG, 0,sizeof(mid),B.mdata, sizeof(B.mdata),B.mdata,&sz,&Bmsgh)) { ss.Format("%s(%d,%d)", IP2Name(md->host),md->,md->tid); if (B.msgh.size == sizeof(OFORM)) s.Format("%4d \t%s\t%-8s\t%2d %-10s",i + 1,ss,po->cust,po->qty,po else if (sz) s.Format("%4d \t%s\t%s,i + 1,ss,b.mdata); else s.Format("%4d \t%s\t<<Empty>>",i + 1,ss); lb->DeleteString(i); lb->InsertString(i,s) else s.Format("%d Error requesting %s(%d,%d)",i + l,IP2Name(md->host),md- SetDlgItemText(IDC~SERSTAT,s); break; // Stop here md = (lpMID)((char *)md + sizeof(MID)); else s.Format("Error - no reply") if (!strstr(LPCTSTR(s),"Error")) s.Format("%d Matches:",matches); SetDlgItemText(IDC~SERSTAT,s); <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> Sleep(500); <BR> GetDlgItem(IDSEARCHB)->EnableWindow(TRUE); void CKeySearch::OnTimer(UINT nIDEvent) if (nIDEvent == KEYTIMER) int com,uncom; CString s; if ((g~pic[m~id] != mpic)) GetDlgItem(IDC~KPICS[g~pic[m~id]])->ShowWidow(SW~SHOW);&l t;BR> <BR> GetDlgItem(IDC~KPICS[m~pic])->ShowWindow(SW~HIDE); m~pic = g~pic[m~id]; // Set Title <BR> <BR> this->SetWindowText("View " + g~que[m~id] );<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> if (m~committed != (com = g~s[m~id].commited~entries))<BR> <BR> s.Format("%3d Committed entries.", (m~commTtted = com));<BR> <BR> <BR> <BR> SetDlgItemText(IDC~COM~R,s); <BR> }<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> if (m~committed != (uncom = g~s[m~id].pending~gets + g~s[m~id].pending~p<BR> s.Format("%3d Uncommitted entries.",(m~uncommitted = uncom));<BR> <BR> <BR> <BR> SetDlgItemText(IDC~UNCOM~R,s);<BR> } if (m~total~entries != (com + uncom)) { s.Format("All %d entries.", (m~total~entries = com + uncom)); SetDlgItemText(IDC~ALL~R,s);<BR> }<BR> <BR> <BR> <BR> <BR> <BR> else <BR> <BR> <BR> <BR> CDialog::OnTimer(nIDEvent);<BR> void CKeySearch::OnAllR()<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> { m~search~type = SEARCH~ALL~ENT;}<BR> <BR> void CKeySearch::OnComR()<BR> <BR> <BR> <BR> <BR> <BR> { m~search~type = SEARCH~COM~ENT;}<BR> <BR> void CKeySearch::OnUncomR() { m~search~type = SEARCH~UNCOM~ENT;} void CKeySearch::OnRButtonDown(UINT nFlags, CPoint point) GetParentFrame ()->SetMessageText (""); this->Invalidate(); CDialog::OnRButtonDown(nFlags, point); // qman.cpp : Defines the class behaviors for the application.

#include "stdafx.h" *include "qman.h" #include "mainfrm.h" *include "qmandoc .

#include "qmanview.h" *ifdef DEBUG *undef THIS~FILE static char BASED~CODE THIS~FILE[] = FILE #endif //////////////////////////////////////////////////////////// ///////////////// // CQmanApp BEGIN~MESSAGE MAP(CQmanApp, CWinApp) // ( (AFXMSG~MAP (CQmanApp) ON~COMMAND(ID~APP~ABOUT, OnAppAbout) // NOTE - the ClassWizard will add and remove mapping macros her // DO NOT EDIT what you see in these blocks of generated code<BR> <BR> <BR> //}}AFX~MSG~MAP // Standard file based document commands ON~COMMAND(ID FILE~NEW, CWinApp::OnFileNew) ON~COMMAND(ID~FILE~OPEN, CWinApp::OnFileOpen) // Standard print setup command ON COMMAND(ID FILE PRINT SETUP, CWinApp: :OnFilePrintSetup) END~MESSAGE~MAP() //////////////////////// // CQmanApp construction CQmanApp::CQmanApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance /////////////////////////////////// // The one and only CQmanApp object CQmanApp theApp; /////////////////////////////////// // CQmanApp initialization BOOL CQmanApp::InitInstance() { // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need.

Enable3dControls(); LoadStdProfileSettings(); // Load standard INI file options (including // Register the application's document templates. Document templates // serve as the connection between documents, frame windows and views.

CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR~MAINFRAME, RUNTIME~CLASS(CQmanDoc), RUNTIME~CLASS(CMainFrame), // main SDI frame window RUNTIME~CLASS(CQmanView)); AddDocTemplate(pDocTemplate); // create a new (empty) document OnFileNew(); if (m~lpCmdLine[0] != '\0') // TODO: add command line processing here return TRUE; //////////////////////////////////////////////////////////// ///////////////// // CAboutDlg dialog used for App About class CAboutDlg public CDialog public: CAboutDlg(); // Dialog Data //{{AFX~DATA(CAboutDlg) enum { IDD = IDD~ABOUTBOX }; //}}AFX~DATA CFont m~title~font; // Implementation protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // ( (AFXMSG (CAboutDlg) virtual BOOL OnInitDialog(); //}}AFX~MSG DECLARE MESSAGE MAP() CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) //{{AFX~DATA~INIT(CAboutDlg) //}}AFX~DATA~INIT void CAboutDlg::DoDataExchange(CDataExchange+ pDX) CDialog::DoDataExchange(pDX); //((AFX DATA MAP(CAboutDlg) //}}AFX~DATA~MAP BEGIN~MESSAGE MAP(CAboutOlg, CDialog) //((AFX MSG~MAP(CAboutDlg) //))AFXMSG~MAP END~MESSAGE~MAP() // App command to run the dialog void CQmanApp: :OnAppAbout() CAboutDlg aboutDlg; aboutDlg.DoModal(); //////////////////////////////////////////////////////////// ///////////////// // CQmanApp commands BOOL CAboutDlg::OnInitDialog() CDialog::OnInitDialog(); LOGFONT lf; memset(&lf,0,sizeof(LOGFONT)); strcpy(lf.lfFaceName,"Monotype Corsiva"); lf.lfHeight = 24; m~title~font.CreateFontIndirect(&lf); <BR> <BR> GetlgItem(IDC ABOUT1)->SetFont(&m~title~font); // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE // qman.h : main header file for the QMAN application #ifndef~AFXWIN~H~ &num error include 'stdafx.h' before including this file for PCH #endif *include "resource.h" // main symbols //////////////////////////////////////////////////////////// ///////////////// // CQmanApp: // See qman.cpp for the implementation of this class class CQmanApp : public CWinApp public: CQmanApp(); // Overrides // ClassWizard generated virtual function overrides //{{AFX:VIRTUAL(CQmanApp) public: virtual BOOL InitInstance(); //}}AFX~VIRTUAL // Implementation //{{AFX~MSG(CQmanApp) afx~msg void OnAppAbout(); // NOTE - the ClassWizard will add and remove member function // DO NOT EDIT what you see in these blocks of generated code //) }AFXMSG DECLARE MESSAGE MAP() // qmandoc.cpp . implementation of the CQmanDoc class &num include "stdafx.h" &num include "qman.h" #include "qmandoc .

*ifdef DEBUG *undef THIS FILE static char BASED CODE THIS~FILE[] = FILE #endif //////////////////////////////////////// // CQmanDoc IMPLEMENT~DYNCREATE(CQmanDoc, CDocument) BEGIN~MESSAGE MAP(CQmanDoc, Document) //((AFX~MSG~MAP(CQmanDoc) // NOTE - the ClassWizard will add and remove mapping macros her // DO NOT EDIT what you see in these blocks of generated code //}}AFX~MSG~MAP<BR> <BR> END~MESSAGE~MAP() '= //////////////////////////////////// // CQmanDoc construction/destruction CQmanDoc::CQmanDoc() { // TODO: add one-time construction code here CQmanDoc::~CQmanDoc() { } BOOL CQmanDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; // TODO: add reinitialization code here // (SDI documents will reuse this document) return TRUE; //////////////////////////////////////////////////////////// ///////////////// // CQmanDoc serialization void CQmanDoc::Serialize(CArchive& ar) if (ar.IsStoring()) // TODO: add storing code here else // TODO: add loading code here } } ////////////////////////////////////////////// // CQmanDoc diagnostics #ifdef ~DEBUG void CQmanDoc::AssertValid() const { CDocument::AssertValid(); } void CQmanDoc::Dump(CDumpContext& dc) const CDocument::Dump(dc); ))endif //~DEBUG //////////////////////////////////////////////////////////// ///////////////// // CQmanDoc commands // qmandoc.h interface of the CQmanDoc class<BR> // class CQmanDoc : public CDocument protected: // create from serialization only CQmanDoc(); DECLARE~DYNCREATE(CQmanDoc) // Attributes public: // Operations public: // Overrides lj ClassWizard generated virtual function overrides //((AFX~VIRTUAL(CQmanDoc) public virtual BOOL OnNewDocument(); //}}AFX~VIRTUAL // Implementation public: virtual CQmanDoc(); virtual void Serialize(CArchive& ar); // overridden for document i/o ))ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; ;)endif protected: // Generated message map functions protected: //{{AFX~MSG(CQmanDoc) // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //}}AFX~MSG DECLARE MESSAGE MAP() // qmanview.h interface of the CQmanView class class CQmanView public CFormView { protected: // create from serialization only CQmanView() DECLARE~DYNCREATE(CQmanView) public: <BR> <BR> //( (AFX DATA(CQmanView) <BR> enum( IDD = IDD~QMAN~FORM } // NOTE: the ClassWizard will add data members here //}}AFX~DATA // Attributes int m maxtrack; CString m~que[3]; public: CQmanDoc* GetDocument(); // Operations public: // Overrides // ClassWizard generated virtual function overrides //((AFX~VIRTUAL(CQmanView) public: virtual void OnInitialUpdate(); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnPrint(CDC* pDC, CPrintInfo*); virtual void OnDraw(CDC* pDC); //}}AFX~VIRTUAL //void InitTrackBar(HWND hTrack, int IDMIN, int TMIN, int IDMAX, int TMAX, in //DWORD Poll(); //DWORD CQmanView: :Poll(); void CQmanView::OpenQue(int i, int IDC~QUES); // meter painting void DrawKey(); void GetMeterBoxes() void TestMeters(); void CQmanView::LoadList(int QN, int IDC~QUES); void CQmanView::DrawMeter(int i); void CQmanView::CmdLine(int pass); void CQmanView::DrawKeyColor(int ID, int HS, COLORREF COL); // font CFont m~title~font; // Implementation public: virtual ~CQmanView() #ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; 4endif protected: // Generated message map functions protected: //{{AFX~MSG(CQmanView) afxmsg void OnExit(); afx~msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx~msg void OnSelchangeQues1(); afx~msg void OnSelchangeQues2(); afxmsg void OnSelchangeQues3(); afx~msg void OnAdminb1(); afx~msg void OnAdminb2(); afx~msg void OnAdminb3(); afx~msg void OnDatab1(); afxmsg void OnDatab2(); afx~msg void OnDatab3(); afx~msg void OnTimer(UINT nIDEvent); afx~msg void OnRButtonDown(UINT nFlags, CPoint point); afx~msg void OnSetFocusQues1(); afx~msg void OnSetFocusQues2(); afx msg void OnSetfocusQues3(); //}}AFX~MSG DECLARE~MESSAGE~MAP() ))ifndef DEBUG // debug version in qmanview.cpp inline CQmanDoc* CQmanView::GetDocument() { return (CQmanDoc*)m~pDocument; #endif // qmanview.cpp . implementation of the CQmanView class #include "stdafx.h" *include "qman.h" *include "qmandoc.h" #include "qmanview.h" #include "admindlg.h" //4include "datadlg.h" #include "KeySearch.h" //+++++++++++++ QLIB +++++++++++++++++++ *include "qlib.h" #include "qadmin.h" &num include "rt.h" define MYTIMER 100 #define TITLETIMER 101 #define MIN~POLL~DLY 100 #define MAX~POLL~DLY 5000 extern lpSMBUFH sm base; lpQHANDLE QS[3] = {NULL,NULL,NULL}; QADMSTATS g~s[3+3]; // 3 Current + 3 Old int g~starting[3]; // forces first N updates of meter //HWND g~track[3]; HWND g~tmin[3]; HWND g~tmax[3]; HWND g~tlab[3]; CString gque[] = int ALL~TEXT[] = {IDC~TMIN1,IDC~TMIN2,IDC~TMIN3, IDC~TMAX1,IDC~TMAX2,IDC~TMAX3, IDC~TLAB1,IDC~TLAB2,IDC~TLAB3, IDC~ADMINB1,IDC~ADMINB3,IDC~ADMINB3, IDC~DATAB1.IDC~DATAB2,IDC~DATA3, IDC~QUES1,IDC~QUES2,IDC~QUES3, IDC~EXIT,0,0,0}; int IDC TMINS[] = {IDC~TMIN1,IDC~TMIN2,IDC~TMIN3 int IDC~TMAXS[] = {IDC~TMAX1,IDC~TMAX2,IDC~TMAX3 int IDC~TLABS[] = {IDC~TLAB1,IDC~TLAB2,IDC~TLAB3 int IDCMETERS[] = {IDC~METER1,IDC~METER2,IDC~METER3}; int IDC~PICS[3][8] = {{IDC~QNONE1,IDC~QDOWN1,IDC~QSTOP1,IDC~QNOPUT1,IDC~QNOGET1 {IDC~QNONE4,IDC~QDOWN4,IDC~QSTOP4,IDC~QNOPUT4,IDC~QNOGET4 {IDC~QNONE5,IDC~QDOWN5,IDC~QSTOP5,IDC~QNOPUT5,IDC~QNOGET5 enum pics (QNONE,QDOWN,QSTOP,QNOPUT,QNOGET,QUP,QNOPG,QFULL) int g~pic[3+3-F3]; int g~poll; int g~poll~delay = 2000; CFont g~text~font; typedef struct met { // Thread parameters CRect b~rec; CRect c~rec; CRect p~rec; CRect g~rec; CRect h~rec; CRect f~rec; int commit,pendp,pendg,hole,free,min,max; } MET, *pMET; MET g~met[3+4]; //+++++++++++++ QLIB +++++++++++++++++++ *ifdef DEBUG #undef THIS~FILE static char BASED~CODE THIS~FILE[] = FILE #endif //////////////////////////////////////////////////////////// ///////////////// // CQmanView IMPLEMENT~DYNCREATE(CQmanView, CFormView) BEGIN~MESSAGE~MAP(CQmanView, CFormView) //{{AFX~MSG~MAP(CQmanWiew) ON~BN~CLICKED(IDC~EXIT, OnExit) ON WM HSCROLL() ONCB SELCHANGE(IDC QUES1, OnSelchangeQuesl) ON-CBN-SELCHANGE(IDC-QUES2, OnSelchangeQues2) ON-CBN-SELCHANGE(IDC-QUES3, OnSelchangeQues3) ON~BN~CLICKED(IDC~ADMINB1, OnAdminb1) ONBNCLICKED (IDCADMINB2, OnAdminb2) ON-BN-CLICKED(IDC-ADMINB3, OnAdminb3) ON~BN~CLICKED(IDC~DATAB1, OnDatab1) ON BN CLICKED(IDC DATAB2, OnDatab2) ONZBNZCLICKED(IDCrDATAB3, OnDatab3) ON~WM~TIMER() ON () ON~CBN~SETFOCUS(IDC~QUES1, OnSetfocusQues1) ON~CBN~SETFOCUS(IDC~QUES2, OnSetfocusQues2) ONCBNSETFOCUS (IDC~QUES3, OnSetfocusQues3) //}}AFX~MSG~MAP<BR> <BR> <BR> // Standard printing commands ON~COMMAND(ID~FILE~PRINT, CFormView::OnFilePrint) ON~COMMAND(ID~FILE~PRINT~PREVIEW, CFormView::OnFilePrintPreview) END~MESSAGE~MAP() ///////////////////////////////////// // CQmanView construction/destruction CQmanView::CQmanView() : CFormView(CQmanView::IDD) //{{AFX~DATA~INIT(CQmanView) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT // TODO: add construction code here CQmanView::~CQmanView() { } void CQmanView::DoDataExchange(CDataExchange* pDX) { CFormView::DoDataExchange(pDX); <BR> <BR> <BR> <BR> //({AFX-DATA-MAP(CQmanView) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP } //////////////////////////////////////////////////// // CQmanView printing BOOL CQmanView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); void CQmanView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) // TODO: add extra initialization before printing void CQmanView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) // TODO: add cleanup after printing void CQmanView::OnPrint(CDC* pDC, CPrintInfo*) // TODO: add code to print the controls //////////////////////// // CQmanView diagnostics #ifdef ~DEBUG void CQmanView: :AssertValid() const CFormView::AssertValid(); void CQmanView::Dump(CDumpContext& dc) const CFormView::Dump(dc); CQmanDoc* CQmanView::GetDocument() // non-debug version is inline ASSERT(m~pDocument->IsKindOf(RUNTIME~CLASS(CQmanDoc))); return (CQmanDoc*)m pDooument; 4endif //~DEBUG ///////////////////////////// // CQmanView message handlers void CQmanView::OnExit() { g~poll = 0; // Stop the threads AfxGetMainWnd()->DestroyWindow(); // METER METER METER METER METER METER METER METER METER METER METER METER // METER METER METER METER METER METER METER METER METER METER METER METER // METER METER METER METER METER METER METER METER METER METER METER METER b~rec // +---------+---------+---------+---------+ // Committ Pending holes Free // // +---------+---------+---------+---------+ // c rec p p~rec h rec f rec void CQmanView: :GetMeterBoxes() for (int i=0;i<3i++){ GetDlgItem(IDC~METERS[i])->GetWindowRect(&g~met[i].b~rec) ; // Adjust coordantates for 0,0,1,b g~met[i].b~rec.right -= g~met[i].b~rec.left; g~met[i].b~rec.bottom -= g~met[i].b~rec.top; g~met[i].b~rec.left = g~met[i].b~rec.top = 0; g~met[i].c~rec.left = 0; // Commit always starts at 0,0 g~met[i].f~rec.right = g~met[i].b~rec.right; // Free always ends at max g~met[i].c~rec.top = g~met[i].p~rec.top = g~met[i].g~rec.top = g~met[i].h~rec.top = g~met[i].f~rec.top = g~met[i].b~rec.top; // 0 g~met[i].c~rec.bottom = g~met[i].p~rec.bottom = g~met[i].g~rec.bottom = g~met[i].h~rec.bottom = g~met[i].f~rec.bottom = g~met[i].b~rec.bottom; // All the same hight void CQmanView::DrawKeyColor(int ID, int HS, COLORREF COL)( CRect c~rec; CBrush *pCBrush; if ( HS == -1) pCBrush = new CBrush(COL); else pCBrush = new CBrush(HS,COL) GetDlgItem(ID)->GetWindowRect(&c~rec); // Adjust coordantates for 0,0,1,b c~rec.right -= c~rec.left; c~rec.bottom -= c~rec.top; c~rec.left = c rec.top = O; // The DC for the meter CDC* pCOLORDC = GetDlgItem(ID)->GetDC(); // Select this brush, save the old CBrush *pOldBrush = pCOLORDC->SelectObject(pCBrush); pCOLORDC->Rectangle(c~rec); GetDlgItem(ID)->Invalidate(); delete(pCBrush); ReleaseDC(pCOLORDC); void CQmanView::DrawKey()( DrawKeyColor(IDC~KEY~COM, -1, RGB(127,255,255); DrawKeyColor(IDC-KEY-PENPUT, HS BDIAGONAL, RGB(O0C, 182,255)); DrawKeyColor(IDC~KEY~PENGET, HS~FDIAGONAL, RGB(000,182,255)); DrawKeyColor(IDC~KEY~HOLE, HS~DIAGCROSS, RGB(255,128,128)); #define MAXPIXELS g~met[i].b rec.right void CQmanView::TestMeters(){ int c,pg,pp,h; // Pixel width of each rectangle for (int i=0;i<3i++) ( // If any change if((g~met[i].commit != g~s[i].committed~entries) (g~met[i].pendg != g~s[i].pending~gets ) (g~met[i].pendp != g~s[i].pending~puts) (g~met[i].hole != g~s[i].holey~entries ) (g~met[i].free != g~s[i] .num~free~entries) II g~met[i].max != g~s[i].max~entries) ) { if (!g~s[i].max~entries) g~s[i].max~entries=1; // No divide by zero // Update old values g~met[i].commit = g~s[i].committed~entries; g~met[i].pendg = g~s[i].pending~gets; g~met[i].pendg = g~s[i].pending~gets; g~met[i].hole = g~s[i].holey~entries; g~met[i].free = g~s[i].num~free~entries; g~met[i].max = g~s[i].max~entries; // c,pp,pg,h,f are points on a line between min, max scaled to #pixe c = O + (MAXPIXELS * g~met[i].commit)/g~met[i].max; pp= c + (MAXPIXELS * gmet[i].pendp)/gmet[i].max; pg=pp + (MAXPIXELS * g~met[i].pendg)/g~met[i].max; h =pg + (MAXPIXELS * g~met[i].hole)/g~met[i].max; // f = h + (MAXPIXELS * g~met[i] .free)/gmet[i] .max; // constant // Make 5 rectangles to fill with colors // g~met[i].c~rec.left = 0; // constant g~met[i].c~rec.right = c; g~met[i].p~rec.left = c; g~met[i].p~rec.right = pp; g~met[i].g~rec.left = pp; g~met[i].g~rec.right = pg; g~met[i].h~rec.left = pg; g~met[i].h~rec.right = g~met[i].f~rec.left = // g~met[i].f~rec.right = g~met[i].max; // constant DrawMeter(i); void CQmanView::DrawMeter(int i)( // Create the Brush CBrush *pCBrush = new CBrush( RGB(127,255,255) ); CBrush *pPBrush = new CBrush( HS~BDIAGONAL, RGB(000,182,255) ); CBrush *pGBrush = new CBrush( HS~FDIAGONAL, RGB(000,182,255) ); CBrush *pHBrush = new CBrush( HS~DIAGCROSS, RGB(255,128,128) ); // The DC for the meter CDC* pCOLORDC = GetDlgItem(IDC~METERS[i])->GetDC(); // Create a PEN // CPen *pQPen = new CPen(PS~SOLID, 3,RGB(0,0,255)); // CPen *pOldPen = pXDC->SelectObject(pQPen); // Select this brush, save the old CBrush *pOldBrush = pCOLORDC->SelectObject(pCBrush); pCOLORDC->Rectangle(g~met[i].c~rec); pCOLORDC->SelectObject(pPBrush); pCOLORDC->Rectangle(g~met[i].p~rec); pCOLORDC->SelectObject(pGBrush); pCOLORDC->Rectangle(g~met[i].g~rec); pCOLORDC->SelectObject (pHBrush) pCOLORDC->Rectangle(g~met[i].h~rec); pCOLORDC->SelectStockObject(WHITE~BRUSH); pCOLORDC->Rectangle(g~met[i].f~rec); pCOLORDC->SelectObject(&pOldBrush); // Reset the brush GetDlgItem(IDC~METERS[i])->Invalidate(); delete(pCBrush); delete(pPBrush); delete(pGBrush) delete(pHBrush), ReleaseDC(pCOLORDC); /* //////////////////////////////////// // Init the track bar // 0 TPS 100 // // |------------[]------------| //<BR> <BR> // MIN MAX // //////////////////////////////////// void InitTrackBar(HWND track, HWND HMIN, int TMIN, HWND HMAX, int TMAX) CString s; //HWND hTrack = GetDlgItem(ID)->m~hWnd; ::SendMessage(hTrack,TBM SETRANGEMIN,TRUE,TMIN); ' ::SendMessage(hTrack,TBM~SESTRAGEMAX,TRUE,TMAX); :SendMessage(hTrack,TBM SETTICFREQ,1,TRUE); ::SendMessage(hTrack,TBM~SETPOS,TRUE,TMIN); ::SendMessage(hTrack,TBM~SETSELSTART,TRUE,TMIN); // Select from start // Track Bar lables //s.Format("%d",TMIN); SetDlgItemText(IDMIN,s); //s.Format("%d",TMAX); SetDlgItemText(IDMAX,s); <BR> <BR> s.Format("%d",TMIN); .:SendMessage(HMIN,WM~SETTEXT,0,(LPARAM)(LPCTSTR) s);<BR> s.Format("%d",TMAX); ::SendMessage(HMAX,WM~SETTEXT,0,(LPARAM)(LPCTSTR) s); } */ DWORD Poll(LPVOID qnum) MSGH mh; CString s,sl; int used = 1; // Clear the track bar if not in use int i = (int)(qnum); int repeated~error = 0; g~poll = 1; while(g~poll) { if (QS[i]) { int sz;<BR> <BR> <BR> <BR> <BR> <BR> <BR> used++;<BR> if (QS[i]->open~time)<BR> ::SendMessage(g~tlab[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) "STARTING..."<BR> <BR> <BR> if (QSUCCESS >= (QsendAndReceive(QS[i],ADMINREQ MODE,QADM~REQ~STATS, 0,<BR> sizeof(g~s[i]),(char *)&g~s[i],&sz,&mh))){<BR> <BR> <BR> <BR> <BR> <BR> if ((mh.mode == ADMINREP~MODE || mh.mode ==ACK~MODE ) && (sz > 0<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> // Note: now, mode is ADMINREP~MODE if local @ if (!g~starting[i] && !memomp( &g~s[i+3], &gs[i],sizeof(QADMsTAT goto skip; memcpy( &g~s[i+3], &g~s[i],sizeof(QADMSTATS)); // set history=cu if (g~starting[i]) g~starting[i]--; // stop forcing m repeated~error = 0; // Assign a picture if (g~s[i].qget~state && g~s[i].qput~state) g~pic[i] = QUP; else if (g~s[i].qget~state) g~pic[i] = QNOPUT; else if (g~s[i].qput~state) g~pic[i] = QNOGET; else g~pic[i] = QNOPG; if (g~s[i].num~free~entries == 0) g~pic[i] = QFULL; if (QS[i]->open~time) QS[i]->open~time = 0; // Get rid of "START s.Format ("%s:%s at %s has %d entries",&g~s[i],physical~qname,&g s1.Format("%d",g~s[i] .max~entries); ::SendMessage(g~tlab[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) s); ::SendMessage(g~tmax[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) s1); :SendMessage(g~tmin[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) "0"); else .:SendMessage (g~tlab[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) "BAD REPLY // QS[i] = NULL; if (repeated error++ > 0) g~pic[i] - QDOWN; <BR> <BR> Sleep(5000) <BR> <BR> <BR> else g~pic[i] = STOP; else :SendMessage(gtlab[i] ,WM~SETTEXT,0, (LPARAM) (LPCTSTR) "COMM ERROR") // QS[i] = NULL; if (repeated~error++ > 0) g~pic[i] = QDOWN; Sleep(5000) } else g~pic[i] = QSTOP; } else ( // No open que // if (g~que[i] == // g~pic[i] = QNONE; if (used) used = 0; // The track bar will now be clear memset(&g~s[i],0,sizeof(g~s[i])) g~s[i+3] max~entries = 1; //::SendMessage(g~track[i],TBM~SETPOS,TRUE,0); //::SendMessage(g~track[i],TBM~SETSELEND,TRUE;0); :SendMessage(g~tlab[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) "No Que"); ::SendMessage (g~tmin[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) ""); ::SendMessage(g~tmax[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) ""); skip: Sleep(g~poll~delay); } // While loop return(1) void CQmanView::CmdLine(int pass) CString parm,value,line,nline; int i,poll; line = AfxGetApp()->m~lpCmdLine; while (2 <= (i = sscanf(LPCTSTR(line),"%s 5 parm.GetBuffer(100),value.GetBuffer(100),nline.GetBuffer(100 ) ))) { parm . MakeUpper () if (parm == "POLL") sscanr(LPCTSTR(value),"kd",&poll); if((MIN~POLL~DLY <= poll) && (poll <= MAX~POLL~DLY)) g~poll~delay = poll; if (parm == "1") CComboBox * CB = (CComboBox *) this->GetDlgItem(IDC~QUES1); CB->SelectString(-1,value); OnSelchangeQues1(); if (parm == "2") CComboBox * CB = (CComboBox *) this->GetDlgItem(IDC~QUES2); CB->SelectString(-l,value); OnSelchangeQues2(); if (parm == "3") CComboBox * CB = (CComboBox *) this->GetDlgItem(IDC~QUES3); CB->SelectString(-l,value); OnSelchangeQues3() line = LPCTSTR(nline); nline =""; int g~poll~delay~old; void CQmanView::OnTimer(UINT nIDEvent) // Select ICONS if (nIDEvent == MYTIMER) { for (int i=0;i<3i++) { if (g~pic[i] != g~pic[i+3]){ GetDlgItem(IDC~PICS[i][g~pic[i]])->ShowWindow(SW~SHOW); GetDlgItem(IDC~PICS[i] [97pic[i+3]1)->ShowWindow(SW~HIDE); g~pic[i+3] = g~pic[i]; TestMeters() else if (nIDEvent == TITLETIMER) GetParentFrame()->SetWindowText("QMAN"); KillTimer(TITLETIMER); DrawKey(); else CFormView::OnTimer(nIDEvent); void CQmanView::LoadList(int QN, int IDC~QL) // Called every time the user pick CString s; int i; // LIST OF QUEUES From Routing table and what is in Shared Memory.

// CListBox* lh = (CListBox*) GetDlgItem(IDC~QUE); // lb->InsertString(-1, "Ql") // lb->Insertstring(-l, "Q2") // lb->SetCurSel (0); CComboBox * CHI = (CComboBox *) this->GetDlgItem(IDC~QL); CB1->ResetContent(); // List all logical queues from the Routing Table // APPS: [physical],logical1,logical2,[physical],logical, if (sm~base = AttachSharedMemory()) { lpRT rt = RTROOT; while(rt = NextRT(rt)) char *e,*s = RT~APPS(rt); // Starts after the first letter while (s = strchr(s,',')) ( // Ends at next if (e = strchr(++s,',')) { *e = 0; if ((!strchr(s,'[')) && *s) CB1->AddString(s); // lb->InsertString(-1,s) // Look at shared memory (physical Q names) for "Q"s for ( i=O; i < SHAREDATA(nsbuf); i++ )( lpSMBUF b = SMBUFADDR(i); if ( strcmp(b->name,&"QNETD") && strchr(b->name,'Q') ) I // Anything th if (CB1->FindStringExact(-1,b->name) == CB~ERR) ( // String is not CB1->AddString(b->name); // lb->InsertString(-1,s) else GetParentFrame()->SetMessageText("QNETD not running(?) please start it."); MessageBox("QNETD not running, please start it.",0,MB~ICONSTOP); //AfxGetMainWnd()->DestroyWindow(); } CB1->AddString(""); // CB1->SetCurSel(g~que[QN]); CB1->SelectString(-1, g que[C<BR> CBl->SelectString(-l, g~que[QN]); void CQmanView::OnInitialUpdate() LOGFONT lf; CString s; CFormView::OnInitialUpdate(); // Default from vc++ // Set frame size = Form size GetParentFrame()->RecalcLayout(); ResizeParentToFit(FALSE); ResizeParentToFit(TRUE); GetMeterBoxes(); DrawKey(); for (int i=0;i<3i++) { // g~track[i] = GetDlgItem(IDC~TRACKS[i])->m~hWnd; g~tmin[i] = GetDlgItem(IDC~TMINS[i])->m~hWnd; g~tmax[i] = GetDlgItem(IDC~TMAXS[i])->m~hWnd; g~tlab[i] = GetDlgItem(IDC~TLABS[i])->m~hWnd; g~pic[i] = QNONE; // man g~pic[i+3] = QSTOP; // yellow // Add selections in the list of quenames (needed now, so the CmdLine args wi LoadList(0,IDC~QUES1); LoadList(l,IDC~QUES2); LoadList(2,IDC~QUES3); DWORD id; CreateThread(NULL,0,(LPTHREAD~START~ROUTINE) Poll,(LPVOID) 0,0,&id); CreateThread(NULL,0,(LPTHREAD~START~ROUTINE) Poll,(LPVOID) 1,0,&id); CreateThread(NULL,0,(LPTHREAD~START~ROUTINE) Poll,(LPVOID) 2,0,&id); CmdLine(l); SetTimer(MYTIMER,250,NULL); // 1/4 second SetTimer(TITLETIMER,100,NULL); // Fonts memset(&lf,0,sizeof(LOGFONT)); #ifdef BIGFONT lf.lfHeight = 18; #else lf.lfHeight = 13; *endif g~text~font.CreateFontIndirect(&lf); stropy(lf.lfFaceName,"Matura MT Script Capitals"); strcpy(lf.lfFaceName,"Monotype Corsiva"); lf.lfHeight = 32; m title font.CreateFontIndirect(&lf); GetDlgItem(IDC~TITLE)-&SetFont(&m~title~font); i = O; while (ALL TEXT[i]) GetDlgItem(ALL~TEXT[i++l)->SetFont(&g text font); void CQmanView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) // TODO: Add your message handler code here and/or call default // CFormView::OnHScroll (nSBCode, npos, pScrollBar); // Removed by derek void CQmanView::OpenQue(int i, int IDC~QUES) String s,que; int stat; GetDlgItemText(IDC~QUES,que.GetBuffer(100),100) que.ReleaseBuffer(); if (que != gque[i]) { // the user changed the open que name GetParentFrame()->SetWindowText("QMAN"); if (que == "") g~pic[i] = QNONE; g que[i] = s = "No Que will be used"; Qclose (&QS[i],0); else g~pic[i] = STOP; s.Format("Opening que %s",que); memset(&g~s[i],0,sizeof(QADMSTATS)); // clear g~starting[i] = 500; // Aprox 50 seconds.

GetParentFrame()->SetMessageText(s); // MessageBox(s); causes 2nd pass if (QS[i] = Qopen(que.GetBuffer(0),PUT~MODE,0,Q~FAILOVER,&stat,0,0) ) { g~que[i] = que; s.Format("Qopen(%s)",que); // QS[i]->time~out = 1000; // 1 second else s.Format("Qopen(%s) Error %d",que,stat); g~pic[i] = QDOWN; CComboBox * CB = (CComboBox *) this->GetDlgItem(IDC~QUES); CB->SelectString(-l,""); g~que[i] = GetParentFrame()->SetMessageText(s); void CQmanView::OnSetfocusQues1() { LoadList(0,IDC~QUES1);} void CQmanView::OnSetfocusQues2() { LoadList(1,IDC~QUES2);} void CQmanView::OnSetfocusQues3() { LoadList(2,IDC~QUES3);} void CQmanView::OnSelchangeQues1() { OpenQue(0,IDC~QUES1);} void CQmanView::OnSelchangeQues2() { OpenQue(1,IDC~QUES2);} void CQmanView::OnSelchangeQues3() { OpenQue(2,IDC~QUES3);} void CallAdm(int id) if (OS [id] CAdminDlg adm; adm.m id = id; adm.DoModal(); void CallData(int id){ if (QS[id]) CKeySearch d; // CdataDlg d.m~id = id; d.DoModal(); void CQmanView: :OnAdminbl() CallAdm(O); void CQmanView::OnAdminb2() { CallAdm(1); } void CQmanView::OnAdmin3() { CallAdm(2); } void CQmanView::OnDatab1() { CallData(0); } void CQmanView::OnDatab2() { CallData(1); } void CQmanView::OnDatab3() { CallData(2); } void CQmanView::OnDraw(CDC* pDC) DrawMeter(0); DrawMeter(1); DrawMeter(2); DrawKey(); CFormView::OnDraw(pDC); // this->SetWindowText("Qman av"); // GetParentFrame()->SetWindowText("QQMAN"); void CQmanView::OnRButtonDown(UINT nFlags, CPoint point) GetParentFrame()->SetMessageText("8); this->Invalidate(); CFormView::OnRButtonDown(nFlags, point); // oentrvw.cpp implementation of the COentryView class // /* ** ** Copyright (C) 1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** OpenMQ Demo ** Module: oenrvw.cpp ** Author: Derek Schwenke 10/8/95 &num include "stdafx.h" #include "oentry.h" #include "oentrdoc.h" #include "dbdlg.h" #include "odlg.h" #include "oentrvw.h" #include "orderfm.h" #include "oraomq.h" //+++++++++++++ QLIB +++++++++++++++++++ #include "qlib.h" #include "rt.h" extern lpSMBUFH sm~base; lpQHANDLE Q,Qrep; //+++++++++++++ QLIB +++++++++++++++++++ #define REPLY~SUBMODE 1 #define NOMSGQ~SUBMODE 2 #define DIRECT FILL TIME OVER 121 #define PLACE~ORDER NOQ 0 ((define PLACE ORDER 1 #define FILL~ORDER 2 #define FILL~FROM~ORACLE 3 #define DB DONE TIMER 201 #define WAIT~ANAMATE~TIMER 202 #define DIRECT~FILL~TIMER 203 #define FILL~DELAY~TIMER 204 #define FILL~ANAMATE~TIMER 205 #define SET TST TITLE TIMER 206 #define OPTIONS~DONE~TIMER 207 #define POLL~FILL~TIMER 208 #define PLACE~TIMER 209 #define NEXTBIT(X) (1 & ( X = X / 2 #ifdef DEBUG #undef THIS~FILE static char BASED~CODE THIS~FILE[] = FILE #endif //////////////////////////////////////////////////////////// ///////////////// // COentryView IMPLEMENT~DYNCREATE(COentryView, CFormView) BEGIN MESSAGE MAP(COentryView, CFormView) - //((AFX~MSG~MAP(COentryview) ON~BN~CLICKED(IDC EXITB, OnExitb) ON~BN~CLICKED(IDC~ORDERB, OnOrderb) ON~BN~CLICKED(IDC~AUTOB, OnAutob) ON WM~CTLCOLOR() ON~BN~CLICKED(IDC~PLACER, OnPlacer) ON~BN~CLICKED(IDC~FILLR, OnFillr) ON~CBN~SELCHANGE(IDC~QUE, OnSelchangeQue) ON~MESSAGE(MESSAGEREADY,OnReplyMsg) ON~BN~CLICKED(IDC~SENDREPC, OnSendrepc) ON~BN~CLICKED(IDC~TRANB, OnTranb) ON~BN~CLICKED(IDC~COMMITB, OnCommitb) ON~BN~CLICKED(IDC~ABORTB, OnAbortb) ON~WM~LBUTTONDOWN() ON~WM~TIMER() ON~BN~CLICKED(IDC~SHOWDB, OnShowdb) ON~BN~CLICKED(IDC~FILLDB, OnFilldb) ON~BN~CLICKED(IDC~PLACENOQR, OnPlacenoqr) ON~CBN~EDITUPDATE(IDC~QUE, OnEditupdateQue) ON~BN~CLICKED(IDC~OPTIONSB, OnOptionsb) ON WM RBUTTONDOWN() //}}AFX~MSG~MAP // Standard printing commands ON~COMMAND(ID~FILE~PRINT, CFormView::OnFilePrint) ON~COMMAND(ID~FILE~PRINT~PREVIEW, CFormView::OnFilePrintPreview; END~MESSAGE~MAP() <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> ///////////////////////////////////////<BR> // COentryView construction/destruction COentryView::COentryView() <BR> <BR> CFormView(COentryView: :IDD) <BR> <BR> <BR> <BR> <BR> <BR> <BR> //((AFX DATA INIT(COentryView) m~OrderMode = 1; m inst = T ~T(""); m sendreply = 0; //}}AFX~DATA~INIT // TODD: add construction code here m~runflag = 0; m~mes~sent = 0; m~mes~rec = 0; m~rec~sent = 0; m~rec~rec = 0; m~color = RGB(0,255,0); m~box~color = m~color; m~que = ""; m~order~num = 0; m~tran~state = 0; m~auto~tran = 0; CString g~cust[] = "Jones","James","Johnson","Jacobs","Jaffe","Jackson"}; <BR> <BR> <BR> <BR> <BR> <BR> <BR> CString g~item[] = {"Bolts","Buckets","Buttons","Belts","Bobbins","Boats"};< BR> <BR> int g~price[] = {1,2,3,4,5,6};<BR> <BR> <BR> <BR> <BR> <BR> int g~qty[] = 000,1000,1000,1000,1000,1000); <BR> <BR> <BR> int g~purchases[] = {0,0,0,0,0,0};<BR> int g~num~purchases[] = {0,0,0,0,0,0};<BR> <BR> int g~total~sales = 0; int g~db~run = 0; int g~options~run = 0; // int g~delay = 0; int g~directplace = 0; // Client int g~wait~anamate = 0; // Server<BR> int g~direct~fill = 0; // Server int g~fill~anamate = 0; // Server int g~filling = 0; // Server int g~place~tpm = 60; int g~place~dealy = 1000; int g~fill~delay = 0; int g~poll~pps = 10; int g~poll~delay = 100; int g~clear~stats = 0; int g~ora~state = 0; int g~max~orders = 0; char g~oracle~con~str[80] = "scott/tiger@t:grampa:orcl"; COLORREF g~new~color; CFont g~title~font; CFont g~text~font; <BR> <BR> <BR> <BR> int WAITS[] = {IDC~WAIT0,IDC~WAIT1}; <BR> <BR> int FILLS[] = [IDC~FILL0,IDC~FILL1,IDC~FILL2}; <BR> <BR> <BR> <BR> <BR> <BR> int ALL~TEXT[] = (IDC~MODEBOX,IDC PLACER,IDC~PLACENOQR,IDC~FILLR,IDC~FILLDB IDC~OPTIONSB,IDC~ORDERBOX,IDC~FILLTXT,IDC~SENDREPC,IDC~ORDER B,IDC~AUTOB,IDC~ IDC~QUE,IDC~CUST,IDC~ITEM,IDC~QTY,<BR> IDC~QUELAB,IDC~CUSTALB,IDC~ITEMLAB,IDC~QTYLAB, IDC TRANBOX,IDC TRANB,IDC COMMITB,IDC ABORTB,IDC EXITB, IDC~STATBOX,IDC~RECIPTS~LAB,IDC~RECIPTS,IDC~RECIPT,IDC~MSGS~ LAB,IDC~MSGS,0}; lpQHANDLE g~LQ; // Listener que global for close OnExit() COentryView:.~COentryView() { } void COentryView::DoDataExchange(CDataExchange* pDX) {<BR> <BR> CFormView::DoDataExchange(pDX); //{{AFX~DATA~MAP(COentryView) DDX Radio(pDX, IDC~PLACER, m~OrderMode); // DDX~Text(pDX, IDC~INST, m~inst); DDX Check(pDX, IDC~SENDREPC, m~sendreply); //}}AFX~DATA~MAP //////////////////////////////////////////////////////////// ///////////////// // COentryView printing BOOL COentryView::OnPreparePrinting(CPrintInfo* pInfo) // default preparation return DoPreparePrinting(pInfo); void COentryView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) // TODO: add extra initialization before printing void COentryView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) // TODO: add cleanup after printing void COentryView::OnPrint(CDC* pDC, CPrintInfo*) // TODO: add code to print the controls ///////////////////////////////////// // COentryView diagnostics #ifdef ~DEBUG void COentryView::AssertValid() const CFormView: :AssertValid(); void COentryView::Dump(CDumpContext& dc) consist CFormView::Dump(dc); COentryDoc* COentryView::GetDocument() // non-debug version is inline ASSERT(m~pDocument->IsKindOf(RUNTIME-CLASS(COentryDoc))) return (COentryDoc*)m~pDocument; 4endif //~DEBUG /////////////////////////////// // COentryView message handlers void COentryView::OnExitb() CString s; if (g~LQ) Qclose(&g~LQ,0); if (m~runflag) { m~runflag = 0; while ( s != "Auto" ) { // Read the button until not running <BR> <BR> GetDlgItemText(IDC~AUTOB,s.GetBuffer(100),100);<BR> } } <BR> <BR> <BR> <BR> <BR> <BR> AfxGetMainWnd()->DestroyWindow();<BR> } //GetParentFrame()->SetMessageText("Unknown message"); long COentryView: :OnReplyMsg (WPARAM wparam, LPARAM 1Param){ <BR> <BR> <BR> CString s,ss; switch(wParam){ case REPLY~SUBMODE: if (lParam) StDlgItemText(IDC RECIPT,(char *)1Param); else <BR> <BR> StDlgItemText(IDC RECIPT,OnReplyMsg Unknown REPLY~SUBMODE Message"<BR> SetDlgItemInt(IDC~RECIPTS,++m~rec~rec); break; case NOMSGQ~SUBMODE: if (1Param) MessageBox("NOMSGQ~SUBMODE How did I get here?"); /* SetDlgItemInt(IDC~MSGS,++m~mes~rec); if (g~delay) { SetTimer(FILL~DELAY~TIMER,g~delay,NULL); // g~direct~f<BR> SetTimer(FILL~ANAMATE~TIMER,100,NULL);<BR> <BR> <BR> <BR> <BR> else g~direct~fill = 0; int instock = DbOrder(((pOFORM)1Param)->cust, ((pOFORM)lparam)->item if (instock == 1) ss = "FILLED"; else if (stock == 0) ss = "OUT OF STOCK"; else if (instock == -1) ss = "WRONG CUSTOMER"; else if (instock == -2) ss = "WRONG ITEM"; s.Format("Direct: %s: %s %s %d",LPCTSTR(ss),((pOFORM)1Param)->cust,( SetDlgItemText(IDC~FILLTXT,LPCTSTR(s)); color~the~box( ((pOFORM)1Param)->color,0);<BR> */ break; case DIRECT FILL TIME OVER: GetParentFrame()->SetMessageText(1Param); // SetDlgItemInt(IDC~MSGS,--m~mes sent); break; default: if (1Param) s.Format ("ORM: %d %s",wParam,1Param); else s.Format("Unknown Message ORM"); GetParentFrame()->SetMessageText(s); } return(0); } //////////////////////////////////////////////////////////// ////////// /////////////////////// LISTENER THEREAD /////////////////////////// //////////////////////////////////////////////////////////// ////////// typedef struct tparam { // Thread parameters HWND hwnd; int bnum; // smbuff num to send replys to.

CString inst; TPARAM, *pTPARAM; TPARAM tp; // <-- Global Data so it does not go away.

char g~thd~data[l000]; ///////////////////// MSGH g~thd~mh; // Listener thread // DWORD Listen(pTPARAM tp) ( ///////////////////// int max~dly,md,stat=0; CString s,n = tp->inst if ( g LQ = Qopen(n.GetBuffer(O),GET MODE,O, O,&stat,O,O)) // Save the buffer I will listen to.

tp->bnum = g~LQ->bufs~found[0]; // Replys will be sent to this buffer <BR> <BR> <BR> <BR> <BR> if (SHAREDATA(diag)) <BR> s.Format("Thread Open (%s) bnum=%d",LPCTSTR(n),tp->bnum); ::PostMessage( tp->hwnd,MESSAGEREADY,0,(LPARAM) LPCTSTR(s) /* // REPLY~SUBMODE (pass sub mode as ORM~MES~REC while(QSUCCESS == Qget(g~LQ,&g~thd~mh,data,1000) ) ( - .:PostMessage(tp->hwnd,MESSAGEREADY, g~thd~mh.sub~mode , (LPARAM) data); // .:PostMessage(tp->hwnd,MESSAGEREADY,ORM~MES~RECEIVED,(LPA RAM) data; <BR> <BR> <BR> <BR> <BR> <BR> <BR> */<BR> while(QSUCCESS == QlistenBeforeReply(g~LQ,&g~thd~mh,g~thd~data,1000) ) { // Got a message could be Recipt or direct fill request if (g thd mh.sub~mode == REPLY~SUBMODE) ::PostMessage(tp->hwnd,MESSAGEREADY, g~thd~mh.sub~mode ,(LPARAM) else g~direct~fill = 1; max~dly = 500; // 25 Seconds max check 20 times a second while ((g~direct~fill || g~filling) && (--max~dly)) Sleep(50); // if (max~dly > 0) md = ACK MODE; else { md = NACK~MODE; g~direct~fill = 0; MessageBox(NULL,"SER TIME OVER",NULL,NULL); s.Format("ts: SERVER did not reply to DIRECT FILL",n); :PostMessage(tp->hwnd,MESSAGEREADY, DIRECT~FILL~TIME~OVER ,(LPARA QreplyAfterListen(g~LQ,md,0,g~thd~data,g~thd~mh.size,0); }.

} else { s.Format("Cant Qopen(%s) ERROR=%d", LPCTSTR(n) ,-stat) MessageBox(tp->hwnd,s,"Listener Thread",MB~ICONSTOP); Qclose(&g~LQ,0); return(0); void COentryView::CmdLine(int pass){ CString parm,value,line,nline; int i,r,g,b; line = AfxGetApp()->m~lpCmdLine; while (2 <= (i = sscanf(LPCTSTR(line),"%s 5 parm.GetBuffer(100),value.GetBuffer(100),nline.GetBuffer(100 ) ))) parm.MakeUpper(); // oentry Name xxx Que ssss RGB r,g,b OrderMode m Fill x Poll x Order x if (pass == 1) { if (parm == "NAME") {m~inst = LPCTSTR(value);} if (parm == "RGB") {sscanf(LPCTSTR(value),"%d,%d,%d,&r,&g,&b);m~colo if (parm == "ORDERMODE") {sscanf(LPCTSTR(value),"%d",&m~OrderMode);m~Or if (m OrderMode < 0 || m m~OrderMode > 3) m OrderMod if (parm == "FILL") sscanf(LPCTSRT(value),"%d",&g~fill~delay):} if (parm == "POLL") {sscanf(LPCTSTR(value),"%d",&g~poll~pps) if((MIN~POLL <= g~poll~pps) && (g~poll~pps <= MAX~ g~poll~delay = 1000/g~poll~pps;} if (parm == "ORDER") (sscanf(LPCTSTR(value),"%d",&g~place~tpm); if((MIN~AUTO <= g~place~tpm) &&&& (gplace tpm <= MA g~place~delay = 60000/g~place~tpm:} if (parm == "ORACLE") ( strcpy(g~oracle~con~str ,LPCTSTR(value)); else if (parm == "QUE" || || parm == "SERVER") CComboBox * CB = (CComboBox *) this->GetDlgltem(IDC~QUE); CB->SelectString(-1,value) OnSelchangeQue(); line = LPCTSTR(nline); nline = ""; void COentryView::LoadQList(int mode) // mode=0 . List Non-Ques // mode=1 List Ques int i; CComboBox * CB = (CComboBox *) this->GetDlgltem(IDC~QUE); CB->ResetContent(); // List all logical queues // APPS: [physical],logicall,logical2, [physical],logical, <BR> <BR> if (sm~base = AttachSharedMemory())} lpRT rt = RTROOT; while(rt = NextRT(rt)) char *e,*s = RT~APPS(rt); // Starts after the first letter while (s = strchr(s,',')) { // Ends at next "," if (e = strchr(++s,,')) { *e = 0; if ((!strchr(s,'[')) && *s) if ((mode && strchr(s,'Q')) II (!mode && tstrchr(s,Q))) CB->AddString(s); // lb->InsertString(-1,s)<BR> } *e = ','; } } } // Now add any extra entries from the local node that were not in the RT // lpSMBUF BUF; for (i = 0; i c SHAREDATA(nsbuf) ; i++) if (!strcmp((SMBUFADDR(i))->,"empty")) continue; if (!strcmp((SMBUFADDR(i))->name,"QNETD")) continue; if (CB~ERR != CB->FindStringExact(-1,(SMBUFADDR(i))->name)) continue; / if ((mode && strchr ((SMBUFADDR(i)->name,'Q')) || (!mode && !strchr((SM <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> CB->AddString((SMBUFADDR(i))->name); // lb->InsertString(-1,s)<BR> else MessageBox("QNETD not running. Please restart."); CB->AddString(""); if ( CB~ERR == (i = CB->FindStringExact(-1,m~quel))) CB->SetCurSel(0); else CB->SetCurSel(i); OnSelchangeQue(); } void COentryView::OnInitialUpdate() String s; CFormView::OnInitialUpdate(); // Set frame size = Form size GetParentFrame()->Recalclayout(); ResizeParentToFit(FALSE); ResizeParentToFit(TRUE); m-orderMode = PLACE ORDER; LoadQList(l); CmdLine(l); // Set max size on data fields ( (CEdit *) this->GetDlgltem(IDC CUST) )->LimitText(9); ( (CEdit *) this->GetDlgItem(IDC~ITEM) )->LimitText(9); ( (CEdit *) this->GetDlgItem(IDC~QTY) )->LimitText(9); // Generate unique instance name on this node if (m~inst == "") // May be set by command line "name" m~inst.Format("OE%d",SHAREDATA(ap.app~num)++); OnAnyUserAction(); SetTimer(SET~1ST~TITLE~TIMER,100,NULL); // Calls OnAnyUserAction(); to set t // Start the backgound thread to Qget() messages DWORD id; tp.hwnd = m~hWnd; tp.inst = m~inst; CreateThread(NULL, 0,(LPTHREAD~START~ROUTINE) Listen, (LPVOID) &tp,0,&id); CmdLine(2); ( (CButton *) this->GetDlgItem(IDC~PLACER) )->SetCheck(O); ( (CButton *) this->GetDlgItem(IDC~PLACENOQR) )->SetCheck(0); ( (CButton *) this->GetDlgItem(IDCFILLR) )->SetCheck(0); ( (CButton *) this->GetDlgItem(IDC FILLDB) )->SetCheck(O); if (m OrderMode == PLACE ORDER) ( (CButton *) this->GetDlgItem(IDC~PLACER) )->SetCheck(1); if (m~OrderMode == PLACE~ORDER~NOQ) ( (CButton *) this->GetDlgItem(IDC~PLACENOQR) )->SetCheck(1); if (m~OrderMode == FILL~ORDER) ( (CButton *) this->GetDlgItem(IDC~FILLR) )->SetCheck(1); if (m~OrderMode == FILL~FROM~ORACLE) ( (CButton *) this->GetDlgItem(IDC~FILLDB) )->SetCheck(1); #ifdef ORACLE ((CButton *) this->GetDlgItem(IDC~FILLDB))->EnableWindow(TRUE); #else ((CButton *) this->GetDlgItem(IDC~FILLDB))->EnableWindow(FALSE); #endif PlaceOrFillMode(m~OrderMode); // Fonts LOGFONT lf; memset(&lf,0,sizeof(LOGFONT)); *ifdef BIGFONT lf.lfHeight = 18; #else lf.lfHeight = 13; #endif g~text~font.CreateFontIndirect(&lf); strcpy(lf.lfFaceName,"Monotype Corsiva") lf.lfHeight = 32; g~title~font.CreateFontIndirect(&lf); GetDlgItem(IDC~BIG~TITLE)->SetFont(&g~title~font); int i = 0; while (ALL TEXT[i]) GetDlgItem(ALL~TEXT[i++])->SetFont(&g~text~font); //void COentryView::OnEditchangeQue() void COentryView: :OnEditupdateQue() OnSelchangeQue(); void COentryView::OnSelchangeQue() CString que,s; int stat=0; // Get the que name GetDlgItemText(IDC~QUE,que.GetBuffer(100),100) que.ReleaseBuffer(); if (que != m~que) ( // New value if (Q) Qclose(&Q,0); if (que == "") ( // No que m~que = s = "No Que will be used"; GetDlgItem(IDC AUTOB)->EnableWindow(FALSE); GetDlgItem(IDC~ORDERB)->EnableWindow(FALSE) else ( // Set value s.Format("Opening que 5" ,que); GetParentFrame()->SetMessageText(s); if (Q = Qopen(que.GetBuffer(O),PUT MODE,O,O,&stat,O,D) if (m~sendreply) Q->msgh.reply~smbuf = tp.bnum; m~que = que; s.Format("Qopen(%s)",que); GetDlgItem(IDC~AUTOB)->EnableWindow(TRUE); GetDlgItem(IDC~ORDERB)->EnableWindow(TRUE); if (m~OrderMode == PLACE~ORDER~NOQ) Q->msgh.sub~mode = NOMSGQ~SUBMODE; else s.Format("Qopen(is) Error td",que,stat); GetDlgItem(IDC~AUTOB)->EnableWindow(FALSE) GetDlgItem(IDCORDERB) ->EnableWindow(FALSE); <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> GetParentFrame()->SetMessageText(s); OnAnyUserAction(); OFORM g~buf DWORD DirectPlace() { int flags = 0; QsendAndReceive(Q,0,SUB~MODE~OK, flags,sizeof(g~buf) , (char *) &g~buf, 0,0,U, g~directplace = 0; return(0); //ORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORD ERORDERORDER //ORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORD ERORDERORDER //ORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORD ERORDERORDER //ORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORD ERORDERORDER //ORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORD ERORDERORDER void COentryView: :OnOrderb() ( // Check m~ordermode = 0 to place order or = 1 to fill the order CString que,str,s = int gsize,stat=0,flags,instock,filled=0; // OFORM buf char line[sizeof(OFORM)+10]; MSGH mh; // To get detailed put status DWORD id; if (g~directplace) return; // direct place thread is already working if (g filling) return; // Wait for fill done is already working if (Q) if (!m~runflag) OnAnyUserAction(); if (m~auto~tran) { if(m~auto rand < 16) m auto rand = rand(); // Begin a tran? if ((m~auto~tran == 1) && NEXTBIT(m~auto~rand)) if (!m~tran~state) m~tran~state= 1; // Done by OnTran (causes m~auto~tran = 2; GetDlgItem(IDC~TRANB)->ShowWindow(SW~HIDE); if (m~auto~commit = NEXTBIT(m~auto~rand)) GetDlgItem(IDC~COMMITB)->ShowWindow(SW~SHOW); else GetDlgItem(IDC~ARORTB)->ShowWindow(SW~SHOW); // Set the flags for get or put if (m~tran~state) if (m~tran~state++ == 1) flags = Q~TRAN~BEGIN; else flags = Q~TRAN; else flags = 0; if (m~OrderMode <= PLACE~ORDER) { // Place the order // Read the data to be sent GetDlgItemText(IDC~CUST,g~buf.cust,10); GetDlgItemText(IDC~ITEM,g~buf.item,10); g~buf.qty = GetDlgItemInt(IDC~QTY,NULL,TRUE); gbuf.color = m~color; g~buf.reply~to = SHAREDATA(hostip); SetDlgItemInt(IDC MSGS,++m mes sent); if (m~OrderMode == PLACE~ORDER~NOQ) { g~directplace = 1; GetDlgItem(IDC~ORDERB)->EnableWindow(FALSE); SetTimer(WAIT ANAMATE TIMER,400,NULL); CreateThread(NULL,0, (LPTHREAD~START~ROUTINE) DirectPlace, (LPVOID) C else if (QSUCCESS == (stat = QsendAndReceive(Q,0,SUB~MODE~OK, flags,s if (mh.mode == ACK~MODE && mh.sub~mode == SUB~MODE~OK) { m~tran~sent++; s.Format("%s: %8s 85 %d",m que.GetBuffer(0),g buf.cust,g buf.ite else if (mh.sub mode == SUB~MODE~FULL) if (m~runflag) s.Format("que is FULL"); else MessageBox("que is FULL"); else s.Format("Qput() error %d",mh.sub~mode); else t // not QSUCCESS (communications error) SetDlgItemInt(IDC MSGS,--m~mes~sent); s.Format("Communication error code %d",stat); GetParentFrame()->SetMessageText(s); else ( // FILL~ORDER Fill the order *g~buf.cust = *g~buf.item = 0; g~buf.qty = 0; if (g~direct~fill) ( // There was a direct placed order to fill pOFORM po = (pOFORM) &g~thd~data; CString ss; SetDlgItemInt(IDC~MSGS,++m~mes~rec); if (g fill delay) filling = 1; // Do not fill another until the timer expires SetTimer(DIRECT~FILL~TIMER,g~fill~delay,NULL); // g~di SetTimer(FILL~ANAMATE~TIMER,100,NULL); color~the~box( po->color,0); int instock = DbOrder(po->cust, po->item, po->qty); if (instock == 1) ss = "FILLED"; else if (instock == 0) ss = "OUT OF STOCK"; else if (instock == -1) ss = "WRONG CUSTOMER"; else if (instock == -2) ss = "WRONG ITEM"; filled++; s.Format("Direct: ts: is 5 %d",LPCTSTR(ss), po->cust, po->item, po- SetDlgItemText(IDC~FILLTXT,LPCTSTR(s)); g direct fill = 0; if (g~filling) return; if (QSUCCESS == (stat = QsendAndReceive(Q,REQUEST~MODE,SUB~MODE~OK,flag sizeof(g~buf),(char *) &g~buf,&gsize,&mh))) if (mh.mode == ACK MODE && mh.sub~mode == SUB~MODE~OK) SetDlgItemInt(IDC~MSGS,++m~mes~rec); if (gsize < sizeof(OFORM)) s.Format("Bad reply length"); else I // you got valid message m~tran~rec++; color~the~box(g~buf.color,C); // But dont force it if (m~OrderMode == FILL~FROM~ORACLE) instock = OraOrder(gbuf.cust,g~buf.item,g buf.qty); // Ora else instock = DbOrder(g~buf.cust,g~buf.item,g~buf.qty); if (g~fill-delay) { g~filling = 1; // Do not fill another until the timer expir SetTimer(FILL DELAY TIMER,g fill delayNULL); SetTimer(FILL~ANAMATE~TIMER,100,NULL); else if (mh.sub~mode == SUB~MODE~EMPTY) if (m~runflag || filled) s.Format("Que Empty"); else <BR> <BR> MessageBox("Que Empty");<BR> <BR> <BR> else s.Format("Bad reply mode %d:%d",mh.mode,mh.sub~mode); else I // not QSUCCESS (communications error) mh.mode = O;// Not ACK~MODE s.Format("Communication Error Code %d",stat); if (gsize == sizeof(OFORM)) { if (instock == 1 <BR> <BR> sprintf(line,"FILLED:%9s %9s %d",g~buf.cust,g~buf.item,g~buf.qty)<BR> <BR> else if ( instock == 0) sprintf(line,"OUT OF STOCK %9s %d",g~buf.cust,g~buf.item,g~bu <BR> <BR> else if ( stock == -1)<BR> <BR> sprintf(line,"NO SUCH ITEM:%9s 9s %d",g~buf.cust,g~buf.item,g~bu <BR> <BR> <BR> <BR> <BR> <BR> else // stock == -2<BR> <BR> sprintf(line,"NO SUCH CUSTOMER:%9s %9s %d",g~buf.cust,g~buf.item,<BR> SetDlgItemText(IDC~FILLTXT,line); // else // strcpy(line,""); // Send Reply if requested if ((mh.reply~smbuf >= 0 ) && (mh.reply~smbuf < SHAREDATA(nsbuf)) && mh.mid.host = g~buf.reply~to; // HACK! Makes sure sending host ge Qrep = QopenReply(Qrep,&mh,0,0,O); if (QSUCCESS != (stat = Qput(Qrep,0,REPLY~SUBMODE,0,sizeof(line),lin s.Format("Qput(%s) Error %d", Qrep->msgh.to~server,stat); else s.Format("Replying Qput(Ws) to smbuf %d",Qrep->msgh.to~server,Qre <BR> SetDlgItemInt(IDC~RECIPTS,++m~rec~sent); } GetParentFrame()->SetMessageText(s); /* if (m~runflag && mh.mode == ACK~MODE) // We got something OnOrderb(); // Check again for next message, no need to wait.

else // We didnt get anything color~the~box( m~color,0); // restore old color */ if (|m~runflag && !g~fill~delay) color~the~box( m~color,0); } // place or fill <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> if ((m OrderMode <= PLACE ORDER) II mh.mode == ACK MODE) // Placeing or<BR> <BR> if (m auto tran > 1) { - <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> if ( ( NEXTBIT(m~auto~rand) && NEXTBIT(m~auto~rand) I I (m~auto~tran++ # 8) ) // Commit or Abort tran? if (m~auto~commit) OnCommitb(); else OnAbortb(); m~auto~tran = 1; if ((m~OrderMode >= FILL~ORDER) && m~runflag && mh.mode == ACK MODE && mh.sub~mode == SUB MODE OK) <BR> <BR> if (g~max~orders++ < 200)<BR> OnOrderb(); // Try to get one more item.

else <BR> <BR> max orders = 0;<BR> else g~max~orders = 0; // The order or fill button will be active until we are done.

// CButton * CB = (CButton *) this->GetDlgltem(IDC~ORDERB); // CB->SetState(TRUE); } // // m~auto~tran: // 0 No auto trans // 1 No tran yet // 2 After OnAutob() // <BR> <BR> int g~poll~delay~old;<BR> <BR> int g~place~delay~old; void COentryView::OnTimer(UINT nIDEvent) if (nIDEvent == PLACE~TIMER if (g~directplace) return; // direct place thread is already working if (g~filling) return; // Wait for fill done is already working if (g~place~delay~old != g~place~delay) { KillTimer(PLACE TIMER); SetTimer(PLACE~TIMER,g~place~delay~old = g~place~delay,NULL);<BR> }<BR> <BR> <BR> <BR> <BR> <BR> <BR> SetDlgItemText(IDC~CUST,g~cust[m~order~num % 6]);<BR> SetDlgItemText(IDC~ITEM,g-item[morder-nu W 5]);<BR> <BR> <BR> <BR> <BR> <BR> SetDlgItemInt(IDC~QTY,1 + (m~order~num++ % 9),FALSE); OnOrderb(); //CButton * CB = (CButton *) this->GetDlgItem(IDC ORDERB); //CB->SetState(TRUE); else if (nIDEvent == POLL~FILL~TIMER) <BR> <BR> <BR> <BR> if (!g~filling) {<BR> if (g~poll~delay != g~poll~delay~old)<BR> <BR> <BR> <BR> <BR> KillTimer(POLL~FILL~TIMER); SetTimer (POLL~FILL~TIMER,g~poll~delay~old = g~poll~delay,NULL);<BR> } OnOrderb(); } else if (nIDEvent == WAIT~ANAMATE~TIMER) { if (g~directplace) // Anomate the wait 0,1 0,1 GetDlgItem(WAITS[g~wait-anamate++])->ShowWindow(SW~HIDE); if (g wait anamate > 1) g~wait~anamate = 0; GetDlgItem(WAITS[g~wait~anamate])->ShowWindow(SW~SHOW);&l t;BR> else KillTimer(WAIT~ANAMATE~TIMER); GetDlgItem(IDC~ORDERB)->EnableWindow(TRUE); GetDlgItem(WAITS[g~wait~anamate])->ShowWindow(SW~HIDE); } else if (nIDEvent == FILL~ANAMATE~TIMER) { if (g filling == 0) ( // End Anamation KiTlTimer(FILL ANAMATE TIMER) GetDlgItem(FILLS[g~fill~anamate])->ShowWindow(SW~HIDE); else { // Anamate 0,1,2 GetDlgItem(FILLS[g~fill~anamate++])->ShowWindow(SW~HIDE); if (g~fill~anamate > 2) g~fill~anamate = 0; GetDlgItem(FILLS[g~fill~anamate])->ShowWindow(SW~SHOW); if (1) ( // g~progress // ( (CButton *) this->GetDlgItem(IDC~PLACER) )->SetCheck(C); // GetDlgItem(IDC~PROG))->SetRange(0,100); // ((CProgressCtrl *) this->GetDlgItem(IDC PROG))->SetRange(O,l00); // ((CProgressCtrl *) this->GetDlgItem(IDC~PROG))->SetPos(50); // ((CProgressCtrl *) this->GetDlgItem(IDC~PROG))->ShowWindow(SW~SHOW } else if (nIDEvent == DIRECT~FILL~TIMER) g~direct~fill = 0; // let Qsar() return.

g~filling = 0; // End Anamation, let next order in KillTimer(DIRECT~FILL~TIMER); color~the~box( m color,0); // Restore the old color } else if (nIDEvent == FILL~DELAY~TIMER) ( g filling = 0; // End Anamation, let next order in KlllTimer(FILL~DELAY~TIMER); color~the~box( m color,0); // Restore the old color } else if (nIDEvent == SET~1ST~TITLE~TIMER) ( // Only done once KillTimer(SET 1ST TITLE TIMER); OnAnyUserAction(); <BR> <BR> <BR> <BR> } else if (nIDEvent == DB~DONE~TIMER) {<BR> <BR> if (g~db~run == 40) { g~db~run = C; GetDlgItem(IDC~SHOWDB)->EnableWidow(TRUE); KillTimer(DB~DONE~TIMER); else if (nIDEvent == OPTIONS~DONE~TIMER) if (g~options~run == 40) ( // End g~options~run = 0; GetDlgItem(IDC~OPTIONSB)->EnableWindow(TRUE); KillTimer(OPTIONS~DONE~TIMER); if (m~color != g~new~color) { color~the~box(m~color = g~new~color,1);<BR> }<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> if (g~clear~stats) { g~clear~stats = 0; m~mes~sent = 0; m~mes~rec = 0; m~rec~sent = 0; m~rec~rec = 0; SetDlgItemInt(IDC~MSGS, 0); SetDlgItemInt(IDC~RECIPTS, 0); <BR> <BR> <BR> <BR> <BR> <BR> else <BR> <BR> <BR> <BR> <BR> <BR> <BR> CFormView::OnTimer(nIDEvent); void COentryView: :OnAutob() if (m~runflag) ( KillTimer(PLACE TIMER); KillTimer(POLL~FILL~TIMER); m~runflag = 0; // You are no longer running if (m~auto~tran) OnAbortb(); m~auto~tran = 0; SetDlgItemText(IDC~AUTOB,"Auto"); GetDlgItem(IDC~EXITB)->EnableWindow(TRUE); ((CButton *) this->GetDlgItem(IDC PLACER))->EnableWindow(TRUE) ((CButton *) this->GetDlgItem(IDC-PLACENOQR))->EnableWindow(TRUE); ((CButton *) this->GetDlgItem(IDC~FILLR))->EnableWindow(TRUE); *ifdef ORACLE ((CButton *) this->GetDlgItem(IDC~FILLDB))->EnableWindow(TRUE) #endif color~the~box( m~color,l); // Restore default color j else m~runflag = 1; // You will be running m~order~num = 0; // 1st order number Controls order selections m auto tran = m tran state; // make random transactions too?.

if ( m~OrderMode > PLACE ORDER ) // FILL SetTimer(POLL~FILL~TIMER,g~poll~delay~old = g~poll~delay,NULL); else SetTimer(PLACE~TIMER,g~placer~delay~old = g~place~delay,NULL); SetDlgItemText(IDC AUTOB," Stop "); GetDlgltem(IDC~EXITB) ->EnableWindow(FALSE); ( (CButton *) this->GetDlgItem(IDC~PLACER) )->EnableWindow(FALSE); ( (CButton *) this-sGetDlgItem(IDC PLACENOQR) )->EnableWindow(FALSE); ( (CButton *) this->GetDlgItem(IDC-FILLR) )->EnableWindow(FALSE)- ( (CButton *) this->GetDlgItem(IDCrFILLDB) )->EnableWindow(FALSE); OnAnyUserAction(); // Color Color Color Color Color Color Color Color Color Color // Color Color Color Color Color Color Color Color Color Color // Color Color Color Color Color Color Color Color Color Color void COentryView: :OnColor() CHOOSECOLOR cc; // common dialog box structure COLORREF acrCustClr[16]; // Setup the custom colors as a grey scale for (int v=O,i=O; i < 16; v=17 * i++) acrCustClr[i] = RGB(v,v,v); // Initialize the necessary members.

cc.lStructSize = sizeof(CHOOSECOLOR) cc.hwndowner = NULL; // = hwnd; cc.lpCustColors = (LPDWORD) acrCustClr; cc.Flags = CC~FULLOPEN; // CC~PREVENTFULLOPEN if (ChooseColor(&cc)){ CString s; m~box~color = m color = cc.rgbResult; // lpCustColors Invalidate(); // Display the new color else GetParentFrame()->SetMessageText("Color was not changed"); OnAnyUserAction(); //Hinit = 1; HBRUSH COentryView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) if (nCtlColor == CTLCOLOR~EDIT) if (pWnd-,GetDlgCtrlID() == IDC~COLORBOX) pDC->SetBkColor(m~color); m~brush = CreateSolidBrush(m~color); return(m~brush); else if (nCtlColor == CTLCOLOR~BTN ) ( // CTLCOLOR~EDIT if (pWnd->GetDlgCtrlID() == IDC~AUTOB) if (m~runflag) { pDC->SetBkColor(RGB (255,0,0)); // SetBkColor SetTextColor pDC->SetTextColor(RGB(255,255,255)); // SetBkColor SetTextColor m~brush = CreateSolidBrush(m color); return(m~brush); // j else if (nCtlColor == CTLCOLOR~STATIC ) ( // CTLCOLOR~EDIT // if (pWnd->GetDlgCtrlID() == IDC~INST)( // // pDC->SetBkColor(RGB(255,0,0)); // SetBkColor SetTextColor // // pDC->SetTextColor(RGB(255,255,255)); // SetBkColor SetTextColor // // m~brush = CreateSolidBrush(m~color); // m~brush = CreateSolidBrush(m~box~color); // empty non-text background pDC->SetBkColor(m~box~color); // behind the letters // return(m~brush); HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor); return hbr; int COentryView::Dborder(char *cust, char *item, int qty) int custn=0,itemn=0; while(strcmp(item,g~item[itemn])) if (++itemn == 6) return(-l); while(strcmp(cust,g~cust[custn])) if (++custn == 6) return(-2); if (g~qty[itemn] >= qty) g~qty[itemn] -= qty; g~purchases[custn] += qty * g~price[itemn]; g~num~purchases[custn]++; g~total~sales += qty * g~price[itemn] ) else return(0); return(l); int COentryView::OraOrder(char *cust, char *item, int qty) int custn=0,itemn=0, price,stock,rc,cust~orders,cust~sales; String s; while(strcmp(item,g~item[itemn])) if (++itemn == 6) return(-l); while(strcmp(cust,g cust[custn])) if (++custn == 6) return(-2); if (g~ora~state == 0) GetParentFrame()->SetMessageText("Cant Order from oracle: not connected"); return(0); // Read Oracle if ( (rc = oraread(item, &price, &stock)) s.Format ("OraRead Error td",rc); GetParentFrame ()->SetMessageText (s); return (0); if ( (rc = oracustr(cust, &cust~orders, &cust~sales)) s.Format ("OraCustRead Error %d",rc); GetParentFrame()->SetMessageText(s); if (qty > stock) return(0) ; // MessageBox("OutOfStock"); } else stock -= qty; g~total~sales += qty * price; cust~sales += qty * price; cust~orders++; // Write Oracle if ( (rc = orawrite(item, stock)) s.Format("OraWrite Error td",rc); GetParentFrame ()->SetMessageText (s); return(0); if ( (rc = oracustw(cust, cust~orders, cust~sales)) ) ( s.Format("OraCustWrite Error td",rc); GetParentFrame ()->SetMessageText (s); return(l); void COentryView::PlaceOrFillMode(int mode) m~OrderMode = mode; int SHOW, HIDE, IsPlaceMode; if (mode <= PLACE~ORDER) HIDE = SW~HIDE; SHOW = SW~SHOW; IsPlaceMode = TRUE; } else HIDE = SW~SHOW; SHOW = SW~HIDE; IsPlaceMode = FALSE; GetDlgltem(IDC~SENDREPC)->ShowWindow(SHOW); // Show sendreply checkbox if (m~OrderMode <= PLACE~ORDER)( SetDlgtemText (IDC~ORDERB, "Order"); // Order = Order SetDlgItemText (IDC~ORDERBOX, "Place Orders"); // Order = Order SetDlgItemText (IDC~BIG~TITLE; "OpenMQ Place Orders"); // Order = } else { SetDlgItemText(IDC ORDERB,"Fill"); SetDlgItemText(IDCZORDERBOX,"Fill Orders") SetDlgItemText(IDC~BIG~TITLE,"OpenMQ Fill Orders"); GetDlgItem (IDC~SHOWDB)->ShowWindow (HIDE); GetDlgItem (IDC~CUST)->ShowWindow (SHOW); GetDlgItem (IDC~ITEM)->ShowWindow (SHOW); GetDlgItem (IDC~QTY)->ShowWindow (SHOW); GetDlgItem (IDC~CUSTLAB)->ShowWindow (SHOW); GetDlgItem (IDC~ITEMLAB)->ShowWindow (SHOW); GetDlgItem (IDC~QTYLAB)->ShowWindow (SHOW); GetDlgItem (IDC~FILLTXT)->ShowWindow (HIDE); (CEdit *) this->GetDlgltem(IDC~CUST) )->SetReadOnly(FALSE); (CEdit *) this->GetDlgItem(IDC~ITEM) )->SetReadOnly(FALSE); (CEdit *) this->GetDlgItem(IDC~QTY) )->SetReadOnly(FALSE); // Stats if (mode <= PLACE~ORDER) SetDlgItemText (IDC~MSGS~LAB, "Sen t: "); SetDlgItemText (IDC~RECIPTS~LAB, "Received:"); SetDlgItemInt (IDC~MSGS, m~mes~sent); <BR> <BR> SetDlgItemInt(IDCIRECIPTS, m~rec~rec); <BR> <BR> <BR> else SetDlgItemText (IDC~MSGS~LAB, "Received:") SetDlgItemText (IDC~RECIPTS~LAB, "Sent:"); SetDlgItemInt (IDC~MSGS, m~mes~rec); SetDlgItemInt (IDC~RECIPTS, m~rec~sent); if (mode != PLACE ORDER~NOQ) { GetDlgItem (IDCTRANBOX)->ShowWindow (SW~SHOW); if (m~tran~state) GetDlgItem (IDC~COMMITB)->ShowWindow (SW~SHOW); GetDlgItem (IDC~ABORTB)->ShowWindow (SW~SHOW); <BR> <BR> else <BR> <BR> <BR> GetDlgItem(IDC TRANB)->ShowWindow(SW~SHOW); <BR> <BR> <BR> else GetDlgItem (IDC~TRANBOX)->ShowWindow (SW~HIDE); GetDlgItem (IDC~TRANB)->ShowWindow (SW~HIDE); GetDlgItem (IDC~COMMITB)->ShowWindow (SW~HIDE); GetDlgItem (IDC~ABORTB)->ShowWindow (SW~HIDE); GetDlgItem(IDC SENDREPC)->ShowWindow(SW~HIDE); if (mode == PLACE~ORDER~NOQ) LoadQList(O); // Load non-Que else LoadQList(l); // Load Que names // DB if (mode <= PLACE~ORDER) if (g~db~run) g~db~run = 40; // Turn off the DB display if it was left on.

if (mode == FILL~FROM~ORACLE) { if (g~ora~state == 0) if(oraconn(g oracle con str)) MessageBox("Oracle Connect Failed"); else g ora state = 1; else I - if (g~ora state == 1) if (oradisc()) MessageBox("Oracle DisConnect Failed"); else g~ora~state = 0; OnAnyUserAction (); void COentryView::OnPlacenoqr() if (!((CButton *)GetDlgItem(IDC~PLACENOQR))->GetCheck()) return; PlaceOrFillMode(PLACE~ORDER~NOQ); OnAnyUserAction(); void COentryView::OnPlacer() if (!((CButton *)GetDlgItem(IDC~PLACER))->GetCheck()) return; PlaceOrFillMode(PLACE~ORDER); OnAnyUserAction(); void COentryView::OnFillr() if (!((CButton *)GetDlgItem(IDC~FILLR))->GetCheck()) return; PlaceOrFillMode(FILL~ORDER); OnAnyUserAction(); void COentryView: :OnFilldb() if (!((CButton *)GetDlgItem(IDC~FILLDB))->GetCheck()) return; PlaceOrFillMode(FILL FROM ORACLE); OnAnyUserAction(); void COentryView::OnAnyUserAction() SetDlgItemText(IDC~RECIPT,""); SetDlgItemText(IDC~FILLTXT,""); if (m que == GetParentFrame()->SetWindowText(m~inst + ": No server is selected" ); else if (m~OrderMode == PLACE~ORDER) GetParentFrame() ->SetWindowText (m inst + ": Place orders into queue " + m else if (m~OrderMode == PLACE~ORDER~NOQ) GetParentFrame()->SetWindowText(m~inst + ": Place orders directly to " + m else // FILL GetParentFrame() ->SetWindowText (m~inst + ": Fill orders from queue " + m~q m~box~color = m~color; void COentryView::OnSendrepc() m~sendreply = !m~sendreply; // How can I get this info? if ( Q ) if ( m sendreply ) Q->msgh.reply~smbuf = tp.bnum; else Q->msgh.reply~smbuf = -1; void COentryView::color~the~box(COLORREF color, BOOL forceit){ if (( m~box~color != color ) || forceit) { m~box~color = color; // The DC for the color box CDC* pCOLORDC = GetDlgItem(IDC~COLORBOX)->GetDC(); // pCOLORDC->GetRect(); // Create a PEN // CPen *pQPen = new CPen(PS~SOLID, 3,RGB(0,0,255)); // CPen *pOldPen = pXDC->SelectObject(pQPen); // Create the Brush CBrush *pQBrush = new CBrush(color); // Select this brush, save the old CBrush *pOldBrush = pCOLORDC->SelectObject(pQBrush); // Draw the box // pCOLORDC->Rectangle(CRect(1,1,65,65)); pCOLORDC->Rectangle(m color box rec); pCOLORDC->SelectObject(&pOldBrush); // Reset the brush delete(pQBrush); ReleaseDC(pCOLORDC); <BR> <BR> <BR> // GetDlgItem(IDC LOGO Q)->Invalidate(); <BR> <BR> <BR> <BR> // GetDlgItem(IDCrINST->Invalidate(); void COentryView::OnDraw(CDC* pDC) { /* pControlDC->SelectStockObject(WHITE~BRUSH); */ // The DC for the Instance name /* CDC* pINSTDC = GetDlgItem(IDC~INST)->GetDC(); pINSTDC->SetBkColor(m~color); pINSTDC->SetTextColor(m~color); pINSTDC->SetBkMode(TRANSPARENT); pINSTDC->SelectStockObject(HOLLOW~BRUSH); */ <BR> <BR> GetDlgItem(IDC~COLORBOX)->GetWindowRect(&m~color~box~rec) ;<BR> <BR> <BR> m~color~box~rec.right -= m~color~box~rec.left; //ScreenToClient (&rec); m~color~box~rec.bottom -= m~color~box~rec.top; m~color~box~rec.left = m~color~box~rec.top = 0; color~the~box(m~box~color,1); CFormView::OnDraw (pDC); } /*void COentryView::OnResetb() { m~mes~sent = 0; m~mes~rec = 0; m~rec~sent = 0; m~rec~rec = 0; SetDlgItemInt(IDC~MES~REC,O); <BR> <BR> <BR> <BR> SetDlgItemInt(IDC~REC~REC,0); SetDlgItemInt(IDC~MES~SENT,0); SetDlgItemInt(IDC~REC~SENT,0);+ OnAnyUserAction(); } */ // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT TTTTTTTTTT // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT TTTTTTTTTT // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT TTTTTTTTTT void COentryView: :OnTranb() m~tran~state = 1; GetDlgItem(IDC~TRANB)->ShowWindow(SW HIDE): GetDlgItem(IDC~ABORTB)->ShowWindow(SW~SHOW); GetDlgltem(IDC~COMMITB) ->ShowWindow(SW~SHOW); OnAnyUserAction(); void COentryView::OnCommit(int action) // Anyway get rid of the commit/abort buttons GetDlgItem(IDC~TRANB)->ShowWindow(SW~SHO GetDlgItem(IDC~ABORTB)->ShowWindow(SW~HIDE); GetDlgItem(IDC~COMMITB)->ShowWindow(SW~HIDE); // Do the commit if ((Q) && (m~tran~state > 1)) Qcommit(action); m~tran~rec = 0; m~tran~sent = 0; m tran state = 0; void COentryView::OnCommitb() OnCommit(Q~COMMIT); void COentryView::OnAbortb() OnCommit(Q~ABORT); m~mes~sent -= m~tran~sent; m rec rec -= m tran rec; void COentryView::OnLButtonDown(UINT nFlags, CPoint point) CRect rec; // WINDOWPLACEMENT GetWindowPlacement CRect // MessageBeep(0); GetDlgItem(IDC COLORBOX)->GetWindowRect(&rec); ScreenToClient(&rec); if (rec.PtInRect(point)) OnColor() CFormView::OnLButtonDown(nFlags, point) void COentryview: :OnRButtonDown(UINT nFlags, CPoint point) ClearDisplay(); CFormViewOnRButtonDown(nFlags, point) void COentryView: :ClearGisplay() <BR> <BR> <BR> <BR> GetParentFrame()->SetMessageText(""); <BR> <BR> <BR> thìs->Invalidate(); OnAnyUserAction () void COentryView: :OnShowdb() GetDlgItem(IDC~SHOWDB)->EnableWindow(FALSE); SetTimer(DB~DONE~TIMER,2000,NULL); // When the DB is done re-enable // CDbDlg dbd; // dbd.DoModal(); dbd.Create(IDD~DBDLG); //GetParentFrame()->SetMessageText("After dbd.Create "); void COentryView::OnOptionsb() GetDlgItem(IDC~OPTIONSB)->EnableWindow(FALSE) SetTimer(OPTIONS DONE TIMER,2000,NULL); // When the options are done re-en // o dlg.Create(IDD~O~DLG); if (o~glg.m~inst != m~inst) { // Init o~dlg.m~inst = m~inst; // o~dlg.m~parentptr = this; o~dlg.Create(IDD~O~DLG); g~new~color = m~color; o~dlg.ShowWindow(SW~SHOW); // oentrvw.h interface of the COentryView class<BR> // &num define MESSAGEREADY WM~USER + 3000 //#define IDD~TPSTIMER 100 class COentryView public CFormView protected: // create from serialization only COentryView(); DECLARE~DYNCREATE (COentryView) public: //( (AFX DATA(CoentryView) enum { IDD = IDD~OENTRY~FORM } int m~OrderMode; CString m~inst; BOOL m sendreply; //)}AFX-DATA BOOL m~runflag; // Running or not int m~millisec; // Delay when ordering int m~mes~sent; int m~mes~rec; int m~rec~sent; int m~rec~rec; HBRUSH m~brush; COLORREF m~color; COLORREF m~box~color; CString m~que; CRect m~color~box~rec; int m~order; int m~order~num; int m~tran~state; int m tran rec int m~tran~sent; int m~auto~tran; int m~auto~rand; int m~auto~commit; void AutoRun(); void color~the~box(COLORREF c, BOOL update) void CmdLine(int pass); void OnCommit(int action); void OnAnyUserAction(); void OnColor(); void ShowRateBar(int act); void PlaceOrFillMode(int mode); int DbOrder(char *cust, char *item, int qty); int OraOrder(char *cust, char *item, int qty); void LoadQList(int mode); void ClearDisplay(); CDbDlg dbd; COdlg o~dlg; // Attributes public: COentryDoc* GetDocument(); // Operations public: // Overrides // ClassWizard generated virtual function overrides //( (AFX~VIRTUAL(CoentryView) public: virtual void OnInitialUpdate(); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnPrint(CDC* pDC, CPrintInfo*); virtual void OnDraw(CDC* pDC); //}}AFX~VIRTUAL // Implementation public: virtual ~COentryView(); *ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; 4endif protected: // Generated message map functions protected: //( (AFX~MSG(CoentryView) afx~msg void OnExitb(); afx~msg void OnOrderb(); afx~msg void OnAutob(); afx~msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); afx~msg void OnPlacer(); afx~msg void OnFillr(); afx~msg void OnSelchangeQue(); afx~msg long OnReplyMsg(WPARAM wParam, LPARAM lParam); afx~msg void OnSendrepc(); afx~msg void OnTranb(); afx~msg void OnCommitb(); afx~msg void OnAbortb(); afx~msg void OnLButtonDown(UINT nFlags, CPoint point); afx~msg void OnTimer(UINT nIDEvent); afx~msg void OnShowdb(); afx~msg void OnFilldb(); afx~msg void OnPlacenoqr(); afx~msg void OnEditupdateQue(); afx~msg void OnOptionsb(); afx msg void OnRButtonDown(UINT nFlags, CPoint point); //}]AFX~MSG DECLARE MESSAGE MAP() &num ifndef ~DEBUG // debug version in oentrvw.cpp inline COentryDoc* COentryView::GetDocument() return (COentryDoc*)m~pDocument; *endif //////////////////////////////////////////////////////////// ///////////////// // oentrvw.cpp implementation of thr COentryView class<BR> <BR> <BR> // /* ** ** Copyright (C) 1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ Demo ** Module: oenrvw.cpp ** Author: Derek Schwenke 10/8/95 ** */ #include "stdafx.h" *include "oentry.h" ;)include oentrdoc.h' #include "dbdlg.h" #include "odlg.h" 4include oentrvw.h *include 'orderfm.h" include "oraomq.h" //+++++++++++++ QLIB +++++++++++++++++++ #include "qlib.h" 4include "rt.h" extern lpSMBUFH sm~base; lpQHANDLE Q,Qrep; //+++++++++++++ QLIB +++++++++++++++++++ #define REPLY SUBMODE 1 #define NOMSGQ SUBMODE 2 #define DIRECT~FILL~TIME~OVER 121 #define PLACE~ORDER~NOQ 0 #define PLACE~ORDER 1 #define FILL~ORDER 2 #define FILL~FROM~ORACLE 3 #define DB~DONE~TIMER 201 #define WATT ANAMATE TIMER 202 &num define DIRECT FILL TIMER 203 &num define FILL DELAY TIMER 204 #define FILL~ANAMATE~TIMER 205 #define SET~1ST~TITLE~TIMER 206 #define OPTIONS~DONE~TIMER 207 #define POLL~FILL~TIMER 208 #define PLACE~TIMER 209 #define NEXTBIT(X) (1 & ( X = X / 2 )) ifdef DEBUG #undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE~ *endif /////////////////////////////////////////// // COentryView IMPLEMENT~DYNCREATE(COentryView, CFormView) BEGIN MESSAGE MAP(COentryView, CFormView) //{[AFX~MSG~MAP(COentryView) ON~BN~CLICKED(IDC~EXITB, OnExitb) ON-BN-CLICKED(IDC-ORDERB, OnOrderb) ON~BN~CLICKED(IDC~AUTOB, On Autob) ON~WM~CTLCOLOR() ON-BN-CLICKED(IDC PLACER, OnPlacer) ON~BN~CLICKED(IDC~FILLR, OnFillr) ON~CBN~SELCHANGE(IDC~QUE, OnSelchangeQue) ON~MESSAGE(MESSAGEREADY,OnReplyMsg) ON~BN~CLICKED(IDC~SENDREPC, OnSendrepc) ON~BN~CLICKED(IDC~TRANB, OnTranb) ONBN-CLICKED(IDC-COMMITB, OnCommitb) ON~BN~CLICKED(IDC~ABORTB, OnAbortb) ON~WM~LBUTTONDOWN() ON~WM~TIMER() ON~BN~CLICKED(IDC~SHOWDB, OnShowdb) ON-BNCLICKED (IDC-FILLDB, OnFilldb) ON-BNCLICKED(IDC-PLACENOQR, OnPlacenoqr) ON~CBN~EDITUPDATE(IDC~QUE, OnEditupdateQue) ON BN CLICKED(IDC OPTIONSB, OnOptionsb)<BR> <BR> ON~WM~RBUTTONDOWN() ON~CBN~SETFOCUS(IDC~QUE, OnSetfocusQue) //}}AFX~MSG~MAP // Standard printing commands ON COMMAND(ID FILE PRINT, CFormView::OnFilePrint) ON~COMMAND(ID~FILE~PRINT~PREVIEW, CFormView::OnFilePrintPreview) END~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// // COentryView construction/destruction COentryView::COentryView() CFormView(COentryView::IDD) //((AFX~DATA~INIT(CoentryView) m~OrderMode = 1; m~inst = T(""); m~sendreply = 0; //)}AFX~DATA~INIT // TODD: add construction code here m~runflag = 0; m mes sent = 0; m~mes~rec = 0; m~rec~sent = 0; m~rec~rec = 0; m~color = RGB(0,255,0); m~box~color = m~color; mque = m~order~num = 0; m~tran~state = 0; m~auto~tran = 0; CString g~cust[] = {"Jones", "James", "Johnson", "Jacobs", "Jaffe", $Jackson"}; <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> CString g~item[] = {"Bolts", "Buckets", "Buttons", "Belts", "Bobbins", "Boats"};<BR> <BR> int g~price[] = {1,2,3,4,5,6};<BR> <BR> <BR> <BR> <BR> <BR> <BR> int g~qty[] = {1000,1000,1000,1000,1000,1000};<BR> <BR> int g~purchases[] =<BR> <BR> <BR> <BR> int g~num~purchases[] = {0,0,0,0,0,0,};<BR> <BR> <BR> int g~total~sales = 0; int g~db~run = 0; int g~options~run = 0; // int g delay = 0; int g~directplace = 0; // Client int g~wait~anamate = 0; // Server int g~direct~fill = 0; // Server int g~fill~anamate = o; // Server int g~filling = 0; // Server int g~place~tpm = 60; int g~place~delay = 1000; int g~fill~delay = 0; int g~poll~pps = 10; int g~poll~delay = 100; int g~clear~stats = 0; int g~ora~state = 0; int g~max~orders = 0; char g~oracle~con~str[80] = "scott/tiger@t:grampa:orcl"; COLORREF g~new~color; CFont g~title~font; CFont g~text~font; <BR> <BR> <BR> <BR> <BR> int WAITS[] = {IDC~WAIT0~IDC~WAIT1];<BR> int FILLS[] = {IDC~FILL0,IDC~FILL1,IDC~FILL2};<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> int ALL~TEXT[] = { IDC~MODEBOX,IDC~PLACER,IDC~PLACENCQR,IDC~FILLR,IDC~FILLDB< ;BR> <BR> <BR> <BR> IDC~OPTIONS, IDC~ORDER,IDC~FILLTXT,IDC~SENDREPC,IDC~ORDERB, IDC~AUTOB,IDC~<BR> IDC~QUE, IDC~CUST,IDC~ITEM,IDC~QTY, IDC~QUELAB;IDC~CUSTLAB,IDC~ITEWMLAB,IDC~QTYLAB, IDC~TRANBOX, IDC~TANb, IDC~COMMITB,IDC~ABORTB,IDC~EXITB, IDC~STATBOX,IDC~RECIPTS~LAB,IDC~RECIPTS,IDC~RECIPT,IDC~MSGS~ LAB,IDC~MSGS,0}; lpQHANDLE g~LQ; // Listener que global for close OnExit() COentryView::~COentryView() { } void COENTRYView::DoDataExchange (CDataExchange* pDX) { CFormView::DoDataExchange(pDX); <BR> <BR> //((AFX DATA MAP(COentryView) DDX~Radio (pDX, IDC~PLACER, m~OrderMode); // DDX~Text (pDX, IDC~INST, m~inst); DDX Check(pDX, lOC~SENDREPC, m sendreply); //}AFX~DATA~MAP } ////////////////////////////////////////////////////// // COentryView printing BOOL COentryView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); void COentryView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) // TODO: add extra initialization before printing void COentryView::OnEndPrinting (CDC* /*pDC*/, CPrintInfo* /*pInfo*/) // TODO: add cleanup after printing void COentryView::OnPrint(CDC* pDC, CPrintInfo*) // TODO: add code to print the controls ///////////////////////////////////// // COentryView diagnostics #ifdef ~DEBUG void COentryView::AssertValid() const { CFormView: :AssertValid(); void COentryView::Dump (CDumpContext& dc) const CFormView::Dump(dc); COentryDoc* COentryView::GetDocument() // non-debug version is inline ASSERT(m~pDocument->IsKindOf(RUNTIME~CLASS(COentryDoc))); return (COentryDoc*)m~pDocument; *endif //~DEBUG /////////////////////////////// // COentryView message handlers void COentryView::OnExitb() { CString s; if (g~LQ) Qclose (&g~LQ,0); if (m~runflag) { m~runflag = 0; while( s != "Auto" ) ( // Read the button until not runnning GetDlgItemText(IDC~AUTOB,s.GetBuffer(100),100) AfxGetMainWnd()->DestroyWindow(); //GetParentFrame ()->SetMessageText ("Unknown message") long COentryView: :OnReplyMsg(WPARAM wparam, LPARAM lParam) CString s,ss; switch(wParam) case REPLY~SUBMODE: if (lParam) SetDlgItemText(IDC~RECIPT, (char *)lParam); else SetDlgItemText(IDC~RECIPT,"OnReplyMsg Unknown REPLY~SUBMODE Message" SetDlgItemInt(IDC~RECIPTS,++m rec rec); break; case NOMSGQ~SUBMODE: if (1Param) MessageBox("NOMSGQ~SUBMODE How did I ger here?"); /* SetDlgItemInt(IDC~MSGS,++m~mes~rec); if (g~delay) { SetTimer(FILL~DELAY~TIMER,g~delay,NULL); // g~direct~f SetTimer(FILL~ANAMATE~TIMER,100,NULL); else g~direct~fill = 0; int instock = DbOrder(((pOFORM)1Param)->cust, ((pOROFM)lParam)->item if (instock == 1) ss = "FILLED"; else if (instock == 0) ss = "OUT OF STOCK"; else if (instock == -1) ss = "WRONG CUSTOMER"; else if (instock == -2) ss = "WRONG ITEM"; s.Format("Direct: %s: %s %s %d",LPCTSTR(ss), ((pOFORM)lParam)->cust,( SetDlgltemText(IDC~FILLTXT,LPCTSTR(s)); color~the~box( ((pOFORM)lParam)->color,0); break; case DIRECT~FILL~TIME~OVER: GetParentFrame()->SetMessageText(lParam); // SetDlgItemInt(IDC~MSGS,--m~mes sent); break; default: if (1Param) s.Format("ORM: %d %s",wParam,1Param); else s.Format("Unknown Message ORM"); GetParentFrame()->SetMessageText(s); / return (0); } //////////////////////////////////////////////////////////// ////////// /////////////////////// LISTENER THREAD /////////////////////////// //////////////////////////////////////////////////////////// ////////// typedef struct tparam // Thread parameters HWND hwnd; int bnum; // smbuff num to send replys to.

CString inst; TPARAM, *pTPARAM; TPARAM tp; // <-- Global Data so it does not go away.

<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> char g thd~data[1000]; /////////////////////<BR> MSGH g~thd~mh; // Listener thread // DWORD Listen(pTPARAM tp) { ///////////////////// int max~dly,md,stat=0; String s,n = tp->inst if ( g LQ = Qopen(n.GetBuffer)0),GET~MODE,0, 0,&stat,0,0)) // Save the buffer I will listen to.

tp->bnum = g~LQ->bufs~found[0]; // Replys will be sent to this buffer if (SHAREDATA(diag)) { s.Format("Thread Open(%s) bnum=%d",LPCTSTR(n),tp->bnum); ::PostMessage( tp->hwnd,MESSAGEREADY,0,(LPARAM) LPCTSTR(s) / <BR> <BR> <BR> <BR> <BR> /* // REPLY~SUBMODE (pass sub mode as ORM~MES~REC<BR> <BR> while(QSUCCESS == Qget(g~LQ,&g~thd~mh,data,1000) ) ( - ::PostMessage(tp->hwnd,MESSAGEREADY, g thd mh.sub mode , (LPARAM) data); // ::PostMessage(tp->hwnd,MESSAGEREADY;ORM~MES~RECEIVED,(LPA RAM) data); */ while (QSUCCESS == QlistenBeforeReply(g~LQ,&g~thd~mh,g~thd~data,1000) ) { // Got a message could be Recipt or direct fill request <BR> <BR> if (g~thd~mh.sub~mode == REPLY SUBMODE)<BR> <BR> ::PostMessage(tp->hwnd,MESSAGEREADY, g~thd~mh.sub~mode , (LPARAM) gt <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> else g~direct~fill = 1; max~dly = 500; // 25 Seconds max check 20 times a second while ((g~direct~fill || g~filling) && (--max~dly)) Sleep (50); // if (max~dly > 0) md = ACK MODE; else { md = NACK~MODE; g~direct~fill = 0; MessageBox(NULL,"SER TIME OVER",NULL,NULL); s.Format("%s: SERVER did not reply to DIRECT FILL",n); ::PostMessage(tp->hwnd,MESSAGEREADY, DIRECT~FILL~TIME~OVER ,(LPARA <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> QreplyAfterListen(g~LQ,md,O,g thd data,g thd mh.size,0); <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> else s.Format("Cant Qopen(%s) ERROR=%d",LPCTSTR(n),stat); MessageBox(tp->hwnd,s,"Listener Thread",MB~ICONSTOP); Qclose(&g~LQ,0) return(0); void COentryView::CmdLine(int pass) String parm,value,line,nline; int i,r,g,b; line = AfxGetApp()->m~lpCmdLine; while (2 <= (i = sscanf(LPCTSTR(line),"%s is %[^@]", parm.GetBuffer(100),value.GetBuffer(100),nline.GetBuffer(100 ) ))) { parm.MakeUpper(); // oentry Name xxx Que ssss RGB r,g,b OrderMode m Fill x Poll x Order x if (pass == 1) if (parm == "NAME") minst = LPCTSTR(value);} if (parm == "RGB") {sscanf(LPCTSTR(value),"%d,%d,%d",&r,&g,&b);m~colo if (parm == "ORDERMODE") {sscanf(LPCTSTR(value),"%d",&m~OrderMode);m~Or if (m~OrderMode < 0 || m~OrderMode > 3) m~OrderMod if (parm == "FILL") sscanf(LPCTSTR(value),"%d",&g~fill~delay);} if (parm == "POLL") sscanf(LPCTSTR(value),"%d",&g~poll~pps); if((MIN~POLL <= g~poll~pps) && (g~poll~pps <= MAX~ g~poll~delay = 1000/g~poll~pps;} if (parm == "ORDER") {sscanf(LPCTSTR(value),"%d",&g~place~tpm); if((MIN~AUTO <= g~place~tpm) && (g~place~tpm <= MA g~place~delay = 60000/g~place~tpm;} if (parm == "ORACLE") I strcpy(g~oracle~con~str ,LPCTSTR(value)); } else { if (parm == "QUE" || parm == "SERVER") CComboBox * CB = (CComboBox *) this->GetDlgItem(IDC~QUE); CB->SelectString(-1,value); OnSelchangeQue(); line = LPCTSTR(nline); nline = ""; void COentryView::LoadQList(int mode) // mode=0 List Non-Ques // mode=1 List Ques int i; CComboBox * CB = (CComboBox *) this->GetDlgItem(IDC~QUE); CB->ResetContent(); // List all logical queues // APPS: [physical], logical1, logical2, [physical], logical, if (sm~base = AttachSharedMemory())( lpRT rt = RTROOT; while(rt = NextRT(rt)) char *e,*s = RT~APPS(rt); // Starts after the first letter while (s = strchr(s, ', ')) I // Ends at next if (e = strchr (++s,',')) { *e = 0; if ((!strchr (s,'[')) && *s) if ((mode && strchr (s, 'Q')) (!mode && !strchr(s,'Q'))) CB->Addstring(s) ; // lb->InsertString(-1,s) *e = ' // Now add any extra entries from the local node that were not in the RT // lpSMBUF BUF; for (i = 0; i < SHAREDATA(nsbuf) ; i++) if (!strcmp((SMBUFADDR(i))-sname,"empty")) continue; if (!strcmp ((SMBUFADDR (i))#name, "QNETD")) continue; if (CB~ERR != CB->FindStringExact (-1, (SMBUFADDR (i))->name)) continue; / if ((mode && strchr ((SMBUFADDR (i)) ->name, 'Q')) || (!mode && !strchr ((SM CB->AddString ((SMBUFADDR (i)) ->name); // lb->InsertString (-1,s) } else MessageBox("QNETD not running. Please restart."); CB->AddString(""); if ( CB~ERR == (i = CB->FindStringExact(-1,m~que))) CB->SetCurSel (0); else CB->SetCurSel(i); OnSelchangeQue (); void COentryView::OnInitialUpdate() CString s; CFormView::OnInitialUpdate(); // Set frame size = Form size GetParentFrame()->Recalclayout() ; ResizeParentToFit(FALSE); ResizeParentToFit(TRUE); m~OrderMode = PLACE~ORDER; LoadQList (1); CmdLine(1); // Set max size on data fields ( (CEdit *) this->GetDlgltem(IDC CUST) )->LimitText(9); (CEdit *) this->cetDlgItem(IDC-ITEM) ) >LimitText (9); ( (CEdit *) this->GetDlgItem(IDC~QTY) )->LimitText(9); // Generate unique instance name on this node if (m~inst == "") // May be set by command line "name" m inst.Format("OE%d",SHAREDATA(ap.app num)++); OnAnyUserAction (); SetTimer(SET 1ST TITLE TIMER,100,NULL); // Calls OnAnyUserAction(); to set t // Start the background thread to Qget() messages DWORD id; tp.hwnd = m~hWnd; tp.inst = m~inst; CreateThread(NULL,O,(LPTHREAD START ROUTINE) Listen, (LPVOID) &tp,0,&id); CmdLine(2); ( (CButton *) this->GetDlgItem (IDC~PLACER) )->SetCheck(0); ( (CButton *) this->GetDlgItem(IDC~PLACENOQR) )->SetCheck(0); ( (CButton *) this->GetDlgItem(IDC FILLR) )->SetCheck(0); ( (CButton *) this->GetDlgltem(IDC~FILLDB) )->SetCheck(0); if (m~OrderMode == PLACE~ORDER) ( (CButton *) this->GetDlgItem(IDC PLACER) )->SetCheck (1); if (m~OrderMode == PLACE~ORDER~NOQ) ( (CButton *) this->GetDlgItem(IDC~PLACENOQR) )->SetCheck(1); if (m~OrderMode == FILL~ORDER) ( (CButton *) this->GetDlgItem(IDC~FILLR) )->SetCheck (1); if (m~OrderMode == FILL~FROM~ORACLE) (CButton *) this->GetDlgItem(IDC~FILLDB) )->SetCheck(1); #ifdef ORACLE ((CButton *) this->GetDlgItem(IDC FILLDB))->EnableWindow(TRUE); #else ((CButton *) this->GetDlgItem(IDC FILLDB))->EnableWindow(FALSE); 4endif PlaceOrFillMode(m~OrderMode); // Fonts LOGFONT lf; memset (&lf,0,sizeof(LOGFONT)); 4ifdef BIGFONT lf.lfHeight = 18; #else lf.lfHeight = 13; #endif g~text~font.CreateFontIndirect(&lf); strcpy(lf.lfFaceName, "Monotype Corsiva"); lf.lfHeight = 32; g~title~font.CreateFontIndirect(&lf); GetDlgItem (IDC~BIG~TITLE) ->SetFont (&g~title~font); int i = 0; while (ALL~TEXT[i]) GetDlgItem (ALL~TEXT[i++]) ->SetFont (&g~text~font) //void COentryView::OnEditchangeQue() void COentryView::OnEditupdateQue() OnSelchangeQue(); void COentryView::OnSelchangeQue() String que,s; int stat=0; // Get the que name GetDlgItemText (IDC~QUE, que.GetBuffer (100), 100) que.ReleaseBuffer(); if (que != m~que) ( // New value if (Q) Qclose(&Q,0); if (que == "") { // No que m~que = s = "No Que will be used"; GetDlgItem (IDC~AUTOB) ->EnableWindow (FALSE); GetDlgItem (IDC~ORDERB) ->EnableWindow (FALSE); else ( // Set value s.Format("Opening que %s",que); GetParentFrame()->SetMessageText(s); if (Q = Qopen (que.GetBuffer (0), PUT~MODE, 0, 0, &stat, 0, 0) if (m~sendreply) Q-omsgh.reply-smbuf = tp.bnum; m~que = que; s.Format("Qopen(tis)",que); <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> GetDlgItem(IDC AUTOB)->EnableWindow(TRUE); GetDlgItem (IDC~ORDERB) ->EnableWindow (TRUE); if (m~OrderMode == PLACE~ORDER~NOQ) Q->msgh.sub~mode = NOMSGQ~SUBMODE; else s.Format ("Qopen (%s) Error %d", que, stat); GetDlgItem (IDC~AUTOB) ->EnableWindow (FALSE); GetDlgItem (IDC~ORDERB) ->EnableWindow (FALSE); } } GetParentFrame() ->SetMessageText (s); OnAnyUserAction(); OFORM g~buf; DWORD DirectPlace() { int flags = 0; <BR> <BR> QsendAndReceive(Q,O,SUB MODE OK, flags,sizeof(g~buf),(char *) &gbuf, 0,0,0,<BR> g~directplace = 0; return (0); } //ORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORD ERORDERORDER //ORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORD ERORDERORDER //ORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORD ERORDERORDER //ORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORD ERORDERORDER //ORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORDERORD ERORDERORDER void COentryView::OnOrderb() ( // Check m~ordermode = C to place order or = 1 to fill the order CString que,str,s = int gsize,stat=0,flags,instock,filled=0; // OFORM buf char line[sizeof(OFORM)+10]; MSGH mh; // To get detailed put status DWORD id; <BR> <BR> <BR> <BR> <BR> if (g~directplace) return; // direct place thread is already working<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> if (g filling) return; // Wait for fill done is already working<BR> if ca, <BR> if (!m~runflag) OnAnyUserAction();<BR> <BR> <BR> <BR> <BR> <BR> <BR> if (m~auto~tran) {<BR> if(m~auto~rand < 16) m~auto~rand = rand(); // Begin a tran? if ((m~auto~tran == 1) && NEXTBIT(m~auto~rand)) if (!m~tran~state) m~tran~state= 1; // Done by OnTran (causes m~auto~tran = 2; GetDlgItem (IDC~TRANB) ->ShowWindow (SW~HIDE); if (m~auto~commit = NEXTBIT (m~auto~rand)) GetDlgItem (IDC~COMMITB) ->ShowWindow (SW~SHOW); else GetDlgItem(IDC~ABORTB)->ShowWindow(SW SHOW); // Set the flags for get or put if (m~tran~state) if (m~tran~state++ == 1) flags = Q~TRAN~BEGIN; else flags = Q~TRAN; else flags = 0; if (m~OrderMode <= PLACE~ORDER) ( // Place the order // Read the data to be sent GetDlgItemText(IDC CUST,g buf.cust,l0); <BR> <BR> GetDlgItemText(IDC-ITEM,g-buf.item,lO); g~but.qty = GetDlgItemInt (IDC~QTY, NULL, TRUE); g~buf.color = m~color; g~buf.reply~to = SHAREDATA (hostip); SetDlgItemInt(IDC MSGS,++m mes sent); if (m~OrderMode == PLACE~ORDER~NOQ) { d~directplace = 1; GetDlgItem (IDC~ORDERB) ->EnableWindow (FALSE); SetTimer(WAIT~ANAMATE~TIMER,400,NULL); CreateThread(NULL,O,(LPTHREAD START ROUTINE) DirectPlace, (LPVOID) C else if (QSUCCESS == (stat = QsendAndReceive (!, 0, SUB~MODE~OK, flags,s if (mh.mode == ACK~MODE && mh.sub~mode == SUB~MODE~OK) { m~tran~sent++; s.Format ("%s: %8S %8s %d", m~que.GetBuffer (0), g~buf.cust, g~buf.ite else if (mh.sub~mode == SUB~MODE~FULL) if (m~runflag) s.Format("que is FULL"); else MessageBox("que is FULL"); else s.Format("Qput() error modes submode=%d", mh.sub~mode); } else { // not QSUCCESS (communications error) SetDlgItemInt(IDC MSGS,--m mes sent); s.Format("Communication error code %d",stat); GetParentFrame()->SetMessageText(s); else { // FILL~ORDER Fill the order *g buf.cust = *g~buf.item = 0; g~buf.qty = 0; if (g~direct~fill) ( // There was a direct placed order to fill pOFORM po = (pOFORM) &g~thd~data; CString ss; SetDlgItemInt(IDC~MSGS,++m mes~rec); if (g fill delay) g~filling = 1; // Do not fill another until the timer expires SetTimer(DIRECT FILL TIMER,g~fill delay,NULL); // g~di SetTimer(FILL~ANAMATE~TIMER,100,NULL); color~the~box( po->color,0); int instock = DbOrder(po->cust, po->item, po->qty); if (stock == 1) ss = "FILLED"; else if (stock == 0) ss = "OUT OF STOCK"; else if (instock == -1) ss = "WRONG CUSTOMER"; else if (stock == -2) ss = "WRONG ITEM"; filled++; s.Format("Direct: %s: 5 %s %d",LPCTSTR(ss), po->cust, po->item, po- SetDlgItemText(IDC~FILLTXT,LPCTSTR(s)); g direct fill = C; if (g~filling) return; if (QSUCCESS == (stat = QsendAndReceive(Q,REQUEST~MODE,SUB~MODE~OK,flag sizeof(g~buf),(char *) &g~buf,&size,&mh))) { if (mh.mode == ACK MODE && mh.sub~mode == SUB~MODE~OK) SetDlgItemInt (IDC MSGS,++m~mes~rec); if (gsize < sizeof(OFORM)) s.Format("Bad reply length"); else ( // you got valid message m~tran~rec++; color~the ~box(g~buf.color,0); // But dont force it if (m~OrderMode == FILL~FROM~ORACLE) instock = OraOrder(g~buf.cust,g~buf.item,g~buf.qty); // Ora else instock = DbOrder(g~buf.cust,g~buf.item,g buf.qty); if (g~fill~delay) ( - g~filling = 1; // Do not fill another until the timer ex SetTimer(FILL~DELAY~TIMER,g~fill~delay,NULL); // SetTimer(FILL~ANAMATE~TIMER,100,NULL); else if (mh.sub mode == SUB~MODE~EMPTY)<BR> <BR> <BR> <BR> if (m~runflag TI filled)<BR> <BR> <BR> s.Format("Que Empty"); else MessageBox("Que Empty"); } else<BR> s.Format ("Bad reply mode %d:%d", mh.mode,mh.sub~mode);<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> else ( // not QSUCCESS (communications error)<BR> mh.mode = 0;// Not ACK MODE s.Format("Communication Error Code d",stat); if (gsize == sizeof(OFORM)) if (instock == 1) sprintf (line, "FILLED:%9s %9s %d", g~buf.cust,g~buf.item,g~buf.qty) else if (instock == 0) sprintf (line, "OUT OF STOCK:%9s %9s %d", g~buf.cust,g~buf.item,g~bu else if ( stock == -1) sprintf(line,"NO SUCH ITEM:%9s W9s %d",g~buf.cust,g~buf.item,g~bu else // instock == -2 sprintf (line, "NO SUCH CUSTOMER:%9s %9s %d", g~buf.cust,g~buf.item,<BR> SetDlgItemText(IDC~FILLTXT,line); // else // strcpy(line,""); // Send Reply if requested if ((mh.reply~smbuf >= 0 ) && (mh.reply~smbuf < SHAREDATA(nsbuf)) &&<BR> <BR> <BR> <BR> mh.mid.host = g~buf.reply~to; // HACK! Makes sure sending host gets<BR> Orep = QopenReply(Qrep,&mh,0,0,0); if (QSUCCESS != (stat = Qput (Qrep,0,REPLY~SUBMODE,0,sizeof (line), lin s.Format ("Qput (%s) Error %d", Qrep->msgh.to~server,stat); else s.Format ("Replying Qput (%s) to smbuf %d", Qrep->msgh.to~server,Qre SetDlgItemInt (IDC~RECIPTS,++m~rec~sent); } GetParentFrame ()->SetMessageText (s); /* if (m runflag && mh.mode == ACK MODE) // We got something OnOrderb(); // Check again for next message, no need to wait.

else // We didnt get anything color~the~box( m~color,0); // restore old color */ if (!m~runflag && !g~fill~delay) color~the~box( m~color,0); ) // place or fill <BR> <BR> <BR> <BR> <BR> <BR> if ((m~OrderMode c= PLACE~ORDER) || mh.mode == ACK MODE) // Placeing or @@ <BR> if (m auto tran > 1) if ( ( NEXTBIT(m~auto~rand) && NEXTBIT(m~auto~rand) II (m~auto~tran++ > 8) ) // Commit or Abort tran? if (m~auto~commit) OnCommitb(); else OnAbortb(); m auto tran = 1; if ((m~OrderMode >= FILL~ORDER) && m~runflag && mh.mode == ACK~MODE && mh.sub~mode == SUB~MODE OK) if (g~max~orders++ < 200) OnOrder(); // Try to get one more item.

else g max orders = 0; else g~max~orders = 0; // The order or fill button will be active until we are done.

// CButton * CB = (CButton *) thix->GetDlgItem (IDC~ORDERB); // CB->SetState (TRUE); // m~auto~tran: // C No auto trans // 1 No tran yet // 2 After OnAutob() int g~poll~delay~old; int g place~delay~old; void COentryView::OnTimer (UINT nIDEvent) if (nIDEvent == PLACE~TIMER <BR> <BR> <BR> <BR> if (g~directplace) return; // direct place thread is already working<BR> <BR> <BR> if (g~filling) return; // Wait for fill done is already working if (g~place~delay~old != g~place~delay) KillTimer(PLACE~TIMER); SetTimer (PLACE~TIMER,g~place~delay~old = g~place~delay,NULL);<BR> } SetDlgItemText (IDC~CUST,g~cust[m~order~num % 6]); SetDlgItemText (IDC~ITEM,g~item[m~order~num % 5]); SetDlgItemInt (IDC~QTY,1 + (m~order~num++ k 9),FALSE); OnOrderb(); //CButton * CB = (CButton *) this->GetDlgItem(IDC~ORDERB); //CB->State (TRUE); else if (nIDEvent == POLL~FILL~TIMER) <BR> <BR> <BR> <BR> if (!g~filling) {<BR> if (g~poll~delay != g~poll~delay~old) KillTimer(POLL FILL TIMER); <BR> <BR> SetTimer(POLL~FILL~TIMER,g~poll~delay~old = g~poll~delay,NULL);<BR> <BR> <BR> <BR> <BR> <BR> OnOrderb();<BR> } else if (nIDEvent == WAIT~ANAMATE~TIMER)<BR> if (g~directplace) // Anomate the wait 0,1 0,1 GetDlgItem(WAITS[g wait anamate++])->ShowWindow(SW~HIDE); if (g wait anamate > 1) g~wait~anamate = 0; GetDlgItem(WAITS[g~wait~anamate])->ShowWindow(SW~SHOW);&l t;BR> } else<BR> <BR> KillTimer(WAIT~ANAMATE~TIMER); <BR> GetDlgItem(IDC~ORDERB)->EnableWindow(TRUE);<BR> <BR> <BR> GetDlgItem(WAITS[g~wait~anamate])->ShowWindow(SW~HIDE);&l t;BR> <BR> else if (nIDEvent == FILL~ANAMATE~TIMER)<BR> <BR> <BR> if (g~filling == 0) I // End Anamation<BR> KillTimer(FILL~ANAMATE~TIMER); GetDlgItem(FILLS[g~fill~anamate])->ShowWindow(SW~HIDE); else ( // Anamate 0,1,2 GetDlgItem(FILLS[g~fill~anamate++])->ShowWindow(SW~HIDE); if (g~fill~anamate > 2) g~fill~anamate = 0; <BR> <BR> <BR> <BR> <BR> GetDlgItem(FILLS[g~fill~anamate])->ShowWindow(SW~SHOW);&l t;BR> if (1) ( // g~progress <BR> // ( (CButton *) this->GetDlgltem(IDC~PLACER) )->SetCheck(0);<BR> // GetDlgItem(IDC~PROG))->SetRange(0,100); // ((CProgressCtrl *) this->GetDlgItem(IDC~PROG))->SetRange(0,100); // ((CProgressCtrl *) this->GetDlgItem(IDC~PROG))->SetPos(50);<BR> // ((CProgressCtrl *) this->GetDlgItem(IDC~PROG))->ShowWindow (SW~SHOW<BR> <BR> <BR> }<BR> <BR> <BR> } else if (nIDEvent == DIRECT~FILL~TIMER) g~direct~fill = 0; // let Qsar() return.

filling = 0; // End Anamation, let next order in KillTimer(DIRECT~FILL~TIMER); color~the~box( m~color,0); // Restore the old color else if (nIDEvent == FILL~DELAY~TIMER) <BR> <BR> <BR> g~filling = 0; // End Anamation, let next order in<BR> KillTimer (FILL~DELAY TIMER); color~the~box( m~color,0); // Restore the old color else if (nIDEvent == SET~1ST~TITLE~TIMER) { // Only done once KillTimer(SET~1ST-TITLE-TIMER); OnAnyUserAction(); } else if (nIDEvent == DB DONE TIMER) if (g db run == 40) { - - g~db~run = 0; GetDlgItem(IDC~SHOWDB)->EnableWindow(TRUE); KillTimer(DB~DONE~TIMER); else if (nIDEvent == OPTIONS~DONE~TIMER) if (goptions run == 40) ( // End g~options~run = 0; GetDlgItem(IDC~OPTIONSB)->EnableWindow(TRUE); KillTimer(OPTIONS~DONE~TIMER); if (m~color != g~new~color) color~the~box(m~color = g~new~color,l); if (g~clear~stats) { g~clear~stats = 0; m~mes~sent = 0; m~mes~rec = 0; m~rec~sent = 0; m~rec~rec = 0; SetDlgItemInt(IDC~MSGS, 0); SetDlgItemInt(IDC~RECIPTS, 0); else CFormView::OnTimer(nIDEvent); void COentryView::OnAutob() if (m runflag) KillTimer(PLACE~TIMER); KillTimer(POLL~FILL~TIMER); m~runflag = 0; // You are no longer running if (m~auto~tran) OnAbortb(); m~auto~tran = 0; SetDlgItemText(IDC~AUTOB, "Auto"); GetDlgItem(IDC EXITB)->EnableWindow(TRUE); ((CButton *) this->GetDlgItem(IDC PLACER))->EnableWindow(TRUE); ((CButton *) this->GetDlgItem(IDC~PLACENOQR))->EnableWindow(TRUE); ((CButton *) this->GetDlgItem(IDC~FILLR))->EnableWindow(TRUE); #ifdef ORACLE ((CButton *) this->GetDlgItem(IDC~FILLDB))->EnableWindow(TRUE); #endif color~the~box( m color,1); // Restore default color else m~runflag = 1; // You will be running m order num = 0; // 1st order number Controls order selections m~auto~tran = m~tran~state; // make random transactions too?.

if ( m~OrderMode > PLACE~ORDER ) // FILL SetTimer(POLL~FILL~TIMER,g~poll~old = g~poll~delay, NULL); else SetTimer (PLACE~TIMER,g~place~delay~old = g~place~delay,NULL); SetDlgItemText(IDC AUTOB," Stop "); GetDlgItem(IDC~EXITB)->EnableWindow(FALSE); ( (CButton *) this->GetDlgltem(IDC~PLACER) )->EnableWindow(FALSE); ( (CButton *) this->GetDlgltem(IDC~PLACENOQR) )->EnableWindow(FALSE); ( (CButton *) this->GetDlgItem(IDC FILLR) )-sEnableWindow(FALSE); ( (CButton *) this->GetDlgltem(IDC~FILLDB) )->EnableWindow(FALSEi; OnAnyUserAction(); // Color Color Color Color Color Color Color Color Color Color // Color Color Color Color Color Color Color Color Color Color // Color Color Color Color Color Color Color Color Color Color void COentryView::OnColor() CHOOSECOLOR cc; // common dialog box structure COLORREF acrCustClr[16]; // Setup the custom colors as a grey scale for (int v=0,i=0; i < 16; v=17 * i++) acrCustClr[i] = RGB(v,v,v); // Initialize the necessary members.

cc.lStructSize = sizeof(CHOOSECOLOR); cc.hwndOwner = NULL; // = hwnd; cc.lpCustColors = (LPDWORD) acrCustClr; cc.Flags = CC~FULLOPEN; // CC~PREVENTFULLOPEN if (ChooseColor(&cc)){ String s; m~box~color = m color = cc.rgbResult; // lpcustcolors Invalidate(); /7 Display the new color else GetParentFrame()->SetMessageText("Color was not changed"); OnAnyUserAction(); //Hinit = 1; HBRUSH COentryView::OnCtlColor(CDC* pDC, CWnd* pwnd, UINT nCtlColor) if (nCtlColor == CTLCOLOR~EDIT) if (pWnd->GetDlgCtrlID() == IDC~COLORBOX) { pDC-sSetBkColor(m~color); m~brush = CreateSolidBrush(m~color); return(m~brush); else if (nCtlColor == CTLCOLOR~BTN ) ( // CTLCOLOR EDIT if (pWnd->GetDlgCtrlID() == IDC~AUTOB)<BR> <BR> <BR> <BR> <BR> <BR> if (m~runflag)<BR> <BR> <BR> <BR> <BR> pDC->SetBkColor(RGB(255,0,0)); // SetBkColor SetTextColor<BR> <BR> <BR> pDC->SetTextColor(RGB(255,255,255)); // SetBkColor SetTextColor m~brush = CreateSolidBrush(m~color); return(m~brush); } // } else if (nCtlColor == CTLCOLOR~STATIC ) { // CTLCOLOR~EDIT<BR> <BR> // if (pWnd->GetDlgCtrlID() == IDC~INST) {<BR> // // pDC->SetBkColor(RGB(255,0,0)); // SetBkColor SetTextColor<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> // // pDC->SetTextColor(RGB(255,255,255)); // SetBkColor SetTextColor<BR> <BR> <BR> <BR> <BR> <BR> <BR> // // m brush = CreateSolidBrush (m~color);<BR> brush = CreateSolidBrush(m~box color); empty non-text background<BR> <BR> <BR> <BR> <BR> <BR> <BR> // pDC->SetBkColor(m~box~color); // behind the letters<BR> // return(m~brush); HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor); return hOr; int COentryView::DbOrder(char *cust, char *item, int qty) int custn=0,itemn=0; <BR> <BR> while(strcmp(item,g~item[itemn])) if (++itemn == 6) return(-1);<BR> while(strcmp(cust,g~cust[custn])) if (++custn == 6) return(-2); if (g~qty[itemn] >= qty) g~qty[itemn] -= qty;<BR> <BR> <BR> g~purchases[custn] += qty * g~price[itemn];<BR> <BR> <BR> <BR> <BR> <BR> g~num~purchases[custn]++;<BR> g~total~sales += qty * g~price[itemn];<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> else return(0); return(1); int COentryView::OraOrder(char *cust, char *item, int qty) { <BR> <BR> int custn=0, itemn=0, price,stock,rc,cust~orders,cust-sales;<BR> <BR> <BR> CString s;<BR> <BR> <BR> while(strcmp(item,g~item[itemn])) if (++itemn == 6) return(-1);<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> while(strcmp(cust,g~cust[custn])) if (++custn == 6) return(-2);<BR> <BR> if (g~ora~state == 0) {<BR> <BR> <BR> <BR> GetParentFrame()->SetMessageText("Cant Order from oracle: not connected");<BR> return(0); // Read Oracle if ( (rc = oraread(item, &priee, &stock)) s.Format ("OraRead Error %d",rc); GetFarentFrame()->SetMessageText(s); return (0); if ( (rc = oracustr(cust, &cust~orders, &eust~sales)) s.Format("OraCustRead Error %d",rc); GetParentFrame()->SetMessageText(s); if (qty > stock) return(0); // MessageBox("OutOfStock") else stock -= qty; g total sales += qty * price; cust-sales += qty * price; cust~orders++; // Write Oracle if ( (rc = orawrite(item, stock)) s.Format("OraWrite Error kd",rc); GetParentFrame()->SetMessageText(s); return (0); if ( (rc = oracustw(cust, cust~orders, eust~sales)) s.Format("OraCustWrite Error %d",rc); GetParentFrame()->SetMessageText(s); return(1) void COentryView::PlaceOrFillMode(int mode) m OrderMode = mode; int SHOW, HIDE, IsPlaceMode; if (mode <= PLACE~ORDER) HIDE = SW~HIDE; SHOW = SW~SHOW; IsPlaceMode = TRUE; else HIDE = SW~SHOW; SHOW = SW~HIDE; IsPlaceMode = FALSE; GetDlgItem(IDC~SENDREPC)->ShowWindow(SHO // Show sendreply checkbox if (m~OrderMode <= PLACE ORDER) SetDlgItemText(IDC~ORDERB,"Order"); // Order = Order SetDlgItemText(IDC~ORDERBOX,"Place Orders"); // Order = Order SetDlgItemText (IDC BIG TITLE, "OpenMQ Place Orders"); // Order = <BR> else SetDlgItemText(IDC~ORDERB,"Fill"); SetDlgItemText(IDC~ORDERBOX,"Fill Orders"); SetDlgItmeText(IDC~BIG~TITLE,"OpenMQ Fill Orders");<BR> } GetdlgItem(IDC~SHOWDB)-&ShowWindow(HIDE); GetDlgItem(IDC~CUST)->ShowWindow(SHOW); GetDlgItem(IDC~ITEM)->ShowWindow(SHOW); GetDlgItem(IDC~QTY)->ShowWindow(SHOW); GetDlgItem (IDC~CUSTLAB)- >ShowWindow (SHOW) ; GetdlgItem(IDC~ITEMLAB)-&ShowWindow(HIDE); GetdlgItem(IDC~QTYLAB)-&ShowWindow(HIDE); GetdlgItem(IDC~FILLTXT)-&ShowWindow(HIDE); // ( (CEdi@ *) this->GetDlgItem(IDC~CUST) )->SetReadOnly(FALSE); // ( (CEdit *) this->GetDlgItem(IDC~ITEM) )->SetReadOnly(FALSE); // ( (CEdit *) this->GetDlgltem(IDCQTY) )->SetReadOnly(FALSE); // Stats if (mode <= PLACE~ORDER) { SetDlgItmeText(IDC~MSGS~LAB,"Sent:"); SetDlgItemText(IDC RECIPTS LAB,"Received:"); SerDlgItemInt(IDC~MSGSm m~mes~sent); SetDlgItemInt(IDC~RECIPTS, m rec rec-); <BR> else <BR> <BR> <BR> <BR> SetDlgItemText(IDC MSGS LAB,"Received:"); SetDlgItemText(IDC~RECIPTS~LAB,"Sent:") SetDlgItemInt(IDC~MSGS, m~mes~rec); SetDlgItmeInt(IDC#RECIPTS, m~rec#sent); if (mode != PLACE~ORDER~NOQ) I GetDlgItem (IDC-TRANBOX)-> ShowWindow( SW~SHOW) ; <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> if (m~tran~state) { GetDlgItem(IDC~COMMOTB)->ShowWindow(SW~SHOW); <BR> <BR> GetDlgItem(IDC~ABORTB)->ShowWindow(SW~SHOW);<BR> else <BR> <BR> <BR> <BR> GetDlgItem(IDC~TRANB)->ShowWindow(SW~SHOW);<BR> else GetDlgItem(IDC~TRANBOX)->ShowWindow(SW~HIDE); GetDlgItem(IDC~TRANB)->ShowWindov(SW~HIDE); GetDlgItem(IDC~COMMITB)->ShowWindow(SW~HIDE);<BR> GetDlgItem(IDC~ABORTB)->ShowWindow(SW~HIDE);<BR> GetDlgItem(IDC~SENDREPC)->ShowWindow(SW~HIDE); if (mode == PLACE ORDER~NOQ) LoadQList(0); 7/ Load non-Que else LoadQList(l); // Load Que names if (mode <= PLACE~ORDER) if (g~db~run) g~db~run = 40; // Turn off the DB display if it was left On if (mode == FILL~FROM~ORACLE) { if (g ora state == 0) if(oraconn(g oracle con str)) MessageBox("Oracle Connect Failed") else <BR> <BR> g~ora~state = 1;<BR> else if (g ora state == 1) if(oradisc()) MessageBox("Oracle DisConnect Failed"); else g~ora~state = 0; OnAnyUserAction(); // Re load the que list just incase a new que was launched void COentryView::OnSetfocusQue() if (m~OrderMode == PLACE~ORDER~NOQ) LoadQList(0); // Load non-Que else LoadQList(1); // Load Que names void COentryView::OnPlacenogr() { if (!((CButton *)GetDlgItem(IDC~PLACENOQR))->GetCheck()) return; PlaceOrFillMode(PLACE ORDER NOQ); OnAnyUserAction(); } void COentryView::OnPlacer() { if (!((CBitton *)GetDlgItem(IDC~PLACER))->GetCheck()) return; PlaceOrFillMode(PLACE~ORDER); OnAnyUserAction(); void COentryView::OnFillr() if (!((CButton *)GetDlgItem(IDC~FILLR))->GetCheck()) return; PlaceOrFillMode(FILL~ORDER); OnAnyUserAction (); void COentryView: :OnFilldb() if (!((CButton *)GetDlgItem(IDC~FILLDB))->GetCheck()) return; PlaceOrFillMode(FILL~FROM~ORACLE); OnAnyUserAction(); void COentryView::OnAnyUserAction() <BR> <BR> <BR> <BR> <BR> SetDlgltemText(IDC~RECIPT,""); <BR> <BR> <BR> <BR> SetDlgItemText(IDC FILLTXT,""); if (mque == GetParentPrame()->SetWindowText(m~inst + ": No server is selected" else if (m OrderMode == PLACE ORDER) GetParentFrame()->SetWindowText(m inst + ": Place orders into queue " + m else if (m OrderMode == PLACE ORDER NOQ) GetParentFrame()->SetWindowText(m~inst + ": Place orders directly to " + m else // FILL GetParentFrame()->SetWindowText(m~inst + ": Fill orders from queue " + .~ m~box~color = m~color; void COentryView: :OnSendrepc() m~sendreply = sm-sendreply; // How can I get this info? if ( Q ) if ( m~sendreply Q->msgh.reply~smbuf = tp.bnum; else Q->msgh.reply~smbuf = -1; void COentryView::color~the~box(COLORREF color, BOOL forceit) { if ((m~box~color != color ) || forceit) { m~box~color = color; // The DC for the color box CDC* pCOLORDC = GetDlgItem(IDC COLORBOX)->GetDC(); // pCOLORDC->GetRect(); // Create a PEN // CPen *pQPen = new CPen(PS~SOLID, 3,RGB(0,0,255)); // CPen *pOldPen = pXDC->SelectObject (pQPen); // Create the Brush CBrush *pQBrush = new CBrush(color); // Select this brush, save the old CBrush *pOldBrush = pCOLORDC->SelectObject(pQBrush); // Draw the box // pCOLORDC->Rectangle(CRect(1,1,65,65)); pCOLORDC->Rectangle(m~color~box~rec); pCOLORDC->SelectObject(&pOldBrush); // Reset the brush delete(pQBrush); ReleaseDC(pCOLORDC); // GetDlgItem(IDC LOGO Q)->Invalidate(); // GetDlgItem(IDC~INST)->Invalidate(); } } void COentryView::OnDraw(CDC* pDC) { /* pControlDC->SelectStockObject (WHITE~BRUSH); */ // The DC for the Instance name /* CDC* pINSTDC = GetDlgItem(IDC~INST)->GetDC(); pINSTDC->SetBkColor(m~color); pINSTDC->SetTextColor(m~color); pINSTDC->SetBkMode(TRANSPARENT); <BR> <BR> pINSTDC->SelectStockObject(HOLLOW~BRUSH);<BR> <BR> */<BR> <BR> <BR> GetDlgItem(IDC COLORBOX)->GetWindowRect(&m~color~box~rec);<BR> <BR> m~color~box~rec.right -= m~color~box~rec.left; //ScreenToClient(&rec); m~color~box~rec.bottom -= m~color~box~rec.top; m color-box-rec.left = m~color~box~rec.top = 0; eolor~the~box(m~box~color,1); CFormView::OnDraw(pDC); /*void COentryView::OnResetb() m mes sent = 0; m~mes~rec = 0; m~rec~sent = 0; m~rec~rec = 0; SetDlgltemlnt(IDC MES~REC,0); <BR> <BR> SetDlgItemInt(IDC~REC~REC,O); <BR> <BR> SetDlgItemInt(IDCMES~SENT,O); <BR> <BR> SetDlgItemInt(IDC#REC~SENT,0); OnAnyUserAction(); // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT TTTTTTTTTT // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT TTTTTTTTTT // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT TTTTTTTTTT void COentryView: :OnTranb() m~tran~state ) = 1; GetDlgItem)IDC~TRANB)->ShowWindow(SW~HIDE); GetDlgItem(IDC~ABORTB)->ShowWindow(SW~SHOW); GetDlgItem(IDCCOMMITB) ->ShowWindow(SW~SHOW); OnAnyUserAction(); void COentryView::OnCommit(int action) // Anyway get rid of the commit/abort buttons GetDlgItem(IDC~TRANB)-&ShowWindow(SW~SHOW); GetDlgItem(IDC~ABORTB)->ShowWindow(SW~SHOW); GetDlgItem(IDC~COMMITB)->ShowWindow(SW~SHOW); // Do the commit if ((Q) && (m~tran~state > 1)) Qcommit(action); m~tran~rec = 0; m~tran~sent = 0; m~tran~state = 0; void COentryView::OnCommitb() OnCommit(Q COMMIT); void COentryView: :OnAbortb() OnCommit(Q~ABORT); m~mes~sent -= m#tran~sent; m~rec~rec -= m~tran~rec; void COentryView::OnLButtonDown(UINT nFlags, CPoint point) CRect rec; // WINDOWPLACEMENT GetWindowPlacement CRect // MessageBeep)0); GetDlgItem(IDC~COLORBOX)->GetWindowRect(&rec); ScreenToClient(&rec); if (rec.PtInRect(point)) OnColor(); CFormView::OnLButtonDown(nFlags, point); void COentryView::OnRButtonDown(UINT nFlags, CPoint ppint) ClearDisplay(); CFormView::OnRButtonDown(nFlags, point); void COentryView::ClearDisplay() GetParentFrame()->SetMessageText("0); this->Invalidate(); OnAnyUserAction(); void COentryView::OnShowdb() { GetDlgItem(IDC~SHOWDB)->EnableWindow(FALSE); SetTimer(DB~DONE~TIMER,2000,NULL); // When the DB is done re-enable // CDbDlg dbd; // dbd.DoModal(); dbd.Create(IDD~DBDLG); //GetParentFrame()->SetMessageText("After dbd.Create void COentryView: :OnOptionsb() GetDlgltem(IDC OPTIONSB) ->EnableWindow(FALSE); SetTimer(OPTIONS~DONE~TIMER,2000,NULL); // When the options are done re-enabl // o~dlg.Create(IDD~O~DLG); if (o~dlg.m~inst != m~inst) { // Init o~dlg.m~inst = m~inst; // o~dlg.m~parentptr = this; o~dlg.Create(IDD~O~DLG); g~new~color = m~color; o~dlg.ShowWindow(SW~SHOW); DROP TABLE omq~stock; CREATE TABLE omq~stock (item VARCHAR2(10) PRIMARY KEY, price NUMBER, qty NUMBER); INSERT INTO omq~stock VALUES ('Bolts',1,1000); INSERT INTO omq~stock VALUES ('Buckets',2,1000); INSERT INTO omq stock VALUES ('Buttons',3,1000); INSERT INTO omq~stock VALUES ('Belts',4,1000); INSERT INTO omq stock VALUES ('Bobbins',5,1000); INSERT INTO omq stock VALUES ('Boats',6,1000); COMMIT WORK; DROP TABLE omq~cust; CREATE TABLE omq~cust (customer VARCHAR2(10) PRIMARY KEY, orders NUMBER, sales NUMBER); INSERT INTO omq cust VALUES ('Jacobs',0,0); INSERT INTO omq cust VALUES ('Jackson',0,0); INSERT INTO omq~cust VALUES ('Jaffe',0,0); INSERT INTO omq~cust VALUES ('Johnson',0,0); INSERT INTO omq cust VALUES ('Jones',0,0); INSERT INTO omq cust VALUES (James,0,0) COMMIT WORK; /* File name & Package Name */ struct sqlcxp unsigned short fillen; char filnam[10]; static struct sqlcxp sqlfpn = 9, "oraomq.pc" }; static const unsigned long sqlctx = 822081471; static struct sqlexd unsigned long sqlvsn; unsigned long arrsiz; unsigned long iters; unsigned short offset; unsigned short selerr; unsigned short sqlety; unsigned short unused; short *cud; unsigned char *sqlest; char *stmt; unsigned char * *sqphsv; unsigned long *sqphsl; short * *sqpind; unsigned long *sqparm; unsigned long * *sqparc; unsigned char *sqhstv[3]; unsigned long sqhstl[3]; short *sqindv[3]; unsigned long sqharm[3]; unsigned long *sqharc[3]; sqlstm = (8,3); extern sqlcx2(/*~ unsigned long , struct sqlexd *, struct sqlcxp * extern sqlcte(/*~ unsigned long , struct sqlexd *, struct sqlcxp * extern sqlbuf(/*~ char * extern sqlora(/*~ unsigned long *, void * static int IAPSUCC = 0; static int IAPFAIL = 1403; static int IAPFTL = 535; extern sqliem(); /* cud (compilation unit data) array */ static short sqlcudO[] = (8,34, <BR> <BR> <BR> <BR> <BR> 2,0,8,0,0,0,0,0,0,0, 0,0,0,0,27,88,0,3, 3,0,1,0,1,9,0,0, 1,10,0,0,1,10,0,0, <BR> <BR> <BR> <BR> <BR> 36,0,8,0,0,0,0,0,0,0,0,0,0,0,30,111,0,0,0,0,1,0, <BR> <BR> <BR> <BR> <BR> 58,0,8,0,0,0,0,0,0,0,0,1,20,0,1,151,0,0,0,0,1,0, <BR> <BR> <BR> <BR> <BR> 80,0,8,0,0,0,0,0,0,0,0,2,19,0,1,152,0,0,0,0,1,0, <BR> <BR> <BR> <BR> <BR> 102,0,8,0,0,0,0,0,0,0,0,3,76,0,44,157,0,0,0,0,1,0, <BR> <BR> <BR> <BR> <BR> 124,0,8,0,0,0,0,0,0 0,0,4,45,0,3,161, 0,0,0,0,1,0, <BR> <BR> <BR> <BR> <BR> 146,0,8,0,0, 0,0,0,0,0,0,5,47,0, 3,162,0,0,0,0,1,0, <BR> <BR> <BR> <BR> <BR> 168,0,8,0,0,0,0, 0,0,0,0,6,47,0,3, 163,0,0,0,0,1,0, <BR> <BR> <BR> <BR> <BR> 190,0,8,0,0,0,0,0,0, 0,0,7,45,0,3,164,0, 0,0,0,1,0, 212,0,8,0,0,0,0, 0, 0,0, 0,8,47,0,3,165,0,0,0,0, 1,0, <BR> <BR> <BR> <BR> 234,0,8,0,0,0,0, 0, 0,0,0,9,45,0,3, 166,0,0,0,0,1, 0, <BR> <BR> <BR> 256,0,8,0,0,0, 0,0,0,0,0,10,82,0, 44,168,0,0,0,0,1,0, <BR> <BR> <BR> <BR> 278,0,8,0,0,0,0,0,0, 0,0,11,41,0,3,172,0,0, 0,0,1,0, <BR> <BR> <BR> <BR> 300,0,8,0,0,0,0,0,0,0,0,12,42,0,3,173,0,0,0,0,1,0, <BR> <BR> <BR> <BR> 322,0,8,0,0,0,0,0,0,0,0,13,40,0,3,174,0,0,0,0,1,0, <BR> <BR> <BR> <BR> 344,0,8,0,0,0,0,0,0, 0,0,14,42,0,3, 175,0,0,0,0,1,0, <BR> <BR> <BR> <BR> 366,0,8,0,0,0,0,0,0, 0,0,15,40,0,3, 176,0,0,0,0,1,0, <BR> <BR> <BR> <BR> 388,0,8,0,0,0,0,0,0,0,0,16,40,0,3,177,0,0,0,0,1,0, 410,0,8,0,0,0,0,0,0,0,0,16,0,0,29,179,0,0,0,0,1,0, <BR> <BR> 432,0,8,0,0,0,0,0,0,0,0,17,58,0,4,211,0,3,1,0,1,0,1,9,0,0,2, 3,0,0,2,3,0,0,<BR> 466,0,8,0,0,0,0,0,0,0,0,18,43,0,5,259,0,2,2,0,1,0,1,3,0,0,1, 9,0,0,<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> 496,0,8,0,0,0,0,0,0,0,0,18,0,0,29,263,0,0,0,0,1,0,<BR> <BR> 518,0,8,0,0,0,0,0,0,0,0,19,64,0,4,306,0,3,1,0,1,0,1,9,0,0,2, 3,0,0,2,3,0,0,<BR> 552,0,8,0,0,0,0,0,0,0, 0,20,59,0,5,356,0,3,3, 0,1,0,1,3,0,0,1,3,0,0, 1,9,0,0, <BR> <BR> <BR> <BR> <BR> <BR> 586,0,8,0,0,0,0,0,0,0,0,20,0,0,29,360,0,0,0,0,1,0, }; /* ** ** Copyright(C)1996 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ Demo ** Module: oraomq.pc ** Author: Frederick J. Igo, Jr. 1/15/96 ** */ #include <stdlib.h> incl#ude <stdio.h> 4include <ctype.h> #include <string.h> # include "sqlproto.h" # include "ociproto.h" # define ORACLE # include "oraomq.h" /* SQL stmt #1 EXEC SQL INCLUDE SQLCA.H; */ /* Copyright (c) 1985,1986 by Oracle Corporation. */ /* NAME SQLCA : SQL Communications Area.

FUNCTION Contains no code. Oracle fills in the SQLCA with status info during the execution of a SQL stmt.

NOTES If the symbol SQLCA~STORAGE~CLASS is defined, then the SQLCA will be defined to have this storage class. For example: #define SQLCA~STORAGE~CLASS extern will define the SQLCA as an extern.

If the symbol SQLCA~INIT is defined, then the SQLCA will be statically initialized. Although this is not necessary in order to use the SQLCA, it is a good pgming practice not to have unitialized variables. However, some C compilers/OS's don't allow automatic variables to be init'd in this manner. Therefore, if you are INCLUDE'ing the SQLCA in a place where it would be an automatic AND your C compiler/OS doesn't allow this style of initialization, then SQLCA INIT should be left undefined -- all others can define SQLCA~INIT if they wish.

New rules for defining SQLCA~INIT, SQLCA~STORAGE~CLASS, and DLL in OS/2: Users should not define SQLCA~STORAGE~CLASS if defining DLL.

SQLCA~STORAGE~CLASS is primarily used for single-threaded programs and for internal development.

MODIFIED Okamura 08/15/89 - OS/2: users must define SQLMT for multi-threaded case Okamura 06/23/89 - OS/2: modify for multi-threaded case Clare 12/06/84 - Ch SQLCA to not be an extern.

Clare 10/21/85 - Add initialization.

Bradbury 01/05/86 - Only initialize when SQLCA~INIT set Clare 06/12/86 - Add SQLCA~STORAGE~CLASS option.

*/ #ifndef SQLCA #define SQLCA 1 struct sqlca /* ubl */ char sqlcaid[8]; /* b4 */ long sqlabc; /* b4 */ long sqlcode; struct /* ub2 */ unsigned short sqlerrml; /* ubl */ char sqlerrmc[70]; }sqlerrm; /* ubl */ char sqlerrp[8]; /* b4 */ long sqlerrd[6]; /* ubl */ char sqlwarn[8]; /* ubl */ char sqlext[8]; }; #ifdef SQLMT extern struct sqlca *sqlcamt(); /* For multi-threaded version */ # define sqlca (*sqlcamt()) #else /* SQLMT */ #ifdef SQLCA~STORAGE~CLASS SQLCA STORAGE CLASS struct sqlca sqlca # ifdef SQLCA INIT ( , 'Q' , 'L' , 'L, C', 'A' A, t , t ' , ' ' } , }, sizeof(struct sqlca) <BR> <BR> 0,<BR> { 0, {0}}, {'N', 'O', 'T', ' ', 'S', 'E', 'T', ' 0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0 } <BR> <BR> <BR> <BR> <BR> &num endif /* SQLCA~INIT */<BR> &num else /* SQLCA~STORAGE~CLASS */ struct sqlca sqlca ' ; /* For single-threaded version */ <BR> <BR> <BR> <BR> <BR> &num ifdef SQLCA~INIT<BR> = {<BR> <BR> <BR> <BR> <BR> {'S', 'Q', 'L', 'C', 'A', ' ', ' ', '<BR> sizeof(struct sqlca)<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> 0,<BR> 'S', 'E', 'T', ' <BR> 0,0, 0, 0, 0, 0),<BR> (o, 0, 0, 0, 0, 0,<BR> <BR> {0, 0, 0, 0, 0, 0, 0, # endif * SQLCA~INIT */ 4endif /* SQLCA~STORAGE~CLASS */ 4endif /* SQLMT */ /* end SQLCA */ #endif /* SQLCA */ /* #include <C:\ORANT\PRO16\C\sqlca.h> */ /* NAME oraomq FUNCTION Openmq Oracle Pro* C subroutines NOTES oraerrrpt(); -- Prints SQL Errors msgs & codes oraconn(...); -- -- CONNECTS to ORACLE using given oracle string.

oradisc(); -- DISCONNECTS from ORACLE oracreate(); -- Creates omq~stock & omq~cust tables in ORACLE.

oraread(...); -- Given ITEM name, reads PRICE & QTY.

orawrite(. .); -- Given ITEM name & QTY, updates QTY IN db.

oracustr(...); -- Given CUSTOMER name, reads #ORDERS & $SALES.

oracustw(...); -- Given CUSTOMER name, #ORDERS & $SALES, updates db.

C:\ORANT\PRO16\C> nmake -f oraomq.mak */ /* ------------------------------------------------------------ -------------- ORAERRRPT prints the ORACLE error msg and number.

--------------------------------------------------------- ----------- */ oraerrpt() { printf("%.70s (%d)\n", sqlca.sqlerrm.sqlerrmc, -sqlca.sqlcode);<BR> <BR> return(0); } /* ------------------------------------------------------------ ------------ ORACONN connects to ORACLE as user demo.

Oracle String is provided by caller as: "SCOTT/TIGER@T:GRAMPA:ORCL".

returns 0 on success and 1 on SQL error.

--------------------------------------------------------- ----------- */ oraconn (orastring) <BR> <BR> char orastring[80];<BR> {<BR> <BR> <BR> <BR> <BR> /* SQL stmt &num 2 EXEC SQL BEGIN DECLARE SECTION; */ struct { unsigned short len; unsigned char arr[80]; } oracleid; /* VARCHAR oracleid[80]; /o username/password@dbstring o/ EXEC SQL END DECLARE SECTION; */ /* SQL stmt #4 EXEC SQL WHENEVER SQLERROR GOTO errexit; */ strcpy ((char *) oracleid.arr,orastring); oracleid.len = strlen ((char *) oracleid.arr); /* SQL stmt #5 EXEC SQL CONNECT : oracleid; */ { struct sqlexd sqlstm={8,3}; sqlstm.iters = (unsigned int )10; sqlstm.offset = (unsigned int )2; sqlstm.cud = sqlcudO; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlstm.sqhstv[0] = (unsigned char *) &oracleid sqlstm.sqhstl[0] = (unsignated int) 82; sqlstm.sqindv[0] = ( short *)0; sqlstm.sqharm[0] = (unsigned int )0; sqlstm.sqphsv = sqlstm.sqhstv; sqlstm.sqphsl = sqlstm.sqhstl; sqlstm.sqpind = sqlstm.sqindv; sqlstm.sqparm = sqlstm.sqharm; sqlstm.sqparc = sqlstm.sqharc; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; return(0); /* Here if SQL Error */ errexit: /* SQL stmt 46 EXEC SQL WHENEVER SQLERROR CONTINUE; */ return (1); } ORADISC disconnects from ORACLE.

returns 0 on success and 1 on SQL error. ------------------------------------------------------------ -------------- */ oradisc() { /* SQL stmt #7 EXEC SQL WHENEVER SQLERROR GOTO errexit; */ /* SQL stmt #8 EXEC SQL COMMIT RELEASE; */ { struct sqlexd sqlstm={8,0}; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )36; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; return(0) /* Here if SQL Error */ errexit: /* SQL stmt #9 EXEC SQL WHENEVER SQLERROR CONTINUE; */ return (1); } /* ------------------------------------------------------------ ------------- ORACREATE creates omq~stock & omq~cust tables in ORACLE as follows: omq~stock: ITEM PRICE QTY Bolts $1 10000 Buckets $2 10000 Buttons $3 10000 Belts $4 10000 Bobbins $5 10000 Boats $6 10000 omq~cust: CUSTOMER ORDERS SALES Jacobs 0 0 Jackson C 0 Jaffe O 0 Johnson 0 0 Jones C 0 James 0 0 returns 0 on succes and 1 on SQL error.

--------------------------------------------------------- ----------------- */ oracreate() { /* Expect an error if table already dropped */ /* SQL stmt #10 EXEC SQL WHENEVER SQLERROR GOTO ignore; EXEC SQL DROP TABLE omq~stock; struct sqlexd sqlstm={8,0}; sqlstm.stmt = "DROP TABLE OMQ~STOCK"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )58; sqlstm.cud = sqlcudO; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto ignore; /* SQL stmt #12 <BR> <BR> EXEC SQL DROP TABLE omq~cust;<BR> <BR> */<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> {<BR> <BR> struct sqlexd sqlstm={8,0}; sqlstm.stmt = "DROP TABLE OMQ~CUST"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )80; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn)i <BR> <BR> if (sqlca.sqlcode < 0) goto ignore;<BR> ignore: /* SQL stmt #13 EXEC SQL WHENEVER SQLERROR GOTO errexit; /* SQL stmt #14 EXEC SQL CREATE TABLE omq~stock (item VARCHAR2(10) PRIMARY KEY, price NUMBER, qty NUMBER); struct sqlexd sqlstm=(8,0); <BR> <BR> sqlstm.stmt = "CREATE TABLE OMQ~STOCK(ITEM VARCHAR2(10)PRIMARY KEY,PRIC\<BR> E NUMBER,QTY NUMBER)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )102; sqlstm.cud = sqlcudO; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt 415 EXEC SQL INSERT INTO omq~stock VALUES('Bolts',1,10000); */ {<BR> <BR> struct sqlexd sqlstm={8,0}; sqlstm.stmt = "INSERT INTO OMQ~STOCK VALUES('Bolts',1,10000)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )124; sqlstm.cud = sqlcudO; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #16 EXEC SQL INSERT INTO omq~stock VALUES('Buckets',2,10000); */ {<BR> <BR> struct sqlexd sqlstm={8,0}; sqlstm.stmt = "INSERT INTO OMQ~STOCK VALUES('Buckets',2,10000)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )146; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #17 EXEC SQL INSERT INTO omq~stock VALUES('Buttons',3,10000); */ {<BR> <BR> struct sqlexd sqlstm={8,0}; sqlstm.stmt = "INSERT INTO OMQ STOCK VALUES('Buttons',3,10000)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )168; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; } /* SQL stmt #18 <BR> <BR> EXEC SQL INSERT INTO omq-stock VALUES ('Belts',4,10000);<BR> */ { struct sqlexd sqlstm={8,0}; sqlstm.stmt = "INSERT INTO OMQ STOCK VALUES('Belts',4,1O000)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )190; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #19 EXEC SQL INSERT INTO omq~stock VALUES('Bobbins',5,10000); */ { struct sqlexd sqlstm={8,0}; sqlstm.stmt = "INSERT INTO OMQ STOCK VALUES('Bobbins',5,l0OO0)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )212; sqlstm.cud = sqlcudO; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #20 EXEC SQL INSERT INTO omq~stock VALUES('Boats',6,10000); */ { struct sqlexd sqlstm={8,0}; sqlstm.stmt = "INSERT INTO OMQ STOCK VALUES('Boats',6,10000)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )234; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #21 EXEC SQL CREATE TABLE omq~cust (customer VARCHAR2(10) PRIMARY KEY, orders NUMBER, sales NUMBER); */ {<BR> <BR> struct sqlexd sqlstm={8,0}; sqlstm.stmt = "CREATE TABLE OMQ CUST(CUSTOMER VARCHAR2(10)PRIMARY K\ EY,ORDERS NUMBER,SALES NUMBER)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )256; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #22 EXEC SQL INSERT INTO omq~cust VALUES ('Jacobs',0,0); */ <BR> {<BR> <BR> <BR> struct sqlexd sqlstm={8,0}; sqlstm.stmt = "INSERT INTO OMQ~CUST VALUES('Jacobs',0,0)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )278; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); <BR> <BR> if (sqlca.sqlcode < 0) goto errexit;<BR> <BR> /* SQL stmt &num 23 <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> EXEC SQL INSERT INTO omq~cust VALUES('Jackson',0,0);<BR> <BR> struct sqlexd sqlstm={8,0}; sqlstm.stmt = "INSERT INTO OMQ~CUST VALUES('Jaokson',0,O)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )300; sqlstm.cud = sqloudo; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; <BR> <BR> /* SQL stmt &num 24 <BR> <BR> EXEC SQL INSERT INTO omq~cust VALUES('Jaffe',0,0); { struct sqlexd sqlstm={8,0}; sqlstm.stmt = "INSERT INTO OMQ~CUST VALUE ('Jaffe',0,0)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )322; sqlstm.cud = sqlcudo; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode c 0) goto errexit; /* SQL stmt #25 <BR> <BR> EXEC SQL INSERT INTO omq~cust VALUES('Johnson',0,0);<BR> */ { struct sqlexd sqlstm={8,0}; sqlstm.stmt = "INSERT INTO OMQ~CUST VALUES('Johnson',O,0)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )344; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqletx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #26 EXEC SQL INSERT INTO omq~eust VALUES('Jones',0,0); struct sqlexd sqlstm={8,0}; sqlstm.stmt = "INSERT INTO OMQ CUST VALUES('Jones',0,0)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )366;<BR> sqlstm.cud = sqlcudo; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #27 EXEC SQL INSERT INTO omq~cust VALUES('James',O,O); struct sqlexd sqlstm=(8,0}; sqlstm.stmt = "INSERT INTO OMQ~CUST VALUES('James',0,0)"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )388; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #28 EXEC SQL COMMIT WORK; */ { struct sqlexd sqlstm={8,0}; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )410; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; return(0); /* Here if SQL Error */ errexit: /* SQL stmt #29 EXEC SQL WHENEVER SQLERROR CONTINUE; */ return (1); } /* ------------------------------------------------------------ -------------- ORAREAD reads QTY & PRICE from omq~stock table given ITEM.

returns 0 on success, 1 on SQL error and 2 on noitem.

--------------------------------------------------------- ----------------- */ <BR> <BR> <BR> int oraread (itemname, itemprice, itemqty)@@)<BR> char itemname[l0]; int *itemprice, *itemqty; /* SQL stmt 430 EXEC SQL BEGIN DECLARE SECTION; */ struct { unsigned short len; <BR> <BR> unsigned char arr[10]; <BR> <BR> <BR> } item; /* VARCHAR item[10]; /o item name o/ */ int price; /* item price */ int qty; /* item quantity */<BR> /* SQL stmt &num 31 EXEC SQL END DECLARE SECTION; */ /* SQL stmt #32 EXEC SQL WHENEVER NOT FOUND GOTO noitem; EXEC SQL WHENEVER SQLERROR GOTO errexit; */ strcpy ((char *)item.arr,itemname); item.len = strlen(itemname) /* SQL stmt #34 EXEC SQL SELECT PRICE, QTY INTO :price, :qty FROM omq~stock WHERE ITEM = :item; */ { struct sqlexd sqlstm={8,3}; sqlstm.stmt = "SELECT PRICE,QTY INTO:bl,:b2 FROM OMQ~STOCK WHERE ITEM=:b3"; sqlstm.iters = (unsigned int )1; <BR> sqlstm.offset = (unsigned int )432;<BR> sqlstm.selerr = (unsigned short)l; sqlstm.cud = sqlcudO; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlet.y = (unsigned short)0; sqlstm.sqhstv[0] = (unsigned char *)&item sqlstm.sqhstl[0] = (unsigned int )12; sqlstm.sqindv[0] = ( short *)0; sqlstm.sqharm[0] = (unsigned int )0; sqlstm.sqhstv[1] = (unsigned char *)&price sqlstm.sqhstl[l] = (unsigned int )4; sqlstm.sqindv[l] = ( short *)0; sqlstm.sqharm[l] = (unsigned int )0; sqlstm.sqhstv[2] = (unsigned char *)&qty sqlstm.sqhstl[2] = (unsigned int )4; sqlstm.sqindv[2] = ( short *)0; sqlstm.sqharm[2] = (unsigned int )0; sqlstm.sqphsv = sqlstm.sqhstv; sqlstm.sqphsl = sqlstm.sqhstl; sqlstm.sqpind = sqlstm.sqindv; sqlstm.sqparm = sqlstm.sqharm; sqlstm.sqparc = sqlstm.sqharc; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode == 1403) goto noitem; if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt 435 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ *itemprice = price: *itemqty = qty; return(0); /* Here if item NOT found in dbs */ noitem: /* SQL stmt #37 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ return (2); /* Here if SQL Error */ errexit: /* SQL stmt 439 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ return (1); } /* ------------------------------------------------------------ -------------- ORAWRITE updates QTY for a given ITEM in the omq~stock table.

returns 0 on succes, 1 on SQL error and 2 on noitem.

--------------------------------------------------------- ----------------- */ int orawrite (itemname, itemqty) <BR> <BR> char itemname[10]<BR> int itemqty; /* SQL stmt 441 EXEC SQL BEGIN DECLARE SECTION; */ struct { unsigned short len; unsigned char arr[10]; } item; /* VARCHAR item[10]; /o item name o/ */ <BR> <BR> int qty; /* item quantity */<BR> /* SQL stmt &num 42 EXEC SQL END DECLARE SECTION; /* SQL stmt #43 EXEC SQL WHENEVER NOT FOUND GOTO noitem; EXEC SQL WHENEVER SQLERROR GOTO errexit; */ strcpy((char *)item.arr,itemname); item.len = strlen(itemname); qty = itemqty; /* SQL stmt 445 EXEC SQL UPDATE omq~stock SET QTY = :qty WHERE ITEM = :item; */ {<BR> <BR> <BR> struct sqlexd sqlstm={8,2}; sqlstm.stmt = "UPDATE OMQ~STOCK SET QTY=:bl WHERE ITEM=:b2"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )466; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlstm.sqhstv[0] = (unsigned char *)&qty sqlstm.sqhstl[0] = (unsigned int )4; sqlstm.sqindv[0] = ( short *)0; sqlstm.sqharm[0] = (unsigned int )0; sqlstm.sqhstv[1] = (unsigned char *)&item sqlstm.sqhstl[1] = (unsigned int )12; sqlstm.sqindv[1] = ( short *)0; sqlstm.sqharm[1] = (unsigned int )0; sqlstm.sqphsv = sqlstm.sqhstv; sqlstm.sqphsl = sqlstm.sqhstl; sqlstm.sqpind = sqlstm.sqindv; sqlstm.sqparm = sqlstm.sqharm; sqlstm.sqparc = sqlstm.sqharc; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode == 1403) goto noitem; if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #46 EXEC SQL COMMIT WORK; struct sqlexd sqlstm={8,0}; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )496; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #47 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ return(0); /* Here if item NOT found in dbs */ noitem: /* SQL stmt #49 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ return (2); /* Here if SQL Error */ errexit: /* SQL stmt #51 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ return (1); } /* ------------------------------------------------------------ -------------- ORACUSTR reads ORDERS & SALES from omq~cust table given customer name. returns 0 on succes, 1 on SQL error and 2 on noncustomer.

--------------------------------------------------------- ----------------- */ int oracustr (custname, custorders, custsales) char custname[10]; int *custorders, *custsales; /* SQL stmt 453 EXEC SQL BEGIN DECLARE SECTION; */ struct { unsigned short len; unsigned char arr[1O] } customer; /* VARCHAR customer[10]; /o cust name o/ */ int orders; /* cust #orders */ int sales; /* cust $sales */ /* SQL stmt #54 EXEC SQL END DECLARE SECTION; */ /* SQL stmt #55 EXEC SQL WHENEVER NOT FOUND GOTO noitem; EXEC SQL WHENEVER SQLERROR GOTO errexit; */ strcpy((char *)customer.arr,custname); customer.len = strlen(custname); /* SQL stmt &num 57 EXEC SQL SELECT ORDERS, SALES INTO :orders, :sales FROM omq~cust WHERE CUSTOMER = customer; struct sqlexd sqlstm=(8,3); sqlstm.stmt = "SELECT ORDERS,SALES INTO:bl,:b2 FROM OMQ~CUST WHERE CUSTOM\ ER=:b3"; sqlstm.icers = (unsigned int )1; sqlstm.offset = (unsigned int )518; sqlstm.selerr = (unsigned short)l; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlstm.sqhstv[0] = (unsigned char *)&customer sqlstm.sqhstl[0] = (unsigned int )12; sqlstm.sqindv[0] = ( short *)0; sqlstm.sqharm[0] = (unsigned int )0; sqlstm.sqhstv[1] = (unsigned char *)&orders sqlstm.s hstl[1] = (unsigned int )4; sqlstm.sqindv[1] = ( short *)0; sqlstm.sqharm[l] = (unsigned int )0; sqlstm.sahstv[2] = (unsigned char *)&sales sqlstm.sahstl[2] = (unsigned int )4; sqlstm.sqlndv[2] = ( short *)0; sqlstm.sqharm[2] = (unsigned int )0; sqlstm.sqphsv = sqlstm.sqhstv; sqlstm.sqphsl = sqlstm.sqhstl; sqlstm.sqpind = sqlstm.sqindv; sqlstm.sqparm = sqlstm.sqharm; sqlstm.sqparc = sqlstm.sqharc; sqlcex(salctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode == 1403) goto noitem; if (sqlca.sqlcode c 0) goto errexit; /* SQL stmt #58 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ *custorders @ orders@ *custsales = sales; return(0); /* Here if item NOT found in dbs */ noitem: /* SQL stmt #60 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ return(2); /* Here if SQL Error */ errexit: /* SQL stmt #62 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ return(1); } ORACUSTW updates ORDERS & SALES for a given CUSTOMER in the DB.

returns 0 on success, 1 on SQL error and 2 on noncustomer.

--------------------------------------------------------- ----------------- */ int oracustw(custname, custorders, custsales) char custname[l0]; int custorders, custsales; /* SQL stmt #64 EXEC SQL BEGIN DECLARE SECTION; */ struct { unsigned short len; unsigned char arr[10] } customer; /* VARCHAR customer[10]; /o cust name o/ */ int orders; /* cust #orders */ int sales; /* cust $sales<BR> <BR> /* SQL stmt &num 65 EXEC SQL END DECLARE SECTION; */ /* SQL stmt #66 EXEC SQL WHENEVER NOT FOUND GOTO noitem; EXEC SQL WHENEVER SQLERROR GOTO errexit; */ strcpy((char *)customer.arr,custname); customer.len = strlen(custname); orders = custorders; sales = custsales; /* SQL stmt #68 EXEC SQL UPDATE omq~cust SET ORDERS = :orders, SALES = :sales WHERE CUSTOMER = :customer; */ { struct sqlexd sqlstm={8,3}; sqlstm.stmt = "UPDATE OMQ~CUST SET ORDERS=:bl,SALES=:b2 WHERE CUSTOMER=:b\ 3"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )552; sqlstm.cud = sqloudO; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlstm.sqhstv[0] = (unsigned char *)&orders sqlstm.sqhstl[0] = (unsigned int )4; sqlstm.sqindv[0] = ( short *)0; sqlstm.sqharm[c] = (unsigned int )0; sqlstm.sqhstv[1] = (unsigned char *)&sales sqlstm.sqhstl[l] = (unsigned int )4; sqlstm.sqindv[l] = ( short *)0; sqlstm.sqharm[l] = (unsigned int )0; sqlstm.sqhstv[2] = (unsigned char *)&customer sqlstm.sqhstl[2] = (unsigned int )12; sqlstm.sqindv[2] = ( short *)0; sqlstm.sqharm[2] = (unsigned int )0; sqlstm.sqphsv = sqlstm.sqhstv; sqlstm.sqphsl = sqlstm.sqhstl; sqlstm.sqpind = sqlstm.sqindv; sqlstm.sqparm = sqlstm.sqharm; sqlstm.sqpare = sqlstm.sqharc; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode == 1403) goto noitem; if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #69 EXEC SQL COMMIT WORK; struct sqlexd sqlstm=8,0j; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )586; sqlstm.cud = sqlcudO; sqlstm.sqlest = (unsigned char *)&sqlca sqlstm.sqlety = (unsigned short)0; sqlcex(sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) goto errexit; /* SQL stmt #70 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ return(0); /* Here if item NOT found in dbs */ noitem: /* SQL stmt #72 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ return(2); /* Here if SQL Error */ errexit: /* SQL stmt #74 EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; */ return(1); } ** Copyright(C)1996 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ Demo ** Module: oraomq.h ** Author: Derek Schwenke 1/11/96 ** */ #ifdef CPP extern "C" 4endif 4ifdef ORACLE int orawrite ( char itemname[10],int itemqty); int oraread( char itemname[10],int *itemprice, int *itemqty); int oracustw( char custname[l0],int custorders, int custsales); int oracustr( char custname[10] ,int *custorders, int *custsales); int oradisc(); int oraconn( char orastring[80]); int oracreate(); int oraerrrpt(); &num else int orawrite( char itemname[l0],int itemqty) int oraread( char itemname[l0],int *itemprice, int *itemqty) int oracustw( char custname[l0],int custorders, int custsales) int oracustr( char custname[l0],int *custorders, int *custsales) int oradisc() int oraconn( char orastring[80]) int oracreate() int oraerrrpt() 4endif 4ifdef CPP 4endif ** Copyright(C)1996 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ Demo ** Module: oraomq.pc ** Author: Frederick J. Igo, Jr. 1/15/96 ** */ #include <stdlib.h> #include <stdio.h> #include <ctype.h> #include string.h> # include "sqlproto.h" # include "ociproto.h" # define ORACLE # include "oraomq.h" EXEC SQL INCLUDE SQLCA.H; /* #include <C:\ORANT\PRO16\C\sqlca.h> */ /* NAME oraomq FUNCTION Openmq Oracle Pro* C subroutines NOTES oraerrrpt(); -- Prints SQL Errors msgs & codes oraconn(...); -- CONNECTS to ORACLE using given oracle string.

oradisc(); -- DISCONNECTS from ORACLE oracreate(); -- Creates omqstock & omq~cust tables in ORACLE.

oraread(...); -- Given ITEM name, reads PRICE & QTY.

orawrite(. .); -- Given ITEM name & QTY, updates QTY IN db.

oracustr(...); -- -- Given CUSTOMER name, reads &num ORDERS & $SALES.

oracustw(. .); -- Given CUSTOMER name, #ORDERS & $SALES, updates db.

C:\ORANT\PRO16\C> nmake -f oraomq.mak */ /* ------------------------------------------------------------ ------------- ORAERRRPT prints the ORACLE error msg and number.

--------------------------------------------------------- ----------------- oraerrrpt () printf("k.70s (%d)\n", sqlca.sqlerrm.sqlerrmc, -sqlca.sqlcode); return(0); } ---------------------------------------- ORACONN connects to ORACLE as user DEMO.

Oracle String is provided by caller as: "SCOTT/TIGER@T:GRAMPA:ORCL".

returns 0 on success and 1 on SQL error.

--------------------------------------------------------- ----------------- */ oraconn(orastring) char orastring[80]; EXEC SQL BEGIN DECLARE SECTION; VARCHAR oracleid[80]; /* username/password@dbstring */ EXEC SQL END DECLARE SECTION; EXEC SQL WHENEVER SQLERROR GOTO errexit; strcpy((char *)oracleid.arr,orastring); oracleid.len = strlen((char *)oracleid.arr); EXEC SQL CONNECT :oracleid; return(0); /* Here if SQL Error */ errexit: EXEC SQL WHENEVER SQLERROR CONTINUE; return(1); } /* ------------------------------------------------------------ -------------- ORADISC disconnects from ORACLE.

returns 0 on success and 1 on SQL error.

--------------------------------------------------------- ----------------- */ oradisc() { EXEC SQL WHENEVER SQLERROR GOTO errexit; EXEC SQL COMMIT RELEASE; return(0); /* Here if SQL Error */ errexit: EXEC SQL WHENEVER SQLERROR CONTINUE; return(1); ORACREATE creates omq~stock & omq~cust tables in ORACLE as follows: omq~stock: ITEM PRICE QTY Bolts $1 10000 Buckets $2 10000 Buttons $3 10000 Belts $4 10000 Bobbins $5 10000 Boats $6 10000 omq cust: CUSTOMER ORDERS SALES Jacobs 0 0 Jackson 0 0 Jaffe 0 0 Johnson C 0 Jones C ° James C ° returns 0 on success and 1 on SQL error.

--------------------------------------------------------- ----------------- */ oracreate() { /* Expect an error if table already dropped */ EXEC SQL WHENEVER SQLERROR GOTO ignore; EXEC SQL DROP TABLE omq~stock; EXEC SQL DROP TABLE omq~cust; ignore: EXEC SQL WHENEVER SQLERROR GOTO errexit; EXEC SQL CREATE TABLE omq stock (item VARCHAR2(10) PRIMARY KEY, price NUMBER, qty NUMBER); EXEC SQL INSERT INTO omq~stock VALUES('Bolts',1,100O0); EXEC SQL INSERT INTO omq~stock VALUES('Buckets',2,10000); EXEC SQL INSERT INTO omq~stock VALUES('Buttons',3,10000); EXEC SQL INSERT INTO omq~stock VALUES('Belts',4,10000); EXEC SQL INSERT INTO omq~stock VALUES('Bobbins',5,10000); EXEC SQL INSERT INTO omq~stock VALUES('Boats',6,10000); EXEC SQL CREATE TABLE omq oust (customer VARCHAR2(10) PRIMARY KEY, orders NUMBER, sales NUMBER); EXEC SQL INSERT INTO omq~cust VALUES('Jacobs',0,0); EXEC SQL INSERT INTO omq~cust VALUES('Jackson', 0,0); EXEC SQL INSERT INTO omq~cust VALUES('Jaffe',0,O); EXEC SQL INSERT INTO omq~cust VALUES('Johnson',0,0); EXEC SQL INSERT INTO omq~cust VALUES('Jones',O,O); EXEC SQL INSERT INTO omq~cust VALUES('James',0,O); EXEC SQL COMMIT WORK; return(0); /* Here if SQL Error */ errexit: EXEC SQL WHENEVER SQLERROR CONTINUE; return(1); } /* ------------------------------------------------------------ ------------ ORAREAD reads QTY & PRICE from omq~stock table given ITEM.

returns 0 on sucess, 1 on SQL error and 2 on noitem. ------------------------------------------------------------ ------------ */ int oraread(itemname, itemprice, itemqty) char itemname[10]; int *itemprice, *itemqty; EXEC SQL BEGIN DECLARE SECTION; VARCHAR item[1O]; /* item name int prince; /* item price int qty; /* item quantity */ EXEC SQL END DECLARE SECTION; EXEC SQL WHENEVER NOT FOUND GOTO noitem; EXEC SQL WHENEVER SQLERROR GOTO errexit; strcpy((char *)item.arr,itemname); item.len = strlen (itemname) EXEC SQL SELECT PRICE, QTY INTO :price, :qty FROM omq~stock WHERE ITEM = : item; EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; *itemprice = price; *itemqty = qty; return(0); /* Here if item NOT found in dbs */ noitem: EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; return(2); /* Here if SQL Error */ errexit: EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; return(1); } /* ------------------------------------------------------------ ----------- ORAWRITE updates QTY for a given ITEM in the omq~stock table.

returns 0 on success, 1 on SQL error and 2 on noitem.

int orawrite(itemname, itemqty) char itemname[10]; int itemqty; EXEC SQL BEGIN DECLARE SECTION; VARCHAR item[10]; /* item name int qty; /* item quantity */ EXEC SQL END DECLARE SECTION; EXEC SQL WHENEVER NOT FOUND GOTO noitem; EXEC SQL WHENEVER SQLERROR GOTO errexit; strcpy((char *)item.arr,itemname); item.len = strlen(itemname); qty = itemqty; EXEC SQL UPDATE omq~stock SET QTY = :qty WHERE ITEM = : item; EXEC SQL COMMIT WORK; EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; return(0); /* Here if item NOT found in dbs */ noitem: EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; return (2); /* Here if SQL Error */ errexit: EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; return(1); } /* ------------------------------------------------------------ ----------- ORACUSTR reads ORDERS & SALES from omq~cust table given customer name.

returns 0 on success, 1 on SQL error and 2 on nocustomer.

--------------------------------------------------------- --------------- */ int oracustr(custname, custorders, custsales) char custname[10]; int *custorders, *custsales; EXEC SQL BEGIN DECLARE SECTION; VARCHAR customer[10]; /* cust name int orders; /* cust &num orders */ int sales; /* cust $sales */ EXEC SQL END DECLARE SECTION; EXEC SQL WHENEVER NOT FOUND GOTO noitem; EXEC SQL WHENEVER SQLERROR GOTO errexit; strcpy((char *)customer.arr,custname); customer.len = strlen(custname); EXEC SQL SELECT ORDERS, SALES INTO :orders, :sales FROM omq~cust WHERE CUSTOMER = : customer; EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; *custorders = orders; *custsales = sales; return(0); /* Here if item NOT found in dbs */ noitem: EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; return(2) /* Here if SQL Error */ errexit: EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; return(1); } /* ------------------------------------------------------------ ----------- ORACUSTW updates ORDERS & SALES for a given CUSTOMER in the DB.

returns 0 on success, 1 on SQL and 2 on noncustomer.

--------------------------------------------------------- -------------- */ int oracustw(custname, custorders, custsales) char custname[10]; int custorders, custsales; { EXEC SQL BEGIN DECLARE SECTION; VARCHAR customer[l0]; /* cust name int orders; /* cust &num orders */ int sales; /* cust $sales EXEC SQL END DECLARE SECTION; EXEC SQL WHENEVER NOT FOUND GOTO noitem; EXEC SQL WHENEVER SQLERROR GOTO errexit; strcpy((char *)customer.arr,custname); customer.len = strlen(custname); orders = custorders; sales = custsales; EXEC SQL UPDATE omq cust SET ORDERS = : orders, SALES = :sales WHERE CUSTOMER = : customer; EXEC SQL COMMIT WORK; EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; return(0); /* Here if item NOT found in dbs */ noitem: EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; return(2); /* Here if SQL Error */ errexit: EXEC SQL WHENEVER NOT FOUND STOP; EXEC SQL WHENEVER SQLERROR CONTINUE; return(l); /* File name & Package Name */ struct sqlcxp unsigned short fillen; char filnam[11]; static struct sqlcxp sqlfpn = 10, "oratest.pc" static consist unsigned long sqlctx = 822081478; static struct sqlexd unsigned long sqlvsn; unsigned long arrsiz; unsigned long iters; unsigned short offset; unsigned short selerr; unsigned short sqlety; unsigned short unused; short *cud; unsigned char *sqlest; char *stmt; unsigned char * *sqphsv; unsigned long *sqphsl; short * *sqpind; unsigned long *sqparm; unsigned long * *sqparc; unsigned char *sqhstv[1]; unsigned long sqhstl[1]; short *sqindv[l]; unsigned long sqharm[1]; unsigned long *sqharc[1]; } sqlstm = (8,1); extern sqlcx2(/*~ unsigned long , struct sqlexd *, struct sqlcxp * extern sqlcte(/*~ unsigned long , struct sqlexd *, struct sqlcxp * <BR> extern sqlbuf (/*~ char *<BR> <BR> extern sqlora(/*~ unsigned long *, void * static int IAPSUCC = 0; static int IAPFAIL = 1403; static int IAPFTL = 535; extern sqliem(); /* cud (compilation unit data) array */ static short sqlcudO[] = {8, 34,<BR> <BR> <BR> }; /* ** ** Copyright (C)1996 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ Demo ** Module: oratest.pc ** Author: Frederick J. Igo, Jr. 1/15/96 ** *include <stdlib.h> #include <stdio.h> #include ctype.h> *include <string.h> &num include "sqlproto.h" # include "ociproto.h" # define ORACLE #include"Oraomg.h" /* NAME openmq FUNCTION Simple openmq Pro*C sample program NOTES openmq is a simple example program which decrements the stock for ordered items. Checking is done for sufficient stock.

The program queries the user for data as follows: Enter customer name: Enter item name: Enter quantity ordered: The program terminates if null string (<return> key) is entered when the customer name is requested.

If the item qty is updated, the following is printed: "Order for QTY ITEM at PRICE has been placed" C:/ORANT\PRO 16\C> nmake -f openmq.mak OWNER Igo DATE 01/11/96 MODIFIED igo 01/11/96 - create from sample32.pc void main() <BR> <BR> char itemname[10]; /* item name<BR> int itemprice; /* item price int itemqty; /* item quantity */ char custname[10]; /* cust name int custorders; /* cust &num orders */ int custsales; /* cust $sales */ char orastring[80]; /* Oracle ID char orastrinp [8o]; /* Oracle ID */ /* ------------------------------------------------------------ ------------ logon to ORACLE,and open the cursors.

The program exits if any errors accur.

--------------------------------------------------------- ----------------- */ stropy((char *)orastring,"SCOTT/TIGER@T:GRAMPA:ORCL"); if (asks("\nAlter connect string? (null keeps ps SCOOT/TIGER@:ORACLE:ORCL) (char *)orastrinp) > 0 strcpy((char *)orastring,(char *)orastrinp); <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> printf("\nConnecting to Oracle using string 5. .",orastring);<BR> <BR> if (oraconn(orastring) == 1) oraerrrpt(); printf("SQL Error on CONNECT, Bye-bye."); return; printf("connected.\n"); /* Create/Fill DB */ if ( asks("\nShall we create/clear the DB (non-null to create)?", (char *)custname) > 0 print("Creating omq~stok and omq~cust tables in Oracle...\n")<BR> <BR> if (oracreate() == 1) oraerrrpt () printf("SQL Error on CREATE, Bye-bye."); return } } /*---------------------------------------------------------- ----------- Read the user'sinput from STDIN. If the item name is not entered,exit.

Veryfy that the entered quantity is lessthan that item's stock.

--------------------------------------------------------- ----------------*/ for(; ;) { int l,tot,qtyo; /* Get customer name 1 = asks("\nEnter customer name (null to quit): ", (char *)custname); if ( 1 <= C break; <BR> <BR> <BR> <BR> <BR> printf(" Checking Customer ks in DB... ",custname);<BR> switch (oracustr(custname,&custordes,&custsales)) { case 1: oraerrrpt () printf("SQL Error on Customer DB Read, try again.\n"); continue; case 2: printf("No such customer, try again.\n"); continue; /* Get item name to be ordered */ asks("\nEnter item name : ", (char *)itemname); /* Read DB with given item name to get qty and price */ printf(" Cheching item in DB..."); switch (oraread(itemname,&itemprice,&itemqty)) <BR> case 1: oraerrrpt(); printf("SQL Error on Customer DB Read, try again.\n"); continue; } case 2: printf("No such item, try again.\n"); continue; askn("\nEnter quantity ordered: ",&qtyo); printf(" Checking stock for %d 5. ",qtyo,itemname); if (qtyo > itemqty) printf("Insuficient stock: %d.\n"itemqty); continue; /* Here if item was found in dbs and quantity suffucient. */ itemqty -= qtyo; tot = qtyo * itemprice; /* Update DB for given item name printf("Updating % QTY in Stock DB.\n",itemname); <BR> switch (orawrite(itemname,itemqty)) case 0: printf("\nOrder for %d 5 at $';d each placed, qtyo,itemname,itemprice); printf("Sale is $%d %s remain\", tot,itemqty,itemname); break; case 1: oraerrrpt(); printf("SQL Error during DB update, order not placed.\n"); break; case 2: /* Shouldn't get this case, since read found item */ printf("No such item on write, please start over...\n"); break; /* Update Cust DB */ custorders += 1; custsales += tot; switch (oracustw (custname, custorders, custsales)) case 0: prints has placed %d orders for $%d.\n", custname,custorders,custsales); break; case 1: oraerrrpt(); printf("SQL Error during cust DB update.\n"); break; case 2: /* Shouldn't get this case, since read found item */ printf("No such customer on write, please start over\n"); break; printf("\n=============================\n"); printf("ITEM PRICE QTY\n"); strcpy((char *)itemname,"Bolts"); oraread(itemname,&itemprice,&itemqty); printf("Bolts $%d %d\n",itemprice,itemqty); strcpy((char *)itemname,"Buckets"); oraread(itemname,&itemprice,&itemqty); %printf("Buckets $%d %d\n",itemprice,itemqty); strcpy((char *)itemname, "Buttons"); oraread(itemname,&itemprice,&itemqty); printf("Buttons $%d %d\n",itemprice,itemqty); strcpy((char *)itemname,"Belts"); oraread(itemname,&itemprice,&itemqty); printf("Belts $%d %d\n",itemprice,itemqty); strcpy((char *)itemname,"Bobbins"); oraread(itemname,&itemprice,&itemqty); printf("Bobbins $%d %d\n",itemprice,itemqty); strcpy((char *)itemname,"Boats"); oraread(itemname,&itemprice,&itemqty); printf("Boats $%d %d\n",itemprice,itemqty); printf("=============================\n"); printf("CUSTOMER ORDERS SALES\n"); strcpy((char *)custname,"Jacobs"); oracustr(custname,&custorders,&custsales) printf("Jacobs d $Wd\n",custorders,custsales); strcpy((char *)custname,"Jackson"); oracustr(custname,&custorders,&custsales); printf("Jackson %d $Wd\n",custorders,custsales); strcpy((char *)custname,"Jones"); oracustr(custname,&custorders,&custsales); printf("Jones %d $%d\n", custorders,custsales); strcpy((char *)custname,"Jones"); oracustr(custname,&custorders,&custsales); printf("Johnson %d $Wd\n',custorders,custsales); strcpy((char *)custname,"Jaffe"); oracustr(custname,&custorders,&custsales); printf("Jaffe %d $Wd\n",custorders,custsales); strcpy((char *)custname,"James"); oracustr(custname,&custorders,&custsales); printf("James %d $%d\", custorders,custsales); } /* ------------------------------------------------------------ -------------- close the cursors and log off from ORACLE ------------------------------------------------------------ -------------- */ printf ("\nDisconnecting from Oracle.\n"); oradisc(); printf ("\nEnd of OpenMQ/Pro*C example.\n"); return; } /* ------------------------------------------------------------ ----------------- COUNT askn(text,variable) print the 'text' on STDOUT and read an integer variable from SDTIN.

text points to the null terminated string to be printed variable points to an integer variable askn returns a 1 if the variable was read successfully or a -1 if -eof- was encountered int askn(text,variable) char text[]; int *variable; char s[20]; printf(text); fflush(stdout); if ( gets(s) == (char *) 0) return(EOF); *variable = atoi(s); return (1); } /* ------------------------------------------------------------ -------------- COUNT asks(text,variable) print the 'text' on STDOUT and read up to 'len' characters into the buffer pointed to by variable from STDIN.

text points to the null terminated string to be printed variable points to a buffer of at least 'len'+l characters asks returns the number of character read into the string, or a -1 if -eof- was encountered ------------------------------------------------------------ ----------- */ int asks(text,variable) char text[],variable[]; { printf(text); fflush(stdout); return( gets(variable) == (char *)O ? EOF : strlen(variable) ); ** Copyright(C)1996 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ Demo ** Module: oratest.pc ** Author: Frederick J. Igo, Jr. 1/15/96 ** */ #include >stdlib.h> #include stdio.hz *include ctype.hz #include string.ho # include "sqlproto.h" # include "ociproto.h" # define ORACLE # include "oraomq.h" /* NAME openmq FUNCTION Simple openmq Pro* C sample program NOTES openmq is a simple example program which decrements the stock for ordered items. Checking is done for sufficient stock.

The program queries the user for data as follows: Enter customer name: Enter item name: Enter quantity ordered: The program terminates if null string (<return> key) is entered when the customer name is requested.

If the item qty is updated, the following is printed: "Order for QTY ITEM at PRICE has been placed" C:\ORANT\PRO16\C> nmake -f openmq.mak OWNER Igo DATE 01/11/96 MODIFIED igo 01/11/96 - create from sample32.pc */ void main() <BR> <BR> {<BR> <BR> char itemname[10]; /* item name int itemprice; /* item price int itemqty; /* item quantity */ char custname[10]; /* cust name int custorders; /* cust &num orders */ int custsales; /* cust $sales */ char orastring[80]; /* Oracle ID char orastrinp [80]; /* Oracle ID */ /* ------------------------------------------------------------ -------------- logon to ORACLE, and open the cursors.

The program exits if any errors occur.

--------------------------------------------------------- ----------------- */ strcpy((char *)orastring,"SCOTT/TIGER@T:GRAMPA:ORCL"); if (asks("\nAlter connect string? (null keeps SCOTT/TIGER@T:ORACLE:ORCL) (char *)orastrinp) > 0 strcpy((char *)orastring,(char *)orastrinp); <BR> <BR> <BR> <BR> <BR> <BR> <BR> printf("\nConnecting to Oracle using string Ws. .",orastring);<BR> <BR> if (oraconn(orastring) == 1) oraerrrpt(); printf("SQL Error on CONNECT, Bye-bye."); return; printf("connected.\n"); /* Create/Fill DH */ if ( asks("\nShall we create/clear the DB (non-null to create)?", (char *)custname) > 0 printf("Creating omq stock and omq~cust tables in Oracle...\n"); <BR> <BR> if (oracreate() == 1) oraerrrpt(); printf("SQL Error on CREATE, Bye-bye."); return; } /* ------------------------------------------------------------ -------------- Read the user's input from STDIN: If then item name is not entered, exit.

Verify that the entered quantity is lessthan that item's stock.

--------------------------------------------------------- ----------------- */ for ( ; ; ) { int l,tot,qtyo; /* Get customer name 1 = asks("\nEnter customer name (null to quit): ", (char *)custname); if (1 # 0) break; printf(" Checking Customer ts in DB... ", custname); switch (oracustr (custname,&custorders,&custsales)) case 1: oraerrrpt(); printf("SQL Error on Customer DB Read, try again.\n"); continue; case 2: printf("No such customer, try again.\n"); continue; /* Get item name to be ordered */ asks("\nEnter item name : ", (char *)itemname); /* Read DB with given item name to get qty and price */ printf(" Checking item in DB. "); switch (oraread(itemname,&itemprice,&itemqty)) case 1: oraerrrpt(); printf("SQL Error on Customer DB Read, try again.\n"); continue; case 2: printf("No such item, try again.\n"); continue; askn("\nEnter quantity ordered: ",&qtyo); printf(" Checking stock for %d %s... ",qtyo,itemname); if (qtyo > itemqty) printf("Insufficient stock: %d. \n",itemqty); continue; /* Here if item was found in dbs and quantity suffucient. */ itemqty -= qtyo; tot = qtyo * itemprice; /* Update DB for given item name printf("Updating %s QTY in Stock DB.\n",itemname); switch (orawrite(itemname,itemqty)) { case 0: printf("\nOrder for %d is at $%d each placed, qtyo,itemname,itemprice); printf("Sale is $%d, %d %s remain. \n", tot,itemqty,itemname); break; case 1: oraerrrpt (); printf("SQL Error during DB update, order not placed.\n"); break; case 2: /* Shouldn't get this case, since read found item */ printf("No such item on write, please start over...\n"); break; /* Update Cust DB */ custorders += 1; custsales += tot; switch (oracustw(custname,custorders,custsales) case 0: printf("%s has placed %d orders for $%d.\n", custname,custorders,custsales); break; case 1: oraerrrpt(); printf("SQL Error during cust DB update.\n"); break; case 2: /* Shouldn't get this case, since read found item */ printf("No such customer on write, please start over\n"); break; printf("\n=============================\ printf("ITEM PRICE QTY\n"); strcpy((char *)itemname,"Bolts"); oraread(itemname,&itemprice,&itemqty); printf("Bolts $%d %d\n", itemprice,itemqty); strcpy((char *)itemname,"Buckets"); oraread(itemname,&itemprice,&itemqty); printf("Buckets $%d %d\n", itemprice,itemqty); strcpy((char *)itemname,"Buttons"); oraread(itemname,&itemprice,&itemqty); printf("Buttons $%d %d\n", itemprice,itemqty); strcpy((char *)itemname, "Belts"); oraread(itemname,&itemprice,&itemqty); printf("Belts $%d %d\n", itemprice,itemqty); strcpy((char *)itemname,"Bobbins"); oraread(itemname,&itemprice,&itemqty); printf("Bobbins $%d %d\n", itemprice,itemqty); strcpy((char *)itemname,"Boats"); oraread(itemname,&itemprice,&itemqty); %printf("Boats $%d %d\n", itemprice,itemqty); printf("=============================\n"); printf ("CUSTOMER ORDERS SALES\n"); strcpy((char *) custname,"Jacobs"); oracustr (custname,&custorders,&custsales); printf("Jacobs %d $%d\n", custorders,custsales); strcpy((char *) custname,"Jackson"); oracustr (custname,&custorders,&custsales); printf("Jackson %d $%d\n", custorders,custsales); strcpy((char *)custname,"Jones"); oracustr(custname,&custorders,&custsales printf("Jones %d $%d\n",custorders,custsales); strcpy((char *)custname,"Johnson"); oracustr (custname,&custorders,&custsales); printf("Johnson %d $%d\n", custorders,custsales); strcpy((char *)custname,"Jaffe"); oracustr (custname,&custorders,&custsales); printf("Jaffe %d $%d\n", custorders,custsales); strcpy((char *) custname,"James"); oracustr (custname,&custorders,&custsales); printf("James %d $%d\n", custorders,custsales); } ------------------------------------------------------------ -------------- close the cursors and log off from ORACLE ------------------------------------------------------------ -------------- */ printf ("\nDisconnecting from ORACLE.\n"); oradisc (); printf ("\nEnd of OpenMQ/Pro*C example.\n"); return; /*---------------------------------------------------------- ---------------- COUNT askn(text,variable) print the 'text' on STDOUT and read an integer variable from SDTIN.

text points to the null terminated string to be printed variable points to an integer variable askn returns a 1 if the variable was read successfully or a -1 if -eof- was encountered int askn(text,variable) char text[]; int *variable; char s[20]; printf(text); fflush(stdout); if ( gets(s) == (char *)O ) return(EOF); *variable = atoi(s); return (1); } /* ------------------------------------------------------------ -------------- COUNT asks(text,variable) print the 'text' on STDOUT and read up to 'len' characters into the buffer pointed to by variable from STDIN.

text points to the null terminated string to be printed variable points to a buffer of at least 'len+1 characters asks returns the number of character read into the string, or a -1 if -eof- was encountered ------------------------------------------------------------ -------------- */ int asks (text,variable) char text [], variable []; { printf(text); fflush(stdout); return( gets(variable) = (char *)0 ? EOF : strlen(variable) User: root Host: bunny Class: bunny Job: stdin SETUP: Install SQL*Net TCP\IP Client 1.1.6.8 on client.

Install Pro*C 1.6.4.0.1.

For execution you only need C:\ORANT\PRO16\LIB\SQLNT16.DLL.

I've saved a copy here for execution of oratest, if Pro*C is not installed.

For building a .pc file, you need Pro*C installed.

Add "C:\ORANT\BIN" to system Path variable to pickup Oracle DLLs.

(A copy of MSVCR40.DLL is saved here for execution of oratest.exe, if MSVC 4.0 is not installed.) NOTES: ORATEST currently uses oracleid SCOTT/TIGER@T:GRAMPA:ORCL, but this can be altered when prompted for a connect string.

ORATEST can be used to verify the install on SQL*NET.

ORATEST can create the omq~stock and omq~cust tables in Oracle.

ORATEST can be used to view the omq~stock and omq~cust tables.

** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: putu.cpp ** Author: Derek Schwenke 9/8/95 */ // putu.cpp : Defines the class behaviors for the application.

// *include "stdafx.h" *include "putu.h" *include "putudlg.h" 4ifdef DEBUG *undef THIS FILE static char BASED~CODE THIS~FILE[] = FILE #endif //////////////////////////////////// // CPutuApp BEGIN~MESSAGE~MAP(CPutuApp, CWinApp) //((AFX MSG MAP(CPutuApp) // NOTE - the ClassWizard will add and remove mapping macros her // DO NOT EDIT what you see in these blocks of generated code //)}AFX MSG ON COMMAND(ID HELP, CWinApp::OnHelp) END~MESSAGE~MAP() //////////////////////// // CPutuApp construction CPutuApp::CPutuApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance /////////////////////////////////// // The one and only CPutuApp object CPutuApp theApp; /////////////////////////////////// // CPutuApp initialization BOOL CPutuApp::InitInstance() { // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need.

Enable3dControls(); LoadStdProfileSettings(); // Load standard INI file options (including CPutuDlg dlg; m~pMainWnd = &dlg int nResponse = dlg.DoModal(); if (nResponse == IDOK) // TODO: Place code here to handle when the dialog is // dismissed with OK else if (nResponse == IDCANCEL) // TODO: Place code here to handle when the dialog is // dismissed with Cancel // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump.

return FALSE; // putu.h : main header file for the PUTU application if#ndef ~AFXWIN~H~ #error include 'stdafx.h' before including this file for PCH *endif #include "resource.h" // main symbols //////////////////////////////////////////////////// // CPutuApp: // See putu.cpp for the implementation of this class // class CPutuApp public CWinApp public: CPutuApp(); // Overrides // ClassWizard generated virtual function overrides //({AFX~VIRTUAL(CPutuApp) public: virtual BOOL InitInstance(); //))AFX~VIRTUAL //virtual void printer( char *mess // Implementation <BR> <BR> <BR> //{{AFX~MSG(CPutuApp)<BR> // NOTE - the ClassWizard will add and remove member function.

// DO NOT EDIT what you. see in these blocks of generated code //))AFX~MSG DECLARE MESSAGE MAP() // putudlg.cpp . implementation file #include "stdafx.h" #include "putu.h" #include "putudlg.h" #include "putuqopt.h" #include "putumopt.h" #include "qlib.h" //#include <windowsx.h> // ListBox~AddString //extern lpRT RTroot; ///////////////////////////// lpQHANDLE Q; extern lpSMBUFH sm~base; ///////////////////////////// 4ifdef DEBUG 4undef THIS FILE static char BASED~CODE THIS~FILE[] = ~FILE~ 4endif //////////////////////////////////////////////////////////// ///////////////// // CAboutDlg dialog used for App About class CAboutDlg public CDialog public: CAboutDlg(); // Dialog Data //{{AFX~DATA(CAboutDlg)<BR> <BR> enum ( IDD = IDD~ABOUTBOX ); //))AFX~DATA // Implementation protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV suppo, // ( (AFX~MSG (CAboutDlg) virtual BOOL OnInitDialog(); //}}AFX~MSG DECLARE MESSAGE MAP() CAboutDlg: :CAboutDlg () . CDialog(CAboutDlg::IDD) //{{AFX~DATA~INIT(CAboutDlg) //}}AFX~DATA~INIT void CAboutDlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //((AFX DATA MAP(CAboutDlg) //}}AFX~DATA~MAP BEGIN MESSAGE~MAP(CAboutD1g, CDialog) //((AFX~MSG~MAP(CAboutDlg) // No message handlers //))AFX~MSG~MAP END~MESSAGE~MAP() ////////////////////////////// // CAboutDlg message handlers BOOL CAboutDlg::OnInitDialog() { CDialog::OnInitDialog(); CenterWindow(); // TODO: Add extra about dlg initialization here return TRUE; // return TRUE unless you set the focus to a control ///////////////////////////////////////// // CPutulDlg dialog CPutuDlg::CPutuDlg(CWnd* pParent /*=NULL*/) CDialog(CPutuDlg::IDD, pParent) //{{AFX~DATA~INIT(CPutuDlg) m-qnames = ~T(""); m~message = T T(""); mqstatus = T ~T(""); m mstatus = T ~T(""); //}}AFX~DATA~INIT // Note that LoadIcon does not require a subsequent Destroy Icon in Wi@@@ <BR> <BR> <BR> m~hIcon = AfxGetApp()->LoadIcon(IDR~MAINFRAME); void CPutuDlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(CPutuDlg) DDX~CBString(pDX, IDC~QNAMES, m~qnames); DDX~Text(pDX, IDC~MESS, m~message); DDX~Text(pDX, IDC~QSTATUS, m~qstatus); DDX Text(pDX, IDC~MSTATUS, m~mstatus); //}}AFX~DATA~MAP } BEGIN~MESSAGE~MAP(CPutuDlg, CDialog) //{{AFX~MSG~MAP(CPutuDlg) ON~WM~SYSCOMMAND() ON~WM~PAINT() ON~WM~QUERYDRAGICON() ON~BN~CLICKED(IDC~BUT~Q~OPEN, OnButQOpen) ON-BNCLICKED(IDC BUT QCLOSE, OnButQclose) ONBNCLICKED(IDC-BUT-SEND, OnButSend) ON~BN~CLIKED(IDC~BUT~QOPTS, OnButQopts) ON~BN~CLIKED(IDC~BUT~MOPTS, OnButMopts) //}}AFX~MSG~MAP AGE~MAP() END~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// // CPutuDlg message handlers BOOL CPutuDlg::OnInitDialog() CDialog::OnInitDialog(); CenterWindow(); // Add "About..." menu item to system menu.

// IDM~ABOUTBOX must be in the system command range.

ASSERT((IDM ABOUTBOX & OxFFFO) == IDM~ABOUTBOX); ASSERT(IDM~ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); String strAboutMenu; strAboutMenu.LoadString(IDS~ABOUTBOX); if (!strAboutMenu.IsEmpty()) pSysMenu->AppendMenu(MF~SEPARATOR); pSysMenu->AppendMenu(MF~STRING, IDM~ABOUTBOX, strAboutMenu); // Set printing window for "C" code CWnd* pLogWin = this->GetDlgItem(IDC~PRINTER); SetWinPtr(pLogWin->m~hWnd); /////////////////////////////////////////////// ////////////// QUE PULL DOWN ////////////////// /////////////////////////////////////////////// CComboBox * CB = (CComboBox *) this->GetDlgItem(IDC~QNAMES); //CB->AddString("INITAL1"); lpRT rtp = GetRTroot(); while (rtp) char *e,*s = rtp->apps // Starts after the first letter while (e = strchr(s,',')) ( // Ends at next *e = 0; if (!strchr(s,'[')) CB->AddString(s); *e = ','; s = e + 1; rtp = rtp->next return TRUE; // return TRUE unless you set the focus to a control void CPutuDlg::OnSysCommand(UINT nID, LPARAM lparam) if ((nID & OxFFFO) == IDM~ABOUTBOX) CAboutDlg dlgAbout; dlgAbout.DoModal(); else CDialog::OnSysCommand(nID, lParam); // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework.

void CPutuDlg::OnPaint() if (IsIconic()) CPaintDC dc(this); // device context for painting SendMessage(WM ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM~CXICON); int cyIcon = GetSystemMetrics(SM~CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m~hIcon); else CDialog::OnPaint(); // The system calls this to obtain the cursor to display while the user drags // the minimized window.

HCURSOR CPutuDlg::OnQueryDragIcon() return (HCURSOR) m hIcon; void CPutuDlg::OnButQOpen() int status; char qname[100],line[100]; SetDlgItemText(IDC~QSTATUS,"Opening..."); GetDlgItemText(IDC~QNAMES,qname,100); ReadParms(); if (!(Q = Qopen(qname,PUTTING,0,0,0,0,0))) sprintf(line,"FAILED to open %s",qname); else sprintf(line,OPENED ts"/qname); SetDlgItemText(IDC~QSTATUS,line); void CPutuDlg::OnButQclose() SetDlgItemText(IDC~QSTATUS,CLOSED"); void CPutuDlg: :OnButSend() char got[100], line[100]; <BR> <BR> <BR> <BR> <BR> GetDlgItemText(IDC~MESS,got,90); <BR> sprintf(line,"Sending:ts",got); // C++ does this better?<BR> <BR> <BR> SetDlgItemText(IDC~MSTATUS,line); SetDlgItemText(IDC~MESS,""); // Blank out the message // How do I force these to print out here? // PeekMessage // AddItem(); if (QSUCCESS != Qput(Q,0,O, 0,sizeof(got),got)) sprintf(line,"FAILED to send:%s",got); else sprintf(line,"Sent:ts",got); SetDlgItemText(IDC~MSTATUS,line); } /* void CPutuDlg::printer(char *mess) { // CEdit::SetWindowText CEdit * CE = (CEdit *) this->GetDlgltem(IDC PRINTER); //CEdit * CE = (CEdit *) GetDlgItem(IDC-PRINTER) //CE->GetWindowText("); CE->SetWindowText("NEW TEXT 1 \n SECOND LINE \n"); void printer(char *mess) SetDlgItemText(IDC~MESS,mess); /* void CPutuDlg::OnButQopts() { CPutuQOpts qopt; TRACE("AT QOPTS BUTTON"); int nResponse = qopt.DoModal(); if (nResponse == IDOK) // TODO: Place code here to handle when the dialog is // dismissed with OK else if (nResponse == IDCANCEL) // TODO: Place code here to handle when the dialog is // dismissed with Cancel void CPutuDlg::OnButMopts() // TODO: Add your control notification handler code here TRACE("AT MOPTS BUTTON"); CPutuMOpts mopt; int nResponse = mopt.DoModal(); if (nResponse == IDOK) // TODO: Place code here to handle when the dialog is // dismissed with OK else if (nResponse == IDCANCEL) // TODO: Place code here to handle when the dialog is // dismissed with Cancel // putudlg.h : header file //////////////////////////////////////// // CPutuDlg dialog class CPutuDlg : public CDialog { // Construction public: CPutuDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX~DATA(CPutuDlg) enum ( IDD = IDD~PUTU~DIALOG ); CString m~qnames; CString m~message; String m~qstatus; Stringm~mstatus; //}}AFX~DATA // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(CPutuDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV suppo //}}AFX~VIRTUAL // void printer( char *mess ) ; // This worked // Implementation protected: HICON m~hIcon; // Generated message map functions //{{AFX MSG(CPutuDlg) virtual BOOL OnInitDialog(); afx~msg vod OnSysCommand(UINT nID, LPARAM lParam); afx~msg void OnPaint(); afx~msg HCURSOR OnQueryDragIcon(); ~afx~msg void OnButQOpen(); afxmsg void OnButQclose();<BR> <BR> <BR> afx~msg void OnButSend();<BR> <BR> <BR> afxmsg void OnButQopts();<BR> <BR> <BR> <BR> <BR> afx msg void OnButMopts();<BR> //}}AFX~MSG DECLARE~MESSAGE~MAP() }; ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: putumopt.c ** Author: Derek Schwenke 9/8/95 */ // putumopt.cpp : implementation file // #include "stdafx.h" 4include "putu.h" #include "putumopt.h" 4ifdef DEBUG 4undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE~ *endif /////////////////////////////////////////////// // CPutuMOpts dialog CPutuMOpts::CputuMOpts(CWnd* pParent /*=NULL*/) I CDialog(CPutuMOpts::IDD, pParent) <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> //((AFX~DATA~INIT(CPutuMOpts) <BR> // NOTE: the ClassWizard will add member initialization here //})AFX~DATA~INIT void CPutuMOpts::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //IIAFX~DATAMAP(CPutuM0pts) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN MESSAGE MAP(CPutuMOpts, CDialog) //{{AFX~MSG~MAP(CPutuMOpts)<BR> // NOTE: the ClassWizard will add message map macros here //}}AFX~MSG~MAP END~MESSAGE~MAP() // CPutuMOpts message handlers // putumopt.h header file //////////////////////////////////////// // CPutuMOpts dialog class CPutuMOpts . public CDialog // Construction <BR> <BR> public:<BR> CPutuMOpts(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX~DATA(CPutuMOpts) enum { IDD = IDD~MESS~OPTS }; // NOTE: the ClassWizard will add data members here //))AFX~DATA // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(CPutuMOpts) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //))AFX~VIRTUAL // Implementation protected: // Generated message map functions //{AFX~MSG(CPutuMOpts)<BR> // NOTE: the ClassWizard will add member functions here //}}AFX MSG DECLARE MESSAGE MAP() ** Copyright(C)1995 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ ** Module: putuqopt.c * Author: Derek Schwenke 9/8/95 */ // putuqopt.cpp . implementation file // #include "stdafx.h" 4include "putu.h" #include "putuqopt.h" *ifdef DEBUG *undef THIS FILE static char BASED~CODE THIS~FILE[] = FILE *endif //////////////////////////////////////////////////////////// ///////////////// // CPutuQOpts dialog CPutuQOpts::CPutuQOpts(CWnd* pParent /*=NULL*/) CDialog(CPutuQOpts::IDD, pParent) //{(AFX~DATA~INIT(CPutuQOpts) m~log~sw = FALSE; m~trace~sw = FALSE; m tran sw = FALSE; //}}AFX~DATA~INIT } void CPutuQOpts::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //(AFX DATA MAP(CPutuQOpts) DDX~Check(pDX, IDC~LOG~SW, m~log~sw); DDX~Check(pDX, IDC~TRACE~SW, m~trace~sw); DDX Check(pDX, IDC~TRAN~SW, m~tran~sw); //}}APX~DATA~MAP BEGIN MESSAGE~MAP(CPutuQOpts, CDialog) - //(IAFX MSG MAP(CPutuQOpts) // NOTE: the ClassWizard will add message map macros here //})AFX MSG MAP END MESSAGE MAP() //////////////////////////////////////////////////////////// ///////////////// // CPutuQOpts message handlers // putuqopt.h header file //////////////////////////////////////// // CPutuQOpts dialog class CPutQOpts : public CDialog { // Construction public: CPutuQOpts(CWnd* pParent = NULL); // standard constructor // Dialog Data //((AFX~DATA(CPutuQOpts) enum ( IDD = IDD~OPEN~OPTS } BOOL m~log~sw; BOOL m~trace~sw; BOOL m~tran~sw; //}}AFX~DATA // Overrides // ClassWizard generated virtual function overrides //((AFX~VIRTUAL(CPutuQOpts) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL // Implementation protected: // Generated message map functions //((AFX~MSG(CPutuQOpts) // NOTE: the ClassWizard will add member functions here //}}AFX~MSG DECLARE~MESSAGE~MAP() //( (NO~DEPENDENCIES)) // Microsoft Visual C++ generated include file.

// Used by putu.rc &num define IDM~ABOUTBOX 0x0010 #define IDD~ABOUTBOX 100 #define IDD~ABOUTBOX 101 #define IDD~PUTU~DIALOG 102 #define iDC~PRINTER 104 #define IDR~MAINFRAME 128 #define IDD~OPEN~OPTS 130 #define IDD~MESS~OPTS 131 #define IDC~QNAMES 1000 #define IDC~MESS 1004 #define IDC~BUT~Q~OPEN 1005 #define IDC~BUT~SEND 1006 #define IDC~BUT~QCLOSE 1007 #define IDC~BUT~QCLOSE 1007 #define IDC~QSTATUS 1008 #define IDC~MSTATUS 1009 #define IDC~BUT~QOPTS 1010 #define IDC~BUT~MOPTS 1011 #define IDC~LOG~SW 1018 #dfine IDC~TRACE~SW 1019 #define IDC~TRAN~SW2 1021 #define IDC~TRAN~SW3 1022 // Next default values for new objects *ifdef APSTUDIO INVOKED *ifndef APSTUDIO~READONLY SYMBOLS #define ~APS~NEXT~RESOURCE~VALUE 132 #define ~APS~NEXT~COMMAND~VALUE 32771 #define ~APS~NEXT~CONTROL~VALUE 1019 #define ~APS~NEXT~SYMED~VALUE 101 *endif *endif ** Copyright(C)1996 MITSUBISHI ELECTRIC ITA. ALL RIGHTS RESERVED.

** UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT ** LAWS OF THE UNITED STATES. USE OF A COPYRIGHT NOTICE ** IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION ** OR DISCLOSURE.

** ** THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND ** TRADE SECRETS OF MITSUBISHI ELECTRIC ITA. USE, DISCLOSURE, ** OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR ** EXPRESS WRITTEN PERMISSION OF MITSUBISHI ELECTRIC ITA.

** ** OpenMQ Demo ** Module: oraomq.h ** Author: Derek Schwenke 1/11/96 ** */ #ifdef CPP extern "C" *endif 4ifdef ORACLE int orawrite( char itemname[10],int itemqty); int oraread( char itemname[10],int *itemprice, int *itemqty); int oracustw( char custname[10],int custorders, int custsales) int oracustr( char custname[10] ,int *custorders, int *custsales); int oradisc(); int oraconn( char orastring[80]); int oracreate(); int oraerrrpt(); &num else int orawrite ( char itemname[10],int itemqty) int oraread( char itemname[10],int *itemprice, int *itemqtly) int oracustw( char custname[10],int custorders, int custsales) int oracustr( char custname[10],int *custorders, int *custsales) int oradisc() int oraconn( char orastring[80]) int oracreate() int oraerrrpt() *endif 4ifdef CPP *endif // Demo app's order form typedef struct oform I // Thread parameters char cust[10]; char item[10]; int qty; int color; int reply to; }OFORM, *pOFORM, *1pOFORM; // dbdlg.cpp implementation file *include "stdafx.h" //#include "oentrvw.h" *include "oentry.h" *include "dbdlg.h" #include "Odlg.h" // #define ORACLE causes oraread() orawrite() to be exteraly defined 4ifndef ORACLE #define ORACLE *endif *include "oraomq.h" 4ifdef DEBUG *undef THIS FILE static char BASED CODE THIS~FILE[] = ~FILE~ *endif #define DB~TIMER 200 #define INIT~TIMER 10 #define RESTOCK~QTY 10000 int g~orders~mode = 0; // Display orders or items extern CString g~item[]; extern CString g~cust[]; extern int g~price[6]; extern int g~qty[6]; int g~qty~old[6]i extern int g~purchases[6]; int g~purchases~old[6]; extern int g~num~purchases[6]; int g~num~purchases~old[6]; extern int g~total~sales; int g~total~sales~old; extern int g~db~run; extern int g~ora~state; int g~ora~state~old = -1; extern CFont g~title~font; extern CFont g~text~font; enum dbIDC {qty~IDC,price~IDC,item~IDC}; int ALL~TEXT~DB[] = (IDC~ORDERS~ITEMS,IDC~DB~REFILL,IDC~DB~BOX,IDOK, IDC~DB~SALEST,IDC~DB~SALES, IDC~T11,IDC~T12,IDC~T13, IDC~T21,IDC~T22,IDC~T23, IDC~DB~Q0,IDC~DB~Q1,IDC~DB~Q2,IDC~DB~Q3,IDC~DB~Q4,IDC~DB~Q5 IDC~DB P0,IDC~DB~P1,IDC~DB~P2 IDC~DB~P3 IDC~DB~P4,IDC~DB \ IDC~DB~I0,IDC~DB~I1,IDC~DB~I2,IDC~DB~I3,IDC~DB~I4,IDC~DB~ int g~IDCt[2] [3] ={{IDC~T11,IDC~T12,IDC~T13}, {IDC~T21,IDC~T22,IDC~T23}}; int g~IDCs[3] [6] = {{IDC~DB~Q0,IDC~DB~Q1,IDC~DB~Q2,IDC~DB~Q3,IDC~DB~Q4,IDC~DB~Q <BR> <BR> <BR> {IDC~DB~P0,IDC~DB~P1,IDC~DB~P2,IDC~DB~P3,IDC~DB~P4,IDC~DB~P5 <BR> {IDC~DB~I0,IDC~DB~I1,IDC~DB~I2,IDC~DB~I3,IDC~DB~I4,IDC~DB~I5 <BR> String gitem tites[] = {"Qty","Price","Item"}; <BR> <BR> <BR> <BR> CString g~order~titles[] = {"&num ","Amt","Customer"}; //////////////////////////////////////////////////////////// ///////////////// // CDbDlg dialog CDbDlg::CDbDlg(CWnd* pParent /*=NULL*/) CDialod(CDbDlg::IDD, pParent) //{{AFX~DATA~INIT(CDbDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void CDbDlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); // ( (AFXDATA~MAP (CDbDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN~MESSAGE~MAP(CDbDlg, CDialog) //{{AFX~MSG~MAP(CDbDlg) ON BN CLICKED(IDC ORDERS~ITEMS, OnOrdersItems) ON~WM~TIMER() ON~WM~CREATE() ON~WM~DESTROY() ON BN CLICKED(IDC DB REFILL, OnDbRefill) ON~WM~RBUTTONDOWN() //}}AFX~MSG~MAP AGF~MAP() END~MESSAGE~MAP() //////////////////////////// // CDbDlg message handlers void CDbDlg::OnOrdersItems() { int i,j; CString s; if (g~orders~mode) ( // Go into Items mode g~orders~mode = 0; SetDlgItemText(IDC~DB~REFILL,Refill"); // Set DB titles SetDlgItemText(IDC~DB~BOX,"Database Items"); SetDlgItemText(IDC~ORDERS~ITEMS,"Orders"); for (i=O;i<2i++) for (j=0;j<3j++) SetDlgItemText (g IDCt[i] [j],g item~tites[j]); // Set DB values for (i=O; i<6 ;i++) ( // For each item SetDlgItemInt(g~IDCs[qty~IDC] [i] ,g~qty[i]); s.Format("$%d.00",g~price[i]); SetDlgItemText(g~IDCs[price~IDC] [i],s); SetDlgItemText(g~IDCs[item~IDC] [i],g~item[i]); else ( // Go into Orders mode g~orders~mode = 1; SetDlgItemText(IDC~DB~REFILL,"Clear"); // Set DB titles SetDlgItemText(IDC~DB~BOX,"Database Orders"); SetDlgItemText(IDC ORDERS ITEMS,"Items"); for (i=0;i<2i++) for (j=0;j<3j++) SetDlgItemText(g~IDCt[i][j],g~order~titles[j]); // Set DB values for (i=0; i<6 ;i++) ( // For each item SetDlgItemInt(g~IDCs[qty~IDC] [i] ,g~num~purchases[i]) SetDlgItemInt(g~IDCs[price~IDC] [i] ,g~purchases[i]); SetDlgItemText(g~IDCs[item~IDC] [i] ,g~cust[i]); for (i=O; i<6 ;i++) ( // Invalidate any histoy g~num~purchases~old[i] = g~purchases~old[i] = g~qty~old[i] = -1; void CDbDlg::OnTimer(UINT nIDEvent) int i,rc,price,stock,cust orders,cust sales; CString s; if (nIDEvent == DB~TIMER) { if (g~db~run < 20) ( if (g~db~run == 0) this->DestroyWindow(); if (g~db~run == 1) (gorders~mode = 1; OnOrdersItems(); g~db~run = 20;} if (g~ora~state) ( // oracle db if (g~orders~mode){ for (i=0; i<6 ;i++) ( // For each item if ( (rc = oracustr(g~cust[i].GetBuffer(0), &cust~orders, just s.Format("OraCustRead ErroR %d",rc); GetParentFrame()->SetMessageText(s); if (g~num~purchases~old[i] != cust orders) SetDlgItemInt(g~IDCs[qty~IDC] [i] ,(g~num~purchases~old[i] = c if (g~purchases~old[i] != cust~sales) SetDlgItemInt (g~IDCs[price~IDC] [i],(ggurchases old[i] = cu } else { for (i=O; i<6 ;i++) ( // For each item if ( (rc = oraread(g~item[i].GetBuffer(0), &price, &stock)) s.Format("OraRead ErroR %d",rc); GetParentFrame()->SetMessageText(s); if (g~qty~old[i] != stock) SetDlgItemInt(g~IDCs[qty~IDC] [i] ,(g~qty~old[i] = stock)); else if (g~orders~mode) { // NOT ora~state, so use the local db for (i=0; i<6 ;i++) ( // For each item if (g~num~purchases~old[i] != g~num~purchases[i]) SetDlgItemInt(g~IDCs[qty~IDC][i] ,(g~num~purchases~old[i] = g~nu if (g~purchases~old[i] != g~purchases[i]) SetDlgItemInt(g~IDCs[price~IDC] [i],(g~purchases~old[i] = g~purcha else { // local db for (i=O; i<6 ;i++) ( // For each item if (g qty[i] != g~qty~old[i]) SetDlgItemInt(g~IDCs[qty~IDC] [i] ,(g~qty~old[i] = g~qty[i])); if (g~total~sales~old != g~total~sales) SetDlgItemInt(IDC~DB~SALES,(g~total~sales~old = g~total~sales)); if (g~ora~state~old != g~ora~state) { if (g~ora state~old = g~ora~state) SetDlgItemText(IDC~BIG~TITLE,"Oracle"); else SetDlgItemText(IDC BIG TITLE,"Local DBM); else if (nIDEvent == INIT~TIMER) KillTimer(INIT~TIMER); GetDlgItem(IDC~BIG~TITLE)->SetFont(&~title~font); if (g~ora~state) SetDlgItemText(IDC~BIG~TITLE,"Oracle"); else <BR> <BR> SetDlgItemText(IDC BIG TITLE,"Local DBR); <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> else CDialog::OnTimer(nIDEvent); int CDbDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) if (CDialog::OnCreate(lpCreateStruct) == -1) return -1; SetTimer(DB~TIMER,200,NULL); SetTimer(INIT~TIMER,200,NULL); g~db~run = 1; // Start return 0; void CDbDlg::OnDestroy() g~db~run = 40; CDialog::OnDestroy(); KillTimer(DB~TIMER); } void CdbDlg::OnOK() { g~db~run = 40; // Re enable the show db call button this->DestroyWindow(); // CDialog::OnOK(); void CDbDlg::OnDbRefill() int i,rc; CString s; <BR> <BR> <BR> if (g~ora~state) {<BR> for (i=o;i<6i++) { if (g~orders~mode) { if ( (rc = oracustw(g~cust[i].GetBuffer(0), 0, 0))<BR> s.Format("OraCustWrite ERRor td",rc); GetParentFrame()->SetMessageText(s); else ( // in items mode if (rc = orawrite(g~item[i].GetBuffer(0), RESTOCK~QTY))<BR> s.Format("OraWrite ERRor td",rc); GetParentFrame()->SetMessageText(s); } else for (i=0;i<6i++) if (g orders mode) { g~purchases[i] = 0; g~num~purchases[i] = 0; else { // in items mode g~qty[i] = RESTOCK~QTY; void CDbDlg::OnRButtonDown(UINT nFlags, CPoint point) GetParentFrame()->SetMessageText(""); this->Invalidate(); CDialog::OnRButtonDown(nFlags, point); BOOL CDbDlg::OnInitDialog() CDialog::OnInitDialog(); // Fonts int i = 0; while (ALL~TEXT~DB[i]) GetDlgItem(ALL TEXT DB[i++l)->SetFont(&g~text~font); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE // dbdlg.h : header file //////////////////////////////////////////////////////////// ///////////////// // CDbDlg dialog class CDbDlg public Coialog // Construction public: CDbDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX~DATA(CDbDlg) enum ( IDD = IDD~DBDLG }; // NOTE: the ClassWizard will add data members here //}}AFX~DATA // Overrides // ClassWizard generated virtual function overrides //t{AFX~VIRTUAL(CDbDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL CFont m~title~font; int m~was~inited; // Implementation protected: // Generated message map functions //((AFX~MSG(CDbDlg) afx~msg void OnOrdersItems(); afxmsg void OnTimer(UINT nIDEvent); afx~msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx~msg void OnDestroy(); virtual void OnOK(); afx~msg void OnDbRefill(); afxmsg void OnRButtonDown(UINT nFlags, CPoint point); virtual BOOL OnInitDialog(); //}}AFX~MSG DECLARE MESSAGE MAP() NOT TO BE TAKEN INTO ACCOUNT FOR THE PURPOSE OF INTERNATIONAL PROCESSING CMainFrame: : CMainFrame () int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m~wndToolBar.Create(this) II m~wndToolBar.LoadBitmap(IDR-MAINFRAME) || !m wndToolBar.SetButtons(buttons, sizeof (buttons) /sizeof (UINT) TRACEO("Failed to create toolbar return -1; // fail to create /* Derek's remove tool bar */ m~wndToolBar.ShowWindow(SW~HIDE); if (!m~wndStatusBar.Create(this) II -!m~wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; // fail to create // TODO: Delete these three lines if you don't want the toolbar to // be dockable m~wndToolbar.EnableDocking(CBRS~ALIGN~ANY); EnableDocking(CBRS~ALIGN~ANY); DockControlBar(&m~wndToolBar); // TODO: Remove this if you don't want tool tips m wndToolBar.SetBarStyle(m wndToolBar.GetBarStyle() I<BR> <BR> CBRS~TOOLTIPS I CBRS~FLYBY); return 0; } ///////////////////////// // CMainFrame diagnostics #ifdef ~DEBUG void CMainFrame: :AssertValid() consist CFrameWnd: :AssertValid(); void CMainFrame::Dump(CDumpContext& dc) const CFrameWnd::Dump(dc); } #endif // ~DEBUG //////////////////////////////////////////////////////////// ///////////////// // CMainFrame message handlers // mainfrm.h interface of the CMainFrame class <BR> <BR> <BR> <BR> <BR> //////////////////////////////////////////////////////////// /////////1/////// class CMainFrame : public CFrameWnd protected: // create from serialization only CMainFrame () DECLARE DYNCREATE(CMainFrame) // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //( (AFX VIRTUAL(CMainFrame) //}}AFX~VIRTUAL // Implementation public: virtual ~CMainFrame() *ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) consist; *endif protected: // control bar embedded members CStatusBar m~wndStatusBar; CToolBar m~wndToolBar; // Generated message map functions protected: //{{AFX~MSG(CMainFrame) afx~msg int OnCreate(LPCREATESTRUCT lpcreateStruct); // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //}}AFX~MSG DECLARE~MESSAGE~MAP() // Odlg.cpp : implementation file #include "stdafx.h" &num include "oentry.h" #include "Odlg.h" // #define ORACLE causes oraread() orawrite() to be exteraly defined 4ifndef ORACLE #define ORACLE 4endif #include "oraomq.h" 4ifdef ~DEBUG #define new DEBUG~NEW 4undef THIS FILE static char THIS~FILE[] = ~FILE~ #endif extern int g~options~run; extern int g~fill~delay; extern int g~place~delay; extern int g~place~tpm; extern int g~poll~pps; extern int g~poll~delay; extern int g~clear~stats; extern int g~ora~state; extern COLORREF g~new~color;<BR> <BR> <BR> extern char g~oracle~con~str[80]; extern CFont g~text~font, int ALL~TEXT~0[] = { IDOK,IDC~COLOR,IDC~CLRSTATS,IDC~ORACREATE, IDC~FILLBOX,IDC~DLY~EB,IDC~DLYMAX,IDC~DLYMIN,IDC~DLY~LAB, IDC~POLL~BOX,IDC~POLL~EB,IDC~POLLMAX,IDC~POLLMIN,IDC~POLL~L IDC~AUTOBOX,IDC~AUTO~EB,IDC~AUTOMAX,IDC~AUTOMIN,IDC~AUTO~LA //////////////////////////////////////////////////////////// ///////////////// // COdlg dialog COdlgg::COdlg(CWnd* pParent /*=NULL*/) : CDialog(COdlg::IDD, pParent) //{{AFX DATA~INIT(COdlg) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void COdlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX);<BR> <BR> //((AFX~DATA~MAP(COdlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP NOT TO BE TAKEN INTO ACCOUNT FOR THE PURPOSE OF INTERNATIONAL PROCESSING if (nSBCode == SB~ENDSCROLL) { } else if (pScrollBar->getDlgCtrlID () == IDC~DLY~SLD( { if (((int)nPos != g fill~delay) && (MIN OLY <= nPos) && (nPos <= M <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> SetDlgItemInt (IDC~DLYrEB,grfill delay = MAX~DLY + MINDLY - nPos); } else if (pScrollBar->GetDlgCtrlID () == IDC~AUTO~SLD) { if (((int)nPos != g place~delay) && (MIN~AUTO <= nPos) && (nPos <= MA SetDlgItemInt (IDC~AUTO EB, (eplace tpm = MAX~AUTO + MIN~AUTO - nPos)); <BR> g~place~delay = 60000/g~place~tmp;<BR> } } else if (pScrollBar->GetDlgCtrlID () == IDC~POLL~SLD) { if (((int)nPos != g~poll~pps) && (MIN~POLL <= nPos) && (nPos <= MAX~P SetDlgItemInt (IDC~POLL~EB, (g~pollgps = MAX~POLL + MIN~POLL - nPos));<BR> g~poll~delay = 1000/g~poll~pps; CDialog::OnVScroll(nSBCode, nPos, pScrollBar); BOOL COdlg::OnInitDialog() CDialog::OnInitDialog(); // GetParentFrame () ->SetWindowText (m~inst + " Options"); this->SetWindowText (m~inst + " Options"); <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> SetDlgItemlnt(IDC~DLYMAX,MAX~DLY); <BR> SetDlgItemInt(IDC~DLYMIN,MIN~DLY);<BR> <BR> SetDlgItemInt (IDC AUTOMAX,MAX AUTO); SetDlgItemInt (IDC~AUTOMIN, MIN~AUTO); SetDlgItemInt (IDC POLLMAX,MAX POLL); SetDlgItemInt (IDC~POLLMIN, MIN~POLL); SetDlgItemInt(IDC DLY EB,g fill delay); SetDlgItemInt (IDC~POLL~EB, g~poll~pps); SetDlgItemInt(IDC AUTO EB,g~place~tpm); // (CSliderCtrl *) xxx = GetDlgItem(IDC~DLY~SLD); HWND hTrack = GetDlgItem(IDC DLY SLD)->m hWnd; : :SendMessage (hTrack, TBM~SETRANGEMIN, TRUE, MIN~DLY);// MINDLY : :SendMessage (hTrack, TBM~SETRANGEMAX, TRUE, MAX~DLY);// MAXDLY : :SendMessage (hTrack, TBM~SETTICFREQ; 100, TRUE); // 10 ticks (MAXDLY - MINDLY : :SendMessage (hTrack, TBM~SETPOS, TRUE, MIN~DLY + MAX~DLY - g~fill~delay); // 1 hTrack = GetDlgItem(IDC AUTO SLD)->m hWnd; : :SendMessage (hTrack, TBM~SETRANGEMIN, TRUE, MIN~AUTO);// MINDLY : :SendMessage (hTrack, TBM~SETRANGEMAX, TRUE, MAX~AUTO);// MAXDLY : :SendMessage (hTrack, TBM~SETTICFREQ, 500, TRUE); // 10 ticks (MAXDLY - MINDLY : :SendMessage (hTrack, TBM~SETPOS, TRUE, MAX~AUTO + MIN~AUTO - g~place~tpm); // hTrack = GetDlgItem(IDC POLL SLD)->m hWnd; : :SendMessage (hTrack, TBM~SETRANGEMIN, TRUE, MIN~POLL);// MINDLY : : SendMessage (hTrack, TBM~SETRANGEMAX, TRUE, MAXrPOLL) ; // MAXDLY : :SendMessage (hTrack, TBM~SETTICFREQ, 10, TRUE); // 10 ticks (MAXDLY - MINDLY) : :SendMessage (hTrack, TBM~SETPOS, TRUE, MAX~POLL + MIN~POLL - g~poll~pps); // // Fonts int i = 0; while (ALL~TEXT O[i]) GetDlgItem (ALL~TEXT~O [i++]) ->SetFont (&g~text~font); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE void COdlg::OnUpdateAutoEb() int tpm = GetDlgItemInt(IDC~AUTO EB,NULL,TRUE); if ((g~place~tpm != tpm) && (tpm >= MIN~AUTO) && (tpm <= MAX~AUTO)) g~place~delay = 60000/tpm; g~place~tpm = tpm; HWND hTrack = GetDlgItem (IDC~AUTO~SLD) ->m~hwnd; : :SendMessage (hTrack, TBM~setpos; TRUE, MAX~AUTO + MIN~AUTO - tpm); void COdlg::OnUpdatePollEb() int poll = GetDlgItemInt(IDC~POLL~EB,NULL,TRUE); if ((g~place~tpm != poll) && (poll >= MIN~AUTO) && (poll <= MAX~AUTO)) g~poll~delay = 1000/poll; g~poll~pps = poll; HWND hTrack = GetDlgItem(IDC POLL SLD)->m hWnd; :SendMessage (hTrack, TBM~SETPOS, TRUE,MAXOLL + MIN~POLL - poll); void COdlg::OnUpdateDlyEb() int dly = GetDlgItemInt(IDC DLY EB,NULL,TRUE); if ((g fill delay != dly) && (dly >= MIN~DLY) && (dly <= MAX~DLY)) g~fill~delay = dly; ~ HWND hTrack = GetDlgItem(IDC~DLY~SLD)->m~hWnd; : :SendMessage (hTrack, TBM~SETPOS, TRUE, MAX~DLY + MINDLY - dly); void COdlg::OnColor() CHOOSECOLOR cc; // common dialog box structure COLORREF acrCustClr [16]; // Setup the custom colors as a grey scale for (int v=O,i=O; i < 16; v=17 * i++) acrCustClr[i] = RGB(v,v,v); // Initialize the necessary members.

cc.lStructSize = sizeof(CHOOSECOLOR); cc.hwndowner = NULL; // = hwnd; cc.lpCustColors = (LPDWORD) acrCustClr; cc.Flags = CC FULLOPEN; // CC~PREVENTFULLOPEN if (ChooseColor(&cc)){ g~new~color = cc.rgbResult; // lpCustColors } else ( GetParentFrame()->SetMessageText("Color was not changed") void COdlg::OnClrstats() g~clear~stats++; void COdlg::OnOracreate() // Create the database in oracle int org~ora~state = g~ora~state; if (g~ora~state == 0) if(oraconn(g~oracle~con~str)) MessageBox("Oracle Connect Failed"); else g~ora~state = 1; if (g~ora~state) if(oracreate()) MessageBox("Oracle oracreate Failed"); if (org~ora~state == 0) if(oradisc()) MessageBox("Oracle DisConnect Failed"); else g~ora~state = 0; // Odlg.h : header file //////////////////////////////////////// // COdlg dialog class COdlg : public CDialog // Construction public:<BR> COdlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //((AFX~DATA(COdlg) enum { IDD = IDD~O~DLG }; // NOTE: the ClassWizard will add data members here //}}AFX~DATA CString m~inst; // COentryView* m~parentptr; // Overrides // ClassWizard generated virtual function overrides //({AFX~VIRTUAL(COdlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL // Implementation protected: // Generated message map functions // ( (AFXMSG (COdlg) afx~msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx msg void OnUpdateAutoEb();<BR> afxmsg void OnVScroll(UINT nSBCode, UINT npos, CScrollBar* pScrollBar);<BR> <BR> <BR> <BR> virtual BOOL OnInitDialog();<BR> <BR> <BR> afx~msg void OnUpdatePollEb(); afx msg void OnUpdateDlyEb(); afx~msg void OnColor();<BR> <BR> virtual void OnOK();<BR> <BR> afx~msg void OnClrstats();<BR> <BR> afx msg void OnOracreate()i <BR> //}}AFX~MSG DECLARE~MESSAGE~MAP() // oentrdoc.cpp : implementation of the COentryDoc class #include "stdafx.h" #include "oentry.h" //#include "OpDlg.h" #include "oentrdoc.h" 4ifdef DEBUG #undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE~ 4endif //////////////////////////////////////////////////////////// ///////////////// // COentryDoc IMPLEMENT~DYNCREATE(COentryDoc, Document) BEGIN MESSAGE MAP(COentryDoc, Document) //((AFX~MSG~MAP(COentryDoc) <BR> <BR> <BR> <BR> <BR> // NOTE - the ClassWizard will add and remove mapping macros her<BR> <BR> <BR> // DO NOT EDIT what you see in these blocks of generated code //}}AFX~MSG~MAP END~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// // COentryDoc construction/destruction COentryDoc::COentryDoc() // TODO: add one-time construction code here COentryDoc:: COentryDoc() BOOL COentryDoc::OnNewDocument() if (!CDocument::OnNewDocument()) return FALSE; // TODO: add reinitialization code here // (SDI documents will reuse this document) return TRUE; } //////////////////////////////////////////////////////////// ///////////////// // COentryDoc serialization void COentryDoc::Serialize(CArchive& ar) if (ar.IsStoring()) // TODO: add storing code here else // TODO: add loading code here //////////////////////////////////////////////////////////// ///////////////// // COentryDoc diagnostics *ifdef DEBUG void COentryDoc: :AssertValid() consist CDocument::AssertValid(); void COentryDoc::Dump(CDumpContext& dc) const { Cdocument::Dump(dc); } 4endif //~DEBUG //////////////////////////////////////////////////////////// ///////////////// // COentryDoc commands // oentrdoc.h : interface of the COentryDoc class // ///////////////////////////////////////////////// class COentryDoc : public CDocument { protected: // create from serialization only COentryDoc(); DECLARE~DYNCREATE(COentryDoc) // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //((AFX~VIRTUAL(COentryDoc) public: virtual BOOL OnNewDocument(); //}}AFX~VIRTUAL // Implementation public: virtual ~COentryDoc(); virtual void Serialize(CArchive& ar); // overridden for document i/o *ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; *endif protected: // Generated message map functions protected: //I(AFX~MSG(COentryDoc) // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //}}AFX~MSG DECLARE~MESSAGE~MAP() // oentry.cpp : Defines the class behaviors for the application.

#include "stdafx.h" #include "oentry.h" #include "mainfrm.h" #include "oentrdoc.h" 4include "dbdlg.h" 4include "Odlg.h" #include "oentrvw.h" *ifdef DEBUG 4undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE~; *endif //////////////////////////////////////// // COentryApp BEGIN~MESSAGE~MAP(COentryApp, CWinApp) //( (AFXMSG MAP(CoentryApp) ON~COMMAND(ID~APP~ABOUT, OnAppAbout) // NOTE - the ClassWizard will add and remove mapping macros her // DO NOT EDIT what you see in these blocks of generated code<BR> <BR> //}}AFX~MSG~MAP // Standard file based document commands ON~COMMAND(ID~FILE~NEW, CWinApp::OnFileNew) ON~COMMAND(ID~FILE~OPEN, CWinApp::OnFileOpen // Standard print setup command ON COMMAND(ID FILE PRINT~SETUP, CWinApp: :OnFileprintSetup) END~MESSAGE~MAP() ////////////////////////// // COentryApp construction COentryApp::COentryApp() { // TODO: add construction code here, // Place all significant initialization in initInstance } //////////////////////////////////////////////////////////// /// // The One and only COentryApp object COentryApp theApp; //////////////////////////////////////////////////////////// /// // COentryApp initialization BOOL COentryApp::InitInstance() { // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need.

Enable3dControls(); LoadStdProfileSettings(); // Load standard INI file options (including // Register the application's document templates. Document templates // serve as the connection between documents, frame windows and views.

CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR~MAINFRAME, RUNTIME~CLASS(COentryDoc), RUNTIME~CLASS(CMainFrame), // main SDI frame window RUNTIME~CLASS(COentyView)); AddDocTemplate(pDocTemplate); // create a new (empty) document OnFileNew(); if (m~lpCmdLine[0] != '\0') // TODO: add command line processing here return TRUE; //////////////////////////////////////////////////////////// ///////////////// // CAboutDlg dialog used for App About class CAboutDlg : public Coialog public: CAboutDlg() // Dialog Data //{{AFX~DATA(CAboutDlg) enum { IDD = IDD~ABOUTBOX }; //) )AFXOATA CFont m~title~font; // Implementation protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //{(AFX~MSG(CAboutDlg) virtual BOOL OnInitDialog() //}}AFX~MSG DECLARE~MESSAGE~MAP() CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) //((AFX OATA INIT(CAboutDlg) //}}AFX~DATA~INIT void CAboutDlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(CAboutDlg)<BR> <BR> //}}AFX~DATA~MAP BEGIN MESSAGE~MAP(CAboutD1g, CDialog) // (AFX~MSG MAP(CAboutDlg) <BR> <BR> //}}AFX~MSG~MAP END~MESSAGE~MAP() // App command to run the dialog void COentryApp: :OnAppAbout() CAboutDlg aboutDlg; aboutDlg.DoModal(); //////////////////////////////////////// // COentryApp commands BOOL CAboutDlg::OnInitDialog() { CDialog::OnInitDialog(); LOGFONT lf; memset(&lf,0,sizeof(LOGFONT)); strcpy lf.1fFaceName,"Monotype Corsiva"); lf.lfHeight = 24; m~title~font.CreateFontIndirect(&lf); GetDlgItem(IDC~ABOUT1)->SetFont(&m~title~font); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE // oentry.h : main header file for the OENTRY application &num define MINDLY 0 #define MAX~DLY 5000 #define MIN~AUTO 2 #define MAX~AUTO 6000 #define MIN~POLL 1 #define MAX~POLL 100 #ifndef ~AFXWIN~H~ *error include 'stdafx.h' before including this file for PCH *endif #include "resource.h" // main symbols //////////////////////////////////////////////////////////// ///////////////// // COentryApp: // See oentry.cpp for the implementation of this class class COentryApp : public CWinApp public: COentryApp(); // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(COentryApp) public: virtual BOOL InitInstance(); //}}AFX~VIRTUAL // Implementation //((AFX MSG(COentryApp) afxmsg void OnAppAbout(); // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //}}AFX~MSG DECLARE MESSAGE MAP() // OPDLG.cpp : implementation file 4include "stdafx.h" *include "oentry.h" #include "OPDLG.h" *ifdef ~DEBUG #define new DEBUG~NEW *undef THIS~FILE static char THIS~FILE[] = ~FILE~ *endif extern int g~options~run; //////////////////////////////////////////// // OPDLG dialog OPDLG::OPDLG(CWnd* pParent /*=NULL*/) . CDialog(OPDLG::IDD~O~DLG, pParent) //((AFX~DATA~INIT(OPDLG) <BR> <BR> <BR> // NOTE: the ClassWizard will add member initialization here<BR> <BR> //}}AFX~DATA~INIT void OPDLG::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange (pDX); //{{AFX DATA MAP(OPDLG) // NOTE: the ClassWizard will add DDX and DDV calls here //)}AFX~DATA~MAP BEGIN~MESSAGE~MAP(OPDLG, CDialog) //{{AFX~MSG~MAP(OPDLG) //}}AFX~MSG~MAP END~MESSAGE MAP() //////////////////////////////////////// // OPDLG message handlers <BR> <BR> <BR> <BR> void OPDLG::OnOK()<BR> {<BR> <BR> g~options~run = 40; // Re-enable the options call button this->DestroyWindow(); CDialog: :OnOK(); User: root Host: bunny Class: bunny Job: stdin // OPDLG.h : header file //////////////////////////////////////// // OPDLG dialog class OPDLG : public CDialog { // Construction public: OPDLG(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX~DATA(OPDLG) // enum ( IDD = IDD OPDLG ); // NOTE: the ClassWizard will add data members here //}}AFX~DATA // Overrides // ClassWizard generated virtual function overrides //( (AFX~VIRTUAL(OPDLG) protected: virtual void DoDataExchange(cDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL // Implementation protected: // Generated message map functions //( (AFX~MSG(OPDLG) virtual void OnOK(); //}}AFX~MSG DECLARE~MESSAGE~MAP() User: root Host: bunny Class: bunny Job: stdin // OptDlg.cpp : implementation file *include "stdafx.h" #include "oentry.h" #include "OptDlg.h" *ifdef ~DEBUG #define new DEBUG~NEW #undef THIS~FILE static char THIS~FILE[] = ~FILE~ #endif extern int g~options~run // OptDlg dialog OptDlg::OptDlg(CWnd* pParent /*=NULL*/) . CDialog(OptDlg::IDD, pParent) //{{AFX~DATA~INIT(OptDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT } void IptDlg: :DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(OptDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP } BEGIN~MESSAGE~MAP(OptDlg, CDialog) //( (AFXMsG MAP(OptDlg) ON BN CLICKEO(IDC~DONE, OnDone) ON~WM~DESTROY() ON~WM~CREATE() //}}AFX~MSG~MAP END~MESSAGE~MAP() ////////////////////////// // OptDlg message handlers void OptDlg::OnDone() { g~options~run = 40; // Re-enable the options call button<BR> this->DestroyWindow(); void OptDlg::OnDestroy() g~options~run = 40; // Re-enable the options call button CDialog::OnDestroy(); int OptDlg::OnCreate(LPCREATESTRUCT lpCreatestruct) if (CDialog::OnCreate(lpCreateStruct) == -1) return -1; g~options~run = 1; // Start return 0; // OptDlg.h . header file //////////////////////////////////////// // OptDlg dialog class OptDlg : public CDialog { // Construction public: OptDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX~DATA (Optdlg) // enum { IDD = IDD~OPTIONS~DLG }; //))AFX~DATA // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(OptDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL // Implementation protected: // Generated message map functions //{{AFX~MSG(OptDlg) afx~msg void OnDone(); afx~msg void OnDestroy(); afx msg int OnCreate(LPCREATESTRUCT lpCreateStruct); //)TAFX~MSG DECLARE~MESSAGE~MAP() //((NO DEPENDENCIES)) // Microsoft Developer Studio generated include file.

// Used by oentry.rc &num define IDD~ABOUTBOX 100 &num define IDD~OENTRY~FORM 101 &num define IDR~MAINFRAME 128 #define IDR~OENTRYTYPE 129 #define IDI~ICON~Q 130 &num define IDB~BITMAPTEST 131 #define IDD~DBDLG 133 #define IDD-O-DLG 138 #define IDR~3DIMES 145 #define IDR~3DMDS 146 #define IDI~ICON~TRASH 147 #define IDI~ICON~TRASH1 148 #define IDI~WAIT0 149 #define IDI~WAIT1 150 #define IDI~WAIT2 151 #define IDI~WAIT3 152 #define IDI~FILL0 153 #define IDI~FILL1 154 #define IDI~FILL2 155 #define IDI~WAIT4 156 #define IDI~WAIT5 157 #define IDI~WAIT6 158 #define IDC~AUTOB 1000 #define IDC~EXITB 1001 #define IDC~ORDERB 1002 #define IDC~CUST 1003 #define IDC~ITEM 1004 #define IDC~QTY 1005 #define IDC~PICT 1006 #define IDC~COLORB 1006 #define IDC~GENERIC1 1007 #define IDC~TPS~EB 1008 #define IDC~TRANB 1010 #define IDC~COLOBOX 1011 #define IDC~LOGO~Q 1012 #define IDC~ABORTB 1013 #define IDC~COMMITB 1014 #define IDC~TOTALR 1015 #define IDC~MSGS 1015 #define IDC~SHOWDB 1016 #define IDC~TPS 1017 #define IDC~QUE 1018 #define IDC~DLYMIN 1019 #define IDC~DLYMAX 1020 #define IDC~PLACER 1021 #define IDC~AUTOMAX 1021 #define IDC~PLACENOQR 1022 #define IDC~AUTOMIN 1022 #define IDC~QUELAB 1023 #define IDC~POLLMAX 1023 #define IDC~CUSTLAB 1024 #define IDC~POLLMIN 1024 #define IDC~ITEMLAB 1025 #define IDC~QTYLAB 1026 #define IDC~SENDREPC 1028 #define IDC~RECIPT 1029 &num define IDC~FILLDB 1030 &num define IDC~RECIPTS 1031 &num define IDC~MSGS~LAB 1032 &num define IDC~RECIPTS~LAB 1033 &num define IDC~FILLR3 1034 &num define IDC~DB~I0 1038 #define IDC~DB~Q0 1039 #define IDC~DB~SALBEST 1040 #define IDC~DB~SALES 1041 #define IDC~DB~BOX 1042 #define IDC~DB~REFILL 1043 #define IDC~ORDERS~ITEMS 1044 #define IDC~T11 1045 #define IDC~T12 1046 #define IDC~T13 1047 #define IDC~T21 1048 #define IDC~T22 1049 #define IDC~DB~P0 1050 #define IDC~T23 1051 #define IDC~ORDERBOX 1052 #define IDC~FILLTXT 1054 #define IDC~AUTOBOX 1055 #define IDC~dmd 1057 #define IDC~POLL~BOX 1057 #define IDC~TRANBOX 1058 #define IDC~WAITO 1060 #define IDC~WAIT1 1061 #define IDC~OPTIONSB 1063 #define IDC~FILL0 1064 #define IDC~FILL1 1065 #define IDC~DB~I1 1066 #define IDC~FILL2 1066 #define IDC~DBQ1 1067 #define IDC~DB~P1 1068 #define IDC~DLY~EB 1068 #define IDC~DB~I2 1069 #define IDC~DLY~SLD 1069 #define IDC~DB~Q2 1070 #define IDC~DLY~LAB 1070 #define IDC P2 1071 #define IDC~AUTO~EB 1071 #define IDC~DB~I3 1072 #define IDC~AUTO~SLD 1072 #define IDC~DB~Q3 1073 #define IDC~AUTO~LAB 1073 #define IDC~DB~P3 1074 #define IDC~FILLBOX 1074 #define IDC~DB~I4 1075 #define IDC~COLOR 1075 #define IDC~DB~Q4 1076 #define IDC~POLL~EB 1076 #define IDC~DB~P4 1077 #define IDC~POLL~SLD 1077 #define IDC~DB~I5 1078 #define IDC~POLL~LAB 1078 #define IDC~DB~Q5 1079 #define IDC~DB~P5 1080 #define IDC~CLRSTATS 1080 #define IDC~ABOUT1 1081 #define IDC~ORACREATE 1081 #define IDC~BIG~TITLE 1082 #define IDC~MODEBOX 1083 #define IDC~STATEBOX 1084 #define IDC~FILLER 2000 #define IDC~TOTALS 2001 // Next default values for new objects // #ifdef APSTUDIO~INVOKED #ifndef APSTUDIO~READONLY~SYMBOLS #define ~APS~3D~CONTROLS 1 #define ~APS~NEXT~RESOURCE~VALUE 140 #define ~APS~NEXT~COMMAND~VALUE 32771 #define ~APS~NEXT~CONTROL~VALUE 1085 #define ~APS~NEXT~SYMED~VALUE 101 *endif 4endif // stdafx.cpp . source file that includes just the standard includes // oentry.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information 4include "stdafx.h" // stdafx.h . include file for standard system include files, // or project specific include files that are used frequently, but are changed infrequently #include <afxwin.h> // MFC core and standard components *include <afxext.h> // MFC extensions // admindlg.cpp : implementation file #include "stdafx.h" *include "qman.h" *include "admindlg.h" #define Q~LIB #include "qlib.h" #include "qadmin.h" #include "rt.h" #define ADMTIMER 102 extern lpSMBUFH sm~base; extern QADMSTATS g~s[3]; extern CString g~que[3]; extern lpQHANDLE QS[3];<BR> <BR> <BR> <BR> int lOC APICS[8] = (IDC~QNONE1,IDC~QDOWN1,IDC~QSTOP1,IDC~QNOGET1,ID <BR> enum pics {QNONE,QDOWN,QSTOP,QNOPUT,QNOGET,QUP,QNOPG,QFULL}; extern int g~pic[3+3+3]; QADMCTLS g~ad; *ifdef DEBUG 4undef THIS FILE static char BASED~CODE THIS~FILE[] = FILE <BR> <BR> *endif<BR> extern CFont G~text font; int ALL~TEXT~A[] = {IDC~STATS,IDC~OGROUP,IDC~SGROUP, IDC~PUTC,IDC~GETC,IDC~HALTC,IDC~SRESETC,IDC~FRESETC,IDC~SA@& lt;BR> <BR> <BR> <BR> <BR> IDC~MAXSIZE,IDC~LIMLAB,IDC~QSIZE,<BR> IDOK,IDC~SET,IDC~REFRESH,0}; //////////////////////////////////////////////////////////// ///////////////// // CAdminDlg dialog CAdminDlg::CAdminDlg(CWnd* pParent /*=NULL*/) CDialog(CAdminDlg::IDD, pParent)<BR> //{{AFX~DATA~INIT(CAdminDlg) // NOTE: the ClassWizard will add member initialization here //))AFX~DATA~INIT void CAdminDlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(CAdminDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN MESSAGE MAP(CAdminDlg, CDialog) //{{AFX~MSG~MAP (CAdminDlg) ON~BN~CLICKED (IDC~REFRESH, OnRefresh) ON~BN~CLICKED (IDC~SET, OnSet) ON-CBN EDITCHANGETIDC QSIZE, OnEditchangeQsize) ON~WM~TIMER () ON () //}}AFX~MSG~MAP END~MESSAGE~MAP() <BR> <BR> <BR> <BR> <BR> <BR> /////////////////////////////////////<BR> // CAdminDlg message handlers void CAdminDlg: :SetDisplay (int init) { CString sp,sg,s,tl,t2; if (int) { tl = gque[m id] + " Status"; t2 = g~que[m~id] + " Settings"; <BR> <BR> <BR> SetDlgItemText(IDC~OGROUP,tl);<BR> SetDlgItemText(IDC~SGROUP,t2);<BR> <BR> CListBox* lb = (CListBox*) GetDlgItem(IDC~STATS);<BR> 1b->ResetContent (); s.Format ("%5d committed entries",g~s [m~id] .committed~entries); 1b->InsertStri s.Format ("%5d uncommitted puts", g-s [m~id] .pending~puts); 1b->InsertStri <BR> <BR> <BR> s.Format ("%5d uncommitted gets", g~s [m~id] .pending~gets); 1b->Inserts<BR> <BR> s.Format ("%5d holes", g~s [m~id] .holey~entries); 1b->InsertStri<BR> s.Format ("%5d max entries", g~s [m~id] .max~entries); 1b-InsertsStri<BR> <BR> <BR> <BR> <BR> <BR> sg = ctime (&g~s [m~id] .first~start~time); sp = ctime (&g~s [m~id] .last~restart~time); s.Format ("%5d restarts", g~s [m~id] .num~restarts); 1b->InsertString (-1, s.Format ("Last restart time %s", LPCTSTR (sg. Left (24))); 1b->InsertString (-1, s.Format("First restart time %s", LPCTSTRS (sp. Left (24))); lb->Insertstring(-1, if (init) s.Format("(%d limit)",g~s[m id3.max entries limit); SetDlItemText (IDC~LIMLAB, LPCTSTR (s)); SetDlgItemInt (IDC~QSIZE, g-s [m-id] .max~entries); // Select a icon // if (init) // for (int i=0; i<6i++) // if (i != gpio[m id])<BR> //GetDlgItem (IDC~APICS [i]) ->ShowWindow (SW-HIDE);<BR> <BR> <BR> <BR> <BR> <BR> <BR> if ((g~pic [m~id] != g~pic [m~id+3+3])) {<BR> <BR> GetDlgItem (IDC~APICS [g-pic [m-id]]) ->ShowWindow (SW~SHOW);<BR> GetDlgItem (IDC~APICS [g-pic [m-id+3+3]]) ->ShowWindow (SH~HIDE);<BR> g~pic [m~id+3+3] = g~pic [m-id]; // Set check box items if (init) ((CButton *) GetDlgItem(IDC GETC))-SetCheck(g~s[m id].qget state); ((CButton *) GetDlgItem(IDC-PUTC))->SetCheck(g s[m-id].qput-state); ((CButton *) GetDlgItem(IDC~SRESETC))->SetCheck(g~ad.stats~reset~flag) ; <BR> <BR> ((CButton *) GetDlgItem(IDC~FRESETC))->SetCheck(g~ad.full~reset~flag); <BR> ((CButton *) GetDlgItem (DC~HALTC)) ->SetCheck (g~ad-halt~flag) } } <BR> <BR> <BR> <BR> BOOL CAdminDlg: :OnInitDialog ()<BR> {<BR> <BR> <BR> <BR> <BR> <BR> CDialog: :OnInitDialog ();<BR> g~pic[m~id+3+3] = QNONE; // history is invalid for (int i=0; i<6 i++) // Turn all pics off.

GetDlgItem (IDC~APICS [i] ->ShowWindow (SH~HIDE); SetDisplay(l); SetTimer(ADMTlMER,1000,NULL); // 1 sec i = O; while (ALL~TEXT A[i]) GetdlgItem (ALL~TEXT~A [i++] ->SetFont (&g~text~font); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE void CAdminDlg::OnRefresh() SetDisplay(l); DWORD SetCt1b (LPVOID m~id) int id = (int)m~id; QsendAndReceive (QS [id] ,ADMINREQ~MODE, QADM~SET~CONTROLS, 0, sizeof (g~ad), (char return (0); void CAdminDlg::OnSet() <BR> <BR> <BR> <BR> memset(&g~ad,0,sizeof(g~ad)); <BR> <BR> <BR> <BR> <BR> if (IsDlgButtonChecked (IDC~OUTC)) g~ad.enable~qputs~flag++;<BR> <BR> <BR> if (IsDlgButtonChecked (IDC~GETC)) g~ad.enable~ggets-flag++;<BR> if (IsDlgButtonChecked (IDC~SRESETC)) g~ad.stats~reset-flag++;<BR> <BR> <BR> <BR> <BR> <BR> <BR> if (IsdlgButtonChecked (IDC~PRESETC)) g~ad.full~reset~flag++; if (IsDlgButtonChecked(IDC~SHUTDOWNC)) g~ad.shutdown~flag++; if (IsdlgButtonChecked (IDC~HALTC)) g-ad-halt~flag++; int qs = GetDlgItemInt(IDC~QSIZE,NULL,TRUE); if ((qs>C)&&(qs<=gs[m~id] .max~entries~limit)) g~ad-max~entries~value = qs; DWORD id; CreateThread (NULL, 0, (LPTHREAD~START~ROUTINE) SetCt1, (LPVOID) m~id, 0, &id); // QsendAndreceive (QS [m~id] ,ADMINREQ~MODE, QADM~SET~CONTROLS, 0, sizeof (g~ad) , ( if (g~ad.shutdown~flag) { g~pic[m~id] = QDOWN; SetDisplay (0); // 0=refresh only.

Sleep (1000); SetDisplay (0); // 0=refresh only.

Sleep (1000); if (g~ad.shutdown~flag) CDialog: :OnOK (); // Exit g~ad.stats~reset~flag = 0; g~ad.full~reset~flag = 0; g~ad.shutdown~flag = 0; g~ad.halt~flag = 0; SetDisplay(1); // 1=init: set buttons void CAdminDlg::OnEditchangeQsize() int qs = GetDlgItemInt(IDC~QSIZE,NULL,TRUE); of (! ((qs>0) && (qs<=g~s [m~id] .max~entries~limit))) SetDlgItemText(IDCQSZE,") ;- void CAdminDlg: :OnTimer (UINT nIDEvent) if (nIDEvent == ADMTIMER) SetDisplay (0) else CDialog::OnTimer(nIDEvent); void CAdminDlg::OnRButtonDown(UINT nFlags, CPoint point) GetParentFrame ()->SetMessageText (""); this->Invalidate(); CDialog::OnRButtonDown(nFlags, point); // admindlg.h : header file <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> //////////////////////////////////////////////////////////// /////////////////<BR> <BR> <BR> // CAdminDlg dialog class CAdminDlg public CDialog // Construction public: CAdminDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{(AFX~DATA(CAdminDlg) enum ( IDD = IDD~ADMINDIALOG }; // NOTE: the ClassWizard will add data members here //}}AFX~DATA int m~id; // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(CAdminDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL void SetDisplay(int i); // Implementation protected: // Generated message map functions //{{AFX~MSG(CAdminDlg) virtual BOOL OnInitDialog(); afx~msg void OnRefresh(); afxmsg void OnSet(); afxmsg void OnEditchangeQsize(); afx-msg void OnTimer(UINT nIDEvent); afx~msg void OnRButtonDown(UINT nFlags; CPoint point); //}}AFX~MSG DECLARE~MESSAGE~MAP() // datadlg.cpp . implementation file #include "stdafx.h" include "qman.h" #include "datadlg.h" *include "KeySearch.h" #define Q~LIB #include "qlib.h" 4include "qadmin.h" #include "rt.h" #include "orderfm.h" extern lpQHANDLE QS[3] extern QADMSTATS g~s[3]; extern CString g~que[3] 4ifdef DEBUG 4undef THIS FILE static char BASED CODE THIS~FILE[] = FILE #endif //////////////////////////////////////////////////////////// ///////////////// // CdataDlg dialog CdataDlg::CdataDlg(CWnd* pParent /*=NULL*/) CDialog(CdataDlg::IDD, pParent) //I(AF~DATA~INIT(CdataDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void CdataDlg::DoDataExchange(CDataExchange* pDX) <BR> <BR> <BR> <BR> <BR> CDialog::DoDataExchange(pDX); <BR> <BR> <BR> //((AFX~DATA~MAP(CdataDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN~MESSAGE MAP(Cdataolg, CDialog) //{{AFX~MSG~MAP(CdataDlg) ON BN CLICKED(IDREFRESHB, OnRefreshb) ON~BN~CLICKED(IDC~CMT, OnCmt) ON~BN~CLICKED(IDC~UNCMT, OnUncmt) ON~BN~CLICKED(IDR~SEARCHB, OnSearchb) //}}AFX~MSG~MAP END~MESSAGE~MAP() SMBUF m; void CdataDlg::ScreenInit() CString s,ss; int i,gotsize; pOFORM po = (pOFORM) &m.mdata if (m~sub~mode == QADM~REQ~COM~DATA) s.Format("%s %4d Commited t20d Uncommited entries",LPCTSTR(g~que[m~id g~s[m~id].committed~entries, g~s[m~id].pending~gets + g~s[m~id].

else s.Format("Ws -',4d Uncommited %20d Commited entries",LPCTSTR(g~que[m~id]), g~s[m~id] .pending~gets + g~s[m~id] .pending~puts, g~s[m~id] .committed~ent SetDlgItemText(IDC~TITLE,LPCTSTR(s)); CListBox* lb = (CListBox*) GetDlgItem(IDC~DATAL); lb->ResetContent(); for (i = C; i < 200; i++) *m.mdata = if (QSUCCESS == QsendAndReceive(QS[m~id],ADMINREQ~MODE,m~sub~mode, 0,sizeof(int),m.mdata, sizeof(m.mdata),m.mdata,&gotsize,&m.msgh)) ss = "%3d\t%s\t%s\t%s"; if (gotsize == sizeof(OFORM)) s.Format(LPCTSTR(ss),i,po->cust,po->item,po->qty,0) ; lb->InsertString(-1,s); else if (gotsize) s.Format("%3d -\t%s",i,m.mdata); lb->InsertString(-1,s); else break; #define FORMATNAME "c:\\q\\formats.txt" char * IsAddr(char *c){ int off = 0; if (strstr(c,"msgh")){ if (strstr(c,"size")) return((char *)m.msgh.size); } else if (strstr(c,"mdata")) sscanf (c, "%*[^[]\[%d", off) ; return((m.mdata + off)) return (0); typedef struct fmts { // Thread parameters void* testa; int testv; char fmt[100]; void* a[10]; fmts* next; } FMTS, *pFMTS; void clearfmt( pFMTS p) { p->testa = NULL; p->testv = 0; *p->fmt = O; for (int i=0;i < 10;i++) p->a[i] = NULL; p->next = 0; } FMT fmts; void PrseFormats () { char line [LINESIZE]; char test [LINESIZE]; char format [LINESIZE] char ops [LINESIZE]; char op1 [LINESIZE]; char op2 [LINESIZE]; char op [LINESIZE]; FILE *fp = fopen (FORMATNAME, "r"); if ( ! fp ) { // Say("cant open the data formats file %s", FORMATNAME) return; while (fgets (line, LINESIZE, fp) <BR> <BR> <BR> <BR> <BR> if ( 3 == sscanf (line, "% [^;];% [^;];% [^;]", test ,format ,ops)) <BR> <BR> if (strchr(test, 'fl' ) continue; if ( 3 != sscanf (test, "%s %s" %s" ,op1, op, op2)) continue; if (strstr (op1, "size")) fmts.testa = &mmsgh.size; sscanf (op2, "%d" ,&fmts.testv); strcpy (fmts.fmt, format); else ; //Say ("ReadParms: Ignoring: %s",line); } } if (ferror (fp)) { // Fail ("read error in parameters file %s" ,PARMNAME) clearerr (fp) fclose(fp) //////////////////////////////////////////////////// // CdataDlg message handlers BOOL Cdatadlg: :OnInitDialog () { CDialog: :OnInitDialog (); m~sub~mode = QADM~REQ~COM~DATA; ((CButton *) GetDlgItem (IDC~CMT)) ->SetCheck (TRUE) ScreenInit (); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE void Cdatadlg: :Onrefreshb () { ScreenInit (); } void CdataDlg::OnCmt() m~sub~mode = QADM~REQ~COM~DATA; ScreenInit (); void CdataDlg::OnUncmt() m~sub~mode = QADM~REQ~UNCOM~DATA; ScreenInit (); void CdataDlg: :OnSearchb() CKeySearch d; d.m~id = m~id; d.DoModal(); // datadlg.h : header file //////////////////////////////////////////////////////////// ///////////////// // CdataDlg dialog class CdataDlg public CDialog // Construction public: CdataDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //( (AFX~GATA(Cdataolg) enum ( IDD = IDD~DATADIALOG ); // NOTE: the ClassWizard will add data members here //))AFX~DATA int m id; int m~sub~mode; void ScreenInit(); // Overrides // ClassWizard generated virtual function overrides //( (AFX~VIRTUAL(Cdataolg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //))AFX~VIRTUAL // Implementation protected: // Generated message map functions //{{AFX~MSG(CdataDlg) virtual BOOL OnInitDialog(); afx~msg void OnRefreshb(); afx~msg void OnCmt(); afx~msg void OnUncmt(); afx msg void OnSearchb(); //}}AFX~MSG DECLARE~MESSAGE~MAP() // KeySearch.h header file //////////////////////////////////////// // CKeySearch dialog class CKeySearch : public CDialog { // Construction public: CKeySearch(CWnd* pParent = NULL); // standard constructor //void CM~switch(int mode); // Dialog Data //{{AFX~DATA(CKeySearch) enum ( IDD = IDD~KEYSEARCH ); // NOTE: the ClassWizard will add data members here //}}AFX~DATA //int m~min~int,m~max~int,m~at~int; //CString m~min~str,m~max~str,m~at~str; int m~id; // 1-3 int m~preds; int m~pred~type[3]; int m~pic; int m~committed; int m~uncommitted; int m~total~entries; int m~search~type; void OnCompChange(int pred); void ChangePredView(int pred, int act); void CopyInput(int pred, int min, int max); // Overrides // ClassWizard generated virtual function overrides //((AFX~VIRTUAL(CKeySearch) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL // Implementation protected: // Generated message map functions //((AFX MSG(CKeySearch) virtual BOOL OnInitDialog(); afx~msg void OnSearchb(); afx~msg void OnAndl(); afxmsg void OnAnd2(); afx~msg void OnSelchangeCompCb1(); afx~msg void OnSelchangeCompCb2(); afx~msg void OnSelchangeCompCb3(); afxmsg void OnEditchangeMinCbl();<BR> afx~msg void OnEditchangeMinCb2();<BR> afx~msg void OnEditchangeMinCb3();<BR> <BR> <BR> <BR> <BR> <BR> <BR> afx~msg void OnEditchangeMaxCbl() ; afx~msg void OnEditchangeMaxCb2(); afx~msg void OnEditchangeMaxCb3(); <BR> <BR> afx~msg void OnTimer(UINT nIDEvent); afx~msg void OnAllR(); afx~msg void OnComR(); afx~msg void OnUncomR(); afx msg void OnRButtonDown(UINT nFlags, CPoint point); //}}AFX~MSG DECLARE~MESSAGE~MAP() // mainfrm.cpp implementation of the CMainFrame class *include "stdafx.h" *include "qman.h" #include "mainfrm.h" 4ifdef DEBUG 4undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE 4endif //////////////////////////////////////////////////////////// ///////////////// // CMainFrame IMPLEMENT~DYNCREATE(CMainFrame, CFrameWnd) BEGIN MESSAGE MAP(CMainFrame, CFrameWnd) //((AFx MSD MAP(CMainFrame) // NOTE - the ClassWizard will add and remove mapping macros her // DO NOT EDIT what you see in these blocks of generated code ON WM CREATE() //}}AFX~MSG~MAP END~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// // arrays of IDs used to initialize control bars // toolbar buttons - IDs are command buttons static UINT BASED~CODE buttons[] = { // same order as in the bitmap 'toolbar.bmp' ID~FILE~NEW, ID~FILE~OPEN, ID FILE SAVE ID~SEPARATOR, ID EDIT~CUT, ID~EDIT~COPY, ID~EDIT~PASTE, ID SEPARATOR, ID~FILE PRINT, ID~APP~ABOUT, static UINT BASED~CODE indicators[] = ID~SEPARATOR, // status line indicator ID~INDICATOR~CAPS, ID~INDICATOR~NUM, ID~INDICATOR~SCRL, }; ////////////////////////////////////// // CMainFrame construction/destruction CMainFrame::CMainFrame() { // TODO: add member initialization code here CMainFrame::~CMainFrame() int CMainFrame::OnCreate(LPCREATESTRUCT lpCreatestruct) if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m wndToolBar.Create(this) II !m~wndToolBar.LoadBitmap(IDR~MAINFRAME) || !m~wndToolBar.SetButtons(buttons, sizeof(buttons)/sizeof(UINT))) TRAcEo("Failed to create toolbar\n"); return -1; // fail to create /* Derek's remove tool bar */ m~wndToolBar.ShowWindow(SW~HIDE); if (!m~wndStatusBar.Create(this) II !m~wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) TRACE0("Failed to create status bar\n"); return -1; // fail to create // TODO: Delete these three lines if you don't want the toolbar to // be dockable m~wndToolBar.EnableDocking(CBRS~ALIGN~ANY); EnableDocking(CBRS~ALIGN~ANY); DockControlBar(&m~wndToolBar); // TODO: Remove this if you don't want tool tips m~wndToolBar.SetBarStyle(m~wndToolBar.GetBarStyle() |<BR> <BR> CBRS~TOOLTIPS | CBRS~FLYBY); return 0; //////////////////////////////////////////////////////////// ///////////////// // CMainFrame diagnostics #ifdef ~DEBUG void CMainFrame::AssertValid() const { CFrameWnd::AssertValid(); void CMainFrame::Dump(CDumpContext& dc) consist CFrameWnd::Dump(dc); *endif //~DEBUG //////////////////////////////////////////////////////////// ///////////////// // CMainFrame message handlers // mainfrm.h interface of the CMainFrame class //////////////////////////////////////////////////////////// ///////////////// class CMainFrame : public CFrameWnd protected: // create from serialization only CMainFrame () DECLARE~DYNCREATE(CMainFrame) // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //( (AFX VIRTUAL)CMainFrame) //}}AFX~VIRTUAL // Implementation public: virtual ~CMainFrame(); #ifdef ~DEBUG virtual void AssertValid() consist; virtual void Dump(CDumpContext& dc) consist; 4endif protected: // control bar embedded members CStatusBar m wndStatusBar; CToolBar m~wndToolBar; // Generated message map functions protected: //{{AFX~MSG(CMainFrame) afx msg int OnCreate(LPCREATESTRUCT lpCreateStruct); // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //))AFX~MSG DECLARE MESSAGE MAP() //////////////////////////////////////////////////////////// ///////////////// User: root Host: bunny Class: bunny Job: stdin // KeySearch.cpp implementation file 4include "stdafx.h" include "qman. h" include "KeySearch.h" #define Q~LIB #include "qlib.h" *include "qadmin.h" #include "orderfm.h" #include "rt.h" #ifdef ~DEBUG #define new DEBUG~NEW *undef THIS~FILE static char THIS~FILE[] = ~FILE~ <BR> <BR> 4endif<BR> &num define KEYTIMER 106 extern lpQHANDLE QS[3]; extern QADMSTATS g~s[3]; extern CString g~que[3]; extern lpSMBUFH sm~base; extern int g~pic[3+3+3]; //////////////////////////////////////////////////////////// ///////////////// #define ID~OBJS 9 <BR> <BR> <BR> <BR> int IDC~KPICS[8] = {IDC~QNONE1,IDC~QDOWN1,IDC~QSTOP1,IDC~QNOPUT1,IDC~QNOGET1 I<BR> enum IDTYPE {COMP,MIN,AT,MAX,AND,OPA,OPB,OPC,OPD};<BR> <BR> <BR> <BR> <BR> int g~id[3][ID~OBJS] = {{IDC~COMP~CB1,IDC~MIN~CB1,IDC~AT~CB1,IDC~MAX~CB1,IDC~A<B R> <BR> <BR> {IDC~COMP~CB2,IDC~MIN~CB2,IDC~AT~CB2,IDC~MAX~CB2,IDC~A<BR > <BR> <BR> {IDC~COMP~CB3,IDC~MIN~CB3,IDC~AT~CB3,IDC~MAX~CB3,IDC~A<BR > // List of items to get big fonts extern CFont g~text font; int ALL~TEXT~S[] = {IDC~ALL~R,IDC~COM~R,IDC~UNCOM~R,IDC~MODE,IDOK,IDSEARCHB,IDC ~ //////////////////////////////////////////////////////////// ///////////////// // CKeySearch dialog CKeySearch::CKeySearch(CWnd* pParent /*=NULL*/) CDialog(CKeySearch::IDD, pParent) //((AFX~DATA~INIT(CKeySearch) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void CKeySearch: :DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(CKeySearch) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN MESSAGE MAP(CKeySearch, CDialog) - //(IAFX~MSG~MAP(CKeySearch) ON~BN~CLICKED(IDSEARCHB, OnSearchb) ON~BN~CLICKED(IDC~AND1, OnAnd1) ON~BN~CLICKED(IDC~AND2, OnAnd2) ON~CB SELCHANGE(DC COMP CB1, OnSelchangeCompCbl) ON~CBNZSELCHANGE(IDC-COMP-CB2, OnSelchangeCompCb2) ON~CBN SELCHANGE(IDC-COMP-CB3, OnSelchangeCompCb3) ON~CBN~EDITCHANGE(IDC~MIN~CB1, OnEditchangeMinCb1) ON~CBN~EDITCHANGE(IDC~MIN~CB2, OnEditchangeMinCb2) ON~CBN EDITCHANGE(IDC-MIN-CB3, OnEditchangeMinCb3) ON~CBN~EDITCHANGE(IDC~MAX~CB1, OnEditchangeMaxCb1) ON~CBN~EDITCHANGE(IDC~MAX~CB2, OnEditchangeMaxCb2) ON~CBN~EDITCHANGE(IDC~MAX~CB3, OnEditchangeMaxCb3) ON~WM~TIMER() ON~BN~CLICKED(IDC~ALL~R, OnAllR) ON~BN~CLICKED(IDC~COM~R, OnComR) ON BN CLICKED(IDC UNCOM R, OnUncomR) ON~WM~RBUTTONDOWN() //}}AFX~MSG~MAP END~MESSAGE~MAP()<BR> <BR> <BR> //////////////////////////////////////// // CKeySearch message handlers BOOL CKeySearch: :OnInitDialog() CDialog::OnInitDialog(); int i,id; m~preds = 1; m~pred~type[0] = m~pred~type[1] = m~pred~type[2] = INT~SEARCH~TYPE; for (id = 1; id < OPA; id++) GetDlgItem(g~id[0][id])->EnableWindow(FALSE); m~pic = (g~pic[m~id] + 1) t 8; ((CButton *) GetDlgItem(IDC~ALL~R))->SetCheck(TRUE); m~search~type = SEARCH~ALL~ENT; m~committed = -1; m~uncommitted = -1; m~total~entries = -1; SetDlgItemText(IDC~MODE,"View " + gque[m~id] + " Entries" SetTimer(KEYTIMER,1000,NULL); // 4 sec i = O; while (ALL~TEXT~S[i]) GetDlgItem(ALL~TEXT~S[i++])->SetFont(&g~text~font); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE int String2Time(const char *s) ( // Thu Nov 30 17:30:00 1995 char mon[80]; int mday,hr,mn,sc,yr,args; tm TM; // If it starts with a day skip it.

sscanf(s,"ts",mon); if (strstr("Mon Tue Wed Thu Fri Sat Sun",mon)) s = s + 4; args = sscanf(s,"ts %d %d:%d:%d td",mon,&mday,&hr,&mn,&sc,&yr); if (!strcmp(mon,"Jan")) TM.tm~mon = 0; else if (!strcmp(mon,"Feb")) TM.tm~mon = 1; else if (!strcmp(mon,"Mar")) TM.tm~mon = 2; else if (!strcmp(mon,"Apr")) TM.tm~mon = 3; else if (!strcmp(mon,"May")) TM.tm~mon = 4; else if (!strcmp(mon,"Jun")) TM.tm~mon = 5; else if (!strcmp(mon,"Jul")) TM.tm~mon = 6; else if (!strcmp(mon,"Aug")) TM.tm~mon = else if (!strcmp(mon,"Sep")) TM.tm~mon = 8; else if (!strcmp(mon,"Oct")) TM.tm~mon = 9; else if (!strcmp(mon,"Nov")) TM.tm~mon = 10; else if (!strcmp(mon,"Dec")) TM.tm~mon = 11; else TM.tm~mon = 12; if ((args == 6) && (TM.tm~mon != 12)) TM.tm~sec = sc; TM.tm min = mn; TM.tm~hour = hr; TM.tm~mday = mday; TM.tm~year = yr - 1900; TM.tm isdst = -1; return(mktime(&TM)); <BR> <BR> else <BR> <BR> <BR> <BR> return(-1) void Time2String(int time,char *s, int printday) if (printday) strcpy(s,ctime~t*)(&time))); else strcpy(s, (ctime((time~t*) (&time)) + 4) ) ; // dont print day s[strlen(s) - 1] = 0; void CKeySearch::OnCompChange(int pred) CString type~str; GetDlgItemText(g~id[pred][COMP],type~str); int comptype = INT~SEARCH~TYPE; if (type~str == "String") comptype = STR SEARCH TYPE; if (type~str == "Short") comptype = SHORT~SEARCH~TYPE; m~pred~type[pred] = comptype; CComboBox * CBat = (CComboBox *) this->GetDlgItem(gid[pred] [AT]); CComboBox * CBmin = (CComboBox *) this->GetDlgItem(g~id[pred][MIN]); CComboBox * CBmax = (CComboBox *) this->GetDlgItem(gid[pred] [MAX]); CBat->ResetContent)); CBmin->ResetContent(); CBmax->ResetContent(); CBmin->AddString(""); CBmin->AddString(""); CBmin->AddString("ANY"); CBmax->AddString(""); CBmax->AddString(""); CBmax->AddString("ANY"); if (type~str == "Time") char tim[80]; Time2String(SHAREDATA(time),tim,0); CBat->AddString("TIME"); CBmin->SetCurSel(-1); CBmin->SetWindowText(tim); // CBmin->ReplaceSel(tim); CBmin->AddString(tim); // add to edit box too? CHmax->AddString(tim) ; // add to edit box too? } else if (comptype == STRSEARCH~TYPE) { CBat->AddString("CUSTOMER"); CBat->AddString("ITEM"); CBat->AddString("to~server"); CBa=->AddString("to~logical") ; } else if (comptype == INT~SEARCH~TYPE) { CBat->AddString("UID"); CBat->AddString("TID"); CBat->AddString("HOST"); CBat->AddString("QUANTITY"); lpRT rt = ROOT; while (rt = NextRT(rt)) CBmin->AddString(RT~NODE(rt));<BR> CBmax->AddString(RT~NODE(rt)); } else if (comptype == SHORT~SEARCH~TYPE) CBat->AddString("MODE"); CBat->AddString("SUB~MODE"); for (int id = 1; id < ID~OBJS; id++) GetDlgItem(g~id(pred][id])->EnableWindow(TRUE); GetDlgItem(IDSEARCHB)->EnableWindow(TRUE); // GetParentFrame()->SetMessageText("); cedit SetDlgItemText(IDC~SERSTAT;"");<BR> ((CComboBox *) this->GetDlgItem(g~id[pred][AT]))->SetCurSel(0); ((CComboBox *) this->GetDlgItem(g~id[pred][MAX]))->SetCurSel(0); ((CComboBox *) this->GetDlgItem(g~id[pred][MIN]))->SetCurSel(0);<B R> }<BR> void CKeySearch::OnSelchangeCompCb1() {OnCompChange(0);}<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> void CKeySearch: :OnSelchangeCompCb2 () OnCompChange (1);<BR> void CKeySearch::OnSelchangeCompCb3() {OnCompChange(2); void CKeySearch::ChangePredView(int pred, int act) int id; for (id = 0; id < ID~OBJS; id++) GetDlgItem(g~id[pred][id])->ShowWindow(act); for (id = 1; id < OPA; id++) GetDlgItem(g~id[pred][id])->EnableWindow(FALSE); if (act == SW~HIDE) for (id = C; id < AND; id++) ((CComboBox *) this->GetDlgItem(g~id[pred][id]))->SetCurSel (-1); <BR> <BR> <BR> if (act == SW~HIDE ) I // Get rid of the ghost of the combo box MFC bug?<BR> this->Invalidate(); this->UpdateWindow(); void CKeySearch::OnAndl() if (m~preds == 1) ChangePredView(i,SW~SHOW); <BR> <BR> <BR> m preds =<BR> else <BR> <BR> <BR> ChangePredView(l,SW~HIDE); ChangePredView(2,SW~HIDE); m~preds = 1; void CKeySearch::OnAnd2() if (mpreds == 2) ChangePredView(2,SW~SHOW); m preds = 3;<BR> else ChangePredView(2,SW~HIDE); m~preds = 2; void CKeySearch::CopyInput(int pred, int from, int to) CString s; int pos; GetDlgItemText(g~id[pred][from],s.GetBuffer(100),100); s.ReleaseBuffer(); pos = ((CComboBox *) this->GetDlgItem(gid[pred] [to]))->GetCurSel(); ((CComboBox *) this->GetDlgItem(g~id[pred][to]))->Delestring(0); ((CComboBox *) this->GetDlgItem(g~id[pred][to]))->InsertString(0,s); ((CComboBox *) this->GetDlgItem(g~id[pred][from]))->Delestring(1); ((CComboBox *) this->GetDlgItem(g~id[pred][from]))->InsertString(l,s) ; if (pos == 0) ((CComboBox *) this->GetDlgItem(g~id[pred][to]))->SetCurSel(0); <BR> <BR> <BR> }<BR> void CKeySearch::OnEditchangeMinCb1() {CopyInput(0,MIN,MAX);}<BR> void CKeySearch::OnEditchangeMinCb2() {CopyInput(1,MIN,MAX);}<BR> void CKeySearch::OnEditchangeMinCb3() {CopyInput(2,MIN,MAX);} void CKeySearch::OnEditchangeMaxCb1() {CopyInput (0,MAX,MIN);} void CKeySearch::OnEditchangeMaxCb2() {CopyInput (1,MAX,MIN);} void CKeySearch: :OnEditchangeMaxCb3 () Copylnput (2,MAX,MIN) void CKeySearch::OnSearchb() SMBUF b,B; QADMSEL key; OFORM order; CString ss,s,at~str,min~str, max~str; int i,at~int, sz, matches; GetDlgItem(IDSEARCHB)->EnableWindow(FALSE) CListBox* lb = (CListBox*) GetDlgItem(IDC~SEARCH~LB); lb->ResetContent(); SetDlgItemText(IDC~SERSTAT;""); // lb->SetTabStops(100); key.num~preds = m~preds; key.search~type = m search type; // SEARCH~ALL~ENT for (int p = 0; p < m~preds; p++) // Set min and max values min str = max str = GetD1ItemText(g id[p] [MIN],min str.GetBuffer(100),100); GetDlgItemText(g~id[p] [MAX], max~str.GetBuffer(100),100); GetDlgItemText(g id[p] [AT],at str.GetBuffer(100) ,100); min~str.RleaseBuffer(); max~str.ReleaseHuffer() at~str.ReleaseBuffer(); at int = GetDlgItemInt(g id[p] [AT],NULL,TRUE); strcpy(key.preds[p] .min~str~val,LPCTSTR(min str)); strcpy(key.preds[p].max~str~val,LPCSTR(max~str)); key.preds[p].min~int~val = GetDlgItemInt(g~id[p][MIN],NULL,TRUE); // min i key.preds[p].max~int~val = GetDlgItemInt(g-id [p] [MAX],NULL,TRUE); // max i key.preds[p].min~sh~val = $key.preds[p].min~int~val; // min short key.preds[p].max~sh~val = $key.preds[p].max~int~val; // max short if (min~str == "ANY"){ key.preds[p].min~switch = 0; key.preds[p].min~str~len = 0; else key.preds[p].min~switch = 1; key.preds[p].min~str~len = strlen(key.preds[p].min~str~val); if (max~str == "ANY") key.preds[p].max~switch = 0; key.preds[p].max~str~len = 0; else key.preds[p].max~switch = 1; key.preds[p].max~str~len = strlen(key.preds[p].max~str~val); if (at~str == "TIME") char tim[80]; if (max str == "NOW") key.preds[p].max~int~val = SHAREDATA(time); if ((i = String2Time(LPCTSTR(max~str))) != -1) key.preds[p].max~int~val = i; if (min str == "NOW") key.preds[p].min~int~val = SHAREDATA(time); if ((i = String2Time(LPCTSTR(min~str))) != -1) key.preds[p].min~int~val = // Time2String(key.preds[p] .min~int~val,tim,l); // s.Format("Time value:ts",tim); // SetDlgItemText(IDC~SERSTAT,s); if (at~str == "HOST") if (i = Name2IP(LPCTSTR(max~str))) key.preds[p].max~int~val = if (i = Name2IP(LPCTSTR(min~str))) key.preds[p] .min~int~val = // Find the offset if (at~str == "TIME") at~int = ((char *) &b.msgh.time) - ((char *) &b.msgh); if (at~str == "MODE") at int = ((char *) &b.msgh.mode) - ((char *) &b.msgh); if (at~str == "SUB~MODE") at int = ((char *) &b.msgh.sub~mode) - ((char *) &b.msgh); if (at~str == "UID") at~int = ((char *) &b.msgh.mid.uid) - ((char *) &b.msgh); if (at~str == "TID") at~int = ((char *) &b.msgh.mid.tid) - ((char *) &b.msgh); if (at~str == "HOST") at~int = ((char *) &b.msgh.mid.host) - ((char *) &b.msgh); if (at~str == "SIZE") at int = ((char *) &b.msgh.size) - ((char *) &b.msgh); if (at~str == "to server") at~int = ((char *) &b.msgh.to~server) - ((char *) &b.msgh); if (at~str == "to logical") at~int = ((char *) &b.msgh.to~logical) - ((char *) &b.msgh); if (at str == "CUSTOMER") at int = sizeof(MSGH) + ((char *) &order.cust) - ((char *) &order); if (at~str == "ITEM") at int = sizeof(MSGH) + ((char *) &order.item) - ((char *) &order); if (at~str == "QUANTITY") at~int = sizeof(MSGH) + ((char *) &order.qty) - ((char *) &order); key.preds[p].offset = at~int; key.preds[p] pred~type = m~pred~type [p]; // Get the list of key matches if (QSUCCESS == QsendAndReceive(QS[m~id],ADMINREQ MODE,QADM REQ SEL DATA, 0,sizeof)key) ,(char *) &key, sizeof(b.mdata),b.mdata,&sz,&b.msgh)) lpMID md = (lpMID) b.mdata; matches = sz / sizeof(MID); if (matches > 0) // char * h = IP2Name(md->host); for (i = C; i < matches ; i++) ss.Format("%s(%d,%d)", IP2Name(md->host),md->uid,md->tid); s.Format("%4d \t%s",i+1,ss ); lb->InsertString(-1,s); md = (lpMID) ((char *)md + sizeof(MID)); else lb->InsertString(-1,"No messages"); lb->UpdateWindow() //Sleep(200); md = (lpMID) b.mdata; IpOFORM po = (lpOFORM)B.mdata; for (i = 0; i < matches ; i++) { memcpy(B.mdata,md,sizeof(MID)); // Copy one mid s.Format("Wd Messages: Reading %d",matches,i); SetDlgItemText(IDC~SERSTAT,s); GetDlgItem(IDC SERSTAT)->UpdateWindow(); if (QSUCCESS == QsendAndReceive(QS[m~id],ADMINREQ~MODE,Q REQ MSG, 0,sizeof(mid),B.mdata, sizeof(B.mdata),B.mdata,&sz,&B.msgh)) ss.Format("%s(%d,%d)", IP2Name(md->host),md->uid,md->tid); if (B.msgh.size == sizeof(OFORM)) s.Format("W4d \t%s\t%-8s\t%2d t-10s",i + 1,ss,po->cust,po->qty,po else if (sz) s.Format("%4d \t%s\t%s",i + 1,ss,b.mdata); else s.Format("%4d \t%s\t<<Empty>>",i + 1,ss); lb->DeleteString(i); lb->InsertString(i,s); else s.Format("%d Error requesting %s(%d,%d)",i + 1,IP2Name(md->host),md- SetDlgItemText(IDC~SERSTAT,s); break; // Stop here md = (lpMID) ((char *)md + sizeof(MID)); else s.Format("Error - no reply") if (!strstr(LPCTSTR(s),"Error")) s.Format("%d Matches:",matches); SetDlgItemText(IDC~SERSTAT,s); Sleep(500); GetDlgItem(IDSEARCHB) - >EnableWindow (TRUE) ; void CKeySearch: :DnTimer(UINT nIDEvent) if (nIDEvent == KEYTIMER) int com,uncom; CString s; if ((g~pic[m~id] != m~pic)) GetDlgItem(IDC~KPICS[g~pic[m~id]]) - >ShowWindow(SW~SHOW) ; GetDlgItem(IDC~KPICS[m~pic])->ShowWindow(SW~HIDE); m~pic = g~pic[m~id]; // Set Title this->SetWindowText("View " + g~que[m~id] if (m~committed != (com = g~s[m~id] .committed~entries)) s.Format("%3d Committed entries.", (m~committed = com)); SetDlgItemText(IDC~COM~R,s); if (m~uncommitted != (uncom = g s[m~id] . pending~gets + g~s[m~id] .pending~p s.Format("%3d Uncommitted entries.", (m~uncommitted = uncom)); SetDlgItemText(IDC~UNCOM~R,s); if m~total~entries != (com + uncom)) s.Format("All %d entries." (m~total~entries = com + uncom)); SetDlgItemText(IDC~ALL~R,s); else CDialog::OnTimer(nIDEvent); void CKeySearch::OnAllR() { m~search~type = SEARCH~ALL~ENT;} void CKeySearch::OnComR() { m~search~type = SEARCH~COM~ENT;} void CKeySearch::OnUncomR() { m~search~type = SEARCH~UNCOM~ENT;} void CKeySearch::OnRButtonDown(UINT nFlags, CPoint point) GetParentFrame() - >SetMessageText("") this->Invalidate(); CDialog::OnRButtonDown(nFlags, point); // qman.cpp . Defines the class behaviors for the application.

#include "stdafx.h" #include "qman.h" #include "mainfrm.h" 4include "qmandoc.h" *include "qmanview.h" #ifdef DEBUG undef THIS FILE static char BASED~CODE THIS~FILE[] = ~FILE 4endif //////////////////////////////////////////////////////////// ///////////////// // CQmanApp BEGIN~MESSAGE~MAP(CQmanApp, CWinApp) //((AFX MSD MAP(CQmanApp) ON~COMMAND(ID~APP~ABOUT, OnAppAbout) // NOTE - the ClassWizard will add and remove mapping macros her<BR> <BR> <BR> <BR> // DO NOT EDIT what you see in these blocks of generated code<BR> //}}AFX~MSG~MAP // Standard file based document commands ON~COMMAND(ID~FILE~NEW, CWinApp::OnFileNew) ON COMMAND(ID FILE OPEN, CWinApp: :OnFileOpen) // Standard print setup command ON COMMAND(ID~FILE~PRINT~SETUP, CWinApp: :OnFilePrintsetup) END~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// // CQmanApp construction CQmanApp: : CQmanApp () // TODO: add construction code here, // Place all significant initialization in InitInstance //////////////////////////////////////////////////////////// ///////////////// // The one and only CQmanApp object CQmanApp theApp; ///////////////////////////// // CQmanApp initialization BOOL CQmanApp::InitInstance() { // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need.

Enable3dControls(); LoadStdProfileSettings(); // Load standard INI file options (including // Register the applications document templates. Document templates serve as the connection between documents, frame windows and views.

CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR~MAINFRAME, RUNTIME~CLASS(CQmanDoc), RUNTIME~CLASS(CMainFrame), // main SDI frame window RUNTIME~CLASS(CQmanView)); AddDocTemplate(pDocTemplate); // create a new (empty) document OnFileNew(); if (mlpCmdLine[0] // TODO: add command line processing here return TRUE; } ///////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX~DATA(CAboutDlg) enum { IDD = IDD~ABOUTBOX } //})AFX~DATA CFont m title~font; // Implementation protected: virtual void DoDataExchange(CdataExchange* pDX); // DDX/DDV support //( (AFX~MSG(CAboutDlg) virtual BOOL OnInitDialog(); //}}AFX~MSG DECLARE MESSAGE MAP() CAboutDlg::CAboutDlg() CDialog(CAboutDlg::IDD) //((AFX DATA INIT(CAboutDlg) //}}AFX~DATA~INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(CAboutDlg) //}}AFX~DATA~MAP BEGIN MESSAGE MAP(CAboutDlg, CDialog) //((AFX~MSG~MAP)CAboutDlg) //)JAFX~MSG~MAP <BR> <BR> END MESSAGE MAP() // App command to run the dialog void CQmanApp::OnAppAbout() CAboutDlg aboutolg; aboutDlg.DoModal(); //////////////////////////////////////////////////////////// ///////////////// // CQmanApp commands BOOL CAboutDlg::OnInitDialog() CDialog::OnInitDialog(); LOGFONT lf; memset(&lf,0,sizeof(LOGFONT)); strcpy(lf.lfFaceName,"Monotype Corsiva') lf.lfHeight = 24; m~title~font.CreateFontIndirect(&lf); <BR> <BR> GetDlgItem(IDC ABOUT1)->SetFont(&m title font); // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE // qman.h . main header file for the QMAN application #ifndef~AFXWIN~H~ &num error include 'stdafx.h' before including this file for PCH *endif 4include "resource.h" // main symbols //////////////////////////////////////////////////////////// ///////////////// // CQmanApp: // See qman.cpp for the implementation of this class class CQmanApp public CWinApp public: CQmanApp(); // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(CQmanApp) public virtual BOOL InitInstance(); //}}AFX~VIRTUAL // Implementation //{(AFX~MSG)CQmahApp) afx~msg void OnAppAbout(); // NOTE - the ClassWizard will add and remove member function // DO NOT EDIT what you see in these blocks of generated coue //}}AFX~MSG DECLARE~MESSAGE~MAP() // qmandoc.cpp : implementation of the CQmanDoc class #include "stdafx.h" #include "qman.h" #include "qmandoc.h" 4ifdef DEBUG *undef THIS FILE static char BASED~CODE~THIS~FILE[] = ~FILE~ #endif //////////////////////////////////////////////////////////// ///////////////// // CQmanDoc IMPLEMENT~DYNCREATE(CQmanDoc, Document) BGIN MESSAGE MAP(CQmanDoc, Document) //{{AFX~MSG~MAP(CQmanDoc) // NOTE - the ClassWizard will add and remove mapping macros her // DO NOT EDIT what you see in these blocks of generated code //}}AFX MSG MAP END~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// // CQmanDoc construction/destruction CQmanDoc::CQmanDoc() // TODO: add one-time construction code here CQmanDoc::-CQmanDoc() BOOL CQmanDoc::OnNewDocument() if (!CDocument::OnNewDocument()) return FALSE; // TODO: add reinitialization code here // (SDI documents will reuse this document) return TRUE; //////////////////////////////////////////////////////////// ///////////////// // CQmanDoc serialization void CQmanDoc::Serialize(CArchive& ar) if (ar.IsStoring()) // TODO: add storing code here else // TODO: add loading code here ////////////////////////////////// // CQmanDoc diagnostics #ifdef ~DEBUG void CQmanDoc::AssertValid() const { CDocument::AssertValid(); void CQmanDoc::Dump(CDumpContext& dc) const CDocument::Dump(dc); 4endif //~DEBUG //////////////////////////////////////////////////////////// ///////////////// // CQmanDoc commands // qmandoc.h interface of the CQmanDoc class // ////////////////////////////////////////////// class CQmanDoc : public CDocument { protected: // create from serialization only CQmanDoc(); DECLARE~DYNCREATE(CQmanDoc) // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(CQmanDoc) public: virtual BOOL OnNewDocument(); //}}AFX~VIRTUAL // Implementation public: virtual CQmanDoc(); virtual void Serialize(CArchive& ar); // overridden for document i/o #ifdef DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; Rendif protected: // Generated message map functions protected: //{{AFX~MSG(CQmanDoc) // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //}}AFX~MSG DECLARE MESSAGE MAP() // qmanview.h interface of the CQmanView class //////////////////////////////////////////////////////////// ///////////////// class CQmanView . public CFormView protected: // create from serialization only CQmanView(); DECLARE DYNCREATE(CQmanView) public: //( (AFX~DATA)CQmanView) enum( IDD = IDD~QMAN~FORM }; // NOTE: the ClassWizard will add data members here //)}AFX~DATA // Attributes int m maxtrack; CString m~que[3]; public: CQmanDoc* GetDocument(); // Operations public: // Overrides // ClassWizard generated virtual function overrides //( (AFx~VIRTUAL(CQmanView) public: virtual void OnInitialUpdate(); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void onEndPrinting(cDc* pDC, CPrintInfo* pInfo); virtual void OnPrint(CDC* pDC, CPrintInfo*); virtual void OnDraw(CDC* pDC); //}}AFX~VIRTUAL //void InitTrackBar(HWND hTrack, int IDMIN, int TMIN, int IDMAX, int TMAX, in //DWORD Poll(); //DWORD CQmanView::Poll(); void CQmanView::OpenQue(int i, int IDC~QUES); // meter painting void DrawKey(); void GetMeterBoxes(); void TestMeters(); void CQmanView::DrawMeter(int i); void CQmanView::CmdLine(int pass); void CQmanView::DrawKeyColor(int ID, int HS, COLORREF COL); // font CFont m~title~font; // Implementation public: virtual -CQmanView(); #ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) consist; 4endif protected: // Generated message map functions protected: //{{AFX~MSG(CQmanView) afx~msg void OnExit(); afx~msg void OnHScroll(UINT nSBCode, UINT npos, CScrollBar* pScrollBar); afx~msg void OnSelchangeQues1(); afxmsg void OnSelchangeQues2(); afx~msg void OnSelchangeQues3(); afx~msg void OnAdminb1(); afx~msg void OnAdminb2(); afxmsg void OnAdminb3(); afx~msg void OnDatab1(); afx~msg void OnDatab2(); afx~msg void OnDatab3(); afx~msg void OnTimer(UINT nIDEvent); afx msg void OnRButtonDown(UINT nFlags, CPoint point); //}}AFX~MSG DECLARE~MESSAGE~MAP() 4ifndef DEBUG // debug version in qmanview.cpp inline CQmanDoc+ CQmanView::GetDocument() { return (CQmanDoc*)m~pDocument; #endif User: root Host: bunny Class: bunny Job: stdin // qmanview.cpp implementation of the CQmanView class #include "stdafx.h" #include "qman.h" #include "qmandoc.h" #include "qmanview.h" #include "admindlg.h" //#include "datadlg.h" #include "KeySearch.h" //+++++++++++++ QLIB +++++++++++++++++++ #include "qlib.h" #include "qadmin.h" #include "rt.h" #define MYTIMER 100 #define TITLETIMER 101 #define MIN~POLL~DLY 100 #define MAX~POLL~DLY 5000 extern lpSMBUFH sm base; lpQHANDLE QS[3] = {NULL,NULL,NULL}; QADMSTATS g~s[3+3]; // 3 Current + 3 Old //HWND g~track[3]; HWND g~tmin[3]; HWND g~tmax[3]; HWND g~tlab[3]; CString g~que[] = int ALL~TEXT[] = {IDC~TMIN1,IDC~TMIN2,IDC~TMIN3, IDC~TMAX1,IDC~TMAX2,IDC~TMAX3, IDC~TLAB1,IDC TLAB2,IDC~TLAB3, <BR> <BR> IDC~ADMINB1,IDC~ADMINB2,IDC~ADMINB3, <BR> <BR> <BR> <BR> <BR> IDC~DATAB1,IDC~DATAB2,IDC~DATAB3, IDC~QUES1,IDC~QUES2,IDC~QUES3, IDC~EXIT,0,0,0}; int IDC~TMINS[] = IIDC~TMIN1,IDC~TMIN2,IDC~TMIN3 int IDC~TMAXS[] = {IDC~TAX1,IDC~TMAX2,IDC~TMAX3}; int IDC~TLABS[] = {IDC~TLAB1,IDC~TLAB2,IDC~TLAB3}, int IDC~METER[] = {IDC~METER1,IDC~METER2,IDC~METER3}; int IDC~PICS[3] [8] = {{IDC~QNONE1,IDC~QDOWN1,IDC~QSTOP1,IDC~QNOPUT1,IDC~QNOGET1 {IDC~QNONE4,IDC~QDOWN4,IDC~QSTOP4,IDC~QNOPUT4,IDC~QNOGET4 {IDC~QNONE5,IDC~QDOWN5,IDC~QSTOP5,IDC~QNOPUT5,IDC~QNOGET5 enum pics (QNONE,QDOWN,QSTOP,QNOPUT,QNOGET,OUP,QNOPG,OFULL} int g~pic[3+3+3]; int g~poll; int g~poll~delay = 2000; CFont g~text~font; typedef struct met ( // Thread parameters CRect b~rec; CRect c~rec; CRect p~rec; CRect g~rec; CRect h~rec; CRect f~rec; int commit,pendp,pendg,hole,free,min,max; MET, *pMET; MET g~met[3+4]; //+++++++++++++ QLIB +++++++++++++++++++ *ifdef DEBUG *undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE~ *endif //////////////////////////////////////////////////////////// ///////////////// // CQmanView IMPLEMENT~DYNCREATE(CQmanView, CFormView) BEGIN MESSAGE MAP(CQmanView, CFormView) //((AFx MSG MAP(CQmanView) ON~BN~CLICKED(IDC~EXIT, OnExit) ON~WM~HSCROLL() ON~CBN~SELCHANGE(IDC~QUES1, OnselchangeQuesl) ON CBN SELCHANGE(IDC QUES1, OnSelchangeQues2) ON-CBN-SELCHANGE(IDC-QUES3, OnSelchangeQues3) ON~BN~CLICKED(IDC~ADMINB1, OnAdminb1) ON~BN~CLICKED(IDC~ADMINB2, OnAdminb2) ON~BN~CLICKED(IDC~ADMINB3, OnAdminb3) ON~BN~CLICKED(IDC~DATAB1, OnDatabl) ON~BN~CLICKED(IDC~DATAB2, OnDatab2) ON~BN~CLICKED(IDC~DATAB3, OnDatab3) ON~WM~TIMER() <BR> <BR> ON () <BR> <BR> <BR> <BR> <BR> //T}AFX~MSG~MAP // Standard printing commands ON~COMMAND(ID~FILE~PRINT, CFormView::OnFilePrint) ON~COMMAND(ID~FILE~PREVIEW, CFormView::OnFilePrintPreview) END~MESSAGE~MAP() <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> /////////////////////////////////////<BR> // CQmanView construction/destruction CQmanView::CQmanView() <BR> <BR> CFormView(CQmanView: :100) <BR> <BR> <BR> <BR> <BR> <BR> <BR> //((AFX~DATA~INIT)CQmanView) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT // TODO: add construction code here CQmanView: -CQmanView() void CQmanView::DoDataExchange(CDataExchange* pDX) <BR> <BR> <BR> <BR> CFormView::DoDataExchange(pDX); <BR> <BR> <BR> //(IAFX DATA MAP(CQmanView) // NOTE: the ClassWizard will add DDX and DDV calls here //))AFX~DATA~MAP //////////////////////////////////////////////////////////// ///////////////// // CQmanView printing BOOL CQmanView::OnPreparePrinting(CPrintInfo* pInfo) // default preparation return DoPreparePrinting(pInfo); void CQmanView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) // TODO: add extra initialization before printing void CQmanView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) // TODO: add cleanup after printing void CQmanView::OnPrint(CDC* pDC, CPrintInfo*) // TODO: add code to print the controls //////////////////////////////////////////////////////////// ///////////////// // CQmanView diagnostics *ifdef ~DEBUG void CQmanView::AssertValid() consist CFormView::AssertValid(); void CQmanView::Dump(CDumpContext& dc) consist CFormView::Dump(dc); CQmanDoc* CQmanView::GetDocument() // non-debug version is inline ASSERT(m~pDocument->IsKindOf(RUNTIME~CLASS(CQmanDoc))); return (CQmanDoc*)m~pDocument; *endif //~DEBUG //////////////////////////////////////////////////////////// ///////////////// //CQmanView message handlers void CQmanView::OnExit() g~poll = 0; // Stop the threads AfxGetMainWnd()->DestroyWindow(); // // // // // // // // // // METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER METER b~rec Committ Pending holes Free c~rec p~rec h~rec f~rec void CQmanView: :GetMeterBoxes ()( for (int i=0;i<3i++){ GetDlgItem(IDC~METERS[i])->GetWindowRect(&g~met[i].b~rec) ; // Adjust coordantates for 0,0,1,b g~met[i].b~rec.right -= g~met[i].b~rec.left; g~met[i].b~rec.bottom -= g~met[i].b~rec.top; g~met[i].b~rec.left = g~met[i].b~rec.top = 0; g~met[i].c~rec.left = 0; // Commit always starts at 0,0 g~met[i].f~rec.right = g~met[i].b~rec.right; // Free always ends at max g~met[i].c~rec.top = g~met[i].p~rec.top = g~met[i].g~rec.top = g~met[i].h~rec.top = g~met[i].f~rec.top = g~met[i].b~rec.top; // 0 g~met[i].c~rec.bottom = g~met[i].p~rec.bottom = g~met[i].g~rec.bottom = g~met[i].h~rec.bottom = g~met[i].f~rec.bottom = g~met[i].b~rec.bottom; // All the same hight void CQmanView::DrawKeyColor(int ID, int HS, COLORREF COL)I CRect c~rec; CBrush *Brush; if ( HS == -1 pCBrush = new CBrush(COL); else pCBrush = new CBrush(HS,COL); GetDlgItem(ID)->GetWindowRect(&c~rec); // Adjust coordantates for 0,0,1,b c~rec.right -= c~rec.left; c~rec.bottom -= C~rec.top; c~rec.left = c~rec.top = 0; // The DC for the meter CDC* pCOLORDC = GetDlgItem(ID)->GetDC(); // Select this brush, save the old CBrush *pOldBrush = pCOLORDC->SelectObject(pCBrush); pCOLORDC->Rectangle(c~rec); GetDlgItem(ID)->Invalidate(); <BR> <BR> delete(pCBrush);<BR> <BR> <BR> ReleaseDC(pCOLORDC);<BR> void CQmanView::DrawKey(){<BR> DrawKeyColor(IDC~KEY~COM, -1, RGB(127,255,255)); DrawKeyColor(IDC~KEY~PENPUT, HS~BDIAGONAL, RGB(000,182,255)); DrawKeyColor(IDC~KEY~PENGET, HS~FDIAGONAL, RGB(000,182,255)); DrawKeyColor(IDC~KEY~HOLE, HS~DIAGCROSS, RGB(255,128,128));<BR> }<BR> <BR> &num define MAXPIXELS g~met[i].b rec.right<BR> <BR> <BR> void CQmanView: :TestMeters()T <BR> int c,pg,pp,h; // Pixel width of each rectangle<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> for (int i=0;i<3i++) { // If any change<BR> if((g~met[i].commit != g~s[i].committed~entrues) || (g~met[i].pendg != g~s[i].pending~gets ) || (g~met[i].pendp != g~s[i].pending~puts) || (g~met[i].hole != g~s[i].holey~entries ) I <BR> (g~met[i].free != g.s[i].num~free~entries) || (g~met[i].max != g.s[i].max~entries) ) { if (!g~s[i].max~entries) g~s[i].max~entries=1; // No divide by zero // Update old values (g~met[i].commit = g~s[i].committed~entries; (g~met[i].pendg = g~s[i].pending~gets; (g~met[i].pendp = g~s[i].pending~puts; (g~met[i].hole = g~s[i].holey~entries; (g~met[i].free = g~s[i].num~free~entries; (g~met[i].max = g~s[i].max~entries; // c,pp,pg,h,f are points on a line between sin, max scaled to #pixels c = 0 + (MAXPIXELS * g~met[i].commit)/g~met[i].max; pp= c + (MAXPIXELS * g~met[i].pendp)/g~met[i].max; pg=pp + (MAXPIXELS * g~met[i].pendg)/g~met[i].max; h =pg + (MAXPIXELS * g~met[i].hole)/g~met[i].max; // f = h + (MAXPIXELS * g~met[i].free)/g~met[i].max; // constant // Make 5 rectangles to fill with colors // g~met[i].c~rec.left = 0; // constant g~met[i].c~rec.right = c; g~met[i].p~rec.left = c; g~met[i].p~rec.right = pp; g~met[i].g~rec.left = pp; g~met[i].g~rec.right = pg; g~met[i].h~rec.left = pg; g~met[i].h~rec.right = h; g~met[i].f~rec.left = h; // g~met[i].f~rec.right = g~met[i].max; // constant DrawMeter(i); void CQmanView::DrawMeter(int i){ // Create the Brush CBrush *pCBrush = new CBrush( RGB(127,255,255) CBrush *pPBrush = new CBrush( HS BOlAGONAL, RGB(000,182,255) ); CBrush *pGBrush = new CBrush( HS~FDIAGONAL, RGB(000,182,255) CBrush *pHBrush = new CBrush( HSDIAGCROSS, RGB(255,128,128) // The DC for the meter CDC* pCOLORDC = GetDlgItem(IDC~METERS[i])->GetDC(); // Create a PEN // CPen *pQPen = new CPen(PS~SOLID, 3,RGB(0,0,255)); // CPen *pOldPen = pXDC->SelectObject(pQPen); // Select this brush, save the old CBrush *pOldBrush = <BR> <BR> pCOLORDC->SelectObject(pCBrush); <BR> <BR> <BR> pCOLORDC->Rectangle(g~met[i].c~rec); pCOLORDC->SelectObject(pPBrush); <BR> <BR> pCOLORDC->Rectangle(g~met[i].p~rec); <BR> <BR> <BR> <BR> <BR> <BR> <BR> pCOLORDC->SelectObject(pGBrush); pCOLORDC->Rectangle(g~met[i].g~rec); <BR> <BR> <BR> <BR> <BR> pCOLORDC->SelectObject(pHBrush); <BR> <BR> <BR> <BR> pCOLORDC->Rectangle(g~met[i] .h~rec); pCOLORDC->SelectStockObject(WHITE~BRUSH); pCOLORDC->Rectangle(g~met[i] .f~rec); pCOLORDC->SelectObject(&pOldBrush); // Reset the brush GetDlgItem(IDC~METERS[i])->Invalidate(); delete(pCBrush); delete(pPBrush); <BR> <BR> delete(pGBrush); <BR> <BR> <BR> delete(pHBrush); ReleaseDC(pCOLORDC); /* //////////////////////////////////// // Init the track bar // o TPS 100 // // |------------[]------------| // // MIN MAX // //////////////////////////////////// void InitTrackBar(HWND track, HWND HMIN, int TMIN, HWND HMAX, int TMAX) CString s; //HWND hTrack = GetDlgItem(ID)->m~hWnd; ::SendMessage(hTrack,TBM~SETRANGEMIN,TRUE,TMIN); ::SendMessage(hTrack,TBM~SETRANGEMAX,TRUE,TMAX); ::SendMessage(hTrack,TBM~SETTICFREQ,1,TRUE); ::SendMessage(hTrack,TBM~SETPOS,TRUE,TMIN); ::SendMessage (hTrack, TBM~SETSELSTART, TRUE, TMIN) ; // Select from start // Track Bar lables //s.Format("%d",TMIN); SetDlgItemText(IDMIN,s); // s.Format("%d",TMAX); SetDlgItemText(IDMAX,s); s.Format("%d",TMIN); :SendMessage(HMIN,WM~SETTEXT,0,(LPARAM)(LPCTSTR) s); s.Format("%d",TMAX); :SendMessage(HMAX,WM~SETTEXT,0,(LPARAM)(LPCTSTR) s); } */ DWORD Poll(LPVOID qnum) { MSGH mh; CString s,sl; int used = 1; // Clear the track bar if not in use int i = (int)(qnum); g~poll = 1; while(g~poll) { if (QS[i]) { int sz; used++; if (QS[i]->open~time) ::SendMessage(g~tlab[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) "STARTING..." if (QSUCCESS >= (QsendAndReceive(QS[i],ADMINREQ~MODE,QADM~REQ~STATS, 0, <BR> <BR> sizeof(g~s[i]),(char *)&g~s[i],&sz,&mh))){<BR> if ((mh.mode == ADMINREP~MODE || mh.mode == ACK~MODE ) && (sz > 0)){ // Note: now, mode is ADMINREP~MODE if local or if (!memcmp( &g~s[i+3], &g~s[i],sizeof(QADMSTATS) )) // nothing c goto skip; memcpy( &g~s[i+3], &g~s[i],sizeof(QADMSTATS)); // set history // Assign a picture if (g~s[i].qget~state && g~s[i].qput-state) g pic[i] = QUP; else if (g~s[i].qget~state) g~pic[i] = QNOPUT; else if (g~s[i].qput~state) g~pic[i] = QNOGET; else g~pic[i] = QNOPG; if (g~s[i].num~free~entries == 0) g~pic[i] = QFULL; if (QS[i]->open~time) QS[i]->open~time = 0; // Get rid of "START <BR> <BR> <BR> <BR> <BR> s.Format("%s:%s at %s has %d entries",&g~s[i].physical~qname,&g<BR> s1.Format("%d",g~s[i].max~entries);<BR> <BR> <BR> <BR> ::SendMessage(g~tlab[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) s);<BR> <BR> ::SendMessage(g~tmax[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) s1);<BR> ::SendMessage(g~tmin[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) "0");<BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> else g~pic[i] = QDOWN; ::SendMessage(g~tlab[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) "BAD REPLY QS[i] = NULL; Sleep(3000); else g~pic[i] = QDOWN; .:SendMessage(g tlab[i],WM SETTEXT,O,(LPARAM)(LPCTSTR) "TIME OUT"); QS[i] = NULL; Sleep(3000); else ( // No open que // if (g~que[i] == // g~pic[i] = QNONE;<BR> <BR> if (used) used = 0; // The track bar will now be clear memset(&g~s[i],0,sizeof(g~s[i])); g~s[i+3] .max~entries = 1; //::SendMessage(g~track[i],TBM~SETPOS,TRUE,0) //::SendMessage(g track[i],TBM SETSELEND,TRUE,O); :SendMessage(g~tlab[i3,WM SETTEXT,O,(LPARAM)(LPCTSTR) "No Que"); ::SendMessage(g~tmin[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) ""); ::SendMessage(g~tmax[i],WM~SETTEXT,0,(LPARAM)(LPCTSTR) ""); } skip: Sleep(g~poll~delay); } // While loop return(1) void CQmanView::CmdLine(int pass) CString parm,value,line,nline; int i,poll; line = AfxGetApp()->m~lpCmdLine; while (2 <= (i = sscanf(LPCTSTR(line),"%s %s %[^@]", parm.GetBuffer(100) ,value.GetBuffer(100) ,nline.GetBuffer(100) ))) parm.MakeUpper(); if (parm == "POLL") sscanf(LPCTSTR(value),"Wd",&poll); if((MIN~POLL~DLY <= poll) && (poll <= MAX-POLL-DLY)) g~poll~delay = poll; if (parm == "1") CComboBox * CB = (CComboBox *) this->GetDlgItem(IDC QUES1); CB->SelectString(-l,value); OnSelchangeQuesl(); if (parm == "2") CComboBox * CB = (CComboBox *) this->GetDlgItem(IDC QUES2); CB->SelectString(-l,value); OnSelchangeQues2(); if (parm == "3") CComboBox * CB = (CComboBox *) this->GetDlgItem(IDC~QUES3); CB->SelectString(-1,value); OnSelchangeQues3(); line = LPCTSTR(nline); nline =""; int g~poll~delay~old; void CQmanView::OnTimer(UINT nIDEvent) { // Select ICONS if (nIDEvent == MYTIMER){ for (int i=0;i<3i++) if (g~pic[i] != g~pic[i+3]){ GetDlgItem(IDC~PICS[i][g~pic[i]])->ShowWindow(SW~SHOW); GetDlgItem(IDC~PICS[i][g~pic[i+3]])->ShowWindow(SW~HIDE); g~pic[i+3] = g~pic[i]; TestMeters(); else if (nIDEvent == TITLETIMER) GetParentFrame()->SetwindowText("QMAN"); KillTimer(TITLETIMER); DrawKey(); else <BR> <BR> <BR> CFormView::OnTimer(nIDEvent); void CQmanView::OnInitialUpdate() LOGFONT lf; CString s; CFormView: :OnInitialUpdate(); // Default from vc++ // Set frame size = Form size GetParentFrame()->RecalcLayout(); ResizeParentToFit(FALSE); ResizeParentToFit(TRUE); GetMeterBoxes(); DrawKey() for (int i=0;i<3i++){ // g~track[i] = GetDlgItem(IDc-TRAcKs[i])->m-hWnd; g~tmin[i] = GetDlgItem(IDC~TMINS[i])->m~hWnd; g~tmax[i] = GetDlgItem(IDC~TMAXS[i])->m~hWnd; g~tlab[i] = GetDlgItem(IDC~TLABS[i])->m~hWnd; g~pic[i] = QNONE; // man g~pic[i+3] = QSTOP; // yellow // LIST OF QUEUES // CListBox* lh = (CListBox*) GetDlgItern(IGC~QUE) // lb->InsertString(-1,"Q1"); // lb->InsertString(-1,"Q2"); // lb->SetCurSel(0); //Q = Qopen)'Q1",PUTTING,0,0,C,0,C) CComboBox * CB1 = (CComboBox *) this->GetDlgItem(IDC~QUES1); CComboBox * CB2 = (CComboBox *) this->GetDlgItem(IDC QUES2); CComboBox * CH3 = (CComboBox *) this->GetDlgItem(IDC~QUES3); CB1->ResetContent(); CB2->ResetContent(); CB3->ResetContent(); // List all logical queues // APPS: [physical],logicall,logical2, [physical],logical, if (sm~base = AttachSharedMemory())( lpRT rt = RTROOT; while(rt = NextRT(rt)) char *e,*s = RT~APPS(rt); // Starts after the first letter while (s = strchr(s,',')) { ( // Ends at next if (e = strchr(++s,',')) { *e = 0; if ((!strchr(s,'[')) && *s) CB1->AddString(s); // lb->InsertString(-1,s) CB2->AddString(s); // lb->InsertString(-1,s) CB3->Addstring)s) ; // lb->Insertstring(-1,s) else GetParentFrame()->SetMessageText("QNETD not running(?) please start it."); MessageBox("QNETD not running, please start it.",0,MB~ICONSTOP);<BR> //AfxGetMainWnd()->DestroyWindow(); } CB1->AddString(**); //CB1->SetCurSel(1); CB2->AddString(""); //CB2->SetCurSel(l); CB3->AddString(**); //CB3->SetCurSel(1); DWORD id; CreateThread(NULL,O, (LPTHREAD~START ROUTINE) Poll,(LPVOID) 0,0,&id); CreateThread(NULL,0,(LPTHREAD~START~ROUTINE) Poll,(LPVOID) 1,0,&id); CreateThread(NULL,0,(LPTHREAD~START~ROUTINE) Poll,(LPVOID) 2,0,&id); CmdLine(1); SetTimer(MYTIMER,250,NULL); // 1/4 second SetTimer(TITLETIMER,100,NULL); // Fonts memset(&lf,0,sizeof(LOGFONT)); ((ifdef BIGFONT lf.lfHeight = 18; #else lf.lfHeight = 13; endif g~text~font.CreateFontIndirect(&1f); strcpy(lf.lfFaceName,"Matura MT Script Capitals"); strcpy(lf.lfFaceName,"Monotype Corsiva"); lf.lfHeight = 32; m~title~font.CreateFontIndirect(&1f); GetDlgItem(IDC~TITLE)->SetFont(&m~title~font); i = O; while (ALL TEXT[i]) GetDlgItem(ALL~TEXT[i++])->SetFont(&g~text~font); void CQmanView::OnHScroll(UINT nSBCode, UINT npos, CScrollBar* pScrollBar) // TODO: Add your message handler code here and/or call default // CFormView::OnHScroll(nSBCode, npos, pScrollBar); // Removed by derek void CQmanView::OpenQue(int i, int IDC~QUES) CString s,que; int stat; GetDlgItemText(IDC~QUES,que.GetBuffer(100),100); que.ReleaseBuffer(); if (que != g~que[i]) I // the user changed the open que name GetParentFrame()->SetWindowText("QMAN") if (que == g~pic[i] = QNONE; g~que[i] = s = "No Que will be used"; Qclose(&QS[i],0); else g~pic[i] = QSTOP; s.Format("Opening que ts",que); memset(&g~s[i],0,sizeof(QADMSTATS)) GetParentFrame()->SetMessageText(s); // MessageBox(s); causes 2nd pass if (QS[i] = Qopen(que.GetBuffer(0),PUT~MODE,0,Q~FAILOVER,&stat,0,0) <BR> g~que[i] = que; s.Format("Qopen(%s)",que); // QS[i]->time~out = 1000; // 1 second <BR> <BR> else <BR> s.Format("Qopen(ts) Error td",que,stat); CComboBox * CB = (CComboBox *) this->GetDlgItem(IDC~QUES); CB->SelectString(-1,""); g~que[i] = ""; g~pic[i] = QDOWN;<BR> } } GetParentFrame()->SetMessageText(s); } <BR> <BR> <BR> <BR> <BR> <BR> <BR> }<BR> void CQmanView::OnSelchangeQues1(){ OpenQue(0,IDC~QUES1);}<BR> <BR> void CQmanView::OnSelchangeQues2(){ OpenQue(1,IDC~QUES2);}<BR> void CQmanView::OnSelchangeQues3(){ OpenQue(2,IDC~QUES3);} void CallAdm(int id)( if )QS[id]) CAdminDlg adm; adm.m~id = id; adm.DoModal(); void CallData(int id)( if (OS [id] CKeySearch d; // CdataDlg d.m~id = id; d.DoModa1(); } } <BR> <BR> <BR> <BR> void CQmanView::OnAdminb1() { CallAdm(0); }<BR> <BR> void CQmanView::OnAdminb2() { CallAdm(1); }<BR> <BR> <BR> <BR> <BR> <BR> void CQmanView::OnAdminb3() CallAdm(2); <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> void CQmanView::OnDatab1() { CallData(0); }<BR> <BR> <BR> <BR> void CQmanView::OnDatab2() CallData(l);<BR> void CQmanView::OnDatab3() { CallData(2); void CQmanView::OnDraw(CDC* pDC) DrawMeter(0); DrawMeter(l); DrawMeter(2); DrawKey(); CFormView::OnDraw(pDC); // this->SetWindowText("Qman av"); // GetParentFrame()->SetWindowText("QQMAN") void CQmanView::OnRButtonDown(UINT nFlags, CPoint point) GetParentFrame()->SetMessageText(""); this->Invalidate(); CFormView::OnRButtonDown(nFlags, point); User: root Host: bunny Class: bunny Job: stdin // bufdlg.cpp implementation file *include "stdafx.h" *include "netman.h" #include "bufdlg.h" // #include "buferdlg.h" //+++++++++++++ QLIB +++++++++++++++++++ #define Q~LIB #include "qlib.h" 4include "rt.h" 4include "netadmin.h" #define BUFTIMER 101 extern lpSMBUFH sm~base; extern SMBUFH g~smhead; extern SMBUFH g~smhead~old; extern Cstring g~node; extern int g~polling; extern int g~remote node; extern int g~pic; extern lpQHANDLE g~q; extern lpRT g~rt; BS g~bs~old; BSA g~bsa, g~bsa~old; int g~lbsel; extern int g~CBufDlg~state; //+++++++++++++ QLIB +++++++++++++++++++ 4ifdef DEBUG #undef THIS FILE static char BASED~CODE THIS~FILE[] = FILE 4endif ///////////////////////////////////////// // CBufDlg dialog CBufDlg::CBufDlg(CWnd* pParent /*=NULL*/) CDialog(CBufDlg::IDD, pParent) //({AFx DATA INIT(CBufDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void CBufDlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(CBufDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN MESSAGE MAP(CBufDlg, CDialog) //((AFX MSG MAP(CBufDlg) ON~WM~TIMER() ON LBN DBLCLK(IDC BUFLB, OnDblclkBuflb) ONZLBNZSELCHANGE(DC~BUFLB, OnSelchangeBuflb) ON WM CREATE() ON~WM~RBUTTONDOWN() //}}AFX~MSG~MAP END~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// //////////////////////////////////////////////////////////// ///////////////// //////////////////////////////////////////////////////////// ///////////////// //////////////////////////////////////////////////////////// ///////////////// // CBufDlg message handlers BOOL CBufDlg::OnInitDialog() { CDialog::OnInitDialog(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE int g~BufPoll = 0; DWORD BufPoll(LPVOID ttype) int i,type = (int)(ttype); if (g~remote~node) { if ((g~BufPoll++ == 0 ) && g~q && g~rt) QsendAndReceive(g-q,QNETDREQ~MODE,NETMAN~SMBUFS, 0,0,0, (sizeof(BSA)),(char *) &g~bsa,O,O); else ( // pack local data into structure lpBSA b = &g bsa b->nsbuf = SHAREDATA(nsbuf); for (i=O; i < SHAREDATA(nsbuf); i++) memcpy(&b->bs[i], SMBUFADDR(i) , sizeof(BS) g~BufPoll = 0; return(1); int g~display~a~buf = 0; #define BUFHS g~bsa.bs[g-lbsel] #define MSGHS g~bsa.bs[g~lbsel].msgh #define SHOWITEM(X) GetDlgItem(X)->ShowWindow(SW~SHOW); #define HIDEITEM(X) GetDlgItem(X)->ShowWindow(SW~HIDE); void CBufDlg::OnTimer(UINT nIDEvent) if (nIDEvent == BUFTIMER){ DWORD id; int i,copy=0;; CString s; if (g~CBufDlg~state >= 10) OnOK(); if ( memcmp(&g~bsa,&g~bsa~old, sizeof(BS) * g~bsa.nsbuf ))( copy++; // will copy memcpy(&g~bsa~old,&g~bsa,sizeof(BSA)); CListBox* lb = (CListBox*) GetDlgItem(IDC~BUFLB); lb->ResetContent(); for (i=0; i < g~bsa.nsbuf; i++) s.Format("%5d %d d tSt,i+1, g~bsa.bs[i].status, g~bsa.bs[i].sub~sta lb->InsertString(-1,s); // g~display~a~buf 1 = init; 2 = run ; 3 = stop; switch (g~display~a~buf) { case 1: // run g~display~a~buf = 2; // run SHOWITEM(IDC~DATE); SHOWITEM(IDC~DATEL); SHOWITEM(IDC~MID); SHOWITEM(IDC~MIDL); SHOWITEM(IDC~TO); SHOWITEM(IDC~TO2); SHOWITEM(IDC~TOL); SHOWITEM(IDC~FROM); SHOWITEM)IDC FROML); SHOWITEM(IDC~PB0); SHOWITEM(IDC~PB1); SHOWITEM(IDC~PB2); SHOWITEM(IDC~PB3); SHOWITEM(IDC~PB4); SHOWITEM(IDC~PB5); SHOWITEM(IDC PB6); SHOWITEM(IDC~PB7); SetDlgItemText(IDC~PB8, g~node + "'s " + BUFHS.name + " buffer"); case 2: // run if (memcmp(&BUFHS,&g bs old,sizeof(BS))) ( // some change memcpy(&g~bs~old,&BUFHS,sizeof(BS)); if (MSGHS.time) SetDlgItemText(IDC~DATE,ctime(&MSGHS.time)); else SetDlgItemText(IDC~DATE,UNo date"); s.Format("from=%s uid=%d tid=%d",((char *)IP2Name(MSGHS.mid.host)),M SetDlgItemText(IDC~MID,s); s.Format("%s 5 ",MSGHS.to server,MSGHS.to logical); SetDlgItemText(IDC~TO,s); s.Format("%s port=%d buf=%d",IP2Name(MSGHS.to~node),MSGHS.to~port @<BR> SetDlgItemText(IDC~TO2,s); s.Format("buffer %d (reply to buffer %d)",MSGHS.from~smbuf,MSGHS.rep SetDlgItemText(IDC~FROM,s); break; case 3: // disable g~display~a~buf = 0; // off HIDEITEM(IDC~DATE); HIDEITEM(IDC~DATEL); HIDEITEM(IDC~MID); HIDEITEM(IDC~MIDL); HIDEITEM(IDC TO); HIDEITEM(IDC~TO2); HIDEITEM(IDC~TOL); HIDEITEM(IDC~FROM); HIDEITEM(IDC~FROML); HIDEITEM(IDC~PB0); HIDEITEM(IDC~PB1); HIDEITEM(IDC~PB2); HIDEITEM(IDC~PB3); HIDEITEM(IDC~PB4); HIDEITEM(IDC~PB5); HIDEITEM(IDC~PB6); HIDEITEM(IDC~PB7); SetDlgItemText(IDC~PB8,"Detail"); if (!g remote~node); Createhread(NULL,O, (LPTHREAD START ROUTINE) BufPoll,(LPVOID) 0,0,&id); else CDialog::OnTimer(nIDEvent); } } /* void CBufDlg::OnLButtonDblClk(UINT nFlags, CPoint point) { // If inside the list box CListBox * LB= (CListBox *) this->GetDlgItem(IDC~BUFLB); g~lbsel = LB->GetCurSel(); CBufDlg d; d.DoModal(); // else CDialog::OnLButtonDblClk(nFlags, point); void CBufDlg::OnDblclkBuflb() // CString s ; CListBox * LB= (CListBox *) this->GetDlgItem(IDC BUFLB); g~lbsel = LB->GetCurSel(); // Somtimes returns out-of-bounds nunmber if ((g~lbsel >=0 )&&(g~lbsel < g~bsa.nsbuf)) if(strcmp(g~bsa.bs[g~Ibsel] .name,"empty")) g~display~a~buf = 1; // init // CBuferDlg d; // d.DoModal(); void CBufDlg: :OnSelchangeBuflb() if (g~display~a~buf) g~display a buf = 3; // stop void CBufGlg: :OnOK() g~CBufDlg~state = 20; KillTimer(BUFTIMER); this->DestroyWindow(); //CDialog::OnOK(); int CBufDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) if (CDialog::OnCreate(lpCreateStruct) == -1) return -1; this->SetWindowText(gnode + n buffers"); memset(&g~bsa~old,0,sizeof(BSA)); SetTimer(BUFTIMER,1000,NULL); // 1 second g~CBufDlg~state = 2; return 0; void CBufDlg::OnRButtonDown(UINT nFlags, CPoint point) GetParentFrame()->SetMessageText(""); this->Invalidate(); CDialog::OnRButtonDown(nFlags, point); User: root Host: bunny Class: bunny Job: stdin // bufdlg.h header file //////////////////////////////////////// // CBufDlg dialog class CBufDlg : public CDialog { // Construction public: CBufDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //I(AFX~DATA(CBufD19) enum ( IDD = IDD~BUF~DLG }; // NOTE: the ClassWizard will add data members here //J)AFX~DATA // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(CBufDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support<BR> //))AFX~VIRTUAL // Implementation protected: // Generated message map functions //{{AFX~MSG(CBufDlg) virtual BOOL OnInitDialog(); afx~msg void OnTimer(UINT nIDEvent); afx~msg void OnDblclkBuflb(); afx~msg void OnSelchangeBuflb(); virtual void OnOK(); afx~msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx msg void OnRButtonDown(UINT nFlags, CPoint point); //}}AFX~MSG DECLARE~MESSAGE~MAP() }; // buferdlg.cpp implementation file #include "stdafx.h" 4include "netman.h" *include "buferdlg.h" #define Q~LIB #define BUFFERTIMER 103 #include "qlib.h" #include 'netadmin.h' extern CString g~node; extern BSA g~bsa; extern int g~lbsel; extern BS g~bs~old; *ifdef DEBUG undef THIS FILE static char BASED CODE THIS~FILE[] = ~FILE~ *endif ///////////////////////////////////////////// // CBuferDlg dialog CBuferDlg::CBuferDlg(CWnd* pParent /*=NULL*/) CDialog(CBuferDlg::IDD, pParent) //{{AFX~DATA~INIT(CBuferDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void CBuferDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange pDX); //{{AFX~DATA~MAP(CBuferDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN MESSAGE MAP(CBuferDlg, CDialog) //{{AFX~MSG~MAP(CBuferDlg) ON WM TIMER() //T}AFX~MSG MAP END~MESSAGE~MAP() ////////////////////////////// // CBuferDlg message handlers BOOL CBuferDlg::OnInitDialog() { CDialog::OnInitDialog(); // TODO: Add extra initialization here memset(&g~bs~old,0,sizeof(BS)); SetTimer(BUFFERTIMER,1000,NULL); // 1 second return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE #define BUFHS g~bsa.bs[g~lbsel] #define MSGHS g-bsa.bs[g~lbsel].msgh #define POST lb->InsertString(-1,s) void CBuferDlg::OnTimer(UINT nIDEvent) if (nIDEvent == BUFFERTIMER) { if (memcmp(&BUFHS, &g~bs~old, sizeof(BS))) { // some change memcpy(&g~bs~old, &BUFHS,sizeof(BS)); CString s,t; CListBox * lb= (CListBox *) this->GetDlgItem(IDC~BUFLB); t = ctime(&MSGHS.time); s = "Message: "+ t; POST; s.Format("Mode=%4d Sub=%4d",MSGHS,mode,MSGHS.sub~mode); POST; s.Format("MID host=%x tid=%d",MSGHS.mid.host,MSGHS.mid.tid); POST; s.Format("To %x Port %d Buffer %x",MSGHS.to~node,MSGHS.to~port.MSGHS.to s.Format("From %d Reply~to %d", MSGHS.from~smbuf,MSGHS.reply~smbuf); POS s.Format("To physical: %s logical: %s",MSGHS.to~server,MSGHS.to~logical this->SetWindowText(gnode + "'s " + BUFHS.name + " buffer else CDialog::OnTimer(nIDEvent); // buferdlg.h : header file //////////////////////////////////////// // CBuferDlg dialog class CBuferDlg : public CDialog { // Construction public: CBuferDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //( (AFX~DATA(CBuferGlg) enum ( IDD = IDD~BUFFER ); // NOTE: the ClassWizard will add data members here //}}AFX~DATA // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(CBuferDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL // Implementation protected: // Generated message map functions //{{AFX~MSG(CBuferDlg) virtual BOOL OnInitDialog(); afx msg void OnTimer(UINT nIDEvent); //}TAFX MSG DECLARE MESSAGE MAP() // mainfrm.cpp : implementation of the CMainFrame class 4include "stdafx.h" #include "netman.h" #include "mainfrm.h" 4ifdef DEBUG 4undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE~; 4endif ////////////////////////////////////////// // CMainFrame IMPLEMENT~DYNCREATE(CMainFrame, CFrameWnd) BEGIN~MESSAGE MAP(CMainFrame, CFrameWnd) //{{AFX~MSG~MAP(CMainFrame) // NOTE - the ClassWizard will add and remove mapping macros her // DO NOT EDIT what you see in these blocks of generated code ON WM CREATE() //}}AFX~MSG~MAP END~MESSAGE~MAP() ........................................

// arrays of IDs used to initialize control bars // toolbar buttons - IDs are command buttons static UINT BASED CODE buttons[] = // same order as in the bitmap 'toolbar.bmp' ID~FILE~NEW, <BR> <BR> ID~FILE~OPEN, <BR> <BR> <BR> <BR> ID~FILE~SAVE, ID~SEPARATOR, ID~EDIT~CUT, ID EDIT~COPY, ID~EDIT~PASTE, ID~SEPARATOR, ID~FILE~PRINT, ID~APP~ABOUT, static UINT BASED CODE indicators[] = ID SEPARATOR, // status line indicator ID~INDICATOR~CAPS, ID~INDICATOR~NUM, ID~INDICATOR~SCRL, }; ////////////////////////////////////// // CMainFrame construction/destruction <BR> <BR> <BR> <BR> CMainFrame::CMainFrame()<BR> {<BR> <BR> <BR> <BR> // TODO: add member initialization code here CMainFrame:-CMainFrame() int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m~wndToolBar.Create(this) || !m~wndToolBar.LoadBitmap(IDR~MAINFRAME) || !m-wndToolBar.SetButtons(buttons, sizeof(buttons)/sizeof(UINT))) TRACE0("Failed to create toolbar\n"); return -1; // fail to create /* Derek's remove tool bar */ m~wndToolBar.ShowWindow(SW~HIDE); if (!m wndStatusBar.Create(this) II m~wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) TRACEO)"Failed to create status bar\n"); return -1; // fail to create // TODO: Delete these three lines if you don't want the toolbar to // be dockable m~wndToolBar.EnableDocking(CBRS-ALIGN~ANY); EnableDocking(CBRS~ALIGN~ANY); DockControlBar(&m~wndToolBar); // TODO: Remove this if you don't want tool tips m wndToolBar.SetBarStyle(m wndToolBar.GetBarStyle() I<BR> <BR> CBRS~TOOLTIPS I CBRS~FLYBY); return 0; } ///////////////////////// // CMainFrame diagnostics #ifdef ~DEBUG void CMainFrame: :AssertValid() consist CFrameWnd::AssertValid(); void CMainFrame::Dump(CDumpContext& dc) const CFrameWnd::Dump(dc); *endif //~DEBUG //////////////////////////////////////////////////////////// ///////////////// // CMainFrame message handlers // mainfrm.h interface of the CMainFrame class // class CMainFrame : public CFrameWnd protected: // create from serialization only CMainFrame(); DECLARE~DYNCREATE(CMainFrame) // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(CMainFrame) //))AFX~VIRTUAL // Implementation public: virtual CMainFrame(); #ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; endif protected: // control bar embedded members CStatusBar m~wndStatusBar; CToolBar m~wndToolBar; // Generated message map functions protected: //((AFX~MSG(CMainFrame) afx~msg int OnCreate(LPCREATESTRUCT lpcreateStruct); // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //))AFX~MSG DECLARE~MESSAGE~MAP() // netmadoc.cpp implementation of the CNetmanDoc class *include "stdafx.h" 4include "netman.h" #include "netmadoc.h" 4ifdef DEBUG #undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE~ #endif //////////////////////////////////////////////////////////// ///////////////// // CNetmanDoc IMPLEMENT~DYNCREATE(CNetmanDoc, CDocument) BEGIN MESSAGE MAP(CNetmanDoc, Document) //((AFX~MSG MAP(CNetmanDoc) // NOTE - the ClassWizard will add and remove mapping macros her // DO NOT EDIT what you see in these blocks of generated code //}}AFX~MSG~MAP END MESSAGE MAP() //////////////////////////////////////////////////// // CNetmanDoc construction/desctruction CNetManDoc::CNetmanDoc() <BR> <BR> {<BR> // TODO: add one-time construction code here CNetmanDoc:: CNetmanDoc() BOOL CNetmanDoc::OnNewDocument() if (!CDocument::OnNewDocument()) return FALSE; // TODO: add reinitialization code here // (SDI documents will reuse this document) return TRUE; } //////////////////////////////////////////////////////////// //////////////// // CNetmanDoc serialization void CNetmanDoc::Serialize(CArchive& ar) if (ar.IsStoring()) // TODO: add storing code here else // TODO: add loading code here //////////////////////////////////// // CNetmanDoc diagnostics #ifdef ~DEBUG void CNetmanDoc::AssertVlaid() const { CDocument: :AssertValid(); void CNetmanDoc::Dump(CDumpContext& dc) const CDocument::Dump(dc); #endif //~DEBUG //////////////////////////////////////////////////////////// ///////////////// // CNetmanDoc commands // netmadoc.h : interface of the CNetmanDoc class<BR> // class CNetmanDoc : public Document protected: // create from serialization only CNetmanDoc() DECLARE DYNCREATE(CNetmanDoc) // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //I(AFX~VIRTUAL(CNetmanDoc) public: virtual BOOL OnNewDocument(); //))AFX~VIRTUAL // Implementation public: virtual ~CNetmanDoc(); virtual void Serialize(CArchive& ar); // overridden for document i/o #ifdef DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) consist; #endif protected: // Generated message map functions protected: //{{AFX~MSG(CNetmanDoc) // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //))AFX~MSG DECLARE~MESSAGE~MAP() // netman.cpp Defines the class behaviors for the application.

4include "stdafx.h" #include "netman.

#include "mainfrm.h" 4 include "netmadoc.h" #include "bufdlg.h" #include "netmavw.h" ((ifdef DEBUG ((undef THIS~FILE static char BASED~CODE THIS~FILE[] = FILE #endif ///////////////////////////////////////////// <BR> <BR> //<BR> CNetmanApp BEGIN~MESSAGE~MAP(CNetmanApp, CWinApp) //((AFX~MSG~MAP)CNetmanApp) ON~COMMAND(ID~APP~ABOUT, OnAppAbout) // NOTE - the ClassWizard will add and remove mapping macros her // DO NOT EDIT what you see in these blocks of generated code //))AFX~MSG~MAP // Standard file based document commands <BR> <BR> ON~COMMAND(ID~FILE~NEW, CWinApp::OnFileNew)<BR> ON-COMMAND (ID-FILE-OPEN, CWinApp: :OnFileOpen) // Standard print setup command ON~COMMAND(ID~FILE~PRINT~SETUP, CWinApp::OnFilePrintSetup) END~MESSAGE~MAP() ////////////////////////// // CNetmanApp construction CNetmanApp::CNetmanApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance ///////////////////////////////////// // The one and only CNetmanApp object CNetmanApp theApp; ///////////////////////////////////// // CNetmanApp initialization BOOL CNetmanApp::InitInstance() { // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need.

Enable3dControls(); LoadStdProfilesSettings(); // Load standard INI file options (including // Register the application's document templates. Document templates // serve as the connection between documents, frame windows and views.

CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR~MAINFRAME, RUNTIME CLASS(CNetmanDoc), RUNTIME~CLASS(CMainFrame), // main SDI frame window RUNTIME~CLASS(CNetmanView)); AddDocTemplate(pDocTemplate); // create a new (empty) document OnFileNew(); if (mlpCmdLine[0] != // TODO: add command line processing here return TRUE; /////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX~DATA(CAboutDlg) enum ( IDD = IDD ABOUTBOX ); //)}AFX~DATA CFont m~title~font; // Implementation protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //( (AFX MSG(CAboutDlg) virtual BOOL OnInitDialog(); //))AFX~MSG DECLARE MESSAGE MAP() CAbout::CAboutDlg() CDialog(CAboutDlg::IDD) { //{{AFX~DATA~INIT(CAboutDlg) //}}AFX~DATA~INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); // (AFX~DATA~MAP (CAboutDlg) //}}AFX~DATA~MAP BEGIN~MESSAGE~MAP(CAboutDlg, CDialog) //((AFX MSG MAP(CAboutolg) <BR> //}}AFX~MSG~MAP END~MESSAGE~MAP() // App command to run the dialog void CNetmanApp: :OnAppAbout() CAboutDlg aboutolg; aboutDlg.DoModal(); //////////////////////////////////////// // CNetmanApp commands BOOL CAboutDlg::OnInitDialog() { CDialog::OnInitDialog(); LOGFONT If; memset(&lf,0,sizeof(LOGFONT)); <BR> strcpy(lf.lfFaceName,Monotype Corsiva"); lf.lfHeight = 24; m~title~font.CreateFontIndirect(&lf); GetDlgItem(IDC~ABOUT1) ->SetFont(&m~title~font); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE // netman.h : main header file for the NETMAN application #ifndef ~AFXWIN~H~ #error include 'stdafx.h' before including this file for PCH *endif *include "resource.h" // main symbols ////////////////////////////////////////////////////// // CNetmanApp: // See netman.cpp for the implementation of this class // class CNetmanApp . public CWinApp public: CNetmanApp() // Overrides // ClassWizard generated virtual function overrides //((AFX VIRTUAL(CNetmanApp) public: virtual BOOL InitInstance(); //}}AFX~VIRTUAL // Implementation //{{AFX~MSG(CNetmanApp) afx~msg void OnAppAbout(); // NOTE - the ClassWizard will add and remove member function <BR> <BR> // DO NOT EDIT what you see in these blocks of generated coue <BR> <BR> //))AFX~MSG DECLARE~MESSAGE~MAP() }; // netmavw.cpp implementation of the CNetmanView class #include "stdafx.h" *include "netman.

4include "bufdlg.h" #include "netmadoc.h" &num include "netmavw.h" #include "rtdlg.h" //+++++++++++++ QLIB +++++++++++++++++++ &num include "qlib.h" #include "rt.h" #include "netadmin.h" #define MYTIMER 100 #define SHUTDOWNTIME 101 extern lpSMBUFH sm~base; SMBUFH g~smhead; SMBUFH g~smhead~old; CString g~node; int g~polling = 0; int g~remote~node = 0; int g~CBufDlg~state = 0; int g~pic = lOC~GREEN; int g~con = IDC~IS~CON; lpQHANDLE g~q = NULL; lpRT g~rt; int IDC~LAN[] = {IDC~GREEN, IDC~YELLOW, IDC~RED} //+++++++++++++ QLIB +++++++++++++++++++ *ifdef DEBUG 4undef THIS FILE static char BASED~CODE THIS~FILE[] = ~~FILE~~ 4endif <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> ///////////////////////////////////////////<BR> // CNetmanView IMPLEMENT~DYNCREATE(CNetmanView, CFormView) BEGIN~MESSAGE~MAP(CNetmanView, CFormView) //{{AFX~MSG~MAP(CNetmanView) ON CBN SELCHANGE(IDC~NODES, OnSelchangeNodes) ON~WM~TIMER() ON~BM~CLICKED(IDC~EXITB, OnExitb) ON~BN~CLICKED(IDC~BUFB, OnBufb) ON~BN~CLICKED(IDC~ROUTEB, OnRouteb) OIUBNrCLICKED(IDCIFOLCLEARB, OnFolclearb) ON~WM~RBUTTONDOWN() ON~CBN~SETFOCUS(IDC~NODES, OnSetfocusNodes) //T)AFX~MSG~MAP // Standard printing commands ON~COMMAND(ID~FILE~PRINT, CFormView::OnFilePrint) ON COMMAND(ID FILE~PRINT PREVIEW, CFormView: :OnFilePrint Preview) END MESSAGE MAP() /////////////////////////////////////// // CNetmanView construction/destruction CNetmanView::CNetmanView() : CFormView(CNetmanView::IDD) { //{{AFX~DATA~INIT(CNetmanView) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT // TODO: add construction code here CNetmanView::~CNetmanView() { } void CNetmanView::DoDataExchange(CDataExchange* pDX) { CFormView::DoDataExchange(pDX); //{{AFX~DATA~MAP(CNetmanView) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP } ////////////////////////////////////////////////////// // CNetmanView printing BOOL CNetmanView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); void CNetmanView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) // TODO: add extra initialization before printing void CNetmanView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) // TODO: add cleanup after printing void CNetmanView::OnPrint(CDC* pDC, CPrintInfo*) { //TODO: add code to print the controls } //////////////////////////////////////////////// // CNetmanView diagnostics #ifdef ~DEBUG void CNetmanView: :AssertValid() const CFormView: :AssertValid(); void CNetmanView::Dump(CDumpContext& dc) const CFormView::Dump(dc); CNetmanDoc* CNetmanView::GetDocument() // non-debug version is inline ASSERT(m~pDocument->IsKindOf(RUNTIME~CLASS(CNetmanDoc))); return (CNetmanDoc*)m~pDocument; 4endif //~DEBUG //////////////////////////////////////////////////////// // CNetmanView message handlers void CNetmanView::LoadList() // List the possible nodes { CComboBox * CB1 = (CComboBox *) this->GetDlgItem(IDC-NODES) CB1->ResetContent(); if (sm~base = AttachSharedMemory()) I lpRT rt = RTROOT; while(rt = NextRT(rt)) CB1->Addstring(RT~NOGE(rt)) ; // lb->InsertString(-1,s) void CNetmanView::OnInitialUpdate() // Set frame size = Form size GetParentFrame()->Recalclayout() ; ResizeParentToFit(FALSE); ResizeParentToFit(TRUE); m~d = NULL; /* */ LoadList(); if (!sm~base) { MessageBox("QNETD not running, please start it." ,0,MB~ICONSTOP); <BR> <BR> SetTimer(SHUTDOWNTIME,10,NULL); // Show one PIC g~pic = IDC~RED; g~con = IDC~IS~CON; g~node = SHAREDATA (hostname); Light (IGC YELLOW); Con(IDC~NO~CON); CComboBox * CB1 = (CComboBox *) this->GetDlgItem(IDC~NODES); CB1->SelectString(-1,SHAREDATA(hostname)); SetTimer(MYTIMER,100O,NULL); // 1 second CFormView::OnInitialUpdate(); void CNetmanView::Light(int pic)( if (g pic != pic) GetDlgItem(g~pic)->ShowWindow(SW~HIDE); GetDlgItem(pic)->ShowWindow(SW~SHOW); g~pic = pic; void CNetmanView::Con(int con) if (g con != con) GetDlgItem(g~con)->ShowWindow(SW~HIDE); GetDlgItem(con)->ShowWindow(SW~SHOW); g~con - con; int clock~stop; void CNetmanView::OnSelchangeNodes() CComboBox * CB= (CComboBox *) this->GetDlgItem(IDC~NODES); g~CBufDlg~state = 10; CB->GetLBText( CB->GetCurSel() ,g~node.GetBuffer(100)); g~node.ReleaseBuffer(); if (node == SHAREDATA(hostname)) g~remote~node = 0; else g~remote~node = 1; CString s; s.Format("ts's NETMAN",LPCTSTR(g~node)); GetParentFrame()->SetWindowText(s); SetDlgItemText(IDC FOLBOX, g~node + "'s fail over list"); // Light (IDC~YELLOW); clock stop = 5; g~smhead.time = g~smhead~old.time = 0; void CNetmanView: :UpdateStats() int i; CString s; lpSMBUFH b,bb = &g~smhead~old; // int local = (node == SHAREDATA(hostname)); if (g~remote~node) b = &g~smhead else b = sm~base; // Is the date moving? if(b->time == bb->time) clock~stop++; else clock~stop = 0; bb->time = b->time if (b->stat.warn != bb->stat.warn) SetDlgItemInt(IDC~WARN, (bb->stat.warn = b->stat.warn) if (b->stat.fail != bb->stat.fail) SetDlgItemInt(IDC~WARN, (bb->stat.fail = b->stat.fail) if (b->stat.puts != bb->stat.puts) SetDlgItemInt(IDC~PUTS, (bb->stat.puts = b->stat.puts) if (b->stat.gets != bb->stat.gets) SetDlgItemInt(IDC~GETS, (bb->stat.gets = b->stat.gets) if (b->stat.tx != bb->stat.tx) SetDlgItemInt(IDC~SENT, (bb->stat.tx = b->stat.tx) ) if (b->stat.rx != bb->stat.rx) SetDlgItemInt(IDC~RECEIVED, (bb->stat.rx = b->stat.rx) if (b->rt~rev != bb->rt~rev) SetDlgItemInt(IDC~RTREV, (bb->rt~rev = b->rt~rev) if (b->rt ver != bb->rt~ver) SetDlgTtemInt(IDC RTER,(bb->rt ver = b->rt~ver) if ((b->rt~rev != bb->rt rev)) ( // RT and FOL update: if (!b->failed servers) ( // No Failed servers GetDlgItem(IDC~FOL)->ShowWindow(SW~HIDE); // GetDlgItem(IDC~FOLBOX)->ShowWindow(SW~HIDE); GetDlgltem(IOC~FOLCLEARB) ->ShowWindow(SW~HIDE); <BR> else GetDlgItem(IDC~FOL)->ShowWindow(SW~SHOW); GetDlgItem(IDC~FOLBOX)->ShowWindow(SW~SHOW); GetDlgItem(IDC~FOLCLEARB)->ShowWindow(SW~SHOW); CListBox* lb = (CListBox*) GetDlgItem(IDC~FOL); lb->Resetcontent (); lb->InsertString(-1,"==== FAILOVERS IN USE ===="); for (i=O; i<b->failed~servers; i++) s.FORMAT("%5d %6s %x %d %d",i+1, b->FO[i].name,b->FO[i].ip,b->FO[i].puts,b->FO[i] .gets); lb->InsertString(-1,s); } } } /* if (!memcmp(&b->stat,&bb->stat,sizeof(b->stat)) || moved) { CListBox* lb = (CListBox*) GetDlgItem(IDC~STATS); lb->ResetContent(); s.Format("opens=%d closes=%d openrep=%d",b->stat.opens,b-stat.closes,b s.Format("puts=%d gets=%d tx=%d rx=%d",b->stat.puts,b->stat.gets,b->stat.@ s.Format("commit=%d abort=%d warn=%d fail=%d",b->stat.commit,b->stat.abort moved++; if(local) for(i = 0; i<b->nsbufi++){ CListBox* lb = (CListBox*) GetDlgItem (IDC~STATS); lb->ResetContent(); s.Format("%5d %d %s",);lb->InsertString(-1,s); } */ /* <BR> <BR> if((b->hostip != bb->hostip) ||<BR> <BR> (b->diag !=bb->diag) || moved ) { s.Format("%s @ %x",b->hostname,b->hostip); SetDlgItemText (IDC T1,s); s.Format("nsbuf=%d diag=%d timeout=%d sec",b->nsbuf,b->diag, (b->time out/1 <BR> <BR> s.Format("failed=<id rt~rev=d",b->failed~servers,b->rt rev); SetDlgItemTex memcpy(bb,b,sizeof(*b)); } */ if (clock~stop > 10) Light (IDC~RED); else if (clock~stop > 5 ) Light(IDC~YELLOW); else Light(IDC~GREEN); if (g~remote~node) Con(IDC~ISCON~PIC); else Con(IDC~ISNOTCON~PIC); } DWORD Poll(LPVOID ttype) { int type = (int)(ttype); if(g~polling++) return(1); if (g~node ~ ~ "" || (!g~remote~node) // Not null or local <BR> <BR> goto BYE;<BR> <BR> <BR> <BR> <BR> <BR> <BR> if (!g~q)<BR> g~q = Qopen("QNETD",PUT~MODE,0,0,0,0,0);<BR> if (!g~q) goto BYE;<BR> if (!g~rt || II RT~NODE(g rt) != g~node)<BR> <BR> <BR> if (!(g~rt = ServerByNode (g~node.GetBuffer(0))))<BR> goto BYE; g~q->msgh.to~node = RT~IP(g~rt); g~q->msgh.to~port = RT~PORT(g~rt); <BR> <BR> <BR> <BR> <BR> strcpy(g~q->msgh.to~logical,"QNETD");<BR> <BR> <BR> <BR> <BR> strcpy(g~q->msgh.to~server,"QNETD");<BR> <BR> <BR> <BR> <BR> QsendAndReceive (g~q,QNETDREQ MODE,NETMAN SMBUFH, 0,0,0, (sizeof(SMBUFH) - MAXRTSIZE), (char *) &g~smhead,0,0); BYE: g~polling = 0; return(l); void CNetmanView::OnTimer(UINT nIDEvent) if (nIDEvent == MYTIMER) ( DWORD id; if (g~CBufDlg~state == 20) g~CBufDlg~state = 0; GetDlgItem(IDC~BUFB)->EnableWindow(TRUE); UpdateStats(); if (!g~remote~node); CreateThread(NULL,O, (LPTHREAD~START~ROUTINE) Poll,(LPVOID) 0,0,&id); else if (nIDEvent == SHUTDOWNTIME) OnExitb(); else CFormView::OnTimer(nIDEvent); void CNetmanView::OnExitb() AfxGetMainWnd()->DestroyWindow(); // CBufDlg d; // d.DoModal(); void CNetmanView::OnBufb() GetDlgItem(IDC~BUFB)->EnableWindow(FALSE); g~CBufDlg~state = 1; // Starting if (m d == NULL) m~d = new CBufDlg(this); m~d->Create(IDD~BUF~DLG); void CNetmanView::OnRouteb() CRtDlg d; d.DoModal(); void CNetmanView::OnFolclearb() if (g~remote~node) { QsendAndReceive (g~q, QNETDREQ~MODE, NETMAN~CLR~FOL, 0,0,0, 0,0,0,0); else SHAREDATA(failed~servers) = 0; void CNetmanView::OnRButtonDown(UINT nFlags, CPoint point) GetParentFrame()->SetMessageText(""); this->Invalidate(); CFormView::OnRButtonDown(nFlags, point); void CNetmanView::OnSetfocusNodes() LoadList(); // netmavw.h . interface of the CNetmanView class class CNetmanView : public CFormView { protected: // create from serialization only CNetmanView(); DECLARE DYNCREATE(CNetmanView) public: //{{AFX~DATA(CNetmanView) enum( IDD = IDD~NETMAN~FORM ); // NOTE the ClassWizard will add data members here //})AFX~DATA // CString m~node; int g~pic; CBufDlg *m~d; // Attributes public: CNetmanDoc* GetDocument(); // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(CNetmanView) public: virtual void OnInitialUpdate(); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnPrint(CDC* pDC, CPrintInfo*); //}}AFX~VIRTUAL void UpdateStats(); void LoadList(); void Light(int pic); void Con(int pic); // Implementation public: virtual ~CNetmanView(); 4ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) consist; *endif protected: // Generated message map functions <BR> <BR> protected:<BR> //( (AFX~MSG(CNetmanView) afx~msg void OnSelchangeNodes(); afx~msg void OnTimer(UINT nIDEvent);<BR> <BR> <BR> <BR> <BR> <BR> <BR> afx~msg void OnExitb();<BR> afx~msg void OnBufb();<BR> <BR> <BR> afx~msg void OnRouteb();<BR> <BR> <BR> <BR> afx~msg void OnFolclearb(); afxmsg void OnRButtonDown(UINT nFlags, CPoint point); afx msg void OnSetfocusNodes(); //}}AFX~MSG DECLARE~MESSAGE~MAP() 4ifndef ~DEBUG // debug version in netmavw.cpp inline CNetmanDoc* CNetmanView::GetDocument() { return (CNetmanDoc*)m~pDocument; #endif //( (NO~DEPENDENCIES)) // Microsoft Developer Studio generated include file.

// Used by netman.rc // #define IDD~ABOUTBOX 100 #define IDD~NETMAN~FORM 101 #define IDR~MAINFRAME 128 #define IDR~NETMANTYPE 129 #define IDD~BUF~DLG 130 #define IDR~QUP 131 #define IDD~BUFFER 131 #define 100 RTDLG 132 #define IDR~QDOWN 134 #define IDC~DOWN~PIC 134 #define IDR~DOWN~PIC 134 #define IDR~QNONE 136 define IDR~MAN 136 #define IDR~NET 137 #define IDR~NETMAN 138 #define IDR~LANTERN 139 #define IDR~LAN~RED 140 #define IDR~LAN~GRN 141 #define IDR~LAN~YEL 142 #define IDR~NO~CON 143 #define IDR~IS~CON 144 #define IDR~3DIMES 145 #define IDR~3DMDS 146 #define IDC~NODES 1000 &num #define IDC~ISCON~PIC 1001 #define INC IS CON 1001 #define IDC~ISNOTCON~PIC 1002 #define IDC~NO~CON 1002 #define IDC~GREEN 1003 #define IDC~RED 1004 #define IDC~YELLOW 1005 #define IDC~EXITB 1009 #define IDC~ROUTEB 1010 define IDC~BUFB 1011 #define IDC~TRANB 1012 #define IDC~FOLCLEARB 1013 #define IDC~GETS 1016 #define INC PUTS 1017 #define IDC~SENT 1018 #define IDC~RECEIVED 1019 #define IDC~FAIL 1020 #define IDC~WARN 1021 #define IDCRTREV 1022 #define IDC~RTVER 1023 #define IDC~FOL 1024 #define IDC~BUFLB 1025 #define IDC~BUFER~LB 1025 #define IDC~RTREE 1026 #define IDC~GETB 1027 #define IDC~COPYB 1027 #define IDC~BROADCCASTB 1028 #define IDC~FOLBOX 1028 #define IDC~TREELB 1029 #define IDC~PB1 1030 #define IDC~CONLB 1030 #define IDC~PB2 1031 #define IDC~PB3 1032 #define IDC~PB4 1033 #define IDC~PB5 1034 #define IDC~PB6 1035 #define IDC~PB7 1036 #define IDC~PB8 1037 #define IDC~DATE 1038 #define IDC~MID 1039 #define IDC~TO 1040 #define IDC~FROM 1041 #define IDC~PB0 1042 #define IDC~DATEL 1043 #define IDC~MIDL 1044 #define IDC~TOL 1045 #define IDC~FROML 1046 #define IDC~TO2 1047 #define IDC~RT~TITLE 1048 #define IDC~LOGO 1049 #define IDC~ABOUT1 1050 // Next default values for new objects #ifdef APSTUDIO~INVOKED *ifndef APSTUDIO READONLY SYMBOLS #define ~APS~3D~CONTROLS 1 #define ~APS~NEXT~RESOURCE~VALUE 134 #define ~APS~NEXT~COMMAND~VALUE 32771 #define ~APS~NEXT~CONTROL~VALUE 1051 #define ~APS~NEXT~SYMED~VALUE 101 *endif *endif // rtdlg.cpp : implementation file #include "stdafx.h" #include "netman.h" 4include "rtdlg.h" //+++++++++++++ QLIB +++++++++++++++++++ #define Q~LIB #include "qlib.h" #include "rt.h" #include "netadmin.h" #include "qnetd.h" *define RTTIMER 104 extern lpSMBUFH sm~base; extern SMBUFH g~smhead; extern SMBUFH g~smhead~old; extern CString g~node; extern int g~polling; extern int g~remote~node; extern int g~pic; extern lpQHANDLE g~q; extern lpRT g~rt; //+++++++++++++ QLIB +++++++++++++++++++ 4ifdef DEBUG 4undef THIS FILE static char BASED~CODE THIS~FILE[] = ~FILE~ *endif //////////////////////////////////////////////////////////// ///////////////// // CRtDlg dialog CRtDlg::CRtDlg(CWnd* pParent /*=NULL*/) . CDialog(CRtDlg::IDD, pParent) //((AFX DATA INIT(CRtOlg) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void CRtDlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(CRtDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN MESSAGE MAP(CRtDlg, CDialog) //((AFX MSG~MAP(CRtDlg) ON~BN~CLICKED(IDC~COPYB, OnCopyb) ON~BN~CLICKED(IDC~BROADCASTB, OnBroadcastb) ON~WM~RBUTTONDOWN() <BR> <BR> //}}AFX~MSG~MAP<BR> <BR> END~MESSAGE~MAP()<BR> <BR> /////////////////////////////////////////////////// // CRtDlg message handlers /* typedef struct ~TV~ITEM { tvi UINT mask; HTREEITEM hItem; // item this structure refers to UINT state; UINT stateMask; LPSTR pszText; int cchTextMax; int iImage; int iSelectedImage; int cChildren; LPARAM lParam; // 32-bit value to associate with item } TV~ITEM; */ BOOL CRtDlg::OnInitDialog() { CDialog::OnInitDialog(); CString s; // int i; /* TV~INSERTSTRUCT TreeCtrlItem; TreeCtrlItem.hParent = TVI~ROOT; TreeCtrlItem.hInsertAfter = TVI~LAST; TreeCtrlItem.item.mask = TVIF~TEXT | TVIF PARAM; TreeCtrlItem.item.pszText = "Fire"; TreeCtrlItem.item.lParam = 0; HTREEITEM hTreeIteml = m Property.Insertltem(&TreeCtrlItem); Treectrlltem.hparent = hTreeIteml; TreeCtrlItem.item.pszText = "Decay"; TreeCtrlItem.item.lParam = 1; m~Property.InsertItem(&TreeCtrlItem); TreeCtrlItem.item.pszText = "Flammability"; TreeCtrlItem.item.lParam = 2; m~Property.IsertItem(&TreeCtrlItem); TreeCtrlItem.item.pszText = "Maximum Heat"; Treectrlltem.item.lParam = 3; m~Property.IsertItem(&TreeCtrlItem); TreeCtrlItem.hParent = TVI~ROOT; TreeCtrlItem.item.pszText = "Render"; TreeCtrlItem.item.lParam = 0; HTREEITEM hTreeItem2 = m~Property.InsertItem(&TreeCtrlItem) ; TreeCtrlItem.hParent = hTreeItem2; TreeCtrlItem.item.pszText = "Smoothness"; TreeCtrlItem.item.lParam = 6; <BR> <BR> m~Property.InsertItem(&TreeCtrlItem); <BR> <BR> <BR> <BR> <BR> <BR> <BR> m Property.Expand(hTreeIteml,TVE EXPAND); m~Property.Expand(hTreeItem2,TVE~EXPAND); */ /* TV~ITEM tvi; TV~INSERTSTRUCT tvins; tvins.hParent = TVI~ROOT; tvins.hInsertAfter = TVI~LAST;// TVI~FIRST tvins.item = tvi; tvi.mask = TVIF~TEXT I TVIF~PARAM; tvi.hItem = NULL; tvi.state = NULL; tvi.stateMask = NULL; tvi.pszText = "TEXZT"; tvi.cchTextMax = 6; tvi.iImage = NULL; tvi.iSelectedImage = NULL; tvi.cChildren = NULL; tvi.mask = NULL; tvi.lParam = NULL; HTREEITEM til, ti = NULL; CTreeCtrl * CT; CT = (CTreeCtrl *) this->GetDlgItem(IDC~RT~TREE) til = CT->InsertItem(&tvins); tvi.pszText = "TEXZT"; tvi.lParam = 1; ti = CT->InsertItem(&tvins); tvi.pszText = "TEXZT"; tvi.lParam = 2; ti = CT->InsertItem(&tvins); CT->Expand(ti1,TVE~EXPAND); */ // GetDlgItem(IDC~COPYB)->ShowWindow(SW~SHOW); s.Format("%s's Routing Table (rev %d/%d)",g~node,g~smhead.rt~ver,g~smhead.rt~ SetDlgItemText(IDC RT TITLE,s); if (gremote~node) ( - GetDlgItem(IDC~COPYB)->EnableWindow(TRUE); GetDlgItem(IDC~BROADCASTB)->EnableWindow(FALSE); } else { GetDlgItem(IDC~COPYB)->EnableWindow(FALSE); GetDlgItem(IDC BROADCASTB)->EnableWindow(TRUE); CListBox* lb = (CListBox*) GetDlgItem(IDC~TREELB); lb->ResetContent(); CString indent; SMBUF b; lpRT rt = RTROOT; // Get the RT Data if (g remote node) memset(&b.mdata,0, (sizeof(b.mdata))); QsendAndReceive (g~q,QNETDREQ~MODE, NETMAN RT READ, 0,0,0, (sizeof(b.mdata)),(char*) &b.mdata,0,0); rt = (RT*) &b.mdata } else rt = RTROOT; // Load the box while(rt = NextRT(rt)) s.Format("%-12s %s",RT~NODE(rt),RT~NTYPE(rt)); lb->InsertString(-1,s) <BR> <BR> <BR> <BR> <BR> <BR> char t, *e, *s = RT~APPS(rt); <BR> while (strlen(s) > 2 if (*s == [') ( indent = " "; s++; } else if (*s == ']') indent = " "; s++; else if (*s == ',') I indent = " "; else if (e = strpbrk(s,",]")) { t = *e; *e = NULL; lb->InsertString(-1,indent + *e = t; s = e; } else { break; // should never happen } } } } /* // Load the sockets box lb = (CListBox*) GetDlgItem(IDC~CONLB); lb->ResetContent(); if (g~remote~node) { memset(&b.mdata,0,(sizeof(b.mdata))); QsendAndReceive(g~g,QNETDREQ~MODE,NETMAN~SOCKETS, 0,0,0, (sizeof(b.mdata)),(char*) &b.mdata,0,0); lpSSA sa = (SSA*) &b.mdata for (i = 0;i < sa->sockets i++) s.Format("%x %d",sa->ss[i].ip, sa->ss[i].port); lb->InsertString(-1,indent); } } else { // local /* lpST stp = STroot; while (stp) s.Format("%x %d",stp->ip, stp->port); lb->InsertString(-1,indent); } } */ return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE void CRtDlg::OnCopyb() GetDlgItem(IDC~COPYB)->EnableWindow(FALSE); if (g~q) if (CopyRT(gq->msgh'.tonode)) GetDlgItem(IDC~BROADCASTB)->EnableWindow(TRUE); GetDlgItem(IDC~COPYB)->EnableWindow(TRUE); void CRtDlg::OnBroadcastb() GetDlgItem(IDC~BROADCASTB)->EnableWindow(FALSE); <BR> <BR> <BR> <BR> <BR> BroadcastRT();<BR> GetDlgItem(IDC~BROADCASTB)->EnableWindow(TRUE); void CRtDlg::OnRButtonDown(UINT nFlags, CPoint point) GetParentFrame ()->SetMessageText (""); this->Invalidate(); CDialog::OnRButtonDown(nFlags, point); // rtdlg.h : header file //////////////////////////////////////// // CRtDlg dialog class CRtDlg : public CDialog // Construction <BR> <BR> public:<BR> CRtDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX~DATA(CRtDlg) enum ( IDD = IDD~RTDLG ) // NOTE: the ClassWizard will add data members here //))AFX~DATA // Overrides // ClassWizard generated virtual function overrides //( (AFX~VIRTUAL(CRtDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL // Implementation protected: // Generated message map functions <BR> <BR> //((AFX MSG(CRtDlg) <BR> virtual BOOL OnInitDialog(); afx~msg void OnCopyb(); afx~msg void OnBroadcastb(); afx msg void OnRButtonDown(UINT nFlags, CPoint point); //}}AFX~MSG DECLARE~MESSAGE~MAP() // stdafx.cpp . source file that includes just the standard includes // netman.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h" // stdafx.h include file for standard system include files, // or project specific include files that are used frequently, but are changed infrequently #include <afxwin.h> // MFC core and standard components #include <afxext.h> // MFC extensions #include <afxcmn.h> // MFC TREE // dbdlg.cpp implementation file #include "stdafx.h" //#include "oentrvw.h" #include "oentry.h" *include "dbdlg.h" *include "Odlg.h" // #define ORACLE causes oraread() orawrite() to be exteraly defined 4ifndef ORACLE #define ORACLE *endif &num include "oraomq.h" 4ifdef DEBUG #undef THIS FILE static char BASED CODE THIS~FILE[] = FILE *endif #define DB~TIMER 200 #define INIT~TIMER 10 define RESTOCK~QTY 100000 int g~orders~mode = 0; // Display orders or items extern CString g~item[]; extern CString gcust[); extern int gprice[6]; extern int g~qty[6]; int g~qty~old[6]; extern int g~purchases[6]; int g~purchases~old[6]; extern int g~num~purchases[6]; int g~num~purchases~old[6]; extern int g~total~sales; int g~total~sales~old; extern int g~db~run; extern int g~ora~state; int g~ora~state~old = -1; extern CFont g~title~font; extern CFont g~text~font; enum dbIDC {qty~IDC,price~IDC,item~IDC); int ALL~TEXT~DB[] = {IDC~ORDERS~ITEMS,IDC~DB~REFILL,IDC~DB~BOX,IDOK lOOK IDC~T11,IDC~T12,IDC~T13, IDC~T21,IDC~T22,IDC~T23, IDC~DB~Q0,IDC~DB~Q1,IDC~DB~Q2,IDC~DB~Q3,IDC~DB~Q4,IDC~DB~Q5 IDC~DB~P0,IDC~DB~P1,IDC~DB~P2,IDC~DB~P3,IDC~DB~P4,IDC~DB~P5, IDC~DB~I0,IDC~DB~I1,IDC~DB~I2,IDC~DB~I3,IDC~DB~I4,IDC~DB int g~IDCt[2][3] = {{IDC~T11,IDC~T12,IDC~T13} {IDC~T21,IDC~T22,IDC~T23}}; int g~IDCs[3][6] = {{IDC~DB~Q0,IDC~DB~Q1,IDC~DB~Q2,IDC~DB~Q3,IDC~DB~Q4,IDC~DB~Q {IDC~DB~P0,IDC~DB~P1,IDC~DB~P2,IDC~DB~P3,IDC~DB~P4,IDC~DB~P5 ,<BR> <BR> <BR> {IDC~DB~I0,IDC~DB~I1,IDC~DB~I2,IDC~DB~I3,IDC~DB~I4,IDC~DB~I5 ,<BR> CString g~item~tites[] = {"Qty","Price","Item"};<BR> CString g~order~tiles[] = {"&num ","Amt","Customer"}; //////////////////////////////////////////////////////////// ///////////////// // CDbDlg dialog CDbDlg::CDbDlg(CWnd* pParent /*=NULL*/) . CDialog(CDbDlg::IDD, pParent) //{{AFX DATA INIT(CDbDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void CDbDlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(CDbDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN MESSAGE MAP(CDbDlg, CDialog) //{{AFX~DATA~MAP(CDbDlg) ON BN CZICKED(IDC ORDERS ITEMS, OnOrdersItems) ON~WM~TIMER() ON WM CREATE() ON~WM~DESTROY() ON BN CLICKED(IDC DB REFILL, OnDbRefill) ONWM-RBUTTONDOWNT) - //T)AFX MSG~MAP END~MESSAGE MAP() //////////////////////////// // CDbDlg message handlers void CDbDlg::OnOrdersItems() int i,j; CString s; if (g~orders~mode) I // Go into Items mode g~orders~mode = 0;<BR> <BR> SetDlgItemText(IDC~DB~REFILL,"Refill"); // Set DB titles SetDlgItemText(IDC~DB~BOX,"Database Items"); SetDlgItemText(IDC~ORDERS~ITEMS,"(Orders"); for (i=0;i<2i++) for (j=0;j<3j++) SetDlgItemText(gIOCt[i] [j] ,gitem~tites[j] ) // Set DB values for (i=0; i<6 ;i++){ // For each item SetDlgItemInt(g~IDCs[qty~IDC][i] ,g~qty[i]); s.Format("$%d.00",g~price[i]) SetDlgItemText(g~IDCs[price~IDC][i],s); SetDlgItemText(g~IDCs[item~IDC][i],g~item[i]); else ( // Go into Orders mode g~orders~mode = 1; SetDlgItemText(IDC~DB~REFILL,"Clear"); // Set DB titles SetDlgItemText(IDC~DB~BOX,"Database Orders"); SetDlgItemText(IDC~ORDERS~ITEMS,"Items"); for (i=0;i<2i++) for (j=0;j<3j++) SetDlgItemText(g~IDCt[i][j],g~order~titles[j]); // Set DB values for (i=0; i<6 ;i++) { // For each item SetDlgItemInt(g~IDCs[qty~IDC][i] ,g~num~purchases[i]); SetDlgItemInt(g~IDCs[price~IDC][i],g~purchases[i]); SetDlgItemText(g~IDCs[item~IDC][i],g~cust[i]); for (i=0; i<6 ;i++) ( // Invalidate any histoy g~num~purchases~old[i] = g~purchases~old[i] = g~qty~old[i] = -1; void CDbDlg: :OnTimer(UINT nIDEvent) int i,rc,price,stock,cust orders,cust sales; CString s; if (nIDEvent == DB~TIMER) { if (g~db~run < 20) ( if (g~db~run == 0) this->DestroyWindow(); if (g~db~run == 1) (g~orders~mode = 1; OnOrdersItems(); g~db~run = 20;} if (g~ora~state) ( // oracle db if (g~orders~mode) { for (i=0; i<6 ;i++) ( // For each item if ( (rc = oracustr(g~cust[i].GetBuffer(0), &cust~orders, &cust~ s.Format("OraCustRead Error %d",rc); GetParentFrame()->SetMessageText(s); if (g~num~purchases~old[i] != cust orders) SetDlgItemInt(g~IDC[qty~IDC][i] ,(g~num~purchases~old[i] = c if (g.purchases old[i] != cust sales) SetDlgItemInt(g~IDCs[price~IDC][i],(g~purchases~old[i] = cust else for (i=O; i<6 ;i++)( // For each item if ( (rc = oraread(g-item[i].GetBuffer(o)l &price, &stock)) ) s.Format("OraRead ErroR %d",rc); GetParentFrame()->SetMessageText(s); if (gqty~old[i] != stock) SetDlgItemInt(g~IDCs[g~IDC] [i] ,(g~qty~old[i] = stock)); else if (gorders mode) ( // NOT ora~state, so use the local db for (i=0; i<6 ;i++){ // For each item if (g~num~purchases~old[i] != g~num~purchases[i]) SetDlgItemInt(g~IDCs[qty~IDC] [i] ,(g~num~purchases~old[i] = g~nu if (g~purchases~old[i] != g~purchases[i]) SetDlgItemInt(g~IDCs[price~IDC] [i],(g~purchases~old[i] = g~purcha } else ( // local db for (i=O; i<6 ;i++) ( // For each item if (g~qty[i] != g~qty~old[i]) SetDlgItemInt(g~IDCs[qty~IDC] [i] ,(g~qty~olid[i] = g~qty[i])); if (g~total~sales~old != g~total~sales) SetDlgItemInt(IDC~DB~SALES, (g~total~sales~old = g~total~sales)); if (g~ora~state~old != g~ora~state){ if (g~ora state~old = g~ora~state) SetDlgItemText(IDC~BIG~TITLE,"Oracle"); else SetDlgStemText(IDC BIG TITLE,Local DB"); else if (nIDEvent == INIT~TIMER) KillTimer(INIT~TIMER); GetDlgItem(IDC~BIG~TITLE)->SetFont(&g title font); if (g~ora~state) SetDlgItemText(IDC~BIG~TITLE,"Oracle"); else SetDlgItemText(IDC BIG TITLE,"Local DB"); } else CDialog::OnTimer(nIDEvent); int CDbDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) if (CDialog::OnCreate(lpCreateStruct) == -1) return -1; SetTimer(DB~TIMER,200,NULL); SetTimer(INIT~TIMER,200,NULL); g~db~run = 1; // Start return 0; void CDbDlg::OnDestroy() g~db~run = 40; CDialog::OnDestroy(); KillTimer(DB~TIMER); void CDbDlg::OnOK() g db~run = 40; // Re enable the show db call button this->DestroyWindow(); // CDialog::OnOK(); void CDbDlg::OnDbRefill() int i,rc; String s; <BR> <BR> <BR> <BR> if (g~ora~state) {<BR> <BR> for (i=0;i<6i++) { if (g~orders~mode { if ( (rc = oracustw(g~cust[i].GetBuffer(0), 0, 0))<BR> s.Format("OraCustWrite ERRor %d",rc); GetParentFrame()->SetMessageText(s); else { // in items mode if (rc = orawrite(g~item[i].GetBuffer(0), RESTOCK~QTY))<BR> s. Format("OraWrite ERRor %d",rc); GetParentFrame()->SetMessageTxt(s); } else <BR> <BR> <BR> <BR> for (i=0;i<6i++) {<BR> if (g~orders~mode)<BR> <BR> <BR> <BR> <BR> <BR> <BR> g~purchases[i] = 0;<BR> <BR> <BR> <BR> g~num~purchases[i] = 0; else ( // in items mode g~qty[i] = RESTOCK~QTY; void CDbDlg::OnRButtonDown(UINT nFlags, CPoint point) GetParentFrame ()->SetMessageText (""); this->Invalidate(); CDialog::OnRButtonDown(nFlags, point); BOOL CDbDlg::OnInitDialog() CDialog::OnInitDialog(); // Fonts int i = 0; while (ALL~TEXT~DB[i]) GetDlgItem(ALL~TEXT~DB[i++])->SetFont(amp;g~text~font); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE // dbdlg.h header file //////////////////////////////////////////////////////////// ///////////////// // CDbDlg dialog class CDbDlg : public CDialog // Construction public: CDbDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //( (AFX~DATA(CDbDlg) enum I DD = IDD~DBDLG }; // NOTE: the ClassWizard will add data members here //))AFX~DATA // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(CDbDlg) protected: virtual void DoDataExchange(cDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL CFont m~title~font; int m~was~inited; // Implementation protected: // Generated message map functions //{{AFX MSG(CDbDlg) afx~msg void OnOrdersItems(); afx~msg void OnTimer(UINT nIDEvent); afx~msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx~msg void OnDestroy(); virtual void OnOK(); afx~msg void OnDbRefill(); afx~msg void OnRButtonDown(UINT nFlags, CPoint point); virtual BOOL OnInitDialog(); //})AFX MSG DECLARE MESSAGE MAP() // mainfrm.cpp : implementation of the CMainFrame class #include "stdafx.h" 4include "oentry.h" //*include "OpDlg.h" #include "mainfrm.h" *ifdef DEBUG #undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE~ 4endif //////////////////////////////////////////////////////////// ///////////////// // CMainFrame IMPLEMENT~DYNCREATE(CMainFrame, CFrameWnd) BEGIN MESSAGE MAP(CMainFrame, CFrameWnd) //{{AFX~MSG~MAP(CMainFrame) // NOTE - the ClassWizard will add and remove mapping macros her<BR> <BR> <BR> <BR> // DO NOT EDIT what you see in these blocks of generated code ON WM CREATE() //T)AFX MSG MAP END~MESSAGE~MAP() - //////////////////////////////////////////////////////////// ///////////////// // arrays of IDs used to initialize control bars // toolbar buttons - IDs are command buttons static UINT BASED~CODE buttons[] // same order as in the bitmap 'toolbar.bmp' ID~FILE NEW, <BR> <BR> ID~FILE~OPEN, <BR> <BR> <BR> <BR> ID~FILE~SAVE, ID~SEPARATOR, ID~EDIT~CUT, ID~EDIT~COPY, ID~EDIT~PASTE, ID~SEPARATOR, ID~FILE~PRINT, ID~APP~ABCUT, static UINT BASED CODE indicators[] = ID~SEPARATOR, // status line indicator ID~INDICATOR~CAPS, ID~INDICATOR~NUM, ID~INDICATOR~SCRL, }; ////////////////////////////////////// // CMainFrame construction/destruction CMainFrame::CMainFrame() { // TODO: add member initialization code here CMainFrame::~CMainFrame() { } int CMainFrame::OnCreate(LPCREATESTRUCT 1pCreateStruct) { if (CFrameWnd::OnCreate(1pCreateStruct) == -1) return -1; if (!m~wndToolBar.Create(this) || !m wndToolBar.LoadBitmap(IDR MAINFRAME) || !mwndToolBar.SetButtons(buttons, sizeof(buttons)/sizeof(UINT))) TRACEO("Failed to create toolbar\n"); return -1; // fail to create /* Derek's remove tool bar */ m wndToolBar.ShowWindow(SW HIDE); if (!m~wndStatusBar.Create(this) || !m~wndStatusBar.SetIndicators(indicators, sizeof(indicators) /sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; // fail to create } // TODO: Delete these three lines if you don't want the toolbar to // be dockable <BR> <BR> m wndToolBar.EnableDocking(CBRS~ALIGN~ANY);<BR> <BR> <BR> EnableDocking(CBRS ALIGN~ANY); <BR> <BR> <BR> DockControlBar(&m~wndTooBar); // TODO: Remove this if you don't want tool tips m~wndToolHar.SetBarStyle wndToolBar.GetBarStyle() I<BR> <BR> <BR> CBRS~TOOLTIPS I CBRS~FLYBY); return 0; } //////////////////////////////////// // CMainFrame diagnostics #ifdef ~DEBUG void CMainFrame::AssertValid() const <BR> <BR> {<BR> <BR> CFrameWnd::AssertValid(); void CMainFrame::Dump(CDumpContext& dc) consist CFrameWnd::Dump(dc); } #endif //~DEBUG //////////////////////////////////////////////////////////// ///////////////// // CMainFrame message handlers // mainfrm.h : interface of the CMainFrame class //////////////////////////////////////////////////////////// ///////////////// class CMainFrame : public CFrameWnd protected: // create from serialization only CMainFrame (); DECLARE~DYNCREATE(CMainFrame) // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides <BR> <BR> //( (AFX VIRTUAL)CMainFrame) <BR> <BR> <BR> <BR> //) )AFXVIRTUAL // Implementation public: virtual ~CMainFrame(); 4ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) consist; 4endif protected: // control bar embedded members CStatusBar m~wndStatusBar; CToolBar m wndToolBar; // Generated message map functions protected: // ( (AFX~MSG (CMainFrame) afx~msg int OnCreate(LPCREATESTRUCT lpCreateStruct); // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //))AFX~MSG DECLARE MESSAGE MAP() // Odlg.cpp implementation file #include "stdafx.h" #include "oentry.h" #include "Odlg.h" // #define ORACLE causes oraread() orawrite() to be exteraly defined #ifndef ORACLE #define ORACLE 4endif #include "oraomq.h" 4ifdef ~DEBUG #define new DEBUG~NEW #undef THIS~FILE static char THIS FILE[] = ~FILE~ *endif extern int g~options~run; extern int g~fill~delay; extern int g~place~delay; extern int g~place~tpm; extern int g~poll~pps; extern int g~poll~delay; extern int g clear stats; extern int g~ora~state; extern COLORREF g~new~color;<BR> extern char g~oracle~con~str[80]; extern CFont g~text~font; int ALL~TEXT~O[: = ( IDOK,IDC COLOR,IDC CLRSTATS,IDC~ORACREATE, IDC~FILLBOX,IDC~DLY~EB,IDC~DLYMAX,IDC~DLYMIN,IDC~DLY~LAB, IDC~POLL~BOX,IDC~POLL~EB,IDC~POLLMAX,IDC~POLLMIN,IDC~POLL~L IDC~AUTOBOX,IDC~AUTO~EB,IDC~AUTOMAX,IDC~AUTOMIN,IDC~AUTO~LA //////////////////////////////////////////////////////////// ///////////////// // COdlg dialog <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> COdlg::COdlg(CWnd* pParent /*=NULL*)<BR> <BR> <BR> CDialog(COdlg::IDD, pParent) //((AFX DATA INIT(COdlg) // NOTE: the ClassWizard will add member initialization here<BR> <BR> //)}AFX~DATA~INIT void COdlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //((AFX DATA MAp(cOdlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN MESSAGE MAP(COdlg, CDialog) //{{AFX~MSG~MAP(COdlg) ON~WM~CREATE() ON~EN~UPDATE(IDC~AUTO~EB, OnUpdateAutoEb) ON~WM~VSCROLL() ON-ENUPDATE(IDC POLL EB, OnupdatepollEb) ON~EN~UPDATE(IDC~DLY~EB, OnUpdateDlyEb) ON-BN-CLICKED(IDC~COLOR, OnColor) ON-BN-CLICKED(IDC~CLRSTATS, OnClrstats) ON-BN-CLICKED(IDC~ORACREATE, OnOracreate) //}}AFX~MSG~MAP END~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// // COdlg message handlers int COdlg::OnCreate(LPCREATESTRUCT lpCreateStruct) if (CDialog::OnCreate(lpCreateStruct) == -1) return -1; g~options~run = 1; // start return 0; void COdlg::OnOK() g~options~run = 40; // Re-enable the options call button this->ShowWindow(SW-HIDE); // this->DestroyWindow(); // CDialog::OnOK(); } /* void COdlg::OnDestroy() { g~options~run = 40; // Re-enable the options call button // CDialog::OnDestroy(); } */ void COdlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { /* if ((nSBCode == SB~PAGEUP) || (nSBCode == SB~PAGEDOWN)) { if (pScrollBar->GetDlgCtrlID() == IDC~DLY~SLD) pScrollBar->SetScrollPos(MAX~DLY + MIN~DLY - g~fill~delay,TRUE); if (nSBCode == SB~ENDSCROLL) } else if (pScrollBar->getDlgCtrlID() == IDC~DLY SLD) if (((int)nPos != g~fill~delay) && (MIN~GLY <= nPos) && (nPos <= M~.

SetDlgItemInt (IDC~DLY EB,g fill delay = MAXDLY + MINDLY - nPos); else if (pScrollBar->GetDlgCtrlID() == lOC AUTO SLO) if (((int)nPos != g~place~delay) && (MIN~AUTO <= nPos) && (nPos <= MA SetDlgItemInt (IDC~AUTO~EB, (gglace~tpm = MAX~AUTO + MIN~AUTO - nPos)); g~place~delay = 60000/g~place~tpm; ~ } else if (pScrollBar->GetDlgCtrlID() == IDC~POLL~SLD) if (((int)nPos != g~poll~pps) && (MIN~POLL <= nPos) && (nPos <= MAX~P SetDlgItemInt(IDC~POLL~EB, (g~poll~pps = MAX~POLL + MIN~POLL - nPos)); g~poll~delay = 1000/g~poll~pps; CDialog::OnVScroll(nSBCode, npos, pScrollBar); BOOL COdlg::OnInitDialog() CDialog::OnInitDialog(); // GetParentFrame()->SetWindowText(m~inst + " Options"); this->SetWindowText(m~inst + " Options"); <BR> <BR> <BR> <BR> <BR> <BR> <BR> SetDlgItemInt(IDC~DLYMAX,MAX~DLY); <BR> <BR> <BR> SetDlgItemInt(IDC DLYMIN,MIN DLY); <BR> <BR> <BR> <BR> <BR> <BR> SetDlgItemInt (IDC AUTOMAX,MAX AUTO); <BR> <BR> <BR> SetDlgItemIn(IDC AUTOMIN,MIN AUTO); SetDlgItemInt(IDC~POLLMAX, MAX~POLL); <BR> <BR> SetDlgItemInt(IDC~POLLMIN,MIN~POLL); <BR> <BR> <BR> <BR> <BR> <BR> SetDlgItemInt(IDC DLY EB,g fill delay); <BR> <BR> <BR> SetDlgItemInt(IDC-POLT; EB, polr~pps); <BR> <BR> <BR> SetDlgItemInt(IDC-AUTO-EB,g-place tpm); // (CSliderCtrl *) xxx = GetDlgItem(IDC~DLY~SLD); HWND hTrack = GetDlgItem(IDC~DLY SLD)->m hWnd; ::SendMessage (hTrack,TBM~SETRANGEMIN, TRUE, MIN~DLY);// MINDLY ::SendMessage (hTrack,TBM~SETRANGEMAX, TRUE, MAX~DLY);// MAXDLY :SendMessage(hTrack,TBM~SETTICFREQ,100,TRUE); // 10 ticks (MAXDLY MINDLY ::SendMessage(hTrack,TBM~SETPOS,TRUE,MIN~DLY + MAXDLY - g~fill~delay); // 1 hTrack = GetDlgItem(IDC AUTO SLD)->m hWnd; ::SendMessage (hTrack,TBM~SETRANGEMIN, TRUE, MIN~AUTO);// MINDLY ::SendMessage (hTrack,TBM~SETRANGEMAX, TRUE, MAX~AUTO);// MAXDLY ::SendMessage(hTrack,TBM~SETTICFREQ,500,TRUE); // 10 ticks (MAXDLY - MINDLY ::SendMessage(hTrack,TBM~SETPOS,TRUE,MAX~AUTO + MIN~AUTO - g~place~tpm); // hTrack = GetDlgItem(IDC~POLL~SLD)->m-hWnd; ::SendMessage (hTrack,TBM SETRANGEMIN,TRUE, MIN POLL);// MINDLY ::SendMessage (hTrack,TBM~SETRANGEMAX, TRUE, MAX~POLL);// MAXDLY ::SendMessage(hTrack,TBM~SETTICFREQ,10,TRUE); // 10 ticks (MAXDLY - MINDLY) ::SendMessage(hTrack,TBM~SETPOS,TRUE,MAX~POLL + MIN~POLL - g~poll~pps); // // Fonts int i = 0; while (ALL~TEXT~O[i]) GetDlgItem(ALL~TEXT~O[i++])->SetFont(amp;g~text~font); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE void COdlg::OnUpdateAutoEb() int tpm = GetDlgItemInt(IDC AUTO EB,NULL,TRUE); if ((g~place~tpm != tpm) && (tpm >= MIN~AUTO) && (tpm <= MAX~AUTO)) g-place~delay = 60000/tpm; g~place~tpm = tpm; HWND hTrack = GetDlgItem(IDC AUTO SLD)->m hWnd; :SendMessage(hTrack,TBM~SETPOS,TRUE,MAX~AUTO + MIN~AUTO - tpm); void COdlg::OnUpdatePollEb() int poll = GetDlgItemInt(IDC~POLL~EB,NULL,TRUE); if ((g~place~tpm != poll) && (poll >= MIN~AUTO) && (poll <= MAX~AUTO)) g~poll~delay = 1000/poll; g~poll~pps = poll; HWND hTrack = GetDlgItem(IDC POLL SLD)->m hWnd; ::SendMessage(hTrack,TBM~SETPOS,TRUE,MAX~POLL + MIN~POLL - poll); void COdlg::OnUpdateDlyEb() int dly = GetDlgItemInt(IDC~DLY~EB,NULL,TRUE); if ((g~fill delay != dly) && (dly >= MIN DLY) && (dly >= MAX DLY)) g fill delay = dly; HWND hTrack = GetDlgItem(IDC~DLY~SLD)->m~hWnd; SendMessage (hTrack,TBM SETPOS,TRUE,MAX DLY + MINDLY - dly); void COdlg::OnColor() CHOOSECOLOR cc; // common dialog box structure COLORREF acrCustClr[16]; // Setup the custom colors as a grey scale for (int v=0,i=0; i < 16; v=17 * i++) acrCustClr[i] = RGB(v,v,v); // Initialize the necessary members.

cc.lStructSize = sizeof(CHOOSECOLOR); cc.hwndOwner = NULL; // = hwnd; cc.lpCustColors = (LPDWORD) acrCustClr; cc.Flags = CC~FULLOPEN; // CC~PREVENTFULLOPEN if (ChooseColor(&cc)){ g~new~color = cc.rgbResult; // lpCustColors<BR> } else { GetParentFrame()->SetMessageText("Color was not changed"); void COdlg::OnClrstats() { g~clear~stats++; } void COdlg::OnOracreate() { // Create the database in oracle int org~ora~state = g~ora~state; if (g~ora~state == 0) if(oraconn(g~oracle con str)) MessageBox ("Oracle Connect Failed"); else g~ora~state = 1; if (g~ora~stats) { if(oracreate()) MessageBox("Oracle oracreate Failed"); if (org~ora~state == 0) if (oradisc()) MessageBox("Oracle DisConnect Failed"); else g~ora~state = 0; // Odlg.h header file //////////////////////////////////////// // COdlg dialog class COdlg . public CDialog { // Construction public: COdlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX~DATA(COdlg) enum ( IDD = IDD~O~DLG ); // NOTE: the ClassWizard will add data members here //))AFX~DATA String m~inst; // COentryView* m~parentptr; // Overrides // ClassWizard generated virtual function overrides // ( (AFX~VIRTUAL (Codlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //))AFX~VIRTUAL // Implementation protected: // Generated message map functions //((AFX~MSG(Codlg) afx~msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx~msg void OnUpdateAutoEb(); afx~msg void OnVScroll(UINT nSBCode, UINT npos, CScrollBar* pScrollBar); virtual BOOL OnInitDialog(); afx~msg void OnUpdatePollEb(); afx~msg void OnUpdateDlyEb(); afx~msg void OnColor(); virtual void OnOK(); afx~msg void OnClrstats(); afx msg void OnOracreate(); //)7AFX MSG DECLARE MESSAGE MAP() User: root Host: bunny Class: bunny Job: stdin // oentrdoc.cpp : implementation of the COentryDoc class #include "stdafx.h" *include "oentry.h" //#include "OpDlg.h" 4include "oentrdoc.h" *ifdef DEBUG *undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE~; #endif ////////////////////////////////////////// // COentryDoc IMPLEMENT~DYNCREATE(COentryDoc, CDocument) BEGIN MESSAGE MAP(COentryDoc, CDocument) //{{AFX~MSG~MAP(COentryDoc) // NOTE - the ClassWizard will add and remove mapping macros her<BR> // DO NOT EDIT what you see in these blocks of generated code<BR> <BR> <BR> <BR> <BR> //)}AFX~MSG~MAP END~MESSAGE~MAP() //////////////////////////////////////////////////////////// ///////////////// // COentryDoc construction/destruct ion COentryDoc::COentryDoc() // TODO: add one-time construction.code here COentryDoc::-COentryDoc() BOOL COentryDoc::OnNewDocument() if (!CDocument::OnNewDocument()) return FALSE; // TODO: add reinitialization code here // (SDI documents will reuse this document) return TRUE; //////////////////////////////////////// // COentryDoc serialization void COentryDoc::Serialize/CArchive& ar) { if (ar.IsStoring()) // TODO: add storing code here else // TODO: add loading code here <BR> <BR> <BR> <BR> <BR> ////////////////////////////////////////<BR> // COentryDoc diagnostics #ifdef ~DEBUG void COentryDoc: :AssertValid() const CDocument::AssertValid(); void COentryDoc::Dump(CDumpContext& dc) const CDocument::Dump(dc); *endif //~DEBUG //////////////////////////////////////////////////////////// ///////////////// // COentryDoc commands // oentrdoc.h : interface of the COentryDoc class // class COentryDoc : public Document protected: // create from serialization only COentryDoc(); DECLARE~DYNCREATE(COentryDoc) // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //I(AFX~VIRTUAL(COentryDoc) public: virtual BOOL OnNewDocument(); //))AFX~VIRTUAL // Implementation public: virtual ~COentryDoc(); virtual void Serialize(CArchive& ar); // overridden for document i/o #ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; 4endif protected: // Generated message map functions protected: //I(AFX~MSG(COentryDoc) // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //))AFX~MSG DECLARE~MESSAGE~MAP() // oentrvw.h interface of the COentryView class <BR> <BR> <BR> <BR> <BR> //////////////////////////////////////////////////////////// /////////////////<BR> <BR> <BR> &num define MESSAGEREADY WM~USER + 3000 //#define IDD~TPSTIMER 100 class COentryView : public CFormView protected: // create from serialization only COentryView(); DECLARE~DYNCREATE (COentryView) public: //( (AFX~DATA(CoentryView) enum ( IDD = IDD~OENTRY~FORM ); int m~OrderMode; CString m~inst; BOOL m sendreply; //))AFX~DATA BOOL m~runflag; // Running or not int m~millisec; // Delay when ordering int m~mes~sent; int m~mes~rec; int m~rec~sent; int m~rec~rec; HBRUSH m~brush; COLORREF m~color; COLORREF m~box~color; CString m~que; CRect m~color~box~rec; int m~order; int m~order~num; int m~tran~state; int m~tran~rec; int m~tran~sent; int m~auto~tran; int m~auto~rand; int m~auto~commit; void AutoRun(); void color~the~box(COLORREF c, BOOL update); void CmdLine(int pass); void OnCommit(int action); void OnAnyUserAction(); void OnColor(); void ShowRateBar(int act); void PlaceorFillMode(int mode); int DbOrder(char *cust, char *item, int qty); int OraOrder(char *cust, char *item, int qty); void LoadQList(int mode); void ClearDisplay(); CDbDlg dbd; COdlg o~dlg; // Attributes public: COentryDoc* GetDocument(); // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(COentryView) public: virtual void OnInitialUpdate(); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnPrint(CDC* pDC, CPrintInfo*); virtual void OnDraw(CDC* pDC); //}}AFX~VIRTUAL // Implementation public: virtual COentryView(); 4ifdef ~DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) consist; 4endif protected: // Generated message map functions protected: //{{AFX~MSG(COentryView) afx~msg void OnExitb(); afx~msg void OnOrderb(); afx~msg void OnAutob(); afx~msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); afx~msg void OnPlacer(); afx~msg void OnFillr(); afx~msg void OnSelchangeQue(); afx~msg long OnReplyMsg(WPARAM wParam, LPARAM lParam); afx~msg void OnSendrepc(); afx~msg void OnTranb(); afx~msg void OnCommitb(); afx~msg void OnAbortb(); afx~msg void OnLButtonDown(UINT nFlags, CPoint point); afx~msg void OnTimer(UINT nIDEvent); afx~msg void OnShowdb(); afx~msg void OnFilldb(); afx~msg void OnPlacenoqr(); afx~msg void OnEditupdateQue(); afx~msg void OnOptionsb(); afx~msg void OnRButtonDown(UINT nFlags, CPoint point); afx msg void OnSetfocusQue(); //}}AFX~MSG DECLARE MESSAGE MAP() *ifndef DEBUG // debug version in oentrvw.cpp inline COentryDoc* COentryView::GetDocument() { return (COentryDoc*)m~pDocument; } &num endif<BR> //////////////////////////////////////////////////////////// ///////////////// // oentry.cpp : Defines the class behaviors for the application.

*include "stdafx.h" #include "oentry.h" #include "mainfrm.h" #include "oentrdoc.h" *include "dbdlg.h" #include "Odlg.h" #include "oentrvw.h" *ifdef DEBUG *undef THIS~FILE static char BASED~CODE THIS~FILE[] = ~FILE~ 4endif //////////////////////////////////////// // COentryApp BEGIN~MESSAGE~MAP(COentryApp, CWinApp) - //((AFX MSG MAP(COentryApp) ON~COMMAND (ID APP~ABOUT, OnAppAbout) // NOTE - the ClassWizard will add and remove mapping macros her // DO NOT EDIT what you see in these blocks of generated code<BR> <BR> //))AFX~MSG~MAP // Standard file based document commands <BR> <BR> ON~COMMAND(ID~FILE~NEW, CWinApp::OnFileNew)<BR> ON~COMMAND(ID~FILE~OPEN, CWinApp::OnFileOpen) // Standard print setup command ON COMMAND(ID FILE~PRINT~SETUP, CWinApp: :OnFilePrintsetup) END~MESSAGE~MAP() ////////////////////////// // COentryApp construction COentryApp::COentryApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance ///////////////////////////////////// // The one and only COentryApp object COentryApp theApp; ///////////////////////////////////// // COentryApp initialization BOOL COentryApp::InitInstance() { // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need.

Enable3dControls(); LoadStdProfileSettings(); // Load standard INI file options (including // Register the application's document templates. Document templates<BR> // serve as the connection between documents, frame windows and views.

CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR~MAINFRAME, RUNTIME CLASS(COentryDoc), RUNTIME-CLASS(CMainFrame), // main SDI frame window RUNTIME~CLASS(COentryView)); AddDocTemplate(pDocTemplate); // create a new (empty) document OnFileNew(); if (m~lpCmdLine[0] != // TODO: add command line processing here return TRUE; ////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX~DATA(CAboutDlg)<BR> enum ( IDD = IDD~ABOUTBOX ); //}}AFX~DATA CFont m~title~font; // Implementation protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //{{AFX~MSG(CAboutDlg) virtual BOOL OnInitDialog() //)}AFx MSG DECLARE MESSAGE MAP() CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) @ //{{AFX~DATA~INIT(CAboutDlg) //}}AFX~DATA~INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(CAboutDlg)<BR> //}}AFX~DATA~MAP BEGIN MESSAGE MAP(CAboutDlg, CDialog) //{{AFX~MSG~MAP(CAboutDlg)<BR> <BR> //}}AFX~MSG~MAP END~MESSAGE~MAP() // App command to run the dialog void COentryApp::OnAppAbout() CAboutDlg aboutolg; aboutDlg.DoModal(); //////////////////////////////////////// // COentryApp commands BOOL CAboutDlg::OnInitDialog() { CDialog::OnInitDialog(); LOGFONT lf; memset(&lf,0,sizeof(LOGFONT)); strcpy(lf.lfFaceName,"Monotype Corsiva"); lf.lfHeight = 24; m title font.CreateFontIndirect(&lf); GetDlgItem(IDC~ABOUT1)->SetFont(&m~title~font); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE // oentry.h : main header file for the OENTRY application // #define MIN~DLY 0 #define MAX~DLY 5000 #define MIN~AUTO 2 #define MAX~AUTO 3000 #define MIN~POLL 1 #define MAX~POLL 100 #ifndef ~AFXWIN~H~ #error include 'stdafx.h' before including this file for PCH *endif 4include "resource.h" // main symbols ////////////////////////////////////////////////////// // COentryApp: // See oentry.cpp for the implementation of this class // class COentryApp : public CWinApp public: COentryApp(); // Overrides // ClassWizard generated virtual function overrides //{{AFX~VIRTUAL(COentryApp) public: virtual BOOL InitInstance(); //}}AFX~VIRTUAL // Implementation //{{AFX~MSG(COentryApp) afxmsg void OnAppAbout(); // NOTE - the ClassWizard will add and remove member functions h // DO NOT EDIT what you see in these blocks of generated code //}}AFX~MSG DECLARE~MESSAGE~MAP() // OPDLG.cpp : implementation file #include "stdafx.h" 4include "oentry.h" *include "OPDLG.h" *ifdef ~DEBUG #define new DEBUG~NEW 4undef THIS~FILE static char THIS~FILE[] = ~FILE~ *endif extern int g~options~run; //////////////////////////////////////////// // OPDLG dialog OPDLG::OPDLG(CWnd* pParent /*=NULL*/) CDialog(OPDLG::IDD~O~DLG, pParent)<BR> {<BR> <BR> <BR> <BR> //((AFX DATA INIT(oPDLG) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void OPDLG::DoDataExchange(CDataExchange* pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(OPDLG) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN MESSAGE MAP(OPDLG, CDialog) //{{AFX~MSG~MAP (OPDLG) //}}AFX~MSG~MAP END~MESSAGE~MAP() //////////////////////////////////////// // OPDLG message handlers <BR> <BR> <BR> <BR> void OPDLG::OnOK()<BR> {<BR> <BR> <BR> g~options~run = 40; // Re-enable the options call button<BR> <BR> this->DestroyWindow(); CDialog: :OnOK(); // OPDLG.h : header file //////////////////////////////////////// // OPDLG dialog class OPDLG : public CDialog { // Construction <BR> <BR> public:<BR> OPDLG(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX~DATA(OPDLG) // enum I IDD = IDD~OP~DLG ); // NOTE: the ClassWizard will add data members here<BR> //))AFX~DATA // Overrides // ClassWizard generated virtual function overrides // ( (AFX~VIRTUAL (OPDLG) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //))AFX~VIRTUAL // Implementation protected: // Generated message map functions //{{AFX~MSG(OPDLG) virtual void OnOK(); //))AFX~MSG DECLARE~MESSAGE~MAP() // OptDlg.cpp : implementation file 4include "stdafx.h" #include "oentry.h" *include "OptDlg.h" *ifdef DEBUG #define new DEBUG~NEW *undef THIS~FILE static char THIS~FILE[] = ~FILE~ 4endif extern int g~options~run ; //////////////////////////////////////// // OptDlg dialog OptDlg::OptDlg(CWnd* pParent /*=NULL*/) . CDialog(OptDlg::IDD, pParent) //((AFx DATA INIT(OptOlg) // NOTE: the ClassWizard will add member initialization here //}}AFX~DATA~INIT void OptDlg: :DoDataExchange (CDataExchange*, pDX) CDialog::DoDataExchange(pDX); //{{AFX~DATA~MAP(OptDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX~DATA~MAP BEGIN MESSAGE~MAP(OptDlg, CDialog) //{{AFX~MSG~MAP(OptDlg) ON~BN~CLICKED(IDC~DONE, OnDone) ON~WM DESTROY() ON WM~CREATE() //}}AFX~MSG~MAP END~MESSAGE~MAP() ////////////////////////// // OptDlg message handlers void OptDlg::OnDone() { g~options~run = 40; // Re-enable the options call button this->DestroyWindow(); } void OptDlg::OnDestroy() { g~options~run = 40; // Re-enable the options call button CDialog::OnDestroy(); int OptDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) if (CDialog::OnCreate(lpCreateStruct) == -1) return -1; g~options~run = 1; // Start return 0; // OptDlg.h : header file <BR> <BR> <BR> <BR> <BR> <BR> <BR> ////////////////////////////////////////<BR> // OptDlg dialog class OptDlg : public CDialog { // Construction public: OptDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX~DATA(OptDlg) // enum { IDD = IDD~OPTIONS~DLG }; //}}AFX~DATA // Overrides // ClassWizard generated virtual function overrides // ( (AFXVIRTUAL (OptDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX~VIRTUAL // Implementation protected: // Generated message map functions //{{AFX~MSG(OptDlg) afx~mag void OnDone(); afxmsg void OnDestroy(); afx msg int OnCreate(LPCREATESTRUCT lpCreateStruct); //}}AFX~MSG DECLARE~MESSAGE~MAP() }; //{{NO~DEPENDENCIES}} // Microsoft Developer Studio generated include file.

// Used by oentry.rc &num define IDD~ABOUTBOX 100 &num define IDD~OENTRY~FORM 101 &num define IDR~MAINFRAME 128 #define IDR~OENTRYTYPE 129 #define IDI~ICON~Q 130 &num define IDB~BITMAPTEST 131 &num define IDD~DBDLG 133 #defineIDD~O~DLG 138 &num define IDR~3DIMES 145 #defineIDR~3DMDS 146 #define IDI~ICON~TRASH 147 #define IDI~ICON~TRASH1 148 #define IDI~WAIT0 149 #define IDI~WAIT1 150 #define IDI~WAIT2 151 #define IDI~WAIT3 152 #define IDI~FILL0 153 #define IDI~FILL1 154 #define IDI~FILL2 155 #define IDI~WAIT4 156 #define IDI~WAIT5 157 #define IDI~WAIT6 158 #define IDC~AUTOB 1000 #define IDC~EXITB 1001 #define IDC~ORDERB 1002 #define IDC~CUST 1003 #define IDC~ITEM 1004 #define IDC~QTY 1005 #define IDC~PICT 1006 #define IDC~COLORB 1006 #define IDC~GENERIC1 1007 #define IDC~TPS~EB 1008 #define IDC~TRANB 1010 #define IDC~COLORBOX 1011 #define IDC~LOGO~Q 1012 #define IDC ABORTB 1013 #define IDC~COMMITB 1014 #define IDC-TOTALR 1015 #define IDC~MSGS 1015 #define IDCSHOWDB 1016 #define IDC~TPS 1017 #define IDC~QUE 1018 #define IDC~DLYMIN 1019 #define IDC~DLYMAX 1020 #define IDC~PLACER 1021 #define IDC~AUTOMAX 1021 #define IDC~PLACENOQR 1022 #define IDC~AUTOMIN 1022 #define IDC~QUELAB 1023 #define IDC~POLLMAX 1023 #define IDC~CUSTLAB 1024 #define IDC~POLLMIN 1024 #define IDC~ITEMLAB 1025 #define IDC~QTYLAB 1026 #define IDC~SENDREPC 1028 #define IDC~RECIPT 1029 #define IDC~FILLDB 1030 &num define IDC~RECIPTS 1031 &num define IDC~MSGS~LAB 1032 &num define IDC~RECIPTS~LAB 1033 #define IDC~FILLR3 1034 #define IDC~DB~I0 1038 #define IDC~DB~DB~Q0 1039 #define IDC~DB~SALEST 1040 &num define IDC~DB~SALES 1041 #define IDC~DB~BOX 1042 #define IDC~DB~REFILL 1043 #define IDC ORDERS~ITEMS 1044 define IDC~T11 1045 #define IDC~T12 1044 #define IDC~T13 1047 #define IDC~T21 1048 #define IDC~T22 1049 define IDC~DB~P0 1050 #define IDC~T23 1051 #define IDC~ORDERBOX 1052 #define IDC~FILLTXT 1054 #define IDC~AUTOBOX 1055 #define IDC~dmd 1057 #define IDC~POLL BOX 1057 #define IDC~TRANBOX 1058 #define IDC~WAITO 1060 #define IDC~WAIT1 1061 #define IDC~OPTIONSEB 1063 #define IDC~FILL0 1064 #define IDC~FIll1 1065 #define IDC~DB~I1 1066 #define IDC~DB~FILL2 1066 #define IDC~DB~Q1 1067 #define IDC~DB~P1 1068 #define IDC~DLY~EB 1068 #define IDC~DB~I2 1069 #define IDC~DLY~I2 1069 #define IDC~DB~Q2 1070 #define IDC~DLY~LAB 1070 #define IDC~DB~O2 1071 #define IDC~AUTO~EB 1071 #define IDC~DB~I3 1072 #define IDC~AUTO~SLD 1072 #define IDC~DB Q3 1073 #define IDC~AUTO~LAB 1073 #define IDC~DB~P3 1074 #define IDC~FILLBOX 1074 #define IDC~DB~14 1075 #define IDC COLOR 1075 #define IDC~DB~Q4 1076 #define IDC~POLL~EB 1076 #define IDC~DB P4 1077 #define IDC~POLL~SLD 1077 #define IDC~DB~15 1078 #define IDC~POLL~LAB 1078 #define IDC~DB~Q5 1079 #define IDC~DB~P5 1080 #define IDC~CLRSTATS 1080 #define IDC ABOUT1 1081 #define IDC~ORACREATE . 1081 #define IDC~BIG~TITLE 1082 #define IDC~MODEBOX 1083 #define IDC~STATBOX 1084 #define IDC~FILLR 2000 #define IDC~TOTALS 2001 // Next default values for new objects #ifdef APSTUDIO~INVOKED 4ifndef APSTUDIO READONLY~SYMBOLS #define ~APS~3D~CONTROLS #define ~APS~NEXT~RESOURCE~VALUE 140 #define ~APS~NEXT~COMMAND~VALUE 32771 #define ~APS~NEXT~CONTROL~VALUE 1085 #define ~APS~NEXT~SYMED~VALUE 101 *endif *endif Having above indicated several embodiments of the Subject Invention, it will occur to those skilled in the art that modifications and alternatives can be practiced within the spirit of the invention, it is accordingly intended to define the scope of the invention only as indicated in the following claims.