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