|
|
1.1 root 1: /*************************************************************/
2: /** **/
3: /** Microsoft RPC Examples **/
4: /** Dictionary Application **/
1.1.1.2 ! root 5: /** Copyright(c) Microsoft Corp. 1992 **/
1.1 root 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;
1.1.1.2 ! root 281: Record * curr_record;
1.1 root 282:
283: if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
284: status = EMPTY_DICTIONARY;
285: *item = NULL; }
286: else {
287: // old code uses DICT_CURR_ITEM as iterator state
288: // status = Dict_Next(pdict, DICT_CURR_ITEM(pdict));
289: // *item = DICT_CURR_ITEM(pdict);
290:
291: // update RDICT_CURR_RECORD(pdict)
292: status = Dict_Next(pdict, RDICT_CURR_RECORD(pdict));
293: ItemCopy(DICT_CURR_ITEM(pdict), RDICT_CURR_RECORD(pdict));
294: *item = DICT_CURR_ITEM(pdict);
295: }
296: *item = ItemDuplicate(*item);
297: return( (VDict_Status)status );
298: }
299:
300: VDict_Status
301: VDict_Curr_Prev(
302: IN VDict v_dict,
303: OUT Record ** item
304: )
305: // get predecessor of RDICT_CURR_RECORD(v_dict),
306: // and update *item to point to it (global iterator prev)
307: {
308: Dictionary * pdict = (Dictionary*) (v_dict);
309: RDict * prdict = (RDict*) pdict; // for debug ease...
310: Dict_Status status;
1.1.1.2 ! root 311: Record * curr_record;
1.1 root 312:
313: if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
314: status = EMPTY_DICTIONARY;
315: *item = NULL; }
316: else {
317: // update RDICT_CURR_RECORD(pdict)
318: status = Dict_Prev(pdict, RDICT_CURR_RECORD(pdict));
319: ItemCopy(DICT_CURR_ITEM(pdict), RDICT_CURR_RECORD(pdict));
320: *item = DICT_CURR_ITEM(pdict);
321: }
322: *item = ItemDuplicate(*item);
323: return( (VDict_Status)status );
324: }
325:
326: VDict_Status
327: VDict_Insert(
328: IN VDict v_dict,
329: IN Record * item
330: )
331: {
332: Dictionary * pdict = (Dictionary*) (v_dict);
333: Dict_Status status;
334: Record * rp = makeRecord(item->key, item->name);
335:
336: status = Dict_Insert(pdict, rp); // No return value required.
337: return( (VDict_Status)status );
338: }
339:
340: VDict_Status
341: VDict_Delete(
342: IN VDict v_dict,
343: IN OUT Record ** item
344: )
345: {
346: Dictionary * pdict = (Dictionary*) (v_dict);
347: Dict_Status status;
348:
349: status = Dict_Delete(pdict, (void **)item); // (*item) is returned by Dict_Delete!
350: // *item = ItemDuplicate(*item);
351: // no need to duplicate *item: deleted items need to be deallocated.
352: return( (VDict_Status)status );
353: }
354:
355: VDict_Status
356: VDict_Curr_Item(
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: else {
368: status = SUCCESS;
369: *item = DICT_CURR_ITEM(pdict);
370: }
371: *item = ItemDuplicate(*item);
372: return( (VDict_Status)status );
373: }
374:
375: VDict_Status
376: VDict_Curr_Delete(
377: IN VDict v_dict,
378: OUT Record ** item
379: )
380: {
381: Dictionary * pdict = (Dictionary*) (v_dict);
382: Dict_Status status;
383:
384: if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
385: status = EMPTY_DICTIONARY;
386: *item = NULL; }
387: else {
388: *item = DICT_CURR_ITEM(pdict);
389: status = Dict_Delete( pdict, (void **)item );
390: }
391: // *item = ItemDuplicate(*item);
392: // no need to duplicate *item: deleted items need to be deallocated.
393: return( (VDict_Status)status );
394: }
395:
396: VDict_Status
397: VDict_Get_Dict(
398: IN VDict v_dict,
399: OUT RDict ** r_dict
400: )
401: // used to transmit the dictionary back to the callee
402: // (In this demo program - for printing on the client side)
403: {
404: Dictionary * pdict = (Dictionary*) (v_dict);
405: RDict * prdict = (RDict*)pdict; // debug...
406:
407: if (pdict == NULL) return(DICT_EMPTY_DICTIONARY);
408: else {
409: prinTree (0, 3, pdict->root, printRecord);
410:
411: *r_dict = RDict_Duplicate((RDict*)pdict);
412: // Duplication is done to avoid freeing the tree by
413: // the callee stub. This is a temporary fix, until we
414: // implement [allocate(dont_free)]!
415:
416: return(DICT_SUCCESS);
417: }
418: }
419:
420: /*************************************************************************/
421: /*** Server Utility Functions ***/
422: /*************************************************************************/
423:
424: void
425: Init_dict(Dictionary * dp)
426: {
427: Record* rp;
428:
429: /*
430: */
1.1.1.2 ! root 431: rp = makeRecord((short)0, "jack_smith"); Dict_Insert(dp, rp);
! 432: rp = makeRecord((short)0, "john_doe"); Dict_Insert(dp, rp);
! 433: rp = makeRecord((short)1, "steve_johnson"); Dict_Insert(dp, rp);
! 434: rp = makeRecord((short)2, "debbie_jones"); Dict_Insert(dp, rp);
! 435: rp = makeRecord((short)0, "mike_jacobs"); Dict_Insert(dp, rp);
! 436: rp = makeRecord((short)2, "bill_jackson"); Dict_Insert(dp, rp);
! 437: rp = makeRecord((short)0, "jane_doe"); Dict_Insert(dp, rp);
! 438: rp = makeRecord((short)1, "james_doe"); Dict_Insert(dp, rp);
! 439: rp = makeRecord((short)1, "jean_doe"); Dict_Insert(dp, rp);
! 440: rp = makeRecord((short)0, "joana_smith"); Dict_Insert(dp, rp);
! 441: rp = makeRecord((short)1, "michael_jones"); Dict_Insert(dp, rp);
! 442: rp = makeRecord((short)0, "dianne_jackson"); Dict_Insert(dp, rp);
! 443: rp = makeRecord((short)0, "jacob_jacobson"); Dict_Insert(dp, rp);
1.1 root 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;
1.1.1.2 ! root 461: Dict_Status status;
1.1 root 462:
463: if (DICT_EMPTY(prdict))
464: return(DICT_EMPTY_DICTIONARY);
465:
466: RecordTreeNodeFree(prdict->root);
467: prdict->root = NULL;
468: return(DICT_SUCCESS);
469: }
470:
471: VDict_Status
472: VDict_I_Dict(
473: IN VDict v_dict,
474: IN short size
475: )
476: // Insert integers from 3 to a specified upper bound into the tree
477: {
478: // Dictionary * pdict = (Dictionary*) (v_dict);
479: RDict * prdict = (RDict*)v_dict;
480: Dict_Status status;
481: short i;
482:
483: // Insert (<num'>, "") for all num' s.t. 3 < num' < num
484:
485: for (i=3; i < size; i++) {
486: status = VDict_Insert(
487: prdict,
1.1.1.2 ! root 488: makeRecord(i, "<")
1.1 root 489: );
490: }
491: return( (VDict_Status)status );
492: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.