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