home *** CD-ROM | disk | FTP | other *** search
/ The Developer Connection…ice Driver Kit for OS/2 3 / DEV3-D1.ISO / devtools / apl2 / ap999.c__ / ap999.c
Encoding:
C/C++ Source or Header  |  1993-12-15  |  13.1 KB  |  319 lines

  1. /*-p-ap999-----------------------------------------------------------
  2.  *
  3.  * Module Name: ap999.c
  4.  *
  5.  * Descriptive Name: Auxiliary Processor 999
  6.  *
  7.  *
  8.  * Copyright:   APL2/6000               Version 1.2
  9.  *              APL2 for OS/2           Version 1.0
  10.  *              APL2 for Sun Solaris    Version 1.0
  11.  *              Licensed Materials - Property of IBM
  12.  *              (C) COPYRIGHT IBM CORP. 1994
  13.  *
  14.  * Function: Sample Auxiliary Processor implementing client-server
  15.  *           protocol.  For hard working programmers with deadlines,
  16.  *           this sample server will "catch some ZZZZZZ's" for a
  17.  *           client who has no time to sleep for himself.
  18.  *
  19.  *
  20.  * Notes:
  21.  *
  22.  *    Dependencies: None
  23.  *
  24.  *    Restrictions: None
  25.  *
  26.  * Module Type: C
  27.  *
  28.  * Change Activity:
  29.  *
  30.  *-Z----------------------------------------------------------------*/
  31.  
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include "aplobj.h"
  35. #include "apserver.h"
  36.  
  37. #define INVALID_REQ  -1                 /* catch-all rc for unfriendly AP   */
  38. #define SYSTEM_LIMIT -2                 /* requested space is unavailable   */
  39.  
  40. int sleep_init(void *);                 /* AP Server "init" callback fn     */
  41. int sleep_server(void *);               /* AP Server "process" callback fn  */
  42. int sleep_exit(void *);                 /* AP Server "exit" callback fn     */
  43.  
  44. static int error_code(void *, int);     /* error handler                    */
  45.  
  46. /*-F-main---------------------------------------------------------------------
  47.  *
  48.  * Purpose:    Auxiliary Processor 999 - main routine runs the general
  49.  *             AP Server with standard callback to one or more of the 4
  50.  *             AP Server callback routines identified in the parameter list.
  51.  *             The 4 callback routines are named in parms 3-6 of apserver, and
  52.  *             provide the following function:
  53.  *                1. AP initialization, prior to accepting the client share
  54.  *                2. multiple event wait and non-SVP event handling
  55.  *                3. process a client request (passed in shared variable)
  56.  *                4. AP exit cleanup on retraction of the share
  57.  *             (Note: if a callback function is not provided, set parm to NULL)
  58.  *
  59.  * Arguments:  int      argc        Number of elements in argv
  60.  *             char **  argv        Argument pointer array
  61.  *             char **  envp        Environment pointer array
  62.  *
  63.  * Results:    int                  Exit Return Code
  64.  *
  65.  *--------------------------------------------------------------------------*/
  66.  
  67. int main(int argc, char **argv, char **envp) {
  68.  
  69.    return(apserver(argc, argv, sleep_init, NULL, sleep_server, sleep_exit));
  70. /*                             init        wait  process       exit        */
  71. }
  72.  
  73.  
  74.  
  75. /*-F-sleep_init---------------------------------------------------------------
  76.  *
  77.  * Purpose:    Server initialization callback - called by the AP Server prior
  78.  *             to accepting the share to fully couple with the client.  The
  79.  *             typical things done by an AP here are to open files, allocate
  80.  *             global storage, initialize a global data structure and store
  81.  *             its address in the user token field of the srvtoken, etc...
  82.  *             Via SRVPXID and SRVNAME, the AP can examine the client's
  83.  *             fully-qualified SVP identification and the name of the share.
  84.  *             If the AP decides not to accept the share, it returns from
  85.  *             this init routine with return code SRV_REJECT_SHARE.
  86.  *
  87.  * Arguments:  void * srvtoken       pointer to AP Server token
  88.  *
  89.  *             SRVUTOK(srvtoken)     macro returns user token (AP defined)
  90.  *             SRVNAME(srvtoken)     macro returns shared variable name
  91.  *             SRVPXID(srvtoken)     macro returns partner's extended ID
  92.  *             SRVSRBP(srvtoken)     macro returns SVP share request block ptr
  93.  *
  94.  * Results:    int      Return Code
  95.  *                      0 = success
  96.  *                      SRV_REJECT_SHARE = AP Server just quietly ends thread
  97.  *                      other = error condition (Server message & end thread)
  98.  *
  99.  *--------------------------------------------------------------------------*/
  100.  
  101. int sleep_init(void * srvtoken) {
  102.  
  103.    SRVUTOK(srvtoken) = malloc(8);       /* fake control block as an example */
  104.    if (SRVUTOK(srvtoken) == NULL)
  105.       return(SRV_REJECT_SHARE);         /* reject share if malloc failed    */
  106.  
  107.    memset(SRVUTOK(srvtoken),'Z',8);     /* initialize fake control block    */
  108.    return(0);
  109. }
  110.  
  111.  
  112.  
  113. /*-F-sleep_server-------------------------------------------------------------
  114.  *
  115.  * Purpose:    Auxiliary processor 999 is a sample server AP which
  116.  *             uses the general AP Server interface (apserver.c) to
  117.  *             implement a client-server type protocol through the
  118.  *             Shared Variable Processor.  It uses a single shared
  119.  *             variable interface, with no name restrictions, and
  120.  *             runs each share request stream asynchronously under
  121.  *             a separate process (AIX, UNIX) or separate thread (OS/2).
  122.  *
  123.  *             AP999 accepts 2 element integer vectors, where the first
  124.  *             value is the number of milliseconds to sleep, and the second
  125.  *             element is the size of the resulting character vector to
  126.  *             return.  To demonstrate the handling of short versus long
  127.  *             requests, AP999 uses a fast path through the SVP for a
  128.  *             sleep of 1 second or less (holding the shared variable
  129.  *             lock from pre-ref until post-spec), while releasing the
  130.  *             lock (via srv_free call) for longer requests.
  131.  *
  132.  * Arguments:  void * srvtoken      pointer to AP Server token
  133.  *
  134.  *             SRVBUF(srvtoken)     macro returns ptr to shared var buffer
  135.  *             SRVBUFL(srvtoken)    macro returns shared var buffer length
  136.  *             SRVUTOK(srvtoken)    macro returns user token (AP defined)
  137.  *             SRVNAME(srvtoken)    macro returns shared variable name
  138.  *             SRVPXID(srvtoken)    macro returns partner's extended ID
  139.  *             SRVSRBP(srvtoken)    macro returns SVP share request block ptr
  140.  *
  141.  * Results:    int            Return Code
  142.  *                            0 = success
  143.  *                        other = error condition (Server retracts & exits)
  144.  *
  145.  *             On return, the AP stores the result of the client's request
  146.  *             in the shared variable buffer, enlarging it if necessary (or
  147.  *             reallocating it if freed with srv_free) using the srv_alloc
  148.  *             callback to the AP Server.  Note that srv_alloc will NOT
  149.  *             preserve the previous contents of the buffer, and SRVBUF
  150.  *             must be used to get addressability to the buffer after the
  151.  *             call to srv_alloc.
  152.  *
  153.  *--------------------------------------------------------------------------*/
  154.  
  155. int sleep_server(void * srvtoken) {
  156.  
  157.    int rc = 0;
  158.    APLOBJ *obj = (APLOBJ *) SRVBUF(srvtoken);  /* request is an APL2 object */
  159.    int objsize;
  160.    int msecs = obj->dim[1];             /* 1st item of request is sleep time*/
  161.    int shape = obj->dim[2];             /* 2nd is shape of char array result*/
  162.  
  163.    if ((obj->type != INTEGER && obj->type != BOOLEAN) ||
  164.         obj->rank != VECTOR || obj->dim[0] != 2) {
  165.       rc = error_code(srvtoken, INVALID_REQ);  /* generate error return code*/
  166.       return rc;
  167.       }
  168.  
  169.    if (obj->type == BOOLEAN) {          /* if boolean, convert to integer   */
  170.       msecs = ((unsigned long)obj->dim[1]) >> ((8*sizeof(long))-1);
  171.       shape = (((unsigned long)obj->dim[1]) << 1) >> ((8*sizeof(long))-1);
  172.       }
  173.  
  174.    if (msecs <= 1000) {                 /* short wait - OK to hold the lock */
  175.       if (msecs > 0) {
  176.          svsleep(msecs);
  177.          }
  178.       }
  179.    else {                               /* long wait                        */
  180.       srv_free(srvtoken);               /* AP Server releases space, unlocks*/
  181.       obj = NULL;                       /* no longer have addressability    */
  182.       if (msecs <= 60000) {             /* bypass sleep if more than 60     */
  183.          svsleep(msecs);                /*    seconds in this sample AP     */
  184.          }
  185.       }
  186.  
  187.    objsize = aplobjsize(CHARACTER, VECTOR, shape);          /* result size? */
  188.    obj = (APLOBJ *) SRVBUF(srv_alloc(srvtoken, objsize));   /* ask for space*/
  189.    if (obj == NULL) {                              /* if allocation failed, */
  190.       rc = error_code(srvtoken, SYSTEM_LIMIT);     /* set error return code */
  191.       return rc;
  192.       }
  193.  
  194.    obj->ptr = CDRID;                    /* build the CDR header for result  */
  195.    obj->nb = objsize;
  196.    obj->nelm = shape;
  197.    obj->type = CHARACTER;
  198.    obj->rank = VECTOR;
  199.    obj->dim[0] = shape;
  200.  
  201.    memset(&obj->dim[1], 'Z', shape);    /* return some Z's for sleepy client*/
  202.  
  203.    return rc;
  204. }
  205.  
  206.  
  207.  
  208. /*-F-error_code---------------------------------------------------------------
  209.  *
  210.  * Purpose:    Return an error return code to client for this request
  211.  *
  212.  * Arguments:  void * srvtoken       pointer to AP Server token
  213.  *             int        rc         AP return code
  214.  *
  215.  * Results:    int            Return Code (from this function)
  216.  *                            0 = success
  217.  *                           -1 = error condition (srv_alloc failed)
  218.  *
  219.  *--------------------------------------------------------------------------*/
  220.  
  221. int error_code(void * srvtoken, int rc) {
  222.  
  223.    APLOBJ *obj;                         /* ptr to APL2 object in CDR format */
  224.    int objsize;
  225.  
  226.    objsize = aplobjsize(INTEGER, SCALAR, 1);                /* result size? */
  227.    obj = (APLOBJ *) SRVBUF(srv_alloc(srvtoken, objsize));   /* ask for space*/
  228.    if (obj == NULL) {                           /* we're in trouble if we   */
  229.       return (-1);                              /* can't get 32 bytes - die!*/
  230.       }
  231.  
  232.    obj->ptr = CDRID;                            /* construct result header  */
  233.    obj->nb = objsize;
  234.    obj->nelm = 1;
  235.    obj->type = INTEGER;
  236.    obj->rank = SCALAR;
  237.    obj->dim[0] = rc;
  238.  
  239.    return (0);
  240. }
  241.  
  242.  
  243.  
  244.  
  245. /*-F-sleep_exit---------------------------------------------------------------
  246.  *
  247.  * Purpose:    Server exit callback - called by the AP Server prior to
  248.  *             shared variable retraction and termination of this process
  249.  *             thread.  Typical use by the AP is for freeing any dynamic
  250.  *             storage it allocated, closing files and pipes, etc.
  251.  *
  252.  * Arguments:  void * srvtoken       pointer to AP Server token
  253.  *
  254.  *             SRVUTOK(srvtoken)     macro returns user token (AP defined)
  255.  *
  256.  * Results:    int             Return Code
  257.  *                             0 = success
  258.  *                         other = error condition (Server prints error msg)
  259.  *
  260.  *--------------------------------------------------------------------------*/
  261.  
  262. int sleep_exit(void * srvtoken) {
  263.  
  264.    free(SRVUTOK(srvtoken));             /* free the fake control block      */
  265.  
  266.    return(0);
  267. }
  268.  
  269.  
  270.  
  271. /*==========================================================================*/
  272. /*   The following wait callback routine is not used in this sample AP, but */
  273. /*   is provided for documentation purposes.                                */
  274. /*==========================================================================*/
  275.  
  276.  
  277. /*-F-multi_wait---------------------------------------------------------------
  278.  *
  279.  * Purpose:    Server callback to allow wait on multiple file descriptors,
  280.  *             semaphores, or message queues, including the shared variable
  281.  *             event queue.
  282.  *
  283.  *             Return from this function allows the AP Server to handle
  284.  *             shared variable (SVP) events.  Typically an AP will wait on the
  285.  *             notification token along with window, file, or pipe descriptors.
  286.  *             The AP handles non-SVP events, and simply returns from this
  287.  *             function when it wants the AP Server to process SVP events
  288.  *             (which normally result in a call-back to the AP "process" exit
  289.  *             function to handle the client request).
  290.  *
  291.  * Arguments:  void * srvtoken       pointer to AP Server token
  292.  *
  293.  *             SRVNTOK(srvtoken)     macro returns shared variable event
  294.  *                                   notification token (system dependent)
  295.  *             SRVUTOK(srvtoken)     macro returns user token (AP defined)
  296.  *
  297.  * Results:    int             Return Code
  298.  *                             0 = success
  299.  *                         other = error condition (Server retracts & ends)
  300.  *
  301.  *--------------------------------------------------------------------------*/
  302.  
  303. int multi_wait(void * srvtoken) {
  304.  
  305. #ifdef __OS2__
  306.    unsigned long semh = SRVNTOK(srvtoken); /* semaphore handle for sv event */
  307. #else
  308.    unsigned long mqid = SRVNTOK(srvtoken); /* message queue id for sv event */
  309. #endif
  310.  
  311. /* AP typically does poll/select (AIX/UNIX) or muxwait (OS/2) at this point */
  312. /* and continues processing non-SVP events in a while loop until the only   */
  313. /* event outstanding is an SVP event, at which time it will simply return   */
  314. /* to the AP Server to read the share event queue and handle the event.     */
  315.  
  316.    return(0);
  317. }
  318.  
  319.