A Replacement for the ALL-IN-ONE Corporate Telephone Directory using DATATRIEVE and FMS, which may also be used without ALL-IN-ONE. Bart Z. Lederman 2572 E. 22nd St. Brooklyn, N.Y. 11235-2504 Abstract One of the functions supplied with ALL-IN-ONE V2 is a corporate telephone directory. I found that it's usefulness was very limited due to poor performance. I have developed this replacement for the corporate telephone directory which can read the same data file: this allows any information which has already been input to the telephone directory to be saved. The application uses VAX-DATATRIEVE and FMS to present the information in a menu-driven form, which allows better manipulation of the information. The application is also more easily adapted to individual requirements: in this example, a field for a third telephone number has been added, the state is recorded as a separate field, and the information may be entered in lower case so that it will have a better appearance when viewed, and when used for other purposes such as letters, mailing labels, etc. Because the application now runs in DATATRIEVE, it may be used without ALL-IN-ONE, as well as being accessed from within ALL-IN-ONE. I first became acquainted with the AI1 telephone directory when I started my present job. The users had over 1800 entries already in the directory, but were not really able to use the information due to the poor performance of the application. When it was first demonstrated to me on a VAX-11/750 with ONE user, retrieval of the first entry took over 45 seconds, and all subsequent retrievals were equally slow. I decided to create a package which would perform the same or similar function: this application had to be done in a way that could be integrated into AI1 and would require a minimum of training for the users during conversion, and this in turn required the use of menus and forms in a manner similar to AI1. In addition, since a considerable amount of labor had already been expended in creating the 1800+ existing entries, the new application had to be able to read the existing data file. A Replacement for the Corporate Telephone Directory Page 2 Bart Z. Lederman 20 March 1986 Why use DATATRIEVE? I chose DATATRIEVE as it can implement this application with good performance, it takes relatively little time to develop applications, it allows for easy modification of the resulting application, it can read the existing data file, it can be called from AI1, and it works well with FMS (or TDMS) to provide the forms and menu driven interface. The fact that the DATATRIEVE application may also be easily accessed without AI1 is an important asset in many situations, though it happened not to be important at this site at the present time. Why use FMS? Although DATATRIEVE can just as easily work with TDMS, AI1 uses FMS so I also used it for my application. It is important to note that AI1 can be linked with only one DATATRIEVE image, and that image can in turn be lined with either FMS or TDMS but not both; so one should decide which product is going to be used for all (or most) DATATRIEVE applications which will be integrated under AI1 before any are developed: this allows the proper DATATRIEVE image to be linked to AI1. Though you can get to DATATRIEVE from AI1 using scripts or DCL command procedures, and these may invoke any DATATRIEVE image, the fastest way to DATATRIEVE is to invoke the linked copy directly with the DTR command internal to AI1, and this may invoke only the image that was linked to AI1. Since AI1 uses FMS and DATATRIEVE can use FMS, it may also be cheaper to use FMS for both rather than having to buy TDMS: one may also develop FMS applications using the tools within AI1 which cannot be done with TDMS. Creating a compatible record definition. The first step in a conversion project such as this is to create a record definition which matches the existing data file. This could easily be an entire paper in itself: I will simply state here that I used the DUMP utility to look at the existing data, and also looked a little at the form used by the existing application. This information gave me the length of each field, the type of information, and the total record length: with this information it is a very straightforward task to write a matching record definition. I then defined a domain that used this definition on the existing data file, which is OA$DATA:CORPHONE.DAT and looked at the data to see that I indeed had the fields correctly defined: I was also able to scan through the data much more easily than from within AI1 or with the DUMP utility, and get a better idea of how the fields were being used. I also found that there was some empty space in the file: it happened that some of it came just after the telephone numbers, so I used part of that space to store a third telephone number which we happened to need at this site. I also used the last three characters at the end of the field which stores the city to record the state separately (it's three characters rather than two as we have to send letters to Canada, Australia, and other foreign destinations). A Replacement for the Corporate Telephone Directory Page 3 Bart Z. Lederman 20 March 1986 At this point, I now have the essentials of a DATATRIEVE application. If the users could be given a day or so in the use of DTR, this is really all that would be needed to access the information. It happens, however, that the policy at this site is to have all applications pre-defined, with all user functions set in procedures: therefore, procedures for all common functions needed to be defined. In addition, the use of forms often makes the information easier to manipulate: when there are many fields, it is easier to read if the form writes it to an entire screen with titles rather than simply PRINTing it or LISTing it. When an entry has to be added or modified, the use of a form allows the user to move backwards and forwards through all of the fields in a record; the user can see all of the fields while working, and can check to see that they are all correct before committing the record; a simple STORE or MODIFY prompts for the fields in order and does not allow backing up if an entry is incorrect. There are, therefore, many benefits to the use of forms in an application, and forms are relatively easy to use with DATATRIEVE. Creating Forms. This too could be the subject of an entire paper. I followed the basic layout of the AI1 form as I did not want there to be too much of a change visible to the users. By following the same basic layout, very little retraining was needed. Also, the same form was copied for display, add, modify and delete: unfortunately, the forms generally cannot be shared as some fields must be marked DISPLAY ONLY on some forms but not on others: the same form is used for display and delete, however, as they are both basically display only. I referred to the FMS manuals very little, if at all: Bert Roseberry's papers on using FMS with DATATRIEVE were far more readable and informative. The FMS description is the hardest part: once the forms are defined their use within DATATRIEVE is actually quite simple. For example, the procedure that displays a form for modification shows just about everything that needs be done with forms in DATATRIEVE. Once a particular record is selected, the form is selected with a DISPLAY_FORM, then fields are filled in with PUT_FORM, then data is retrieved with GET_FORM. FOR CORPHONE WITH CKEY STARTING WITH LOOKUP||"" AND MORE = "Y" MODIFY USING BEGIN DISPLAY_FORM MODPHONE IN OA$DATA:CORPHONE.FLB USING ! ! Fill in the form with the existing data. ! BEGIN PUT_FORM CKEY = CKEY PUT_FORM NAME = NAME PUT_FORM TITLE = TITLE PUT_FORM BUSINESS = BUSINESS PUT_FORM PERSONAL = PERSONAL PUT_FORM OTHER = OTHER PUT_FORM DEPARTMENT = DEPARTMENT PUT_FORM COMPANY = COMPANY PUT_FORM MAIL_STOP = MAIL_STOP PUT_FORM STREET = STREET A Replacement for the Corporate Telephone Directory Page 4 Bart Z. Lederman 20 March 1986 PUT_FORM CITY = CITY PUT_FORM STATE = STATE PUT_FORM ZIP = ZIP PUT_FORM NODE = NODE PUT_FORM COMMENTS = COMMENTS PUT_FORM PROMPT = "Go on to next entry [Y/N] ?" END RETRIEVE USING BEGIN ! ! Pull back the modified data. ! NAME = GET_FORM NAME TITLE = GET_FORM TITLE BUSINESS = GET_FORM BUSINESS PERSONAL = GET_FORM PERSONAL OTHER = GET_FORM OTHER DEPARTMENT = GET_FORM DEPARTMENT COMPANY = GET_FORM COMPANY MAIL_STOP = GET_FORM MAIL_STOP STREET = GET_FORM STREET CITY = GET_FORM CITY STATE = GET_FORM STATE ZIP = GET_FORM ZIP NODE = GET_FORM NODE COMMENTS = GET_FORM COMMENTS MORE = GET_FORM REPLY ! ! The default is to continue with next entry. ! IF MORE = "" MORE = "Y" END END ! ! See if another entry is wanted. ! DISPLAY_FORM SHOWPHONE IN OA$DATA:CORPHONE.FLB USING BEGIN PUT_FORM PROMPT = "Modify another entry [Y/N] ?" END RETRIEVE USING BEGIN ANSWER = GET_FORM REPLY END END END-PROCEDURE You will notice that I have chosen field names within my FMS form that match the field names in the record definition: this is not necessary, but it does make things much simpler to remember. One feature worth noting is the use of two general purpose fields, "PROMPT" and "REPLY". This lets me put whatever message I want on the screen (FMS is set to right justify it), and do what I want with the answer (which FMS has been set to convert to upper case). Here it is used to prompt the user to determine if this entry should be skipped, and again to determine if a different entry should be modified (answering Y here results in the user being prompted for another lookup key). A Replacement for the Corporate Telephone Directory Page 5 Bart Z. Lederman 20 March 1986 Incorporation into the CDD and ALL-IN-1. The complete DATATRIEVE application may be installed into the CDD by entering DATATRIEVE and invoking the CORPHONE.COM command file (or CORPHONE.OLD as described later): this has been set to go into a company wide dictionary CORPORATE, which is what I have used for data which will be used for the entire company. At this point, any DTR user may invoke the procedure MENU_PHONE to access the telephone directory. To add the application to AI1 requires changing one or more forms to invoke DTR. The important item is the DATA item in the form which invokes DATATRIEVE: the form DATABASE which is supplied with this package has a selection field CP which invokes the telephone directory. An examination of this form and the DATABASE.FLG descriptor will show how DTR is invoked directly from AI1. Note that this requires that AI1 be linked with DTR: the AI1 installation manual shows how this is done, but all it requires is that when you build AI1 that you answer "yes" when you are asked if you want to link with DATATRIEVE. The default DATATRIEVE image DTRSHR is the one you will probably want. If you do not link AI1 to DATATRIEVE, then you will have to write a script or command file, following the examples in section 6.30 of the ALL-IN-1 OFFICE MENU Application Programmer's Reference, Volume 2: Functions manual. Performance will probably not be as good as having AI1 linked to DTR. All of the forms needed by the DATATRIEVE application are included here as forms and in the library CORPHONE.FLB, which the application expects to find in the AI1 dictionary normally pointed to by the logical OA$DATA. There are many benefits to having a complete path name when invoking the procedure. For example, the AI1 command which will be in the form's data field is DTR :CDD$TOP.CORPORATE.MENU_PHONE This also requires the READY and procedure invocations to include a full path name: I have included the path name CDD$TOP.CORPORATE in CORPHONE.COM where needed. If this is done, then the procedure will always be invoked regardless of the current dictionary or default for that user. This would be useful if users also had individual DATATRIEVE applications they wished to invoke from AI1. For example, this package could be copied to replace the personal telephone directory, in which case each user would probably have an individual CDD dictionary: the ALL-IN-1 LOGIN file or the users' individual LOGIN file would assign their default to their own dictionary, the command on the AI1 form to get that DATATRIEVE procedure would NOT have a path name (because all AI1 users will be invoking the same form) and would go to the users' individual dictionary, but the command on the AI1 form for the corporate directory would be as shown above so that the corporate wide directory would be obtained from any users' default directory. I do not expect to implement personal telephone directories, but they could be done the same way (and even share the same forms) as the corporate directory. Including path names is also useful for accessing the directory without AI1, as a user might do from DCL. If you have defined a command to start DATATRIEVE like this one: A Replacement for the Corporate Telephone Directory Page 6 Bart Z. Lederman 20 March 1986 $ DTR32 :== $SYS$SYSTEM:DTR32 in your LOGIN.COM file (or more probably in SYS$MANAGER:SYLOGIN.COM), then you can invoke a DATATRIEVE procedure directly with a command such as: DTR; :CDD$TOP.CORPORATE.MENU_PHONE and go directly into the corporate telephone application main form without having to change your own default dictionary, or indeed knowing anything about DATATRIEVE. It is also possible to define a command to invoke this procedure so users could just type in a command such as CORPHONE in DCL and go straight to the application: CORPHONE :== $SYS$SYSTEM:DTR32 :CDD$TOP.CORPORATE.MENU_PHONE Other modifications. Once you have switched to this version of the telephone directory, you may want to disable the version supplied with AI1. To do this you can remove the DIRCOR choice from the DIR form: you can simply blank it out on the layout, and you will probably want to remove the corresponding choice in the data statements. If you do this, then the forms DIRCOR, DIRCORP, and DIRCORSEL will no longer be used and you may want to remove them from OAFORM to save space when the form library is compiled. In addition, all of the DO scripts that begin with DIRCOR will not be needed, so if you moved them to the OA$DO directory to include them in your TXL (for better performance) you will probably want to move them back to OA$LIB and recompile the TXL to conserve space. The AI1 implementation required that the key field (called CKEY in my applications) be unique. I do not believe that this is a good choice: for example, if you want to store the numbers for various airlines, you can't have them all with the key AIRLINE: you must have something like AIRLINE1, AIRLINE2, etc. Because my package retrieves on keys starting with the given search criteria, this is not too much of a restriction, but I didn't see any reason for it so I defined a new data file named OA$DATA:CORPHONE.DOM using ANALYZE/FDL and allowed the key to have duplicates. I also did this to use the EDIT/FDL optimize script to look for ways to improve the file structure, and then used CONVERT to load the new file from the old one. I have included the FDL file here, but it is set up for the number of entries we have here, so you may wish to analyze your own file. Though DATATRIEVE doesn't care if duplicates are allowed or not, and my package should work either way, I have not included any double checks against duplicates so if your data file has not been defined to allow duplicate keys and you try to enter a new record with a key that duplicates an existing record, the store will abort with an error. NOTE: the command file CORPHONE.COM references my new data file. If you want to read the AI1 data file you must change OA$DATA:CORPHONE.DOM back to OA$DATA:CORPHONE.DAT before defining the domain (or redefine the domain by hand after invoking CORPHONE.COM). A Replacement for the Corporate Telephone Directory Page 7 Bart Z. Lederman 20 March 1986 Bottom line: performance. A good question after all of this is what sort of performance is obtained with the new package, and what did it take to achieve it. To answer the latter question, it took a few hours of work to analyze the old directory file and produce a finished DATATRIEVE record definition that correctly retrieved all of the fields: it would have taken less time to create a new record definition that did not have to correspond exactly with an existing data file. It took another day and a half to create all of the forms and procedures, but this was the first time I had ever used an FMS form with DATATRIEVE: now that I have some experience (and some files of my own to copy) I can bring up a new application in much less time. It took another half a day of concentrated effort to figure out from the ALL-IN-1 manuals how to invoke an application from AI1: again, now that I know how, it takes only a few minutes (plus the time needed to recompile the forms libraries in AI1 for better performance). In short, discounting the time for my learning two new products, the application took very little time to implement. I have probably spent more time writing this document and pushing the package together into a form where I feel I can submit it to the DECUS library and SIG tape than I did developing it in the first place. Performance should be considered in two areas: the time to start the application, and the time to lookup / modify / add / delete entries in the directory. Starting the application from AI1 and a dead start can take 10 to 20 seconds or more, partly from the work needed for AI1 to call up DTR and the time it takes to start (this is slightly faster on subsequent invocations), and partly the time needed to start the procedure MENU_PHONE. Because almost the entire application is contained in one big WHILE loop, DATATRIEVE must parse and "compile" ALL of the statements in all of the procedures before starting. One of the benefits from this is that the application runs quite fast once it is started. Switching from one menu to another is almost as fast as the system can output characters to paint the terminal screen. Within an application such as lookup, once the lookup key is entered retrieving the first entry takes only a second or two, and subsequent retrievals on the same key are about as fast as the screen can be updated. It should be noted, however, that we are running a terrifically overloaded system, and that occasionally when there is a very heavy load the application will stall for a while or be swapped out; when this happens response time slows considerably, but this is not the fault of the application. Using individual dictionaries (not CORPORATE). In my first implementation, I did not use path names: instead I set the users' default dictionary to to CORPORATE. I did this by having the command $ ASSIGN "SYS$USERDEVICE:[ALLIN1]DTRSTART.COM" DTR$STARTUP in the A1LOGIN.COM file. When this is done, DATATRIEVE will process any commands in the DTRSTART command file whenever DTR is run. The command file itself contains the following: A Replacement for the Corporate Telephone Directory Page 8 Bart Z. Lederman 20 March 1986 SET DICTIONARY CDD$TOP.CORPORATE SET PLOTS CDD$TOP.DTR$LIB.PLOTS and in the future may invoke any other startup commands I may need for AI1 users invoking DATATRIEVE. An alternative to this is to include a command such as the following in the A1LOGIN.COM file (or the users' individual LOGIN.COM file): $ ASSIGN "CDD$TOP.DTR$USERS.CORPORATE" CDD$DEFAULT In the absence of any other commands or startup command files, DATATRIEVE will start in the dictionary pointed to by the logical CDD$DEFAULT. Because of the advantages given before for path names, I have dropped this approach but am including here the necessary files, and CORPHONE.OLD which has all of the definitions without path names, to make it easier for anyone who wishes to obtain the various DATATRIEVE definitions without the path names.