Session States vs. Persistent States

This section provides more detailed information about session states and persistent states.

A persistent state is a user-defined memory block containing the information necessary to describe connections and perform the adapter function across multiple invocations of the execute()execute() function. Connection-related information includes filenames and stream URIs. Additional persistent state information includes file offsets, intermediate calculations that span multiple rows, and processing subtotals or summaries. Persistent state information remains available even after the server crashes. If you callC8AdapterGetPersistentState() after a crash, you'll get the same information that you would have gotten before the crash.

A session state is a user-defined memory block containing information that is dependent on transient data items such as file pointers and transient socket connection information. A session state should contain only these transient data items. Session information is not preserved across crashes. If you call C8GetState() after a crash, your session state data will not be available.

A pivotal question in distinguishing between session state and persistent state is, "If the system crashed and the in-process adapter was restarted, what would I have to recreate to properly continue my adapter stream?" The persistent state would contain information that does not change while the session state should contain information that must be re-created each time the adapter re-connects to its data sources.

For example, suppose that an adapter is reading from a data file. The adapter starts with the name of the data file, then calls the fopen() function to get a file pointer to that file. The adapter also keeps track of the line number of the line that it last read from the file. If the computer crashes and the in-process adapter must resume, the name of the input file remains the same, just like the line number at which to resume reading remains the same, so those two pieces of information can be stored in the persistent state. The adapter has to re-open the data file and may get a different file pointer than it had previously. The file pointer should therefore be stored in the session state rather than in the persistent state. After a crash, you use the same persistent state information, but mustre-generate session state information.

The following example shows one method of determining when the system has crashed and needs to re-initialize. Notice the suggested sequence at the beginning of the execute() function:

my_xxx_c8adapter_execute(C8Adapter *i_adapter_ptr)
{
  ...
  // Get the session state
  struct MySessionState *l_session_ptr = (struct MySessionState*)
                       C8AdapterGetSessionState(i_adapter_ptr);
   if( ! l_session_ptr) {
      // The  has been restarted for some reason.
      // Need to recreate the session data.
      if (! my_input_c8adapter_session(i_adapter_ptr)) {
   ...

Refer to the In-Process Input Adapterand In-process Output Adapter sections for more details.

Suggested Session and Persistent State Initialization

This section describes session and persistent state initialization in the event of a system crash.

The session state is set up in the initialization routine. If the Sybase CEP Engine or the system crashes, the session state will return a null pointer when C8AdapterGetSessionState() is called. You must then perform whatever initialization is necessary to properly process information. In the initialization call, files may need to be opened, permissions tested, environments probed and tested, and so on. Similarly, when the Sybase CEP Engine restarts, the session state is again missing and the same initialization sequence must be performed. The only difference between an initial Sybase CEP Engine start and a restart is that the persistent state should be present on a restart, an initial start has no persistent state.

For non-trivial adapters, a session state and persistent state may resemble the following skeleton code:

// Perform session initialization
C8Bool my_xxx_c8adapter_session(C8Adapter *i_adapter_ptr)
{
  // The user must define this struct!
  struct MySessionState *l_session_ptr =
        (struct MySessionState*)C8Malloc(
            (C8UInt) sizeof(struct MySessionState));
  // Open files, sockets, db connections, ...
  // Specific information in the session
  l_session_ptr->m_file = fopen(...);
  ...
  C8AdapterSetSessionState(i_adapter_ptr, (void*)l_session_ptr);
  return C8_TRUE;
}
// Perform adapter initialization
C8Bool my_xxx_c8adapter_initialize(C8Adapter *i_adapter_ptr)
{
  struct MyPersistentData *l_persistent_ptr = 
        (struct MyPersistentData *)C8Malloc(
            (C8UInt) sizeof(struct MyPersistentData));
  // Test ptrs for existence - possibly error out
  ...
  // Populate persistent state - Read parameters, test file 
  // existence, permissions, etc
  ...
  // Create session state. Open files and record session 
  if ( ! my_xxx_c8adapter_session(i_adapter_ptr)) {
        // Could not initialize session!
        C8ErrorSet( ... );
        return C8_FALSE;
  }
  // Save persistent state
  C8AdapterSetPersistentState(i_adapter_ptr, (void*)l_persistent_ptr,
        sizeof(struct MyPersistentData));
  return C8_TRUE;
}

The initialization call provides a proper session state, while the execute() function uses the session state as well as the persistent state. The first call to C8AdapterGetPersistentState() in the initialization function will return a null pointer. You must create whatever memory structure is necessary to perform proper adapter functions. From this point on, C8AdapterGetPersistentState() will return a pointer to the last saved persistent state.