GroupWise Message Logging
Articles and Tips: article
Technical Writer
GroupWare Division
CAROL OERTLI
Technical Editor
GroupWare Division
01 Dec 1996
Explains how to use the GroupWise Message Logging API to access stored data necessary in producing customized billing, tracking, and statistical reports.
- Introduction
- Selecting Types of Messages to Log
- Selecting Amount of Data to Log (Verbosity)
- Configuring Message Logging
- Running GroupWise With Message Logging
- Data Stores and Corruption
- Exploring the Logged Information
- MTA Logging Fields
- Logging Events
- Other Options
- Logging API Overview
- Data Structures
- Error Codes
- Sample Code Segments
Introduction
Gathering information about message traffic on your GroupWise system enables you to perform valuable tasks, such as:
Billing customers for messages delivered
Tracking messages
Gathering statistics to help optimize your GroupWise system
The GroupWise Message Transfer Agent (MTA) provides message logging to help you with such tasks by collecting and storing data as it processes messages. You can access the stored data through the GroupWise Message Logging API, allowing value added programs to produce customized billing, tracking, and statistical reports.
You can turn message logging on and off through Admin. This option is configurable and should be set to match the logging requirements, thus optimizing MTA performance.
With message logging turned on, you can choose whether or not you want the GroupWise MTA to perform logging correlation on the data gathered. Logging correlation maintains the relationship between messages and their corresponding delivery reports (delivery/nondelivery). For example, if a user sends a message and receives a report of "Delivered," updating the database will depend on the logging correlation.
With correlation disabled, the GroupWise MTA does not update the message record associated with the report. However, if the Log Reports parameter is set to "Yes," correlation can be performed offline, reducing the load on the GroupWise MTA.
With correlation enabled, the GroupWise MTA updates the delivery status field of the associated message record with the value of the status in the report.
For optimal MTA performance, make sure the correlation selection matches the requirements of the application that is using the logging database.
Selecting Types of Messages to Log
With message logging turned on, the following types of messages can be logged:
All mail messages.These are GroupWise messages that travel from a sender to a recipient.
Reports. These indicate whether mail messages are delivered or undeliverable. Reports must be logged if offline correlation by a value added program is desired.
User statuses. These are additional responses to mail messages that provide specific, user-requested information about messages sent, such as indicating that messages have been opened or deleted by the recipients. To measure throughput accurately, user statuses must be logged.
Other messages containing system information, such as administration messages for updating domains and post offices. As with user statuses, other messages must be logged to measure throughput accurately.
Selecting Amount of Data to Log (Verbosity)
With message logging turned on, you can choose between two levels:
Brief logging collects message flow data suitable for billing and tracking, such as message identifier, message type, sender, priority, size, next hop, final destination, and customizable flags.
Full logging collects the same data that the brief logging collects plus data suitable for detailed statistical reporting, such as arrival time, queued time, time to send to the next hop, completed time, connection count, and transport specific information.
For a list of specific data logged at the brief and full logging levels, see "MTA Logging Fields" in the Message Logging documentation in the GroupWise SDK.
Configuring Message Logging
Different configurations are appropriate for different message tasks. See Exploring the Logged Information later in this article for information.
Configuration
|
Settings
|
Database Contents
|
Advantages
|
Disadvantages
|
Minimum (Simplest Billing) |
Correlate:No Log Report: No Log Status: No Log Other: No Verbosity: Brief |
Mail Messages (no correlation) |
Small database Low processing overhead |
Cannot measure throughput Cannot correlate Billing based on arrival only |
Speed (Optimal Billing) |
Correlate: No Log Report: Yes Log Status: No Log Other: No Verbosity: Brief |
Mail Messages (no online correlation) Reports |
Low overhead Can correlate offline Billing based on correlation |
Medium sizeddatabase Cannot measure throughput |
Size (Optimal Billing) |
Correlate:Yes Log Report: No Log Status: No Log Other: No Verbosity: Brief |
Mail Messages (online correlation) |
Small database Online correlation Billing based on correlation |
Medium overhead Cannot measure throughput |
Maximum (Billing, Tracking, and Statistics) |
Correlate:Yes Log Report: Yes Log Status: Yes Log Other: Yes Verbosity: Full |
Mail Messages (online correlation) Reports User Status Messages Other Messages |
Can measure throughput Online correlation Billing based on correlation |
Large database Large overhead |
Running GroupWise With Message Logging
Once message logging is turned on and configured, it requires minimal attention. However, you may periodically need to:
Manually archive the current logging database and start a new one
Disable or modify the logging configuration after it has been started. If you do this, some messages may not get correlated.
Data Stores and Corruption
The message logging database consists of a data dictionary and 16 record stores. The storage is divided into 16 stores to improve performance and reduce the conflicts of trying to lock a single store. In the event of a power failure, message store corruption can occur. Call MTALogCheckStore to check a specific store for corruption. The data dictionary is store 0. Stores 1 through 16 contain the message logging information. If LOG_ERR_DB_CORRUPT is returned from MTALogCheckStore, you can call MTALogRepairStore to repair the database. Because this may take some time (depending on the size of your store), a callback routine is available to give you a continuing status and allow you to terminate the repair process. See the MTALogCheckStore function in the GroupWise SDK.
Exploring the Logged Information
Figure 1 illustrates the structure of each message record in the message logging database. The accompanying table lists the fields in each record, a description of each field, the logging level (brief/full) at which the information is recorded, and the event (arrival, queuing, or transfer) at which each piece of information is logged.
MTA Logging Fields
A message is logged to the database at three different times as it passes through the MTA. Each logging event is discussed below. The last column in the table refers to a logging event and indicates when the value for the field is set or updated.
Arrive: The MTA picks up the message from its input queue.
Queue: The MTA has made the routing decisions and is splitting the message to multiple destinations. As the message is successfully queued to the responsible Transport Module, this event is logged.
Transfer: The Transport Module has successfully sent the message to its next hop or to its final destination.
Figure 1: Message records in the message logging database.
Field
|
Description
|
Log Level
|
Event
|
Type |
Messagetype associated with the record. These types include MESSAGE, REPORT, USERSTATUS, ADMINMESSAGE, and ALL (using the syntax RECORD_TYPE_MESSAGE, for example). New types may be added in the future as new applications use the MessageTransfer Service. |
Brief |
Arrive |
IdentifierINDEXED |
Unique identifier for the message |
Brief |
Arrive |
Originator |
Domain Originator's domain ARI UNINDEXED. Additional Routing Information. In caseswhere the originator resides in an external domain relative to the logging MTA, the ARIis stored. PO INDEXED. Post Office UserId INDEXED. GroupWise user ID. Available only in messages originating from GroupWise 5. |
Brief |
Arrive |
Report |
Tracking level selected for this message. Possible values are TRACK_OFF=0, TRACK_ON=1, and TRACK_CONTENT=2.This field tells whether the originator requested a delivery report for the message. |
Brief |
Arrive |
Arrival Time |
Thetime of day the message arrived at this MTA. The time is stored in the following fields:year, month, day, hour, minute, seconds, and hundredths of a second. |
Full |
Arrive |
Queued Time |
The time of day when the MTA placed the message in the queue ready for transfer. The timeisstored in the following fields: year, month, day, hour, minute, seconds, and hundredths of a second. |
Full |
Queue |
Priority |
The priority assigned to the message. This priority is either assigned by the originating useror by the originating application. Values range from 0 to 15, with 8 15 beingidentical to0 7 respectively, except that 8 15 are order dependent. 0 Busy searches, some administrative messages1 Remote requests2 High priority mail, administrative messages3 Reports and user statuses forpriority 24 Normal priority mail, administrative messages5 Reports and user statuses for priority 46 Low priority mail, administrativemessages7 Reports and user statuses for priority 6 |
Brief |
Arrive |
User Flags |
Applications using the MTA logging database can set these flags to indicate the state of the record,(for example, correlated or billed). This field is initialized at 0. |
Brief |
Arrive |
Next Hop Name |
Name of the destination Post Office or next domain in the route |
Brief |
Queue |
Next Hop Type |
Type of the next hopRELAYED=0 The message is relayed to another domain en route to itsfinal destination.DELIVERY=1 The message is delivered to its final destination. This destination may be a PostOffice or an Admin server. New uses may be added in the future. |
Full |
Queue |
Next Hop Size |
Number of bytes in the message file |
Brief |
Queue |
Next Hop Completed Time |
The time of day the message completed transfer to the next hop. The time is stored in the followingfields: year, month, day, hour, minute, seconds, and hundredths of a second. |
Full |
Transfer |
Next Hop Time to Send |
Number of milliseconds required to transfer the message. This value is optional and is obtained fromthe Transport Module. |
Full |
Transfer |
Next Hop Connection Count |
Number of attempts to open a transport connection. A value of 0 indicates that the connection wasalready established for an earlier message and the same connection is being used. |
Full |
Transfer |
Next Hop Module Name |
Name of the Transport Module that successfully sent the message (such as FileCopy or TCP/IP) |
Full |
Transfer |
Next Hop User Defined |
Transport specificinformation in binary format. This information is provided by theimplementors of new transport modules to collect data pertaining to a specific transport. |
Full |
Transfer |
Destination Name |
Fullname of the destination application(ARI:Domain.PO) |
Brief |
Arrive |
Destination Number |
Host number in the original message to which the reports can be mapped |
Brief |
Arrive |
Destination Status |
Current status of the message. In the arrive event, this field is set to Pending if a reportis requested, and to Delivered if a report is not requested. PENDING No report received from destinationDELIVERED A delivery report received for this destination NON DELIVERED A non delivery report received forthis destination This field can be updated by the MTA (Correlation active) or by anoffline process |
Brief |
Arrive |
Logging Events
This example shows the logging events that occur as a message is routed to multiple recipients.
Figure 2: Logging example.
The MTA Logging Options for this example are displayed in the dialog box shown. The administrator has chosen to correlate delivery and nondelivery reports for messages as they pass through the MTA. All the fields will be logged for mail messages but no other kinds of messages will be logged to the database.
Scenario
A user sends a message from North.Supp to four destinations: one recipient in East.Sales, three recipients in East.Dev, two recipients in West.MarCom, and one recipient in West.Testing. The message is routed through the Central domain, which performs the MTA logging.
Figure 3: A message sent to four destinations.
Events
Arrival event. When the MTA in Central receives the message, it is handled by the router. The router extracts the following information from the message and logs it to the database:
Type: MAIL_MESSAGE ID: 3E453B405A10:2:34987 Originator: North.Supp Report: ON Arrival time: 11/15/1995 08:19:08 Queued time: NA Priority: 4 User ags: 00000000 Next Hop: NA Destination: NA
The router in the MTA makes the routing decisions based on the local configuration. Each destination is checked and the next domain or delivery Post Office is determined.
Queue event. The message is divided into two copies. One is sent to the East domain and the other to the west. The message record is updated to contain queued time and next hop subrecords.
Type: MAIL_MESSAGE ID: 3E453B405A10:2:34987 Originator: North.Supp Report: ON Arrival time: 11/15/1995 08:19:08 Queued time: 11/15/1995 08:19:08 Priority: 4 User ags: 00000000 Next Hop: Name: East Type: RELAY Size: 3420 Completed time: NA Time to send: NA Connection count: NA Module name: ASYNC User defined: NA Next Hop: Name: West Type: RELAY Size: 3420 Completed time: NA Time to send: NA Connection count: NA Module name: TCP_IP User defined: NA Destination: Name: East.Sales Number: 1 Delivery: PENDING Destination: Name: East.Dev Number: 2 Delivery: PENDING Destination: Name: West.MarCom Queue: NONE Number: 3 Delivery: PENDING Destination: Name: West.Testing Number: 4 Delivery: PENDING
The copies of the message generated by the dispatcher are queued to the corresponding transport modules, and the dispatcher signals the transport modules that there are message transfers to be made.
Transfer event. The transport module determines when the message is to be transferred based on the local scheduling policy. Once the message is sent, the transport module updates its portion of the database entry. The completion time, time to send, connection count, transport module name, and user defined information fields are updated at this point.
Note: The transport module name was assigned when the message was queued, but is reassigned here because, if an alternate transport mechanism is used, a module other than the initial one may relay the message.
Next Hop: Name: East Type: RELAY Size: 3420 Completed time: 11/15/1995 08:20:24 Time to send: 3450 Connection count: 1 Module name: ASYNC User defined: [user defined]
The West domain is connected via a TCP/IP link:
Next Hop: Name: West Type: RELAY Size: 3420 Completed time: 11/15/1995 08:19:13 Time to send: 20 Connection count: 1 Module name: TCP_IP User defined: [user defined]
Delivery Report is received. The message is delivered to the Post Offices. When the MTA in West delivers a copy of the message to Post Office West. Testing, a delivery report is generated and sent back to the originator in North.Supp. Because the MTA Logging Options for this example specify that the MTA correlates all reports, the MTA, upon receiving the report, looks up the record for the original message in the database and updates the destination record for this Post Office.
Destination: Name: West.Testing Number: 4 Delivery: DELIVERED
The MTA Logging Options also specified that the reports are not logged to the database. Therefore, after correlating this report, the MTA routes it forward without logging the report separately to the database.
The complete record after the four events is:
Type: MAIL_MESSAGE ID: 3E453B405A10:2:34987 Originator: North.Supp Report: ON Arrival time: 11/15/1995 08:19:08 Queued time: 11/15/1995 08:19:08 Priority: 4 User ags: 00000000 Next Hop: Name: East Type: RELAY Size: 3420 Completed time: 11/15/1995 08:20:24 Time to send: 3450 Connection count:1 Module name: ASYNC User defined: [USER DEFINED] Next Hop: Name: West Type: RELAY Size: 3420 Completed time: 11/15/1995 08:19:13 Time to send: 20 Connection count: 1 Module name: TCP_IP User defined: [USER DEFINED] Destination: Name: East.Sales Number: 1 Delivery: PENDING Destination: Name: East.Dev Number: 2 Delivery: PENDING Destination: Name: West.MarCom Number: 3 Delivery: PENDING Destination: Name: West.Testing Number: 4 Delivery: DELIVERED
Other Options
Assume the MTA Logging Options were as shown in this dialog box.
Figure 4: MTA Logging options.
The MTA does not correlate reports to messages. Only the basic fields are included and the MTA logs reports to the database. The resulting records from the events described above are shown below. The mail message has considerably fewer fields in the next hop subrecords.
Type: MAIL_MESSAGE ID: 3E453B405A10:2:34987 Originator: North.Supp Report: ON Arrival time: 11/15/1995 08:19:08 Priority: 4 User flags: 00000000 Next Hop: Name: East Size: 3420 Next Hop: Name: West Size: 3420 Destination: Name: East.Sales Number: 1 Delivery: PENDING Destination: Name: East.Dev Number: 2 Delivery: PENDING Destination: Name: West.MarCom Number: 3 Delivery: PENDING Destination: Name: West.Testing Number: 4 Delivery: PENDING
The received report is logged as an entry to the database. The Message Identifier and the Originator are the same as in the corresponding message. The destination record indicates the delivered status; message/report correlation can be done offline through the Logging API.
Type: REPORT ID: 3E453B405A10:2:34987 Originator: North.Supp Arrival time: 11/15/1995 08:36:12 Priority: 5 User flags: 00000000 Next Hop: Name: North Size: 368 Destination: Number: 4 Delivery: DELIVERED
Logging API Overview
Before accessing the message log database, you must call MTALogOpenDataBase( ). This function will return a pointer to a database context which should be kept and passed into the appropriate functions. The information stored in the database context is for internal use only. When you are finished with the database, you must call MTALogCloseDataBase( ) to free all resources associated with the database context.
If you are writing multithreaded applications, each thread must open the database and get a new database context pointer.
After you have obtained a valid database context pointer, you should create a cursor (a pointer into the database). The four types of cursors are:
Message ID (MTALogCreateMessageIDCursor)
Originator (MTALogCreateOriginatorCursor)
Date (MTALogCreateDateCursor)
Direct access (MTALogCreateCursor)
Message ID, originator, and date cursors can be used to traverse or query the database to find matching message IDs, originator addresses, or records where the Arrival Time is within a set interval. The calls to create these cursors can find and optionally load the message record fields for the first matching record.
MTALogMoveCursorToNext( ) will find and load the next matching record. MTALogMoveCursorToNext( ) may be called repeatedly until a LOG_NOT_FOUND is returned. When you are finished with a cursor, you should call MTALogDestroyCursor( ) to free any resources associated with the cursor.
The direct access cursor is used to retrieve a message directly from the database without searching. To create a direct access cursor, you must know the store and database reference number (DRN). Message records contain Store and DRN fields. You can retain the values from these fields for direct access to the record at a later time. This cursor should not be used in conjunction with MTALogMoveCursorToNext( ). Though this cursor is not used for searching, MTALogDestroyCursor( ) must be called to free any resources associated with the cursor.
Once there is a cursor pointing to a record in the database, you can delete the record, set its user flags, correlate associated records, or traverse the destination or next hop subrecords. Correlation is done by calling MTALogCorrelate( ). The procedure MTALogCorrelate( ) will perform depends on the type of record (message or report) the cursor is pointing to. If the cursor points to a message record, all report records with the same message ID are located.
The destination delivery status is updated to correlate with each report record status. If the cursor points to a report record, the message record with the same message ID is loaded and the proper destination delivery status in the message record is set according to the report record status.
You can traverse all destination subrecords by calling MTALogLoadFirstDestination( ), then MTALogLoadNextDestination( ) until LOG_NOT_FOUND is returned. These calls will find and load the destination subrecord information. To find and load a specific destination subrecord, call MTALogLoadDestination( ) and provide the destination number of that record. Because delivery reports make a reference to the destination number rather than the name of the destination, the destination number is required to tie a record delivery report to a certain destination of a message record.
Traversing all next hop subrecords is similar to traversing the destination subrecords. Call MTALogLoadFirstHop( ) and the MTALogLoadNextHop( ) until LOG_NOT_FOUND is returned. These calls will find and load the hop subrecord information. To find a specific hop subrecord call MTALogLoadHop( ) and provide the name of the hop.
After the database has been opened, if an error occurs, you can call MTALogGetErrorNumber( ) to obtain the internal error number. When you install Admin, it will copy a file called ERROR.TXT to the primary domain directory. Use the error number to cross reference in the ERROR.TXTfor extended meaning and possible solutions.
Data Structures
The three basic data types defined for cross platform purposes are:
L_UBYTE unsigned 8 bit L_UWORD unsigned 16 bit L_UDWORD unsigned 32 bit L_STRING Fields defined with L_STRING are general strings. The format of the string is determined at run time. String type is set when the database is opened or with the MTALogSetStringType function. L_STRING is declared as L_UBYTE. typedef enum { RECORD_TYPE_ALL, RECORD_TYPE_MESSAGE, RECORD_TYPE_ADMIN, RECORD_TYPE_REPORT, RECORD_TYPE_STATUS } RECORD_TYPE; typedef enum { MSG_STATUS_NONE, MSG_STATUS_PENDING, MSG_STATUS_NON_DELIVERED, MSG_STATUS_DELIVERED } MSG_STATUS; typedef struct { L_UWORD year; L_UBYTE month; L_UBYTE day; L_UBYTE hour; L_UBYTE minute; L_UBYTE second; L_UBYTE hundredth; } F_TMSTAMP; #define MESSAGEIDLEN 256 #define ORG_DOMLEN 256 #define ORG_ARIPOLEN 256 #define ORG_USERIDLEN 256 typedef struct { L_UDWORD udStore; L_UDWORD udDrn; RECORD_TYPE eType; /* will never be RECORD_TYPE_ALL */ L_UBYTE ubId[MESSAGEIDLEN + 1]; L_STRING saDomain[ORG_DOMLEN + 2]; L_STRING saAri_PO[ORG_ARIPOLEN + 2]; L_STRING saUser[ORG_USERIDLEN + 2]; L_STRING saARI[ORG_ARILEN + 2]; L_STRING saPO[ORG_POLEN + 2]; L_UBYTE ubReport; F_TMSTAMP ArrivalTime; F_TMSTAMP QueuedTime; L_UBYTE ubPriority; L_UBYTE ubUserFlags; } MESSAGE_RECORD; #define HOPNAMELEN 256 #define NEXTMODULELEN 256 #define USERDEFINEDLEN 256 typedef struct{ L_STRING saName[HOPNAMELEN + 2]; L_UBYTE ubType; L_UDWORD udSize; F_TMSTAMP CompletionTime; L_UDWORD udTimeToSend; L_UWORD uwConnectionCount; L_STRING saNextModule[NEXTMODULELEN + 2]; L_UBYTE ubaUserDe ned[USERDEFINEDLEN]; L_UWORD uwUserDefSize; L_UDWORD udNumber; } HOP_RECORD; #define DESTINATIONNAMELEN 256 typedef struct { L_STRING saName[DESTINATIONNAMELEN]; L_UBYTE ubNumber; MSG_STATUS eStatus; L_UDWORD udHopNumber; } DESTINATION_RECORD;
Error Codes
Message
|
Explanation
|
LOG_SUCCESS |
(0)The function executed successfully. |
LOG_NOT_FOUND |
(1)Not Found. If a create cursor function, suchas MTALogCreateCursor( ) returns this value,no record matched the cursor specifications. |
LOG_ERR_NULL_POINTER |
(2)A NULL pointer was passed as an argument when it was not allowed. |
LOG_ERR_DB_OPEN |
(11)MTALogOpenDataBase( ) could not open the given logging database due to incorrect path orfilename, insufficient rights, or missing database file. |
LOG_ERR_DB_LOCK |
(12)MTALogSetUserFlags( ) and MTALogCorrelate must get a lock on the logging database in order to update the records with new User Flags and Destination Delivery Statuses. It is possible that it timed out before a lock could occur. Retry the function. |
LOG_ERR_DB_CORRUPT |
(13)MTALogCheckStore( ) has determined that your database is corrupted. |
LOG_ERR_TRANS_ACTIVE |
(14)MTALogCheckStore( ) has determined that the transaction is already active. |
LOG_ERR_MAINT_SEQUENCE |
(15)MTALogRepairStore( ) could not obtain a maintenance sequence number. |
LOG_ERR_STORE_REBUILD |
(16)MTALogRepairStore( ) detected an error while repairing the store. |
LOG_ERR_SESSION_OPEN |
(20) MTALogOpenDataBase( ) failed to obtain a session handle to the database. |
LOG_ERR_POOL_RESET |
(21)When a call to MTALogMoveCursorToNext( ) is made, the memory pool which holds the new record must be reset. If you get this error, memory has been corrupted, and the program should not continue. |
LOG_ERR_GET_FIELD |
(30)Could not read a field from the memory pool. Possible corrupt record. |
LOG_ERR_PUT_FIELD |
(31)Error occurred writing a value into the memory pool. MTALogSetUserFlags( ) and MTALogCorrelate( ) are the only API routines that write to the memory pool. |
LOG_ERR_PUT_RECORD |
(32)Error occurred writing memory pool record to the logging database. |
LOG_ERR_MISSING_FIELD |
(33)An expected record field was not found in the current record. |
LOG_ERR_INVALID_CURSOR |
(40)The given cursor is not valid. It may be corrupt, or it may not have been initializedcorrectly. It must have a valid pointer into the memory pool record. |
LOG_ERR_CURSOR_SETUP |
(41)Error occurred setting up or validating a database query. |
LOG_ERR_CURSOR_INIT |
(42)Error occurred initializing cursor. |
LOG_ERR_CURSOR_INDEX |
(43)Error occurred setting index for cursor. |
LOG_ERR_RECORD_TYPE |
(50) Error setting the record type for cursor. |
LOG_ERR_RECORD_READ |
(51)Error reading record from logging database into memory pool. |
LOG_ERR_RECORD_DELETE |
(52) Error occurred deleting record from logging database. |
LOG_ERR_NO_MEMORY |
(60) Could not allocate enough memory for current operation. |
Sample Code Segments
This section shows the API functions required to implement various tasks and provide better understanding of how functions can be used in combination. For clarity, declarations of variables are shown as well. These examples do not contain error checking.
Correlate Messages to Reports
Using C:\TEST.DB database, sets bit 1 of the UserFlags field to indicate that the report record has been correlated.
Note: The user determines the definition of UserFlags. It is 8 bits and can be used for bit fields or an 8 bit value.
RCODE rc; DB_CONTEXT *pDBContext; CURSOR *pCursor; MESSAGE_RECORD MessageRecord; MTALogOpenDataBase ("C:\\TEST.DB", &pDBContext);& rc = MTALogCreateMessageIDCursor (pDBContext, NULL, RECORD_TYPE_MESSAGE, &MessageRecord,& &pCursor);& while (rc == LOG_SUCCESS) { #define CORRELATED 1 if ( !(MessageRecord.UserFlags & CORRELATED) ) { MTALogCorrelate (pCursor); MTALogSetUserFlags (pCursor, CORRELATED); } MTALogMoveCursorToNext (pCursor, &MessageRecord);& } MTALogDestroyCursor (pCursor); MTALogCloseDataBase (pDBContext);
Delete a Specific Record
Deletes a record with a message ID of "3099E597 3521 0000@"
RCODE rc; DB_CONTEXT *pDBContext; CURSOR *pCursor; MTALogOpenDataBase ("C:\\TEST.DB", &pDBContext,& STR_NATIVE) rc = MTALogCreateMessageIDCursor (pDBContext, "3099E59735210000@", RECORD_TYPE_MESSAGE, &MessageRecord, &pCursor);& if (rc == LOG_SUCCESS) MTALogDeleteCursorRecord (pCursor); MTALogDestroyCursor (pCursor); MTALogCloseDataBase (pDBContext);
Traverse All Destinations in a Message Record
RCODE rc; DB_CONTEXT *pDBContext; CURSOR *pCursor; DESTINATION_RECORD DestRec; MTALogOpenDataBase ("C:\\TEST.DB", &pDBContext,& STR_NATIVE) rc = MTALogCreateMessageIDCursor (pDBContext, NULL, RECORD_TYPE_MESSAGE, NULL, &pCursor);& rc = MTALogLoadFirstDestination (pCursor, &DestRec);& while (rc == LOG_SUCCESS) { // use populated DESTINATION_RECORD structure here rc = MTALogLoadNextDestination (pCursor, &DestRec);& } MTALogDestroyCursor (pCursor); MTALogCloseDataBase (pDBContext);
Traverse All Records with Automatic Record Loading
Use C:\TEST.DB database to do this.
RCODE rc; DB_CONTEXT *pDBContext; CURSOR *pCursor; MESSAGE_RECORD MessageRecord; MTALogOpenDataBase ("C:\\TEST.DB", &pDBContext,& STR_NATIVE) rc = MTALogCreateMessageIDCursor (pDBContext, NULL, RECORD_TYPE_ALL, &MessageRecord,& &pCursor);& while (rc == LOG_SUCCESS) { // use populated MessageRecord structure here. printf ("ID: %s", MessageRecord.Id); rc = MTALogMoveCursorToNext (pCursor, &MessageRecord);& } MTALogDestroyCursor (pCursor); MTALogCloseDataBase (pDBContext);
* Originally published in Novell AppNotes
Disclaimer
The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.