.PAGE SIZE 58, 70 .LAYOUT 2, 2 .TITLE O075: Managing ALL-IN-1 with Datatrieve .SUBTITLE B.#Z.#Lederman ITT World Communications, New York .CENTER O075: Managing ALL-IN-1 with Datatrieve .BLANK 2.CENTER Thursday December 10, 1987 .BLANK.CENTER 2:00 p.m. - 3:00 p.m. .BLANK.CENTER Laguna Room Hilton Hotel .BLANK 2.CENTER B.#Z.#Lederman .BLANK.CENTER ITT World Communications .BLANK.CENTER New York, NY 10004-2464 .BLANK .NOTE Abstract This session is intended to illustrate some of the uses for Datatrieve in managing and/or coping with ALL-IN-1, include managing the ALL-IN-1 environment and processing the logging file to determine how ALL-IN-1 is being used. .BLANK PLEASE NOTE: at the request of the Session Notes Editor to conserve paper, listings of most of the record definitions and procedures are not included here. All of the Datatrieve definitions used in this session, and many others, may be obtained through the DECUS Library, on the DTR/4GL SIG Library Tape collection, or the VMS SIG Tape Collection. .BLANK In this paper AI1 is an abbreviation for ALL-IN-1, WPS for any version of WPS-Plus, and DTR for Datatrieve. .END NOTE .PARAGRAPH Datatrieve is a product which allows easy access to and manipulation of data. In reference to office automation, it is usually thought of as a product to manipulate end-user data (data bases containing accounting information, telephone directories, personnel directories, purchase order information, or whatever). What may not be immediately obvious is the data which must be managed when other office automation products are used, particularly ALL-IN-1 and WPS word processing. These products create and use their own database files, and while they also come with their own utilities and commands for the examination and maintenance of those files, there are times when using Datatrieve allows faster, easier, or more versatile access or management of this information. I will present a number of such uses, starting with the document database (the DOCDB.DAT file) which contains the list of documents for each user of ALL-IN-1 and/or WPS-Plus. To save space, two entries are shown side-by-side. .BLANK.NO JUSTIFY.NO FILL DOCUMENT : DEC OUTBOX REFNUM : 999886 999882 TITLE__HASH : DRAFTR TESTX4 FILENAME : [.DOC4]ZRNWAXDCF.WPL OA$SHARE2:ZROMBDKWI.WPL DAF__POINTER : P S TITLE : draft review test new service AUTHOR : Bart Z. Lederman Bart Z. Lederman TYPE : DOCUMENT MAIL UNUSED__SETUP : NONE NONE FORMAT : KEYWORDS : CREATED : 28-Jul-1987 13-Aug-1987 MODIFIED : 24-Aug-1987 13-Aug-1987 MAIL__ORIG : F3 : MAIL__STATUS : SENT F2 : DOCNUM : 114 118 DELETABLE : Y Y MODIFIABLE : Y N CREATED : 28-Jul-1987 13-Aug-1987 CREATED__TIME : 11:17:13.45 14:20:27.60 MODIFIED : 24-Aug-1987 13-Aug-1987 MODIFIED__TIME : 10:52:24.59 14:20:27.60 V1TYPE : DSAB : WPSPLUS WPSPLUS F6 : .JUSTIFY.FILL .BLANK 2.CENTER Why access this other than with ALL-IN-1? .PARAGRAPH There is at least one very important field which is included in this record definition which is not usually obtainable within WPS or AI1, and that is the VMS file which contains the document (the field FILENAME); there are a number of reasons for wanting this information. Sometimes the DOCDB.DAT file becomes corrupted, and then it is necessary to try to coordinate the VMS files with the documents: this record definition allows you to obtain a listing of all documents AI1 (or WPS) knows about and compare it with a directory listing to find missing documents or files. If there are VMS files not recorded in the document database you could add an entry with Datatrieve, though I would recommend you first try using WPS (or EDT, as is appropriate) to create a document and then do a Gold-G (GET) to incorporate that file into a new document. If there is an entry in the document database for which there is no file you can use Datatrieve to delete the entry, though again I would suggest you first try the document database verification procedure supplied for the ALL-IN-1 manager. If the normal procedures don't work, then you may want to use DTR to modify the DOCDB.DAT file. .BLANK 2.CENTER Coordinating ALL-IN-1 with VMS. .PARAGRAPH Some users have reported that they implements expiration dates on their disks to flag old files for archiving. Since this will include the files corresponding to WPS documents, it is necessary to process the DOCDB.DAT file to find out which document goes with which file. This is one way to obtain that information. .BLANK 2.CENTER Faster and more versatile reports. .PARAGRAPH I also find that it is faster to use DTR to obtain an index listing of all documents than it is to use AI1, and it is possible to select the documents you want: .BLANK.NO JUSTIFY.NO FILL.TEST PAGE 8 REDEFINE PROCEDURE DOCDB__REPORT ! ! Fast report of all documents with their VMS file name. ! ! B. Z. Lederman ! REPORT DOCDB ON *."file specification" SET COLUMNS__PAGE = 132 SET LINES__PAGE = 42 PRINT NUMBER, FOLDER, TITLE USING T(48), FILE USING T(24) END__REPORT END-PROCEDURE .BLANK 13-Nov-1986 Page 1 .BLANK NUMBER FOLDER TITLE FILE .BLANK 13 DEC mulvey [.DOC3]ZRDQBBSVI.WPL 2 DICTIONARIES PERSONAL DSK3:[LEDERMAN]PERSONAL.LGP 16 OUTBOX Read Receipt for Test OA$SHARE1:ZRDXBRAEN.TXT 9 PLOTS dtrgraph [.DOC9]ZRBUASZZA.WPL 15 READ Test Mail Message OA$SHARE1:ZRDXBQWZF.TXT .BLANK.JUSTIFY.FILL The sample report has been squeezed to fit the page, but you can still see the information provided. It happens to be sorted by folder because the folder name forms part of the primary key, but with DTR it is possible to easily change the report for the format and sort order you want: for example, all documents written on, before, or after a certain date; documents with particular authors or keywords or words in a title (AI1 lets you search on individual fields, but Datatrieve lets you search on combinations of fields), documents on particular disks or in particular directories, etc. I have even put a Datatrieve procedure like this one into a form and included it as an ALL-IN-1 application so that users can simply type one command and have a complete index of their documents sent to their default printer. .BLANK 2.CENTER Shared definitions and system management. .PARAGRAPH To use a record definition you must also define a domain. Rather than define one for every user, you can take advantage of the logical name created during login to set the correct directory to access: .BLANK DEFINE DOMAIN DOCDB USING DOCDB__RECORD ON OAUSER:DOCDB.DAT; .BLANK The logical name OAUSER should translate to the directory where your document database is (usually [user.WPSPLUS] or [user.OA]). If you intend to use the definition only while you are within ALL-IN-1 you should be able to specify the file as DOCDB.DAT with no directory, as AI1 should already have put you into the correct directory specified in your PROFILE, though you could also assign a logical name similar to OAUSER in the SYLOGIN.COM file so that the same definition can be used if you access DTR from within AI1, or if you go into DTR directly from DCL level. By using logical names, you can put one copy of the record and domain definitions, and any report procedures, into a common dictionary rather than multiplying them for every user. You might also want to define one domain just for the postmaster: .BLANK DEFINE DOMAIN DOCDB__POSTMASTER USING DOCDB__REC ON .BREAK.INDENT SYS$SYSDEVICE:[ALLIN1.POSTMASTE]DOCDB.DAT; .BLANK changing the logical name SYS$SYSDEVICE if you have your AI1 libraries on disk other than the system disk. This way you can look at the POSTMASTER's database (which may include system wide information such as mail messages) without logging into VMS POSTMASTER account, or you may not even have to have a VMS account for the POSTMASTER. This could be important, since the release notes for ALL-IN-1 V2.1 warn against logging into the POSTMASTER account as it can lock out the message router and cause mail messages not to be delivered. .BLANK 2.CENTER The user profile. .PARAGRAPH Next I will show how to manipulate the user environment, as defined by such files as OA$DATA:PROFILE.DAT, the master profile file for ALL-IN-1. This is something that most managers are going to want to reserve to themselves only. The data you get looks like this (with some fields "collapsed" into two columns to save space): .BLANK.NO JUSTIFY.NO FILL USER : LEDERMAN VMSNAM : LEDERMAN FULNAM : Bart Z. Lederman TITLE : Project Engineer DEPART : Advanced Systems Dev STATUS : PASWRD : PHONE : 212-607-2657 RESERVED : DCL : Y SUP : Y ERR : Y CMD : Y SRC : Y CPHD : Y LOG : Y MULTI__NODE : Y RSVD__FOR__TCS : ADDR1 : 2572 E. 22nd Street ADDR2 : Sheepshead Bay, NY ADDR3 : ADDR4 : ZIPCOD : 11235-2504 NOTICE : Y BATCH__NOT : Y PRINT__NOT : Y MAIL__READ__REC : Y TICKLER : Y ACTITEM : Y DIRECTORY : USER$DEVICE:[LEDERMAN.WPSPLUS] FORMLIB : INIT__FORM : MAIN EDITOR : WPSPLUS PRINTER : PORT NODE : PRINT__PORT : Y TERM__MODE : S MAIL__FORWARD : MAIL__REPLY : MAIL__MENU : EMC MAIDES : ALLIN1 CALTIMEING : 00:15 SETUSR : Y YESDAYS : N STARTD : 2 ENDD : 5 STARTH : 08:00A ENDH : 4:30P MEALS : 12:00P MEALE : 01:00P CALDAY : 2 UFLAG1 : UFLAG2 : UFLAG3 : UFLAG4 : UFLAG5 : UFLAG6 : UFLAG7 : UFLAG8 : UFLAG9 : UFLAG10 : CLASS : LANGUAGE : ENGLISH END : .JUSTIFY.FILL .BLANK 2.CENTER Processing multiple entries. .PARAGRAPH Since AI1 gives you access to these fields, why would you use Datatrieve? One answer is that AI1 management is oriented to processing one user at a time. If you want to find out, for example, which users have DCL access enabled, you have to go through several menus and screens to get an index of users, write down their names, then examine them all one at a time to find the ones with DCL. With Datatrieve, you can ready the PROFILE domain and enter 'PRINT#PROFILE#WITH#DCL#=#"Y"' to find all such users. Similarly, operations on large numbers of users such as turning DCL access or logging on or off for everyone, or finding the users whose accounts point to certain disks and/or re-assigning them to other disks, are easier in DTR than in AI1 as presently supplied. You can also use DTR to produce nice formatted reports of all users or groups of users, and you can select which information fields are printed in that report. .BLANK.NO JUSTIFY.NO FILL DTR> for profile print user, directory .BLANK USER DIRECTORY .BLANK CERNY USER$DEVICE:[CERNY.OA] COOK USER$DEVICE:[COOK.WPSPLUS] IVP SYS$SYSDEVICE:[ALLIN1.IVPUSER] LEDERMAN USER$DEVICE:[LEDERMAN.WPSPLUS] MANAGER SYS$SYSDEVICE:[ALLIN1.MGR] POSTMASTER SYS$SYSDEVICE:[ALLIN1.POSTMASTE] .BLANK.JUSTIFY.FILL .PARAGRAPH Because AI1 manipulates several files for user profiles, it is NOT a good idea to add or delete user profiles using DTR, though it could be done in emergencies. .BLANK 2.CENTER The network profile. .PARAGRAPH Another, somewhat less well known, file is OA$DATA:NETWORK.DAT, which contains information on all users who have network or multi-node access (and, I suspect, all users). If you use a VAX Cluster, then you essentially have a multi-node system, and there will be a NETWORK.DAT file with something in it. Most managers probably don't do anything with this file, but there is at least one time it should be looked at, which may be deduced from looking at some sample data. .BLANK.NO JUSTIFY.NO FILL USER__NAME : LEDERMAN NODE : SYS31 LAST__UPDATE : 9-Jan-1987 UPDATE__TIME : 15:10:15.81 FULL__NAM : Bart Z. Lederman TITLE : Project Engineer DEPARTMENT : Advanced Systems Dev TELEPHONE : 212-607-2657 ADDR1 : 2572 E. 22nd Street ADDR2 : Sheepshead Bay, NY ADDR3 : ADDR4 : ZIPCOD : 11235-2504 NETWORK__ADDRESS : LEDERMAN AT A1 AT SYS31 TIMESTAMP : M__NODE : Y DELETED : N .JUSTIFY.FILL .BLANK 2.CENTER Cleaning up after ALL-IN-1. .PARAGRAPH Most of the fields are self explanatory, and many match the fields you will find in the PROFILE, but notice the field "DELETED". I recently had to re-organize my system, and deleted a lot of old user profiles using the normal ALL-IN-1 menus and procedures. I found, however, that there were still a lot (all?) of the old users still in the NETWORK.DAT file. Most, but not all, were marked as deleted, but still: why take up space storing profiles on people who aren't here anymore? (There may be cases where you want to know that a user used to be on a system, but in my case when a user is off the system I want them to be completely off of the system.)# In this instance, Datatrieve is a useful tool for cleaning up when AI1 doesn't do a complete job of managing it's own data, and there will be more examples of this later. .PARAGRAPH The NETWORK__ADDRESS field does not look like a regular node name: the reason is because it's really a Message Router Gateway type address, used when routing mail to other networks or mail agents. .BLANK 2.CENTER Time Management. .PARAGRAPH Time Management is another of the applications which is built into ALL-IN-1. It allows a user to mark a calendar for reminders and action items, and to allow groups of users to schedule meetings by checking all of the users' calendars for conflicts. Although most access to the data is done through AI1, there are times when the users, and especially the AI1 manager, may need to access and/or manipulate the data outside of AI1. .PARAGRAPH To take the easiest case first, here is a definition for OA$DATA:CALACCESS.DAT, the file which determines which users are allowed to access which other users' calendars. .BLANK.NO JUSTIFY.NO FILL.TEST PAGE 11 REDEFINE RECORD AI1__CALACCESS__RECORD 01 AI1__CALACCESS__REC. 10 GRANTUSER PIC X(30) EDIT__STRING T(16) QUERY__HEADER "User"/"Granting"/"Access". 10 ACCUSER PIC X(30) EDIT__STRING T(16) QUERY__HEADER "Access"/"Given"/"To". 10 READ PIC X QUERY__HEADER "Read"/"Your"/"Calendar". 10 WRITE PIC X QUERY__HEADER "Schedule"/"for"/"You". 10 PHONE PIC X QUERY__HEADER "". ; .BLANK.JUSTIFY.FILL When this domain is printed the fields look like this: .BLANK.NO JUSTIFY.NO FILL.TEST PAGE 21 User Access Read Schedule Granting Given Your for Access To Calendar You .BLANK ERSKINE STEVE Y Y ERSKINE ELLIOTT Y Y LEROY REGGIE Y Y LEROY HOWIE Y N LEROY RALPH Y N LEROY SOLON Y N LEROY JOSHI Y N LEROY STEVE Y Y RKELLY VICKIC Y N STEVE ERSKINE Y N VICKIC BEATE Y N VICKIC ERSKINE Y Y VICKIC IRENE Y N VICKIC STEVE Y N VICKIC ELLIOTT Y N VICKIC RKELLY Y N .JUSTIFY.FILL.BLANK Notice the additional information placed in the record definition which describes what the fields are used for (which also automatically prints out as column headers when the data is accessed), and that additional comments can be stored in the Datatrieve definition. This is good documentation as to what the data is and how it's used which is not always found in AI1 FMS forms descriptions. .BLANK 2.CENTER More cleanup after ALL-IN-1. .PARAGRAPH The fields and their use should be fairly obvious: each user has an entry for each other user to which they wish to grant read access and/or scheduling access. What is not immediately obvious is the first important reason why a manager would want Datatrieve access to this file, although it becomes apparent when I explain that none of the persons listed in this domain have access to this system. As mentioned in the previous article, ALL-IN-1 does not clean up after itself properly, especially when deleting users. All of the persons you see listed above were deleted from ALL-IN-1 using the normal System Manager's functions, but AI1 didn't delete their entries from the Calendar Access files (neither this one or the others shown below). Using Datatrieve, it is easy to locate and delete all records which have the name of a person who is no longer an AI1 user in either the GRANTUSER or ACCUSER fields and thus clean up the file. The other reason is that it is much easier to obtain a quick listing of all users in the CALACCESS file with DTR than it is with AI1. These two reasons for using Datatrieve to access ALL-IN-1 data files will appear many times in this series of articles. .PARAGRAPH Something to be aware of is that any user with write access to this file can add or modify records. This is handy if the system manager wants to add new users to have access to many existing users, or if the manager wants to obtain access to other users' calendars, but it's not so good if users give themselves more access then they should have to other users' calendars. You should check to see that the world has read access only to the data file: the AI1 task image is itself privileged and will still have access on behalf of the users. .PARAGRAPH The next file I will consider is OA$DATA:ATTENDEE.DAT, which contains the list of meetings and attendees. A typical record looks like this: .BLANK.NO JUSTIFY.NO FILL NAME1 : IVP DATE : 1-Jan-2010 TIME : 08:00 LENGTH : 0001 NAME2 : NOT__A__REAL__NAME FLAG : YES__NO : YES MESSAGE : I will be a little late. DATE : 18-Nov-1858 TIME : 00:00 LENGTH : DATE : 18-Nov-1858 TIME : 00:00 LENGTH : DATE : 18-Nov-1858 TIME : 00:00 LENGTH : DATE : 18-Nov-1858 TIME : 00:00 LENGTH : DATE : 18-Nov-1858 TIME : 00:00 LENGTH : DATE : 18-Nov-1858 TIME : 00:00 LENGTH : END : .BLANK.JUSTIFY.FILL In the record definition I'm using a REDEFINES clause to take the date and time stored by AI1 as ASCII characters and convert it into the Datatrieve (and VMS) standard binary date and time. This isn't strictly necessary to examine the file or for some management functions, but it does make retrieval by date easier within Datatrieve. .BLANK 2.CENTER Purge old users, meetings. .PARAGRAPH You can probably begin to see from these few records some of the reasons for using DTR to get at this data. As before, removing a user from AI1 does not remove that users' meetings from the data file, so DTR can be used to remove them. There also does not appear to be any mechanism to remove past meetings automatically (notice the meetings scheduled by IVP, the Installation Verification Procedure, are still present) so DTR can be used to remove them. Finally, the reason for using the REDEFINES clauses to put the date into a form where comparisons work well within DTR becomes apparent when a user tries to go in and remove past meetings. I have not found a way to get AI1 to tell me which past days still have meetings assigned, and the tendency is going to be for users to simply leave all past meetings scheduled. Eventually, the ATTENDEE.DAT file is going to be very large, and most of the data within it will be for meetings which already occurred. Using the date comparison within Datatrieve makes it easy to find and delete all past meeting records. You could also store them into a separate domain for journaling if you wish to, but you should keep obsolete data out of ATTENDEE.DAT or else AI1 performance could suffer. .PARAGRAPH Next comes OA$DATA:MEETING.DAT, the file which contains a list of meetings. .BLANK.NO JUSTIFY.NO FILL SCHEDULER : IVP DATE : 1-Jan-2010 TIME : 08:00 LENGTH : 0000 DATE : 1-Jan-2010 TIME : 21:00 LENGTH : 000 PURPOSE : To test Installation Verification Procedures LOCATION : Charlotte PRIORITY : A1 A : NAME2 : B : .BLANK SCHEDULER : IVP DATE : 1-Jan-2010 TIME : 08:00 LENGTH : 0001 DATE : 1-Jan-2010 TIME : 21:30 LENGTH : 000 PURPOSE : To test Installation Verification Procedures LOCATION : Charlotte PRIORITY : A1 A : NAME2 : B : .BLANK.JUSTIFY.FILL As before, this domain contains records of obsolete meetings, meetings for persons no longer using the system, and IVP meetings that are scheduled for the future but really don't need to remain in the file once the Installation Verification Procedure finishes. .PARAGRAPH When cleaning up the ATTENDEE and MEETING files, you should remember that their use is inter-linked: you shouldn't have meetings without attendees, and vice versa. I have not done much in the way of trying to match up the two files: whenever I have had to clean them up it has been a case of deleting all records which refer to a particular ex-user or deleting all records of meetings scheduled before a particular date, and just assuming that this doesn't leave any non-matched records (this is probably a fairly safe assumption). If you do want to try matching things up, then the field MEETING__POINTER, which is a keyed field in both domains, is probably the best place to start. For example (only a few records are reproduced here): .BLANK.NO JUSTIFY.NO FILL DTR>for meeting cross attendee over meeting__pointer - CON>print scheduler, attendee__name, date .BLANK.TEST PAGE 15 ATTENDEE SCHEDULER NAME DATE .BLANK ERSKINE RALPH 29-Aug-1985 ERSKINE STEVE 29-Aug-1985 ERSKINE IRENE 30-Aug-1985 HOWIE STEVE 30-Aug-1985 IRENE PATMC 30-Aug-1985 IVP NOT__A__REAL__NAME 1-Jan-2010 IVP NOT__A__REAL__NAME 1-Jan-2010 IVP YHTALEOJ 1-Jan-2010 LEDERMAN MANAGER 15-Dec-1986 LEDERMAN ERSKINE AT A1 15-Dec-1986 AT SYS31 .JUSTIFY.FILL .BLANK 2.CENTER Pending mail count. .PARAGRAPH Another data file is OA$DATA:PENDING.DAT, which contains the pending mail count. .BLANK.NO JUSTIFY.NO FILL PENDING KEY C A B D ENUM .BLANK FETCHER QUEUE 0 4 0 0 MAIL BRENDER 0 4 0 34 MAIL COOK 0 152 148 2 MAIL DEMO 0 0 0 0 MAIL IVP 0 0 0 0 MAIL MANAGER 0 0 0 0 .BLANK.JUSTIFY.FILL I have not quite figured out what AI1 is doing with all of these fields, but I am reasonably certain what two of them are. PENDING__KEY contains the name of the user queues (there are MAIL entries and message router queue entries), and ENUM contains the number of unread messages. I am using a COMPUTED#BY field here because the data file contains the number with leading blanks, and I want to treat it as a numeric value. If all I ever wanted to do was print out the number, such as I am doing here, I could just use field E. .PARAGRAPH Once there is a domain which accesses this data, it's fairly easy to find out how many messages are waiting: .BLANK.NO JUSTIFY.NO FILL REDEFINE PROCEDURE PRINT__PENDING ! ! Find out how much ALL-IN-1 Electronic Mail is Pending ! ! B. Z. Lederman ! READY AI1__PENDING SHARED DECLARE KEY__FIELD PIC X(65). ! ! Get the pre-defined user name and make it into a retrieval key ! KEY__FIELD = "MAIL " | FN$TRANS__LOG ("USER__NAME") ! FOR AI1__PENDING WITH PENDING__KEY = KEY__FIELD PRINT "Pending Messages = ", ENUM(-) ! FINISH END-PROCEDURE .BLANK.JUSTIFY.FILL The reason I'm translating a logical name here is because I'm assuming that one procedure would be used by everybody in the system (invoked from SYLOGIN.COM, for example), rather than hard-coding a dedicated version for each individual user. For this to work, you have to define a logical name which translated to the users' name. (A complete description of the process has been published in the combined DECUS Newsletter.) .BLANK 2.CENTER ALL-IN-1 useage and tuning: the logging file. .PARAGRAPH There is another type of application using Datatrieve with ALL-IN-1, and that is application usage. AI1 has the ability to generate a logging file, but there are no good utilities or facilities supplied to do anything with the information generated. Datatrieve is a good tool for reading and analyzing this information. A small portion of the raw data looks like this: (It won't fit in 80 columns, so I've removed the FACIL__ID, PROC__ID, and Date fields, which happened to all be the same in this short sample) .BLANK.NO JUSTIFY.NO FILL MSG SYS ELAP ID TIME TIME INPUT FUNCTION TEXT .BLANK 18842411 20:54:30.27 0 Function: SHOW__FORM MAIN 18842411 20:54:30.33 7 Function: OA$FORM__DISPLAY 18842411 20:54:34.12 23 Function: SET__MENU DEFAULT 18842411 20:54:34.26 35 Function: FORM MAIN 18842411 20:54:34.31 40 Function: OA$FORM__MENU 18842403 20:54:45.52 82 em{CR} 18842411 20:54:45.53 83 Function: OA$FLD__DONE .BLANK.JUSTIFY.FILL To make this information more useful, Datatrieve can be used to process the information to extract just FORM and DO script usage, and match it up to the library where the form or script is stored. I include the procedure here to demonstrate an important point. .BLANK.NO JUSTIFY.NO FILL REDEFINE PROCEDURE AI1__NORMALIZE ! ! Process AI1 logging file so that the form names are extracted ! and normalized. This allows looking them up in a table to ! find out which library they are in, and to allow summation ! for statistics on use. ! ! B. Z. Lederman ! DEFINE FILE FOR AI1NORM READY AI1NORM WRITE READY AI1LOG ! ! need a few working variables ! DECLARE A__FORM PIC X(24). DECLARE B__FORM PIC X(24). DECLARE E1 PIC 99 EDIT__STRING Z9. DECLARE E2 PIC 99 EDIT__STRING Z9. ! ! Go through the logging file and pick out uses of forms and ! scrips ! FOR AI1LOG WITH FUNCTION = "FORM", "DO" BEGIN ! ! Now comes the fun part. We want to extract only the form (or ! script) name and normalize it. ! E1 = 0 ! initialize end of string E2 = 0 ! position counters A__FORM = FN$UPCASE (FORM__NAME) ! force upper case E1 = FN$STR__LOC (A__FORM, " ") ! look for end of form name E2 = FN$STR__LOC (A__FORM, "/") ! may have command attached IF E1 > 0 E1 = E1 - 1 ! want last character IF E2 > 0 E2 = E2 - 1 ! not search character ! ! take out the form name if it is not null: the form either ends ! with a null or space or with a slash if there was a command ! attached. ! IF ( (E2 > 0) AND ( (E2 < E1) OR (E1 = 0) ) ) THEN B__FORM = FN$STR__EXTRACT (A__FORM, 1, E2) ELSE B__FORM = FN$STR__EXTRACT (A__FORM, 1, E1) ! ! If we can find this form (script) in the domain table we ! created which lists the library each form is in, use that ! libraries' name, otherwise use a blank space. ! IF (B__FORM IN FORM__TABLE) THEN A__FORM = B__FORM VIA FORM__TABLE ELSE A__FORM = " " ! ! we now have nicely normalized data: store it. ! STORE AI1NORM USING BEGIN FACIL__ID = FACIL__ID MSG__ID = MSG__ID PROC__ID = PROC__ID SYS__DATE = SYS__DATE ELAP__TIME = ELAP__TIME FUNCTION = FUNCTION NAME = B__FORM LIBRARY = A__FORM END END END__PROCEDURE .BLANK.JUSTIFY.FILL The information, after processing, looks like this (again with the constant fields deleted here to save space): .BLANK.NO JUSTIFY.NO FILL MSG SYS ELAP ID TIME TIME FUNCTION NAME LIBRARY .BLANK 18842411 20:54:34.26 35 FORM MAIN MEMRES 18842411 20:54:45.65 90 FORM EMC OAFORM 18842411 20:55:06.23 242 FORM EMHEAD OAFORM 18842411 20:55:37.03 337 FORM AUTO MEMRES 18842411 20:55:39.28 361 FORM AUTO MEMRES 18842411 20:55:41.11 383 FORM AUTO MEMRES 18842411 20:55:41.31 400 FORM OA$EDIT MEMRES 18842411 20:56:59.28 717 FORM WP OAFORM 18842411 20:57:07.93 760 FORM WPINDX OAFORM 18842411 20:57:37.96 851 FORM EMC OAFORM 18842411 20:57:38.53 890 FORM OA$LIST MEMRES 18842411 20:58:03.61 1078 FORM WPINDX OAFORM 18842411 20:58:33.91 1164 FORM MAIN MEMRES .JUSTIFY.FILL .BLANK 2.CENTER Why is this done in Datatrieve? .PARAGRAPH The reason for using Datatrieve is that if you used a "third generation" language such as COBOL or FORTRAN, you would have to write just as much processing code, plus a lot more code for the file and record processing work, to accomplish the same result as the Datatrieve procedure shown here; and it would take much longer to write and test it. In processing one serial file to another as we are here, DTR is going to be close to the same speed as any other program doing the same amount of work, and this is an application where you are going to spend much more time analyzing the data than you will in the conversion process. .PARAGRAPH There is a considerable amount of information one can obtain from this data. For example: how many users access AI1, when they use it, the sequence of commands entered, and what features within AI1 are being used. I concentrated on what FORMS and DO scripts were being used, with the intention of optimizing AI1 performance by putting the most used scripts in the TXL, (and the most used forms in MEMRES, but see the caveat below), and moving the lesser used forms and scripts elsewhere. With DTR, it's quite easy to get summary information (notice how much less work is needed for this report than with 3rd generation languages): .BLANK.NO JUSTIFY.NO FILL REDEFINE PROCEDURE AI1__NORM__RPT ! ! Report summarized use of forms and scripts ! ! B. Z. Lederman ! READY AI1NORM REPORT AI1NORM WITH LIBRARY NE " " SORTED BY FUNCTION, NAME ON *."TT or file name" AT BOTTOM OF NAME PRINT FUNCTION, SPACE 1, LIBRARY, SPACE 1, COUNT, SPACE 1, NAME AT BOTTOM OF FUNCTION PRINT NEW__PAGE END__REPORT END__PROCEDURE .BLANK FUNCTION LIBRARY COUNT NAME .BLANK FORM MEMRES 3 AUTO FORM OAFORM 1 DISPREMINDER FORM OAFORM 4 EMC FORM OAFORM 1 EMHEAD FORM MEMRES 4 MAIN FORM MEMRES 1 OA$EDIT FORM MEMRES 2 OA$LIST FORM OAFORM 1 WP FORM OAFORM 2 WPINDX .JUSTIFY.FILL .! .! This is just a short example, but I actually went through data .! from a much larger sample and rearranged MEMRES and OAFORM to .! match. If one reads the ALL-IN-1 manager's manual, it would .! appear that putting the most used forms in MEMRES, where they are .! compiled and linked into the AI1 executable task image itself, .! would improve performance: and, I've been told, the AI1 and WPS .! developers themselves thought so as well. It was not until I .! presented this material at a previous symposium that I was given .! additional information from an independent testing group within .! DEC that putting more forms in MEMRES not only does not improve .! run-time performance, it slows down task initialization. The more .! forms there are in MEMRES, the larger the task image and the .! longer it takes to start up AI1. If you install MEMRES and OAFORM .! in memory (the normal way AI1 is run), then the first time a form .! is used it is stored in memory, and from then on it doesn't .! matter much which library it was in. .! When I first went through this exercise, I did rearrange the two .! libraries, and saw improvements: upon re-examining the libraries .! involved, I found that, after checking what forms my users .! actually needed, I ended up with fewer forms in MEMRES than the .! DEC distributed libraries, which probably accounted for the .! improvement. Also, I was working on a system which was .! drastically short of memory, so there was a potential for .! improvement in not installing any libraries in memory (something .! which may also be done if you want to run AI1 and WPS on .! the same system), and under these circumstances access to a .! compiled form in MEMRES might be an improvement. Additional .! testing will have to be done to obtain definitive answers. .! .PARAGRAPH .! This does not mean the information is not useful: far from it. .! .BLANK 2.CENTER Optimize DO script placement. .PARAGRAPH Although the above extract doesn't happen to show any, DO script usage accounts for a significant portion of the work done by ALL-IN-1, and putting the most used scripts into the TXL can improve performance: moving unused scripts out conserves memory (and moving them out of the default directory saves directory look-up time). The above process can be used to identify the most and least used scripts. .BLANK 2.CENTER How is ALL-IN-1 being used? .PARAGRAPH This logging information is the best (perhaps only) method of finding out what your users are actually doing in AI1, where the most effort is being expended, and where efforts to improve performance or ease of use will yield the greatest results, and even how you might tune your system or adjust quotas to match the work being done. By noting the forms and scripts used, you can tell if people are doing most of their work with word processing, time management, electronic mail, etc. .BLANK 2.CENTER Other files and information. .PARAGRAPH There are quite a few other AI1 files which may be read with DTR: the lists of font styles, file formats, printer device types, queue priorities, communications hosts and lines, and others. Most of the reasons given for manipulating the files shown before don't apply to these, either because they are so little used, because the ALL-IN-1 facilities are adequate, or because they are never (or should never be) modified. There is value in looking at these files, however, because examining them may give you a better insight into what data is needed by ALL-IN-1 for it's operation and maintenance, and how this data may be used or modified for the user environment. .BLANK 2.CENTER How the Definitions Were Obtained. .PARAGRAPH In case you are wondering how I derived these record definitions, I started by using the DUMP utility and ANALYZE/RMS to get basic information about each file (record length, key field names and positions) and created a Datatrieve record definition with just a few large fields. Using DTR and DUMP, most field boundaries become obvious as the data "lines up", and field names could usually be derived from how the information is used (for example, the PROFILE form). Later, I found a form in MEMRES called DOCDB (there is also one in OAFORM called DOCDBSF for the system shared DOCDB), matched up the corresponding fields with the record definition, and in most cases found the fields corresponded with my definitions (though the names of the fields were sometimes different). I used this technique for the other data files, and in most cases it was quite easy to find the field definitions and names (though occasionally there is space in the file which does not correspond to any field named in the form). .PARAGRAPH Some of the key fields look a little odd, but they match the fields defined by WPS and AI1: you can find out about such fields by doing an ANALYZE/RMS or DIR/FULL on a file to see the fields, or you can look in OA$LIB for the FDL files supplied with the products and used during such things as document database (file cabinet) re-organization. .PARAGRAPH Unlike most of the other definitions you will see in this session, I have not been able to find AI1 forms which display ATTENDEE.DAT or PENDING.DAT, so I cannot be certain that I have the same names for these fields that AI1 uses: therefore, some of the field names may not correspond to their intended use, though there is an FDL file which has the key definitions. .PARAGRAPH I have not found any forms, menus, or scripts in AI1 that will lead you to the DOCDB manipulation form (and I have looked), and once you are in the form it is tedious to use as you can only get one record at a time by using the FIXER field (entering a FOLDER doesn't seem to work). Some of the other data files can be accessed via a form in AI1. This acess method does use FMS to spread the fields out on one screen, which can be nice, and it will allow you to add, delete, or modify records, but I prefer Datatrieve: I can always define my own form (or even copy the AI1 form) and use it from within DTR if I want to.