Message Segments

To make processing more efficient, you can divide a large message into pieces using message segments. Generally, you only divide asynchronous messages into segments.

Message nodes can be specified as “segment aware”. If a node is not segment aware and you send an asynchronous message that is segmented to it, you received an error message when viewing the error message log in message details on the message monitor. No publication contracts are created. If you send a synchronous message that is segmented to a node that is not segment aware, you receive an error.

There are several methods for creating, updating, and deleting segments. There are also two properties that you need to take into consideration when working with segments.

If you specify the SegmentsByDatabase property as false, you can only have the configured number defined in PSADMIN (Message Segment From DB). If you specify this property as true, you can have as many segments as you need.

The SegmentsByDatabase property also specifies whether the segments are kept in memory or written to the database when they are received. If you specify true, the segments are automatically written to the database. If you specify false, the segments are held in memory. If you specify true, then cancel out of the program processing the segments, the changes are not committed to the database.

The SegmentUnOrder property is only applicable for asynchronous messages. If you specify the SegmentUnOrder property as true, the receiving node processes the segments in parallel.

Note: You should use DeleteSegment and UpdateSegment only when writing to memory, or when SegmentsByDatabase is set to False. These methods do not work when writing to the database, or when SegmentsByDatabase is set to True.

The following is an example of how to use the segment properties and methods to send a segmented message. Note that there are only two CreateNextSegment calls. By default the first segment is automatically created. The first time you use CreateNextSegment, the message is split into two segments. The next time, you add a third segment. You don't need to call CreateNextSegment to access the third segment, it's automatically generated.

Local Message &MSG;
Local Rowset &FLIGHT_PROFILE, &RS;
Local boolean &Bo, &Stuff;
Local string &lip;

&nodes = CreateArray("");
&nodes[1] = "QE_YO";
&nodes[2] = "QE_STUFF";

QE_FLIGHTDATA.QE_ACNUMBER.Value = QE_FLIGHTDATA.QE_ACNUMBER + 1;

&FLIGHT_PROFILE = GetLevel0();

&MSG = CreateMessage(OPERATION.QE_FLIGHTPLAN);

/* the next lines copy the rowset into the first segment */

&MSG.CopyRowset(&FLIGHT_PROFILE);
&MSG.CreateNextSegment();

/* This copies the next portion of the rowset into the next segment */

&MSG.CopyRowset(&FLIGHT_PROFILE);
&MSG.CreateNextSegment();

/* This copies the last portion of the rowset into the third segment */

&MSG.CopyRowset(&FLIGHT_PROFILE);

/* This specifies that the message segments can be processed separately */

&MSG.IBInfo.SegmentsUnOrder = True;

%IntBroker.publish(&MSG);

The following is an example of receiving a segmented message. This would be found in a notification PeopleCode program:

Local Message &MSG;
Local Rowset &rs, &rs1;
Local Record &FLIGHTDATA, &REC;

Local string &acnumber_value, &msi_sensor_value, &ofp_value, &actype_value, &callsign_value, &squadron_value, &comm1_value, &comm2_value, &ecm_value;

Local XmlDoc &xmldoc;
Local string &yo;
Local boolean &bo;

&CRLF = Char(13) | Char(10);

&MSG = %IntBroker.GetMessage();

/* It is very important to set the rowset to null for every iteration */

/* Also, you may want to verify if the segment count is
greater than 10, and if it is, set the SegmentsByDatabase property to True */

For &i = 1 To &MSG.SegmentCount
   &rs = Null;
   &MSG.GetSegment(&i);
   
   &rs = &MSG.GetRowset();
   &REC = &rs(1).QE_FLIGHTDATA;
   
   &FLIGHTDATA = CreateRecord(Record.QE_FLIGHTDATA);
   &REC.CopyFieldsTo(&FLIGHTDATA);
   
   /* Parse out Message Data */
   &acnumber_value = &FLIGHTDATA.QE_ACNUMBER.Value;
   &msi_sensor_value = &FLIGHTDATA.QE_MSI_SENSOR.Value;
   &ofp_value = &FLIGHTDATA.QE_OFP.Value;
   &actype_value = &FLIGHTDATA.QE_ACTYPE.Value;
   &callsign_value = &FLIGHTDATA.QE_CALLSIGN.Value;
   &squadron_value = &FLIGHTDATA.QE_SQUADRON.Value;
   &comm1_value = &FLIGHTDATA.QE_COMM1.Value;
   &comm2_value = &FLIGHTDATA.QE_COMM2.Value;
   &ecm_value = &FLIGHTDATA.QE_ECM.Value;
   
   &outstring = "Send Async FLight test";
   
   /* Construct Output String */
   &outstring = &outstring | &acnumber_value | &CRLF | &msi_sensor_value | &CRLF | &ofp_value | &CRLF | &actype_value | &CRLF | &callsign_value | &CRLF | &squadron_value | &CRLF | &comm1_value | &CRLF | &comm2_value | &CRLF | &ecm_value;
   
   /* Log Output String into page record */
   &FLIGHTDATA.GetField(Field.DESCRLONG).Value = &outstring;
   
   SQLExec("DELETE FROM PS_QE_FLIGHTDATA");
   &FLIGHTDATA.Insert();
   
End-For;