Profile Scheme ______________ 24/6/82 The profile scheme provides a way for programs or packages to store and retrieve small amounts of data separately for each user. This information would typically specify options chosen by the individual user. For example, if the program were the text editor ECCE, the information stored might be whether letter case was to be ignored or not when searching for text strings, initial macro definitions, and monitoring level. It is stressed that different users can each select different settings. Along with the information there is stored a version number. This relates to the format of the profile information stored for the program, and provides a mechanism for handling format changes in the information which the program stores. The details are given below. The information is held for all programs using the profile scheme in a file in the user's process called SS#PROFILE. Two external routines are involved: external routine string name ________ _______ read profile(______(11) key, ____ info, integername ___________ version, flag) external routine string name ________ _______ write profile(______(11) key, ____ info, integername ___________ version, flag) These require to be explicitly specified. read profile reads the information stored under the specified keyword in file SS#PROFILE if it exists, and copies it to the name ____-type parameter. write profile copies the contents of the name ____-type parameter to SS#PROFILE, creating the latter if necessary. read profile parameters _______________________ The meanings of the parameters to read profile are as follows: key The keyword relating to the particular profile information; chosen by the program writer. Every call of read profile must specify this (non-null) string. info A scalar variable (not ___ an array) of any type; usually a record or a string. read profile copies the information from SS#PROFILE to info. If the number of bytes held for the specified keyword in SS#PROFILE is greater than the size of info, then only as many bytes as info can hold are passed; truncation of the file information is from the right. If the number of bytes held in SS#PROFILE is less than the size of info (this includes the case where no information is held for the specified keyword) then the rightmost bytes of info are cleared to 0. See also flag, described below. version read profile returns the version number appropriate to the information currently stored in SS#PROFILE. This is 0 if no information is stored for the given keyword (or if SS#PROFILE does not exist). flag Set by read profile as follows: 0 Success. 1 Info held in SS#PROFILE is larger than size of info parameter passed. Some rightmost bytes of file info not transferred. 2 Info held in SS#PROFILE is smaller than size of info parameter passed. Some rightmost bytes of info parameter set to zero. 3 SS#PROFILE does not exist. 4 Keyword not found in SS#PROFILE. 5 Failed to connect SS#PROFILE. The attempts to connect SS#PROFILE are as follows. If the program is running in background mode, the program will attempt to connect SS#PROFILE a total of five times, with a delay of 20 seconds of cpu time between each attempt, before returning this flag. If the program is running in foreground mode, up to 3 attempts will be made, with a delay of 1 second of cpu time between each. 6 File SS#PROFILE corrupt. 7 Keyword is null. If flag=2 on return then the info parameter has been partially padded with zeros, as described above. If flag>2 on return then the info parameter has been cleared to zeros and version has been set to 0. Note that only flag values of 5 or more indicate a definite fault. write profile parameters ________________________ The meanings of the parameters to write profile are as follows: key The keyword relating to the particular profile information; chosen by the program writer. Every call of write profile must specify this (non-null) string. info A scalar variable (not ___ an array) of any type; usually a record or a string. write profile copies the contents of info into SS#PROFILE, creating the file if necessary. See also flag, described below. version write profile sets the version number attached to the information which it is writing into SS#PROFILE to the specified value of version. [Note that version is an integer name _______ ____ parameter although its value is never changed by write profile. This is so that the formal parameter lists for read profile and write profile can be identical.] flag Set by write profile as follows: 0 Success. 1 SS#PROFILE was created. 2 Failed to create SS#PROFILE. 3 Failed to connect SS#PROFILE. First an attempt to connect it in write mode is made; if this fails another attempt is made after a delay of 1 cpu second. If this fails an attempt is made to connect it in read shared mode, and a flag of 3 is returned if this fails. If it succeeds, a copy of SS#PROFILE is made, and changed, then a NEWGEN is attempted; if this fails, a flag of 4 (see below) is returned. 4 Failed to create a copy of SS#PROFILE, or failed to NEWGEN it. A copy is made of SS#PROFILE if it can only be connected in read shared mode (see above) or needs to have its size altered. This usually entails increasing the size, but wasted space can be recovered during the operation and this may actually enable the file to be reduced in size. 5 SS#PROFILE already holds information for the maximum number of keywords permitted (ca. 500). Should not occur. 6 The info parameter is larger than 4060 bytes. This is the largest amount which may be stored for any one keyword. 7 Keyword is null. No information has been written to SS#PROFILE if flag>1 on return. Using the profile scheme ________________________ Without being prescriptive, I would envisage the scheme being used by a program as follows. On entry the program would first establish, by calling read profile, what information relevant to its operation was held. It would then respond accordingly, normally by setting up initial values for relevant variables. In addition, some means would be provided for the user to change the information held in the profile file; this could either be done from within the program itself or as a separate program. One straighforward way of setting profile information from within the program itself is to follow the INITPARMS approach in Subsystem command OPTION: i.e. to provide a means for the user to specify that his defaults are to be the current _______ settings of the relevant variables. Thus, in the case of ECCE, the user could set %L (case sensitive text location), %F (full monitoring) and some appropriate values for the macros %W, %X, %Y, %Z. Then if he gave the command %P say (P for profile), ECCE would call write profile to save %L, %F, and the current macro definitions. When the user called ECCE thereafter, this stored information would be read on entry and the program variables set accordingly. The version number is provided at the suggestion of Sandy Shaw, who has also suggested an elegant use of it, as described below. Suppose that a user used a program ZZZ three years ago, when version 2 of ZZZ's profile information was in use. Now, three years later, he starts using ZZZ again. His SS#PROFILE file contains information stored in the version 2 format, but now version 4 (say) of ZZZ's profile information is in use, which contains different information from that of version 2 and in a different format. The suggested approach is that when ZZZ makes its initial call on read profile it first checks that the flag returned is satisfactory, then uses the version number returned as a switch value and jumps to a piece of code: vsn(0): .... : vsn(1): .... : vsn(2): .... : vsn(3): .... : vsn(4): .... : The code following switch label vsn(1):, for example, transforms profile information held in the version 1 format into the version 2 format. It is assumed that a change in profile format will usually entail appending to the previous format, e.g. appending subfields to a record, although existing subfields could be ignored or reused. The conversion code is added to the program when version 2 of the profile format is introduced. It can also include an output message to the effect that a new version of the program was put into service on such and such a date, contains the following goodies ..., etc. In the case of our user of program ZZZ, after the program has read the user's profile data a jump would be made to label vsn(2): and the code following vsn(2): and vsn(3): would be executed. By this time the information returned by read profile would have been transformed into the version 4 format (the latest version). Thereafter, the program would call write profile to write out the information in the latest (version 4) format if what read profile returned earlier was not in the latest format. Then the run of ZZZ could proceed as per normal. The next time the user calls ZZZ, it will read a profile version number of 4, jump to vsn(4): and proceed directly. Thus the code following each switch label is only executed once for each user. This approach also provides a way of introducing the profile scheme into existing programs. When no information pertaining to a particular program is held in SS#PROFILE (or perhaps SS#PROFILE does not even exist), a version number of 0 is returned by read profile. A jump to vsn(0): thus follows and the code there can set up the profile information, as described above. The version number of the new profile information will be 1. After the vsn(1): code there will be a call of write profile, which will automatically create SS#PROFILE if it does not already exist. The code might have the following form for a program XXX: : record format integer string ______ ______ prof f(_______ a, b, ______(40) c) record ______ (prof f) prof constant integer ________ _______ prof vsn = 1; ! Current version no of profile format. integer _______ flag switch ______ vsn(0:prof vsn) : : read profile("XXXPROF" {keyword unique to this program}, prof {returns information stored for "XXXPROF"}, pvsn {returns version no of stored profile info}, flag {return values described above} ) if start __ flag>4 _____ printstring("Unable to access file SS#PROFILE.") newline return ______ finish ______ -> vsn(pvsn) vsn(0): ! pvsn was 0 on return - no profile info currently stored. prof_a = 4; prof_b = 7; prof_c = "Doughnuts" ! Elements of profile record set to defaults in use prior to ! introduction of profile scheme. printstring("XXX now uses a profile scheme - see documentation") newline ! This code is executed once for each user, ! so each gets message once only. vsn(1): ! Code to transform profile info to a version 2 format ! would go in here. ! Now write profile info to SS#PROFILE in latest format (if ! necessary). if start __ pvsn#prof vsn _____ write profile("XXXPROF", prof, prof vsn, flag) if start __ flag>1 _____ printstring("Failed to write to file SS#PROFILE, FLAG =") write(flag,2); newline finish ______ finish ______