home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / rpc / dict / replay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-12  |  14.9 KB  |  465 lines

  1. /*************************************************************/
  2. /**                                                         **/
  3. /**                 Microsoft RPC Examples                  **/
  4. /**                 Dictionary Application                  **/
  5. /**           Copyright(c) Microsoft Corp. 1992-1996        **/
  6. /**                                                         **/
  7. /*************************************************************/
  8.  
  9. /*************************************************************************/
  10. /***                                                                   ***/
  11. /***  Example dictionary using splay trees:                            ***/
  12. /***                                                                   ***/
  13. /*************************************************************************/
  14.  
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18.  
  19. #include "replay.h"    // header file generated by MIDL compiler
  20. #include "dict0.h"
  21. #include "util0.h"
  22.  
  23. #define TAB_STOPS 3
  24.  
  25. /*************************************************************************/
  26. /***                   Declarations (from replay.h)                    ***/
  27. /*************************************************************************/
  28.  
  29. /*
  30. typedef struct _Record {
  31.     short key;                      // RPC "generation"
  32.     [string] char* name;            // contributor
  33. } Record;
  34.  
  35. typedef struct _RecordTreeNode RecordTreeNode;
  36.  
  37. typedef struct _RecordTreeNode {
  38.     RecordTreeNode *left;           // left child pointer
  39.     RecordTreeNode *right;          // right child pointer
  40.     Record *item;                   // pointer to a Record structure
  41. } RecordTreeNode;
  42.  
  43. typedef struct _RDict {
  44.     RecordTreeNode *root;           // pointer to the root of a SAT
  45.     long size;                      // number of records in dictionary
  46. } RDict;
  47.  
  48. // RDict is used for marshalling a complete dictionary.
  49.  
  50. typedef enum {
  51.     DICT_SUCCESS,
  52.     DICT_ITEM_ALREADY_PRESENT,
  53.     DICT_ITEM_NOT_FOUND,
  54.     DICT_FIRST_ITEM,
  55.     DICT_LAST_ITEM,
  56.     DICT_EMPTY_DICTIONARY,
  57.     DICT_NULL_ITEM
  58. } VDict_Status;
  59.  
  60. typedef struct _DictState {
  61.     short ref_count;               // for shared dictionaries
  62.     Record * curr_record;          // for global iterators
  63. } DictState;
  64. */
  65.  
  66. /*************************************************************************/
  67. /***                   Internal state access methods                   ***/
  68. /*************************************************************************/
  69.  
  70. #define RDICT_CURR_RECORD(dict) (((DictState*)dict->state)->curr_record)
  71.  
  72. #define RDICT_REF_COUNT(dict)   (((DictState*)dict->state)->ref_count)
  73.  
  74. #define RDICT_STATE(dict)       (((RDict*)dict)->state)
  75.  
  76. static int active_dictionary = 0;
  77.  
  78. /*************************************************************************/
  79. /***    Generic Dictionary Operations: (From dict0.h)                  ***/
  80. /***                                                                   ***/
  81. /***    Dictionary *Dict_New(Cmp_rec*, Splay*, print_rec*)             ***/
  82. /***                                                                   ***/
  83. /***    Dict_Status Dict_Find(Dictionary*, Item*)                      ***/
  84. /***    Dict_Status Dict_Next(Dictionary*, Item*)                      ***/
  85. /***    Dict_Status Dict_Prev(Dictionary*, Item*)                      ***/
  86. /***    Dict_Status Dict_Insert(Dictionary*, Item*)                    ***/
  87. /***    Dict_Status Dict_Delete(Dictionary*, Item**)                   ***/
  88. /***                                                                   ***/
  89. /***    Item* DICT_CURR_ITEM(Dict*)                                    ***/
  90. /*************************************************************************/
  91.  
  92. /*************************************************************************/
  93. /***    Virtual Dictionary Operations: (From replay.h)                 ***/
  94. /***                                                                   ***/
  95. /***    VDict_Status VDict_New(OUT VDict **)                           ***/
  96. /***                                                                   ***/
  97. /***    VDict_Status VDict_Find(IN VDict*, IN OUT Record**)            ***/
  98. /***    VDict_Status VDict_Next(IN VDict*, IN OUT Record**)            ***/
  99. /***    VDict_Status VDict_Prev(IN VDict*, IN OUT Record**)            ***/
  100. /***    VDict_Status VDict_Insert(IN VDict*, IN Record*)               ***/
  101. /***    VDict_Status VDict_Delete(IN VDict*, IN OUT Record**)          ***/
  102. /***                                                                   ***/
  103. /***    VDict_Status VDict_Curr_Item(IN VDict*, OUT Record**);         ***/
  104. /***    VDict_Status VDict_Curr_Delete(IN VDict*, OUT Record**);       ***/
  105. /***    VDict_Status VDict_Curr_Next(IN VDict*, OUT Record**);         ***/
  106. /***    VDict_Status VDict_Curr_Prev(IN VDict*, OUT Record**);         ***/
  107. /***                                                                   ***/
  108. /***    VDict_Status VDict_Get_Dict(IN VDict*, OUT RDict**)            ***/
  109. /*************************************************************************/
  110.  
  111. /*************************************************************************/
  112. /***                   context rundown routine                         ***/
  113. /*************************************************************************/
  114.  
  115. void __RPC_USER VDict_rundown (VDict v_dict)
  116. {
  117.     Dictionary * pdict = (Dictionary*) v_dict;
  118.     short count = --RDICT_REF_COUNT(pdict);
  119.  
  120.     printf("# of remaining users of context: %d\n\n",
  121.            RDICT_REF_COUNT(pdict) );
  122.  
  123.     if (RDICT_REF_COUNT(pdict) <= 0) {
  124.         printf("CLOSING CONTEXT\n\n");
  125.  
  126.         // free the splay tree
  127.         RDict_Free_Dict(v_dict);
  128.  
  129.         // free the dictionary object
  130.         free_state((DictState*) pdict->state);
  131.         MIDL_user_free(v_dict);
  132.         if (count == 0)
  133.             active_dictionary = 0;
  134.     }
  135. }
  136.  
  137. //  For now: need to allocate a new item record prior to operation,
  138. //  for all OUT and IN OUT arguments, as the callee stub will free
  139. //  storage allocated for such pointer parameters.
  140. //
  141. //  Will be fixed by the introduction of [allocate(dont_free)]
  142. //  ACF pointer type and parameter attribute.
  143.  
  144. /**************************************************************************
  145.  * VDict_New initializes a new dictionary if (1) a non shared dictionary
  146.  * was requested, or (2) a shared dictionary was requested, but no shared
  147.  * dictionary is currently active.  There is at most one shared dictionary
  148.  * at any point in time.
  149.  *
  150.  * BUGBUG: shared dictionaries are *NOT* locked (by semaphore, to
  151.  * serialize access to them.  They *should be, though...
  152.  **************************************************************************
  153. */
  154.  
  155. VDict_Status
  156. VDict_New(
  157.   IN short shared_dict,
  158.   OUT VDict * v_dict
  159.   )
  160. {
  161.     Dictionary * pdict0;
  162.     static Dictionary * pdict;
  163.  
  164.     if (!active_dictionary  || !shared_dict) {
  165.         // server side dictionary initialization
  166.         pdict0 = Dict_New(comp, tdSplay, printRecord);
  167.  
  168.         // Initializes RDICT_CURR_RECORD(pdict0) to
  169.         // "minus infinity" in the order
  170.         ((RDict*)pdict0)->state = allocate_state();
  171.  
  172.         Init_dict(pdict0);
  173.         *v_dict = (VDict)pdict0;
  174.  
  175.         if (shared_dict) {
  176.             printf("OPENING SHARED DICTIONARY CONTEXT!\n\n");
  177.             active_dictionary = 1;
  178.             pdict = pdict0;
  179.             RDICT_REF_COUNT(pdict)++;
  180.         } // else RDICT_REF_COUNT(pdict0) = 0;
  181.     }
  182.     else {
  183.         RDICT_REF_COUNT(pdict)++;
  184.         printf("# of users of shared context: %d\n\n", RDICT_REF_COUNT(pdict));
  185.         *v_dict = (VDict)pdict;
  186.     }
  187.  
  188.     return(DICT_SUCCESS);
  189. }
  190.  
  191. VDict_Status
  192. VDict_Find(
  193.     IN VDict  v_dict,
  194.     IN OUT Record ** item
  195.     )
  196. {
  197.     Dictionary * pdict = (Dictionary*) (v_dict);
  198.     Dict_Status status;
  199.  
  200.     status = Dict_Find(pdict, *item);
  201.     if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
  202.         *item = NULL;
  203.     }
  204.     else {
  205.         *item = DICT_CURR_ITEM(pdict);
  206.         *item = ItemDuplicate(*item);
  207.     }
  208.     return( (VDict_Status)status );
  209. }
  210.  
  211. VDict_Status
  212. VDict_Next(
  213.     IN VDict  v_dict,
  214.     IN OUT Record ** item
  215.     )
  216. // get successor of *item, and update *item to point to it
  217. {
  218.     Dictionary * pdict = (Dictionary*) (v_dict);
  219.     Dict_Status status;
  220.  
  221.     status = Dict_Next(pdict, *item);
  222.     if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
  223.         *item = NULL;
  224.     }
  225.     else {
  226.         if (*item == NULL)
  227.             ItemCopy(DICT_CURR_ITEM(pdict), RDICT_CURR_RECORD(pdict));
  228.         *item = DICT_CURR_ITEM(pdict);
  229.     }
  230.     *item = ItemDuplicate(*item);
  231.     return( (VDict_Status)status );
  232. }
  233.  
  234. VDict_Status
  235. VDict_Prev(
  236.     IN VDict  v_dict,
  237.     IN OUT Record ** item
  238.     )
  239. // get predecessor of *item, and update *item to point to it
  240. {
  241.     Dictionary * pdict = (Dictionary*) (v_dict);
  242.     Dict_Status status;
  243.  
  244.     status = Dict_Prev(pdict, *item);
  245.     if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
  246.         *item = NULL;
  247.     }
  248.     else {
  249.         if (*item == NULL)
  250.             ItemCopy(DICT_CURR_ITEM(pdict), RDICT_CURR_RECORD(pdict));
  251.         *item = DICT_CURR_ITEM(pdict);
  252.     }
  253.     *item = ItemDuplicate(*item);
  254.     return( (VDict_Status)status );
  255. }
  256.  
  257. VDict_Status
  258. VDict_Curr_Next(
  259.     IN VDict  v_dict,
  260.     OUT Record ** item
  261.     )
  262. // get successor of RDICT_CURR_RECORD(v_dict),
  263. // and update *item to point to it (global iterator prev)
  264. {
  265.     Dictionary * pdict = (Dictionary*) (v_dict);
  266.     Dict_Status status;
  267.  
  268.     if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
  269.         status = EMPTY_DICTIONARY;
  270.         *item = NULL;
  271.     }
  272.     else {
  273.         status = Dict_Next(pdict, RDICT_CURR_RECORD(pdict));
  274.         ItemCopy(DICT_CURR_ITEM(pdict), RDICT_CURR_RECORD(pdict));
  275.         *item = DICT_CURR_ITEM(pdict);
  276.     }
  277.     *item = ItemDuplicate(*item);
  278.     return( (VDict_Status)status );
  279. }
  280.  
  281. VDict_Status
  282. VDict_Curr_Prev(
  283.     IN VDict  v_dict,
  284.     OUT Record ** item
  285.     )
  286. // get predecessor of RDICT_CURR_RECORD(v_dict),
  287. // and update *item to point to it (global iterator prev)
  288. {
  289.     Dictionary * pdict = (Dictionary*) (v_dict);
  290.     Dict_Status status;
  291.  
  292.     if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
  293.         status = EMPTY_DICTIONARY;
  294.         *item = NULL;
  295.     }
  296.     else {
  297.         // update RDICT_CURR_RECORD(pdict)
  298.         status = Dict_Prev(pdict, RDICT_CURR_RECORD(pdict));
  299.         ItemCopy(DICT_CURR_ITEM(pdict), RDICT_CURR_RECORD(pdict));
  300.         *item = DICT_CURR_ITEM(pdict);
  301.     }
  302.     *item = ItemDuplicate(*item);
  303.     return( (VDict_Status)status );
  304. }
  305.  
  306. VDict_Status
  307. VDict_Insert(
  308.     IN VDict  v_dict,
  309.     IN Record * item
  310.     )
  311. {
  312.     Dictionary * pdict = (Dictionary*) (v_dict);
  313.     Dict_Status status;
  314.     Record * rp = makeRecord(item->key, item->name);
  315.  
  316.     status = Dict_Insert(pdict, rp); // No return value required.
  317.     return( (VDict_Status)status );
  318. }
  319.  
  320. VDict_Status
  321. VDict_Delete(
  322.     IN VDict  v_dict,
  323.     IN OUT Record ** item
  324.     )
  325. {
  326.     Dictionary * pdict = (Dictionary*) (v_dict);
  327.     Dict_Status status;
  328.  
  329.     status = Dict_Delete(pdict, (void **)item);
  330.                                     // (*item) is returned by Dict_Delete!
  331.     return( (VDict_Status)status );
  332. }
  333.  
  334. VDict_Status
  335. VDict_Curr_Item(
  336.     IN VDict  v_dict,
  337.     OUT Record ** item
  338.     )
  339. {
  340.     Dictionary * pdict = (Dictionary*) (v_dict);
  341.     Dict_Status status;
  342.  
  343.     if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
  344.         status = EMPTY_DICTIONARY;
  345.         *item = NULL;
  346.     }
  347.     else {
  348.         status = SUCCESS;
  349.         *item = DICT_CURR_ITEM(pdict);
  350.     }
  351.     *item = ItemDuplicate(*item);
  352.     return( (VDict_Status)status );
  353. }
  354.  
  355. VDict_Status
  356. VDict_Curr_Delete(
  357.     IN VDict  v_dict,
  358.     OUT Record ** item
  359.     )
  360. {
  361.     Dictionary * pdict = (Dictionary*) (v_dict);
  362.     Dict_Status status;
  363.  
  364.     if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
  365.         status = EMPTY_DICTIONARY;
  366.         *item = NULL;
  367.     }
  368.     else {
  369.         *item = DICT_CURR_ITEM(pdict);
  370.         status = Dict_Delete( pdict, (void **)item );
  371.     }
  372.     return( (VDict_Status)status );
  373. }
  374.  
  375. VDict_Status
  376. VDict_Get_Dict(
  377.     IN VDict  v_dict,
  378.     OUT RDict ** r_dict
  379.     )
  380. //  used to transmit the dictionary back to the callee
  381. //  (In this demo program - for printing on the client side)
  382. {
  383.     Dictionary * pdict = (Dictionary*) (v_dict);
  384.  
  385.     if (pdict == NULL) {
  386.         return(DICT_EMPTY_DICTIONARY);
  387.     }
  388.     else {
  389.         prinTree(0, 3, pdict->root, printRecord);
  390.  
  391.         *r_dict = RDict_Duplicate((RDict*)pdict);
  392.             // Duplication is done to avoid freeing the tree by
  393.             // the callee stub.  This is a temporary fix, until we
  394.             // implement [allocate(dont_free)]!
  395.  
  396.         return(DICT_SUCCESS);
  397.     }
  398. }
  399.  
  400. /*************************************************************************/
  401. /***                        Server Utility Functions                   ***/
  402. /*************************************************************************/
  403.  
  404. void
  405. Init_dict(Dictionary * dp)
  406. {
  407.     Record* rp;
  408.  
  409.     rp = makeRecord((short)0, "jack_smith"); Dict_Insert(dp, rp);
  410.     rp = makeRecord((short)0, "john_doe"); Dict_Insert(dp, rp);
  411.     rp = makeRecord((short)1, "steve_johnson"); Dict_Insert(dp, rp);
  412.     rp = makeRecord((short)2, "debbie_jones"); Dict_Insert(dp, rp);
  413.     rp = makeRecord((short)0, "mike_jacobs"); Dict_Insert(dp, rp);
  414.     rp = makeRecord((short)2, "bill_jackson"); Dict_Insert(dp, rp);
  415.     rp = makeRecord((short)0, "jane_doe"); Dict_Insert(dp, rp);
  416.     rp = makeRecord((short)1, "james_doe"); Dict_Insert(dp, rp);
  417.     rp = makeRecord((short)1, "jean_doe"); Dict_Insert(dp, rp);
  418.     rp = makeRecord((short)0, "joana_smith"); Dict_Insert(dp, rp);
  419.     rp = makeRecord((short)1, "michael_jones"); Dict_Insert(dp, rp);
  420.     rp = makeRecord((short)0, "dianne_jackson"); Dict_Insert(dp, rp);
  421.     rp = makeRecord((short)0, "jacob_jacobson"); Dict_Insert(dp, rp);
  422.  
  423.     Dict_Print(dp, TAB_STOPS);
  424. }
  425.  
  426. /*************************************************************************/
  427. /***                        Play oriented Functions ...                ***/
  428. /*** (used to empty the tree and replace it by a tree of integers      ***/
  429. /*************************************************************************/
  430.  
  431. VDict_Status
  432. VDict_X_Dict(
  433.     IN VDict  v_dict
  434.     )
  435. // Empty the dictionary
  436. {
  437.     RDict * prdict = (RDict*)v_dict;
  438.  
  439.     if (DICT_EMPTY(prdict))
  440.         return(DICT_EMPTY_DICTIONARY);
  441.  
  442.     RecordTreeNodeFree(prdict->root);
  443.     prdict->root = NULL;
  444.     return(DICT_SUCCESS);
  445. }
  446.  
  447. VDict_Status
  448. VDict_I_Dict(
  449.     IN VDict  v_dict,
  450.     IN short  size
  451.     )
  452. // Insert integers from 3 to a specified upper bound into the tree
  453. {
  454.     RDict * prdict = (RDict*)v_dict;
  455.     Dict_Status status;
  456.     short i;
  457.  
  458.     // Insert (<num'>, "") for all num' s.t. 3 < num' < num
  459.     for (i=3; i < size; i++) {
  460.         status = VDict_Insert(prdict,
  461.                               makeRecord(i, "<"));
  462.     }
  463.     return( (VDict_Status)status );
  464. }
  465.