REPLAY.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:15k
源码类别:

Windows编程

开发平台:

Visual C++

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