|
|
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.