/*! @page ifrtrace Interface Runtime Tracing and Logging
    @par
    @section ifrtrace1 Trace Features    
    @par 
    The Interface Runtime Library can generate trace output to support
    defect analysis and debugging. The trace is usually written to a file,
    and the size of that file can be limited (and the trace starts writing
    at the beginning of the file when the size is exceeded). Also, the trace
    is multi-thread safe, and thread changes are detected and logged.

    The following kinds of trace can be generated:

    @par Call Trace
    The call trace (or short trace) trace is a hierarchical trace that
    shows the names of the internal methods as they get called. Only
    the names are shown, not the arguments of the calls. The function
    names are indented to show the call nesting level.
    
    @par Debug Trace
    All explicit trace statements in the Interface Runtime fall into
    this category.  Thus you will see here all additional diagnostic
    output, to diagnose problems in using the interface runtime.

    @par Profile Trace
    In this trace, the entering and exiting of a profiling sections
    (which are usually, but are not necessarily required to be
    functions) is traced with a timestamp of high resolution. That
    output can be used to gather profiling data about the runtime
    behaviour.

    @par Packet Trace
    In this trace, the content of the packets which are sent to and received
    from the database server is dumped. 
    
    @section ifrtrace2 Controlling the Trace

    @par
    The trace can be enabled by two methods:
    - by using the environment variable <tt>SAPDB_IFR_TRACEOPTIONS</tt>.
    - by using the <tt>ifr_cons</tt> utility.

    @par Trace Control via Environment Variable
    
    The trace options can be controlled by setting the environment
    variable <tt>SAPDB_IFR_TRACEOPTIONS</tt> <i>before</i> the
    application is running. The individual options are separated by 
    double-colons. The following options are provided:

    <table border=1>
      <tr>
        <td><b>Option</b></td>
        <td><b>Description</b></td>
      </tr>
      <tr>
        <td><tt>o<i>&lt;filename&gt;</i></tt></td>
        <td>The output file name. An output file name of '-' means standard output. 
            A <tt>\%p</tt> in the file name is replaced by the process id, so 
            different processes can use the settings without overwriting each other's
            trace. If the file name shall contain a double-colon, you have to repeat it
            (e.g. <tt>oc::\\trace.txt</tt>).
        </td>
      </tr>
      <tr>
        <td><tt>c<i>&lt;limit&gt;</i></tt></td>
        <td>Enable the call trace, with a recursion limit of <tt><i>&lt;limit&gt;</i></tt>.
            Calls more nested than <tt><i>&lt;limit&gt;</i></tt> are not traced, as default
            the recursion limit is not limited, if it is not specified.
        </td>
      </tr>
      <tr>
        <td><tt>p<i>&lt;limit&gt;</i></tt></td>
        <td>Enable the packet trace. The size of individual packet content that is dumped is limited
            by <tt><i>&lt;limit&gt;</i></tt>, which is 1000 bytes as default.   
        </td>
      </tr>
      <tr>      
        <td><tt>g</tt></td>
        <td>Enable the profiling trace.</td>
      </tr>
      <tr>      
        <td><tt>d</tt></td>
        <td>Enable the debug trace.</td>
      </tr>
      <tr>      
        <td><tt>T</tt></td>
        <td>Enable the timestamp prefix in front of each output line</td>
      </tr>
      <tr>
        <td><tt>s<i>&lt;size&gt;</i></tt></td>
        <td>Limit the size of the trace file to <tt><i>&lt;size&gt;</i></tt>
            bytes. As default, the size of the trace file is not limited. If the 
            trace exceeds <tt><i>&lt;size&gt;</i></tt>, the file is overwritten 
            starting at the beginning.
        </td>
      </tr>
    </table>

    @par Trace Control using ifr_cons

    If the use of the environment variable is not feasible (as a process was already started, and 
    so the environment cannot be set), the tool <tt>ifr_cons</tt> can be used to enable 
    or disable trace options.

    The tool <tt>ifr_cons</tt> is called as follows:
<pre>          
ifr_cons [options] [command]
</pre>
    where <tt>[options]</tt> are:

    <table border=1>
      <tr>
        <td><b>Option</b></td>
        <td><b>Description</b></td>
      </tr>
      <tr>
        <td><tt>-f &lt;filename&gt;</tt></td>   
        <td>Use <tt>&lt;filename&gt;</tt> as the name of the shared memory lock file. If no file is 
          supplied, the file specified in the environment variable <tt>SAPDB_IFR_SHAREDMEM</tt> is 
          used. If that environment variable is not set, the file <tt>irtrace.shm</tt> in the
          <i>independent protocol path</i> will be used.
        </td>
      </tr>
      <tr>
        <td><tt>-h</tt></td>   
        <td>Help. Shows usage information, and ignore all commands.</td>
      </tr>
      <tr>
        <td><tt>-p &lt;pid&gt;</tt></td>   
        <td>Execute the command only for the specified process id <tt>&lt;pid&gt;</tt>.</td>
      </tr>
      <tr>
        <td><tt>-v</tt></td>   
        <td>Verbose operation.</td>
      </tr>
    </table>

    and <tt>[commands]</tt> are:

    <table border=1>
      <tr>
        <td><b>Command</b></td>
        <td><b>Description</b></td>
      </tr>
      <tr>
        <td><tt>TRACE CALL|SHORT ON|OFF|&lt;limit&gt;</tt></td>
        <td>Switches the call trace on or off or sets the call trace nesting level</td>
      </tr>
      <tr>
        <td><tt>TRACE DEBUG ON|OFF</tt></td>
        <td>Switches the debug trace on or off</td>
      </tr>
      <tr>
        <td><tt>TRACE LONG ON|OFF</tt></td>
        <td>Switches the long trace (call plus debug trace) on or off</td>
      </tr>
      <tr>
        <td><tt>TRACE PROFILE ON|OFF</tt></td>
        <td>Switches the profile trace on or off</td>
      </tr>
      <tr>
        <td><tt>TRACE PACKET ON|OFF|&lt;limit&gt;</tt></td>
        <td>Switches the packet trace on or off or sets the packet trace size.</td>
      </tr>
      <tr>
        <td><tt>TRACE TIMESTAMP ON|OFF</tt></td>
        <td>Switches the time stamp prefix on or off</td>
      </tr>
      <tr>
        <td><tt>SHOW TRACESETTINGS</tt></td>
        <td>Shows the current trace settings done by this tool.</td>
      </tr>
    </table>

    All command names are case insensitive. Also commands can be abbreviate to a length where 
    they can uniquely identified (e.g. 'S T' is same as 'SHOW TRACESETTINGS').
*/    
 

/** @page pcache Implementation Details: ParseInfo Cache

    As it is expensive to parse commands again each time the parse infos are cached for each
    connection.

    An existing parse info can be used for a command if:
    - the command string is equal
    - the encoding of the command string is the same
    - the isolation level at parse time is the same

    A parse info is in shared use by several SQL statements, and must be therefore guarded
    against concurrent access. 

    @par Inserting a ParseInfo into the Cache
    
    A parse info is create by preparing a statement. Here, it is checked whether there
    is a parse info available, and if not the statement is parsed. Then, the parse info
    is inserted into the cache - hereby setting its flags appropriately.

    During this process the parse info is locked by the creator.

    @par Attaching to a ParseInfo

    When a matching parse info is found on prepare, the statement simply attaches to it.
    This means that the reference count of the parse info is increased. Attaching to a 
    parse info also propagates the parse info also to the top of the LRU list.

    @par Detaching from a ParseInfo

    When a statement is destroyed, it detaches from the parse info. If the parse info is
    cached, the reference count is simply decremented by one. 

    If it is not cached, it is checked whether this was the last referencee, and if yes,
    the resources are freed.

    @par Displacement of ParseInfo
    
    On the insertion of a new ParseInfo into the cache, the cache size is checked. If the
    cache is full, the ParseInfo at the end of the LRU list is displaced, hereby setting 
    its 'cached' flag to false. If its reference count is 0, it is deleted, otherwise that
    task is done by the last statement that detaches from the ParseInfo.    
    
*/

/** @page dataexec Implementation Details: Late Binding (DATA AT EXECUTE)

    ODBC provides the possibility to provide data for input parameters at
    execution time, and this feature is especially used for transferring 
    large objects into the database. Here, the indicator of a host variable
    signals that the data is available at execution time.   

    If at least one of these parameters is found, instead of consisting of
    a single call to <code>execute()</code> or <code>executeBatch</code>,
    the execution of a prepared statement proceeds according to the following 
    sequence:

    <ol>
      <li>Call <code>execute()</code>, it will return <code>IFR_NEED_DATA</code>.</li>
      <li>Call <code>nextParameter(index, address)</code>. Here, index and address 
          will be filled with the next parameter's details. The address here is set
          according to the parameter binding, the binding type, and the position in
          the row array, if batch execution is done. If the method returns 
          <code>IFR_OK</code>, you are finished, if it returns 
          <code>IFR_NEED_DATA</code>, 
      </li>
      <li>Call <code>putData(data, lengthindicator)</code> to actually provide the data.
          Take care that for integral data types, and the speciall NULL and DEFAULT
          values the data must be delivered in one call, otherwise subsequent calls 
          of <code>putData</code> append to the data. Continue with this step 
          until all data for that parameter has been transferred.   
      </li>
      <li>Continue with step 2 until finished.</li>
    </ol>        
    
    @par Internal Execution Sequence

    The calling sequence described above is translated into one EXECUTE message,
    and if necessary, one or more PUTVAL messages. 

    For doing this, the following measures are taken:

    <ol>
      <li>The parameters which are 'normal' bound are converted and inserted into 
          the message. If they are of LONG types, it is kept whether the long data
          did fit into the message, or was truncated.
      </li>
      <li>All non-LONG parameters which have late binding are collected, converted
          and inserted.
      </li>
      <li>If the LONG parameters that were not bound with late binding already  
          did not fit, now the EXECUTE message is sent, and if necessary,
          subsequent PUTVAL messages.
      </li>
      <li>The LONG parameters that were bound with late binding are collected,
          and inserted, hereby sending a PUTVAL message each time the space
          in the request packet is filled up. 
      </li>
    </ol>        
    
    The following example illustrates the behaviour:
    
<pre>
Consider a table TESTDATA defined as follows:

  CREATE TABLE TESTDATA(A INTEGER,
                        B CHAR(200),
                        C LONG BYTE,
                        D CHAR(30),
                        E LONG BYTE)

Assume an INSERT statement on this table, where the parameters for
column C and D are bound having an indicator value DATA AT EXECUTE,
and E is bound to an array of 1000 bytes. We assume also that the
order in the data part is A,B,C,D,E, for the ease of description.

The packet is filled as follows:

(1) execute
    
    The execute step does check whether there is DATA AT EXECUTE,
    and so returns almost immediately.

(2) nextParameter

    The execute step puts the parse id part into the segment, and then 
    all available data. The segment will then look as follows:

    +----------------+
    | ParseID Part   |
    +----------------+
    | Data Part      |   
    | A              |
    | B              |
    | C (Descriptor) |  <== Descriptor is set to 'no data' for now.
    |                |  <== Space for D is kept, but not filled with data.
    | E (Descriptor) |  <== Points to the data, has flag vm_alldata
    | E (Data)       |      to show there is no more data.
    +----------------+    
    
    Furthermore, the internal structures are laid out, and all DATA AT EXECUTE
    parameters are recorded. 

    Finally, the function returns pointing to D, as it is not a LONG column, 
    and non-LONGs are preferred.

(3) putData
   
    The application fills up D using putData, which fills up the value, 
    and eventually returns IFR_DATA_TRUNC when too much data is inserted.

    Now the segment looks like this:

    +----------------+
    | ParseID Part   |
    +----------------+
    | Data Part      |   
    | A              |
    | B              |
    | C (Descriptor) |  
    | D              | 
    | E (Descriptor) |  
    | E (Data)       |  
    +----------------+    

(4) nextParameter

    The next call to this method returns parameter C, and does not
    send any packet - or change anything, as it is not filled up.
    
(5) putData

    Subsequently, C will be filled with data. At some point, the
    segment will look like:

    +----------------+
    | ParseID Part   |
    +----------------+
    | Data Part      |   
    | A              |
    | B              |
    | C (Descriptor) |  
    | D              | 
    | E (Descriptor) |  
    | E (Data)       |  
    | D (Data)       |  
    +----------------+    
    
    and the packet is filled up completely. Then the packet is sent,
    and normal PUTVAL packets for this LONG are created, which are
    sent when they are filled up (which may happen in extreme even
    several times with one putData.

</pre>    


    @par Special Handling for Batch Execution
    
    When DATA AT EXECUTE is spotted during an <code>executeBatch()</code> operation,
    the control flow is similar to the case when this happen during <code>execute()</code>.
    
    The address returned by the <code>nextParameter</code> call will indicate the row, 
    as it would point to the place where the data would be normally expected, if no
    DATA AT EXECUTE would be present.
    
    In contrast to a single execute, the data from the rows accumulates in the packet
    until the packet is full.
    
 */


/*
 TODO fill this table.

 @page hostconv Implementation Details: Parameter Conversion

    The following table lists the implemented conversions for the host and SQL data types.

<table border="1">
<tr>
<td><b>Host Data Type</b></td>
<td><b>BINARY</b></td>
<td><b>ASCII</b></td>
<td><b>UCS2</b></td>
<td><b>UTF8</b></td>
<td><b>UINT1</b></td>
<td><b>INT1</b></td>
<td><b>UINT2</b></td>
<td><b>INT2</b></td>
<td><b>UINT4</b></td>
<td><b>INT4</b></td>
<td><b>UINT8</b></td>
<td><b>INT8</b></td>
<td><b>double</b></td>
<td><b>float</b></td>
<td><b>DATE_STRUCT</b></td>
<td><b>TIME_STRUCT</b></td>
<td><b>TIMESTAMP</b></td>
<td><b>NUMERIC</b></td>
<td><b>GUID</b></td>
</tr>
<tr>
<td><b>SQL Type</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>FIXED</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>FLOAT</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>CHAR ASCII</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>CHAR EBCDIC</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>CHAR BYTE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>LONG ASCII</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>LONG EBCDIC</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>LONG BYTE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>DATE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>TIME</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>TIMESTAMP</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>BOOLEAN</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>CHAR UNICODE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>SMALLINT</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>INTEGER</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>VARCHAR ASCII</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>VARCHAR EBCDIC</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>VARCHAR BYTE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>LONG UNICODE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>VARCHAR UNICODE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>ABAP STREAM</b></td>
<td colspan=19></td>
</tr>
</table>
 */

   
 