|
|
1.1 root 1: /*************************************************************/ 1.1.1.2 ! root 2: /** **/ ! 3: /** Microsoft RPC Examples **/ ! 4: /** Dictionary Application **/ ! 5: /** Copyright(c) Microsoft Corp. 1991 **/ ! 6: /** **/ 1.1 root 7: /*************************************************************/ 8: 9: Overview: 10: --------- 11: 12: This demo is a an example a non trivial local application to RPC. 13: The local program is a character oriented "play" program, which lets a 14: user insert, delete, and iterate over a dictionary. The dictionary is 15: based on splay trees, which are printed out in a format described below. 16: 17: We remoted the basic program by taking the interface to the dictionary 18: (given in dict0.h) and creating an interface to a remote dictionary, 19: (given in replay.idl) which is remoted using RPC. 20: 21: Following the local dictionary interface. which is minimal and uniform, 22: the remote interface is also uniform. However, since the local dictionary 23: is generic (can store any item type, using void* pointers to items), 24: the interface needed to change to deal with predefined (Record) type 25: items in order to be remoted using the Microsoft RPC system. Also, 26: since the local implementation allows a "peek" at the root of the tree 27: using a DICT_CURR_ITEM macro, the whole interface achanged needed a to 28: change. 29: 30: Remote dictionaries are represented by context handles to demonstrate 31: the use of [context_handle]. Context handles are currently initialized 32: using a global primitive handle [implicit_handle]. 33: 34: State was added to remote dictionaries in order to allow sharing them, 1.1.1.2 ! root 35: and maintain reference counts. ! 36: At this time, however, access to shared 1.1 root 37: dictionaries is *not* serialized! By default each client gets his own copy 38: of the dictionaries. To use shared dictionaries, start the client using 39: the -s switch. 40: 41: The use of context to maintain state is also demonstrated by 42: differenciating between a private iterator, activated by "n" for "next" 43: and "p" for "previous", and a global shared iterator activated by "N" 44: for "Next" and "P" for previous. To start iterators, use "h" - go to 45: the "head" of the dictionary, or "t" - go to the "tail" of the dictionary. 46: The private iterator can be reset to DICT_CURR_ITEM using "r". 47: 48: Building on Windows/NT 49: ---------------------- 50: 1.1.1.2 ! root 51: In a Windows/NT SDK environment type to the console: ! 52: ! 53: -> set NT_I386=1 ! 54: ! 55: or ! 56: ! 57: -> set NT_MIPS=1 ! 58: ! 59: depending on your hardware. ! 60: ! 61: In a DOS (or a DOS prompt under Windows 3.X) type: ! 62: ! 63: -> set DOS=1 ! 64: ! 65: In all three environments type: 1.1 root 66: 67: -> nmake cleanall 1.1.1.2 ! root 68: -> nmake 1.1 root 69: 70: To remove only object files type: 71: 72: -> nmake clean 73: 1.1.1.2 ! root 74: Alternatively, in the DOS environment only, you can avoid defining ! 75: the DOS environment variable and invoke nmake as follows: 1.1 root 76: 1.1.1.2 ! root 77: -> nmake -f makefile.dos 1.1 root 78: 79: Using the program: 80: ------------------ 81: 82: To use the local dictionary example, type "play". 83: 84: To use the remote versiom, type "server" on the server side. On the client 85: side, for each client use "client" for a fresh, private copy of the 86: dictionary, or "client -s" for a shared copy of the dictionary. The 87: following command line options are available on the client side. 88: 89: Options: 90: -------- 91: 92: The -? displays the following message: 93: 94: Usage : client [-s] [-m<machine>] [-v<view_option>] 95: 96: The -s option is used for using a shared version of the dictionary. If 97: none exist, a fresh shared version is created. 98: 99: The -v<option> is used for getting different views of the dictionary: 100: -vnormal (default) - default view of the dictionary (see explanation 101: below) 102: -vflat - Flat printout 103: -vrev (or -vreverse) - reversese the tree to print left subtree first 104: followed by the node, followed by the right subtree, at every level 105: 106: The -m<machine_name> is used for specifying a server machine. Without it 107: the server is assumed to run on the same machine. 108: 109: If you use the -m option you have to make sure that the server is 110: ready to receive calls; that is you have to start the server, by typing 111: 112: -> net start server 113: -> server 114: 115: to the console, even if the server is your own machine! 116: 117: Program structure: 118: ================== 119: 120: Basic application: 121: ------------------ 122: 123: dict0.h + dict0.c - These files contain a basic generic dictionary 124: implementation, based on Self Adjusting Trees (Splay trees), 125: invented by Sleator and Tarjan. In the remote dictionary 126: application (replay) the generic dictionary code runs on the server, 127: which maintains a data base to be shared by clients. 128: 129: Note that the generic dictionary data structures contain untyped 130: pointers ((void)*), and thus require a special layer of typed trees 131: (strongly typed tree nodes) containing items of RPC-able types 132: in order to convert the local dictionary package and distribute it 133: using the Microsoft RPC system, and particularly the MIDL compiler. 134: 135: If you are interested in RPC (as opposed to splay trees) treat 136: the generic dictionary as a "black box", and ignore the implementation 137: details. Otherwise, you are probably looking at the wrong README 138: file (and should read Tarjan and Sleators paper first anyhow...) 139: 140: Local dictionary: 141: ----------------- 142: 143: play.h + play.c - These files contain a simple character oriented 144: interactive demo / test program for the dictionary. 145: 146: Remote dictionary: 147: ------------------ 148: 149: replay.idl - The Interface Definition Language (IDL) file contains: 150: 151: o type definitions for the remotable objects required (such as the 152: Record item type, RecordTreeNode, etc) 153: 154: o the context handle definition (a (void)* in this case) providing 155: a handle on a remote dictionary 156: 157: o the signatures for the remote dictionary operations 158: 159: replay.acf - An Attribute Configuration File (ACF), used here to 160: specify the initial binding method. We use implicit_binding to 161: bind to the server initially, and to initialize the context handle. 162: 163: replay.c - This file contains the implementation of the remote, or 164: virtual, dictionary (VDict_...) operations. These are required 165: only on the server side, and are replaced by caller stubs 166: (in replay_c.c) on the client side. 167: 168: Utlities: 169: --------- 170: 171: util0.h + util0.c - These files contain utility routines used by both 172: the client and server applications allocate and to free dictionaries 173: and trees, as well as pretty-print routines, used to print trees on 174: both sides. See description of the user interface portion below for 175: further discussion of the tree printing format. 176: 177: Client side: 178: ------------ 179: 180: client.c - This file contains the driver of the client side program. 181: The client binds to the server, initializes a dictionary, and activates 182: a context handle for the dictionary on the server side. It then goes 183: into a test loop which prints the dictionary tree and prompts the user 184: for additional input by printing the following usage message: 185: 1.1.1.2 ! root 186: Usage: ! 187: Type a single character, followed by an optional key as follows: 1.1 root 188: 189: i <key> :: Insert <key> into dictionary 190: d <key> :: Delete <key> from dictionary 191: f <key> :: Find <key> in dictionary 1.1.1.2 ! root 192: N :: next of current item in dictionary ! 193: P :: previous of current item in dictionary ! 194: n :: Next of local current item in dictionary ! 195: p :: Previous of local current item in dictionary ! 196: h :: Head (first item) of dictionary ! 197: t :: Tail (last item) of dictionary ! 198: ? :: Print this message ! 199: q :: Quit ! 200: ! 201: where <key> is <integer> <string> 1.1 root 202: 1.1.1.2 ! root 203: next op (i d x f n N p P h t ? q): 1.1 root 204: 205: Server side: 206: ------------ 207: 208: server.c - This file contains a pretty standard server main loop for 209: the remote dictionary "replay" demo. 210: 211: Tree print format: 212: ------------------ 213: 214: The tree printing routine prints the keys in a binary search tree using 215: the following "prinTree" recursive algorithm: 216: 217: prinTree (right subtree, with current indentation + one "tab"); 218: print the key at the root (with current indentation); 219: prinTree (left subtree, with current indentation + one "tab"); 220: 221: Keys are a pair of the form <integer, string>. Assume the following tree: 222: 223: 224: ----------- 225: |0 : jack | 226: ----------- 227: / \ 228: ---------- ----------- 229: |0 : don | |0 : jane | 230: ---------- ----------- 231: / \ 232: / \ 233: ----------- ---------- 234: |0 : adam | |0 : eve | 235: ----------- ---------- 236: 237: The above print algorithm would print it as follows: 238: 239: 240: 0 : jane 241: 0 : jack 242: 0 : eve 243: 0 : don 244: 0 : adam 245: 246: The left child of a node is printed on the first line following the node 247: with is indented by one more tab then the given node. 248: The right child of a node is printed on the last line preceding the node 249: with is indented by one more tab then the given node. 250: If you tilt your hand to the left while examining the printed tree format 251: it closely resembles the "traditional" format of a rooted binary tree. 252: 253: Known Limitations: 254: ------------------ 255: 256: Shared dictionaries are unprotected, so serialized access to the 257: dictionary is assumed. Use at your own risk :) 258:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.