The avanti database server Version 1.2 970422 The avanti database server ... ! provides direct access to all allegro databases, taking v14c (i.e. the current version) as standard, but all older databases are also usable ! runs in the same way on PC networks and UNIX systems ! is designed for systems administrators who have little knowledge of allegro, but who wish (or are obliged) to enhance access to existing allegro databases ! enables those with no knowledge of allegro to build "client" functions into all software environments with which they are familiar, from batchfiles and shellscripts to Perl (HTML) and Java programs, as the avanti server ! is programmable in a "command" language that is much easier to learn than the allegro export language (for examples, see end) ! only requires a knowledge of allegro parametrization for complicated tasks; simple exports are possible without parameter files ! can nevertheless use the full range of export parameters, i.e. existing parameters can be built into the export procedure ! offers all the search possibilities of the program VP for building result sets, including sorting by selectable criteria (Pica-like "find" commands, see allegro news 40, with the operators AND, OR, NOT and symbolic index names), plus qualifiers like date of publication (V15 enhancement) ! also provides for write-access, including an update function whereby new records can be incorporated into an allegro database more simply than with the UPDATE program ! can also merge and export ASCII files and the familiar "basic" allegro files ! supersedes an earlier, much more complicated method of WWW access to "allegro" databases ! is a preliminary stage within the Z39.50 project, which is now underway with the approval of the DFG (Deutsche Forschungsgemeinschaft) ! works as fast as one expects with allegro programs In short: avanti enables all allegro databases to be organised into a client/server system, with tailor-made, easily programmable client functions. To prevent any misunderstanding: the programs in use up to now will be neither superseded nor invalidated by avanti. There is no "either/or": all can run SIMULTANEOUSLY. Client/server systems are by nature always indirect, and are therefore less efficient than systems that provide direct access. There are important functions, such as browsing up and down in indexes, which are difficult if not impossible to implement in client/server systems. (Have you ever wondered why so many systems are incapable of offering this?) However, as client/server technology has undisputed advantages (we have touched on a few of them above), we aim to implement these without abandoning what is tried and tested; to enable allegro databases to run ALSO but not ONLY as client/server systems. What works can continue working; there is no obligation to change existing arrangements, nor will performance and flexibility be compromised. How it works You give the server a job file, written in the new "job control language" called avanti. The server answers with a "download file" and an "error file" which you can either view or process with your own software. (The server does not itself produce a screen display or engage in any dialogue with the maker of the job: these are typical tasks for a client program). If the job is called JOB1, for example, the answer comes back as JOB1.DNL (download file) with the supplementary file JOB1.ERR (error file). The name of the download file can be changed by the user (command xport...). Recommendation: Under UNIX only use lower case for file names. We often use upper case in the following pages, but only to make names stand out from the text better. Components Only three components are needed: 1. the server program AVANTI.EXE (Windows) or avanti (UNIX) 2. the utility AV.EXE (DOS) or av (UNIX) 3. the "central job file" (ZAD) avanti.jb0 They are installed and operated as follows: (we append a step-by-step description of a specimen installation for testing under Windows) 1. The server program AVANTI.EXE (Windows) or avanti (UNIX) is started like PRESTO or VP and reads in the "central job file", avanti.jb0, which must be in the same directory as the one in which the server was started (see 3). E.g.: avanti -a3 -df:\allegro\katalog -bcat -ka -lger [Windows] avanti -a3 -d/usr/allegro/katalog -bcat -ka -lger [UNIX] As it runs, messages will appear in the server window. You can start several servers in several directories for either the same or different databases. The normal allegro programs can operate unaffected while the avanti server is active. The server will run (and await jobs) until you stop it, which is done with the command av -s serverpath (input in a DOS or command window) or if necessary, also with Alt+F4 (Windows) or Ctrl+c in the server window (UNIX). Recommendation: put the programs avanti and av in a universally accessible directory, e.g. /usr/avanti (under UNIX) or F:\AVANTI (Novell), together with the files uif0ger and uifsger. With uifsger it is possible to determine which (error) messages go into the .dnl or .err files (for explanation see below). Limit: There is a limit of 1.000.000 command lines for each job. (This sounds enormous, but all runs through a loop are counted!) If this limit is reached the program passes on to the next job. With option -Vc5000 for example, you can set the limit to 5.000 (command lines). 2. The utility AV.EXE (DOS) or av (UNIX) passes a job to the server. Actually the file containing the text of the job (i.e. the˙avanti program) is simply appended to the ZAD. See below for the precise form of the program call. Jobs can even be passed on if the server is not running! Then you get a message from av. As soon as the server is started, it deals with the accumulated jobs in the order of arrival. Recommendation: Make a shellscript or batchfile aj in order to start the program conveniently. The minimum: UNIX: aj Novell: AJ.BAT rm $HOME/$1.dnl del %HOME%\%1.dnl av $HOME/$1 /usr/avanti av %HOME%\%1 f:\avanti 3. The central job file (ZAD, the German acronym for zentrale Auftragsdatei) avanti.jb0 All users must have write permission to this file. (Under UNIX you can do this with access rights). When first called, this file begins with the following line: (The first three positions contain signals for the server and for av) 000xxxx000000016&jobname 0 : free for new jobs, 1: locked (set by av) 0 : server not running, 1: server running (set by server) 0 : normal, 1: hold the server, 2: stop the server (set by av) (in this way the server can be controlled from outside, see below) xxxx : positions not yet in use 000000016 : offset position, where the server begins when next started. The value is 16 when the server is first started, and is changed automatically. The jobs follow immediately, after the ampersand &. jobname is the full pathname of the first job, and is followed by the text of the job. Recommendation: To enable multiple access, send the first ZAD before the server is started. (A very simple command will do, such as help) Then you make the file generally accessible: UNIX: Novell: chmod 666 avanti.jb0 flag avanti.jb0 s For experts: The current method of handing jobs over was chosen because it is the only one that functions on all platforms in the same way. However, it might be more efficient to use a communication through a "pipe" in UNIX or by "WINSOCKET" under Windows. Because we couldn't do everything at once, we first chose a simple solution. Later on (April '97), a solution based on "pipe" for UNIX and another for Windows'95 and NT came along, but for the time being, our Web catalogues have been implemented with the method described above, and run perfectly satisfactorily on a Sun. The new methods are practically available now. What are "jobs"? A "job" must be formulated as an ASCII file in the avanti language, and then passed to the server with av. The program is called as follows: av jobname serverpath the jobname must contain the complete path name, so that the server knows where to direct the downloads. Then av appends the file to the central job file avanti.jb0, which lies in serverpath. & jobname is automatically placed at the beginning of the file, so that the server knows that it has received a new job. A UNIX example: If /usr/mozart/auftrag1.job is jobname, the server produces the error file /usr/mozart/auftrag1.err and the download file /usr/mozart/auftrag1.dnl the jobname can be anything, and need not end with .job. You know when a job is ready because: when the server receives a job, it first opens the file jobname.dn0. Only when the job is finished (or when the download file is replaced using the command x f filename), is jobname.dn0 closed and renamed jobname.dnl. So as soon as you see the file jobname.dnl you can be sure that the file is ready (unless you have changed the name of the download file with the command xport˙file filename!). Recommendation: set up two little batchfiles (or shellscripts) for each directory where the server is to run: Windows: UNIX: ASTART.BAT astart avanti -ka -ddatapath -bdatabase -lger -a3 -Pprogramdirectory ASTOP.BAT astop av -s .\ av -s ./ So you only need to give the command "astart" or "astop" on the current directory in order to start or stop the server. Under Windows, when you start the program you first get a window in which the server gives you messages as it runs. You can now start jobs in a DOS window with aj jobname (see 2 above) and see what the server makes of them. This process is described step by step in the appendix. Diagram (for UNIX & DOS; filenames all lower case under UNIX!) database server -----------------------> /allegro/katalog | user 1 | user 2 | | | /usr/meyer /usr/avanti /usr/bloggs | | | | (waits) | | aj XYJOB avanti.jb0 | XYJOB ----------------> | aj JOB25.JOB | [temporary] | <-------------- JOB25.JOB XYJOB.DN0 <-------------- |(processing of XYJOB.DNL <-------------- | XYJOB) XYJOB.ERR <-------------- | (processing of | -----------------> JOB25.DN0 [temporary] JOB25.JOB) | -----------------> JOB25.DNL | -----------------> JOB25.ERR (waits) It is always possible for a systems manager to set up an extra server for himself on another directory and run it in parallel, this way making provision for higher priority. Stop, pause, continue: The program av has three additional options: pause, stop and continue. These are reserved for the use of the system administrator (but are not yet password protected!): av -h serverpath the server in serverpath is paused av -s serverpath ... is entirely stopped (i.e. stops running after completing the current job) av -r serverpath ... is re-started (after a previous -h) Recommendation: Delete the ZAD from time to time, and do this when the server is waiting for jobs. Stop the server, delete the ZAD, make a new one, make it accessible, and re-start the server. The utility av will have another function to automate this. Overview under UNIX under Novell --------------------------------------------------------------------------- /etc F:\ UTIL aj 755 pass job to server AJ.BAT S /usr/avanti F:\ ALLEGRO avanti 755 server AVANTI.EXE av 755 utility AV.EXE S uif0ger 600 user interface UIF0GER uifsger 600 UIFSGER /serverpath drive:serverpath avanti.jb0 666 job file AVANTI.JB0 S astart 700 start serve ASTART.BAT astop 700 stop ASTOP.BAT Only put the startup file aj on /etc, so that it is automatically accessible to all users. Obviously this directory may have a different name. The system administrator will easily know what file permissions or flags to give. The avanti language for job files "Allegrologists" beware: this language has a totally different function from that of the parameter files, and is constructed quite differently for other reasons too. When designing it, we made a special point of making it much easier to learn, especially by non-"allegrologists". ("Why couldn't the export language be as easy", some of you might groan! Because this has to be extremely compact - and therefore cryptic - as the parameters must not only fit into the computer's memory, but also work extremely fast). There follows the list of commands currently available in avanti (- their scope will be extended in due course). ERROR means that an error variable will be set if something goes wrong with the command. So with if error command or if ok command in the following line you can react and jump elsewhere according to whether there is an error or everything is all right. command can not only be a jump, but also a longer sequence of commands, using ; as a separator. Comment lines have no effect on the error variable. A few examples are given at the end. General rules for jobs ! Avoid empty lines: otherwise av will not function, at least under NT. ! Every command can be abbreviated down to the first letter, except erase and update, which for reasons of security you must write out in full. I.e., instead of write you can put wri or wr or simply w. Important: at least one space should follow each command word or letter! Thus you should put w n , not wn . ! The commands must be written as given below (so in lower case, as a rule); the variables (in italics) can contain whatever characters you like; filenames, of course must obey the rules. ! Lines may begin with one or more spaces, unlike in the export and import languages (!). I.e. you can use indentation as you like for the sake of clarity. ! Multiple spaces are permitted - they have the same effect as a single space. (In write commands they are preserved when enclosed in inverted commas "..." ). ! Tabs have the same effect as spaces. ! Comments begin with // (two forward slashes) and can be placed anywhere. The rest of the line is then ignored. ! Several commands can appear in one line, and must be separated with ; (semicolon). This is especially important with the if command: if the condition is met, all the following commands on that line will be executed; if not, the program jumps to the next line. Error messages from the program will be written to the file jobname.err. Summary of commands In the following pages the commands are arranged in logical groups. There are 7 groups: group type page 1 Control commands 8 2 Search, write, sort, list 8 3 Export (i.e. write records and text to download files) 12 4 Manipulation of data in memory 14 5 Save functions (i.e. write to the database) 15 6 Checks and jumps 17 7 Switches and environment variables 19 Here is a short overview, arranged alphabetically with the group number on the left: 4 copy copy the current record (i.e. make a new one out of it) 3 download export the current record 5 erase delete the current record (and also its index entries) 2 find make a result set (like the "find" command in Pica or other systems) 2 get find a record (which thus becomes the "current record") 2 help give information on the database (names of indexes, &c.) 6 if check, and consequent action 6 jump jump to a label 2 list give a short list of the result set 4 new treat the current record is if it were a new (empty) one 2 order sort the result set (in increasing or decreasing order) 5 put write the current record back into the database (changing index entries accordingly) 2 qrix give an extract from the index 4 read copy the following record (from an ASCII or .ALG file) into the current record 7 set set various internal values and variables 5 upload read in an ASCII file and save it (as new records) 5 update read in an ASCII file, identify its primary key, and replace as necessary (including changes to index) 3 w/W write text and data to a download or error file 3 xport load a parameter file and name an export file 4 # operations with fields and user-variables 1 : label (jumpmark) 1 @ operator identification With most of these, there are several options and sub-commands. In the following pages the shortest form of the command is always indicated in bold. E.g.: instead of list numbered you can put list num, li nu or any other abbreviation, even down to l n (but not ln ). 1. Control commands & jobname Beginning of new job. (This line is produced automatically by av!). jobname is the name of the job file, including path. Server creates names of download and error files out of this. When such a line appears inside a job, it is treated as the beginning of a new job! @ Identity of the giver of the job. Essential for write access! The exact form of this command is not yet fixed. For the time being, you use @3 to switch on write permission. The server must be started with option -a3 in order to carry out write commands. :label Jumpmark; label = any alphanumeric character string e.g. :start Use with the command jump, thus in the present example: jump start 2. Read access 2.1 Get help help Get help on the database (e.g. the names of indexes), so that you can find out what questions you can ask, such as PER for "person"; any qualifier names (R lines in the .API) will also be given. help keys Limitation: only the names of the indexes. ERROR if none have been defined (i.e. there are no I lines in the .API, in which case commands like find per will not function, only find |1 and the like!). help fields List of fields (from the configuration file). 2.2 Search command: make a result set find find command As in VP (see news 40). A result set will be produced. Possibly, it will consist of only a single record - or none! ERROR if nothing found, if the result set is too big, or there is a syntactical error in the command. Maximum size of the result set is currently 16.000. The command find is actually the most important of all, as you use it to select the data with which to work. Complex bracketing is possible. Example: ('?' is the symbol for truncation) f per beethoven? and (tit klavier? or piano?) if error jump nix Records with "beethoven?" as a person and "klavier?" or "piano?" as title keyword will be searched for. If there are either none or too many, a jump will be made to :nix. Special case:: find |iabcd find abcd in index i (where i=1...9, or : for 10) This special case will always work, but you must know what indexes the database has: the command help will tell you this. (In other words, you would first give a job containing only help. Then you examine the list and find out in which indexes the personal names and title keywords, for example, can be found). The far more convenient commands such as f per goethe? can only be used if symbolic names such as "per" have been defined in a given database. You can find out both this and also whether qualifiers are possible (R lines in the .API) with help. The allegro system administrator can assign symbolic names to indexes at any time by simply putting commands of the following type into the index parameter (e.g. CAT.API): I XXX r "freetext name of the index" XXX symbolic index name r index number (1 . 9, :, ;) Eg: I PER 1 "Names index" I AUT 1 "Names index" I TIT 3 "Title keywords" I SER 5 "Periodical and serial titles" So you can see that an index can have a number of different but equally valid names. Different sections of the same index can have their own nam: I DIS 1D. "Dissertations by place name" In CAT.API there is a special section D in index one with a space after the D (hence the full-stop after the D) where theses are filed by place,year. In this way one can find, for example: find dis berlin,1992? // find all Berlin theses for the year 1992 If any qualifiers have been defined (see news 46) they can be used in search commands as follows (in this example there is an R line in which ERJ has been defined): find normal search command and erj >1990 But if you give the command find erj >1990 before any other find command, this has the effect of setting the restriction erj >1990 for all subsequent find commands in the same job. In this way you can prevent a search from failing because there are too many hits, for example. find *new This special command enables you to delete an existing result set and any restrictions that may be in force. A subsequent find command will therefore produce a new result set (without restrictions unless you have defined any). find #numbers Adds given internal recordnumbers to the result set. This function is meaningful if you have already obtained a list of internal record numbers (using list i or qrix), especially in a WWW application. These numbers, separated simply by commas, can be processed immediately as a result set. Limit: 20 numbers, but you can have several such commands, one after the other - they will all be put into a single result set. 2.3 Retrieve records get option Load a record into memory get edit option and immediately make it available for editing (lock it) (- it is unlocked when it is either saved or the next record loaded). option must be one of the following: get first / last Load the first/last record in the result set. g e f / g e l Same, but immediately lock the record. get next / prev Load the next/previous record in the result set. ERROR if the end/beginning is overwritten. g e n / g e p Same, but immediately lock the record. get k Load record k from the result set. ERROR if k<1 or k>N (N = size of the result set), i.e. get 1 has the same effect as get first. get inumber Special case (- has nothing to do with result sets): Read in the record with the internal record number number, default 1 This command is used if you already have a list of internal record numbers obtained by a previous action that are waiting to be processed. ERROR if number is too high or the record has been deleted. (-> list i, list r) 2.4 Make a short-title list The following list commands (to l i) and the sort command order only work if there is an .STL file: list Output the result set as a short-title list in the download file. Sort as required with the command order (see below). list coded Convert ASCII --> ANSI (with table o.apt). Do this if you want to use the list under Windows or UNIX if the database is encoded in ASCII. list numbered Number the list. list recnum Also output the internal record numbers (useful with WWW applications). The numbers will then appear at the beginning of the line, eg: 0001234:abc... l r n c Do all the above ( r, c, n can be used in any combination). Special case (interesting for WWW applications): list internal Instead of text, output only the internal record numbers, separated with a comma, and with ",0" at the end. 2.5 Sort the result set order x position Sort the short-title list from position (a number <72). x = a(scending) or d(escending). ERROR if the result set is too big (limit approx. 12,000). Parameterisers please note: by skilful design of the short-title list, you can create useful sorting possibilities If you require complicated sorting that cannot be done with the short-title list: export with one of the S-*.APR files, then (i.e. when the avanti job is ready) sort with ASORT, then run SRCH with a P-*.APR, as usual (eg. in PR-LIST.BAT). Obviously this takes longer. 2.6 Get index extracts qrix i searchterm List N index entries, starting with searchterm in index i (i = 1...9 and : for 10). '?' after the searchterm will truncate the index (so that the index lines are cut off at this point - corresponds to the fixed truncation in PRESTO). The number N is determined with the command q n (see below). qrix index searchterm index is any symbolic index name (see above). Eg: q per shakespeare, q tit hamlet qrix n N Determine the number N of lines to be output. Eg: q n 20 (default: 10) Valid for all subsequent q commands, until you determine a new N value. qrix m N Determine the maximum number of hits N per line to be displayed (default: 1000). In the case of index entries that point to more than N records, >N appears in front of the entry. A smaller N value works faster. Special case: q m 0 produces index extracts without record counts. qrix format x Specify the output format. At present there are only two: 0 and 1. Format 0 is the standard, fixed format. Example of format 0: 3 index entry Example of format 1: 3index entryrnr1:rnr2:rnr3 is ASCII 09, rnrn are the internal record numbers from which the index entry is produced. Format 1 is particularly suitable for presenting the index itself, in WWW applications, for example. 3. Export (Download) 3.1 Procedure xport file filename Use filename for output. Default: jobname.dnl While an export is taking place, you can also direct the output to other files. The program will first change the last character of the filename to '0', and replace it with the correct one when it is finished, so you can see when the file is ready! Thus it is also possible to react when a job is only partially finished. So you can switch to other parameters independently: xport param parname Load export parameter parname.apr Default: parname=e-w Example: xport par d-w Valid for subsequent download and write commands until the next xport or & command or the end of the job. xport table tabname Load the table tabname.apt. Corresponds to the t command in the export language. If you have previously given the command set d2, these commands will affect download file 2, not 1. 3.2 Output records download Export the current record (for parameter, see xport parname). ERROR if no record is loaded. Default parameter: e-w.apr, otherwise load another with xport p... (see above). download set Export the current result set. ERROR if there isn't one. download family Output all records that may be linked to the current record (by using the record link), including the current record itself (see example 5). Order: determined by the record link. 3.3 Direct output commands write cstring Write cstring to the current download file. The character " will be removed from the beginning and end. You need the inverted commas in case the text begins with one of the other command characters, or a space. A cstring is a string of decimal ASCII codes and text in inverted commas as defined in the Systemhandbuch (168). In addition, the following characters can occur in cstring (see below). Special case: n for "new line", output as 10 under UNIX, 13 10 under DOS. You can use ' instead of " so long as both opening and closing commas are identical. (This is important if either ' or " occur in cstring!) write i j k ... Special case: sequence of decimal ASCII codes i j k Eg: w 27 69 for Esc E write #nnn Write the text of field #nnn to the download file. #nnn can also be a user-variable (of type #uxy) ERROR if the field is not present. write internal Internal record number of the current record. write lastnum Number of hits (size of the current result set). write newline New line (UNIX: code 10, DOS: 13 10). write primkey Primary key of the current record. write relative Running number (relative position) of the current record within the result set. Only if an .STL exists: write short Short-title of the record (.STL entry). 3.4 Output in the error file Commands as above, but with upper case W: Write cstring write cstring to error file jobname.err, eg: Write #nnn Write the text of field #nnn to error file. ... All write commands can be combined at will on a single line, eg: wri "RecNr.: " int new "Place: " #74 ": " #75 ", " #76 ". - " #77 n You can have several spaces between each element, unlike in the export language, without affecting the result set. But here there is at present no possibility of either manipulating the fields or automatically effecting a line break. However, the output file can obviously be worked on by other software - Perl scripts, for example. 4. Manipulation of records in memory 4.1 Load a new record new Clear the record space in internal memory. Make sure you first give the put command to save the record's content if you want to keep it, because after the new the record space is blank and ready for new data. New field lines may now follow (4.2) to fill the record with data! Then use put to save it as a new record (the same with upload). copy Process the current record as a copy (ie, if it is saved, create a new record out of it). Then write as many # commands as you like, ending with put, to save the record and get it out of the way. 4.2 Manipulate fields in the current record #nnn Text Insert field #nnn Text into the current record; replace if already present. No linebreaks within Text! If there is no Text , #nnn will be deleted! If you enter #nnn~Text (~ instead of a blank) field #nnn will not be replaced, but the next available repeated field, #nnna or such like, will be created. This only happens in memory! The edited record is only saved when the put command is given. The edited record can be exported with download, however, even if it hasn't yet been saved. But if you want the field to consist not only of straightforward text, but of portions of text, variables and other fields all joined together, you can proceed as follows: #nnn=cstring Behind the '=' you can use the same elements that can be processed with the write command, so especially other fields and user-variables. NB: the '=' must occupy the position of the first character (see .CFG command k), eg: #40 ="Bloggs, Fred" #402="Schmidt, Kurt" is equivalent to #40 Bloggs, Fred #402Schmidt, Kurt This also applies to the #u variables (user-variables): #ubc="TEXT" or #ubcTEXT The field #nnn may therefore itself be a #u variable. This is then copied into the background memory and can be used later. You therefore have all variables of the type #uxy to do as you like with. The same variables can be used within export parameters in the usual way. For example, if you want to put filed #90 into #usg, you only need to say #usg=#90. read filename Read the first record from an ASCII file or .ALG file filename into the current record (see examples 7+8). For further details see group 5, after update. read Read in the next record (- filename is only needed for the first). ERROR if there are no more. 5. Write functions 5.1 Write and delete individual records The following functions are only possible if you have write permission. All record saves and deletions are recorded in the .LOG file, as with "normal" allegro programs. put Write the current record (object 1) back into the database. ERROR if it doesn't work. Equivalent: put 1 If the record was loaded with get edit ... , and therefore locked, it is immediately unlocked. put 2 Write object 2 (see "set obj ...") back into the database. If you want to edit and save every record in a result set, you have to construct a loop. See example 4. erase Delete the current record. [can't be abbreviated!] ERROR if not possible (because it is either locked or has linked records, or because there is no write permission). erase and update cannot be abbreviated! Example 6 shows how to delete a result set. 5.2 Upload/update functions update filename Load filename and merge into database. upload filename File must be in ASCII (see appendix A) or .ALG format. ERROR if not found or if not readable. update must be written out in full, also the update mode must be set in advance with set uxy. upload works like update , with a previous set u01. Special cases: ! Subfield update With mode set u41 you can specify subfields: If the update record contains a field such as #nnn ??axxxxx?bxxxx... subfields ?a and ?b of the old record are replaced, but the rest of the field is unaffected. ! Save as a new record If you want to save a record as a new record, even if you have given set u11 and the primary key is found, you can write #u1 #####fileno as the first field, before #00. The record will then be saved to fileno (= 1-255). ! Delete a record If the record begins with #u1 @@@@@ it will be deleted. Obviously this will only happen if the primary key has been found and is unambiguous, and the record is not locked. #u1 only needs to be followed by those field(s) that are necessary to define the primary key. If this is in #00 for example, you only need to have #u1 @@@@@ #00 IdNumber in the update file in order to delete the record. ! Hierarchical sub-records Unlike with UPDATE, these will be identified by means of their #01 field, and merged according to the replacement mode. If a #01 field does not exist in the old record, the sub-record is appended to it. upload without filename: load and save the immediately following records (ie. upload and update records can be embedded directly into the job file!). Then you must put update end at the end of the file. The beginning of a new record is identified by field #00, (or to be precise, the first field defined in the .CFG). In the upload file, lines can only begin with '#' or a space, otherwise the upload process will end! You must set the update mode with set uxy in advance, or nothing will happen (see 7). end End the upload/update file - the next line is the continuation of the job. 5.3 Reading in ASCII or basic allegro files read filename Open filename and read in the first record. filename can be an ASCII file (appendix A) or an .ALG file. ERROR if not successful (eg, file not found). read Read in the next record. ERROR if there aren't any. The record will be read into object 2, if set obj 2 has been given in advance, otherwise into object 1 (see --> set object ... ). You can then work with read and put instead of upload or update, but this must be arranged with a loop. This has the advantage of enabling you to work on a record before saving it (see example 7: reading and saving individual records). You can also export basic allegro files with read and download (example 8), and thus use avanti instead of the conventional SRCH program. If write commands fail, because of a locked record, for example, messages will be written to the error file. 6. Checks and jumps We use the symbols: label alphanumeric character string without spaces command any sequence of commands (separated by ;) jump label Jump to the line beginning :label. if error command If the previous command fails, carry out command (which could even be a whole sequence of commands!). if noerror command if ok command The other way round: if it doesn't fail carry out command; ok is the same as noerror. if greater N command If the result set is greater than N, carry out command. Necessary when you want to prevent too big a result set. if less N command If the result set is smaller than N, carry out command. if fam command If the current record belongs to a linked set of records (irrespective of whether it is a main or subordinate record), carry out command. if main command If the current record is the main record of a linked set, carry out command. if sub command If the current record is a subordinate record in a linked set, carry out command. (Subordinate records are detected by the "+" in the record link). if hiera command If the current record is an allegro hierarchical record, carry out command. if #nnn command If field #nnn occurs in the current record, carry out command. if #uxy command The same, but applies to user-variable #uxy. I.e. carry out command if #uxy is present. if #mmm = #kkk command Compare content of #mmm with #kkk , react if the same. if #mmm ! #kkk command Compare content of #mmm with #kkk , react if not the same. if #mmm > #kkk command If content of #mmm is bigger if #mmm < #kkk command or smaller than #kkk, carry out command. #mmm and/or #kkk can be user-variables. If #mmm or #kkk are not present, the check counts as having failed. The operators < = > ! must be surrounded by blanks. You can have a number instead of #kkk, in which case a numerical comparison will be carried out, otherwise a character string will be compared. Subfields can't be compared directly: you must first create user-variables from them: #uv1 = #123$a // copy $a of #123 to #uv1 #uv2 = #234$b // copy $b of #234 to #uv2 if #uv1 = #uv2 ... (As with the write command, you must use '$' here instead of '?'. In this way you can program such things for UNIX, too, with no problem.) 7. Switches and environment variables With the commands switch and set (both have the same effect) you can make a series of dispositions that will affect certain subsequent actions. switch fam Put all records that are linked with the current record into the result set (Pica term: "family"). Subsequent get and list commands will then work on this result set. If it's only a matter of outputting a linked set, you can then simply say "download fam" (see "download"). ERROR if there are no linked records. You can switch back to the actual result set at any time: switch resultset returns you to the same position as you were in before switch fam . The previous current record will be re-loaded internally. The same applies to further switch fam commands: the previous linked set will be re-loaded. All this enables you to work through a result set and deal with all linked records at the same time. See example 5. switch amodus modus=0,1,2,3,4,5 Resolution of version 14 authority record numbers, i.e. the replacement of numbers with text, according to the modalities explained in 10.2.6.8 (Systemhandbuch 213). I.e., switch a1 is the norm. The command must be expressly given for each record that is loaded, but it is ONLY needed if you want to output a single field containing authority record numbers with write #nnn. But you can't re-save the record with put - it's prevented. So if you want to make changes to the record, give the put command BEFORE switch a1. switch coding This switches the code conversion of index entries, short-titles, and output from write˙#... commands on and off. This is important if the database is encoded in ASCII but the data in the download file (.dnl) is needed in ANSI, and also if special characters appear in index entries (see the command qrix). For short-title lists you can also use the option coded (under list). set nfileno Specify a file number for new records (fileno=1...255). Corresponds to option -n in PRESTO. set uxy Specify update mode, before giving the update command (corresponds to -u in the UPDATE program). (x = 0,1,2,3,4, y = 0,1) You must set a mode, or the update command won't work! set object 1/2 Switch to record 1 or 2. There are two internal work stores for records, named "Rec1" and "Rec2". Normally, Rec1 is engaged, i.e., all actions will be performed on Rec1. In a job, you can switch to Rec2 at any time, retrieve a record with get or read, do what you like with it and then save it with put. set download 1/2 Switch to download1 or download2. Two download parameters and files can be specified, Normally, download 1 is active. When you set dow 2 for the first time, you must immediately execute xport p parname and x f filename so that the program knows what must happen during download. Subsequent down commands will then operate with this second set, until set d 1 is encountered. set list i Maximum number of lines for the list command (default is 10). set max i Maximum number of records for the download command. The simplest client: a batchfile Let's say that we're working on K:\USR\JOHNNY and want to pass a series of jobs to the avanti server, which is running on F:\AVANTI. We give the following command once: set PATH=K:\USR\JOHNNY and make ourselves a batchfile like this, called AJS.BAT: @echo off if exist %1.dnl del %1.dnl av %PATH%\%1 f:\avanti :loop if not exist %1.dnl goto loop v %1.dnl So if we then write a jobfile called JOB1, we only need to say: ajs job1 and to wait until JOB1.DNL appears. In this way the download file is deleted before the program call, and as soon as it pops up again, the loop is ended and the file appears. This batchfile can also be used by other users, working on different directories. Recommendation: Make at least one generally accessible batchfile aj, containing: DOS: UNIX: if exist %1.dnl del %1.dnl rm $1.dnl av %HOME%\%1 f:\avanti av $HOME/$1 /usr/avanti Under DOS the user's home directory must lie in the environment variable HOME; under UNIX that happens automatically. We are assuming here that the server has been started on F:\AVANTI or /usr/avanti. Examples You put each set of commands (without commentary!) into a file jobname (any name you like) and give the command av userpath\jobname serverpath or (if you are using a batchfile prepared in advance, such as aj.bat or ajs.bat ): aj jobname 1. Make a result set, output a sorted short-title list: (assuming that the short-title list - in the .STL file - contains a date starting in position 58)) find tit berlin? or hamburg? //find titles containing "berlin" or "hamburg" order descending 58 //sort result set in descending order, //starting at position 58 list //output short-title list 2. Make a result set, output a formatted title list: xport p p-normal //use parameter P-NORMAL.APR for export find tit berlin? or hamburg? //find titles containing "berlin" or "hamburg" order a 1 //sort result set in ascending order, //starting at position 1 download set //output title list 3. Insert a new field into each record in a result set Eg, put #31 Wiener Klassik into all records containing "mozart, w?" as person and "Sinfonie" or "konzer/concert" as title keywords. (This shows how it is possible to work on a result set). xport p p-normal //use parameter P-NORMAL.APR for export find per mozart, w? and (tit sinfo? or konzert or concert) get e first //load and lock (the 'e' does this) first record if error jump end //go to :end if no records (result set empty or too //big) :start //beginning of loop #31 Wiener Klassik //field (with content) to insert put //save record (including unlocking) get e next //load and lock next record if noerror j start //if none, go to :start again, otherwise loop ends :end download set //whole result set (after changes!) ... //further commands, or end of job In its shortest form, this job could be written as follows (all commands are abbreviated to a single letter, and several commands are placed in one line) - the text is not so easy to read, but the effect is the same: x p p-normal f per mozart, w? and (tit sinfo? or konzert or concert) g e f; i e j ende :start #31 Wiener Klassik p; g e n; i o j start :end d s ... //further commands, or end of job 4. Export certain fields from a result set Assuming that an art database contains descriptions of pictures, and that in a few records there is a field #777 containing the name (which could be an URL) of a graphics file; there is an index ART containing the names of artists, and we want to extract the names of graphics files relating to the artist Chagall. f art chagall? get first if error jump end :loop if #777 w #777 n //write out field #777 (if present), then a new line get next //get next record if ok j loop //if found, back to :loop :end This will produce file .dnl, which will contain the names of the graphics files 5. Output the result set together with all linked records A result set is to be exported with the parameter I-1.APR (ie as a "basic" allegro file for further processing). All linked records are also to be exported. (The links of all the subordinate records should indicate their relationship with the main records, eg. 1234 for the main record, 1234+001, 1234+002, &c for the subordinate records, which may themselves have subordinate records: 1234+001+01 &c.). xport p param i-1 //we want export as a "basic" file (hence I-1) find ... //make result set get first //get first record if error jump end //if none (eg. result set empty) :begin //start of outermost loop *********** switch fam //result set to include linked records (first //record too, which will also be exported) if error jump nofam //if none go to :nofam down set //export family switch resultset //switch back to result set *********** jump nextrec /jump to:nextrec :nofam //we get here if there was no family switch res down //then output record :nextrec get next //get next record from result set if ok jump begin //if found, back to :begin :end //all finished .... The four commands between *********** may be replaced with the line: download family or d f You only need to be able to switch between the family and the result set when you want to work on each individual record in a linked set. 6. Delete a result set @3 find ... //make result set get first //load first record if error jump end :loop erase //delete get next if ok jump loop :end 7. Load and save individual records from a file NEWDATA can be either an ASCII file (see appendix A) or a basic allegro file (.ALG structure, see Systemhandnuch 0.2.2) - avanti will automatically recognise what it is! The records are to be edited, then loaded and saved. For the sake of clarity, we give just the outline: @3 read NEWDATA //open source file, load first record :loop //process record with further commands, as necessary put //save record and get rid read //load next record if ok jump loop //if there is one, jump to :loop 8. Export a basic file You can't load ASCII files (see Appendix A) with the old SRCH. However, the avanti server can both read and export them (- together with the familiar .ALG type!). If the file is called RAWDATA, for example, you only need this job: (Nothing will be accessed in the database, unless you've loaded anything or there are V14 links in the data). xport p p-normal //use this parameter //or: //x p i-1 //make a file of the old type xport f LIST //target file is named LIST read RAWDATA //open source file, load first record :loop dow //export record read //load next record if ok jump loop //if found, go to :loop 9. Insert a field/subfield You want to insert a field or subfield into all records of whose primary keys you have a list, or to delete a field (cf. example 3). @3 //specify access permission set u41 //set update mode update //now comes the data that is to be merged: #00 IdNr1 //primary key of the first record #nnn text //insert field (if already present, it will be replaced) #kkk ??xtext //insert subfield ?x into field #kkk #jjj //delete field #jjj #00 IdNr2 //primary key of next record #nnn ... ... #00 IdNrN //primary key of Nth record #nnn ... end //end of update process The list of primary keys and fields can be drawn up however you like, eg. by export with manual editing. So you see that only minimal avanti programming is necessary to carry out such operations with a database. As soon as the field #00 (or the first field defined in the .CFG) or end appears, the current record is saved. Appendix A : Structure of ASCII files The commands update and read can not only read "basic" allegro files, but also ASCII files that you have created with whatever software you like, or a text editor. Such files must however be constructed according to the following rules, which are not too difficult. When we speak of the "current record", we mean the record that has just been loaded into memory. With a read command you can first get a record from the database or construct it inside the job with # commands, and the data loaded with read will then work on this record! ! Lines beginning with '#' will be treated as fields and merged with the current record, as if you had input them manually. ! A line beginning with spaces will be treated as part of the previous line. I.e., long lines can be broken as you like - but only at spaces! - so that they can be put back together perfectly. ! Empty lines will be ignored - they have no function. ! The fields need not be arranged in order - the program will take care of that by itself when they are loaded. ! If a field is already present in the current record, it will be replaced by the new one. But: ! If a field occurs twice in the file, only the second one will be retained. If '~' occurs as a repeat sign after a field number, the field will be added to the record, not substituted if it is already present (cf 4.2 above), according to the "repeat" code specified in the .CFG. You can use this as a way of inserting a repeated field if you don't know what the next permitted field should be. ! Fields in the current record, but not in the new file, remain unaltered. Rules in the .CFG will be observed: fields which have not been declared there or which have impermissible repeat signs will be ignored. Multiple spaces within a field will be got rid of, unless the .CFG contains ?P15 for the field in question. If the file contains just a field number without any text, this field will be deleted from the current record. If it is not there, nothing will happen. ! If one of the hierarchical fields #01 ... #06 is found (- there must be no empty lines in front of them), the program looks in the current record for a sub-record with the same content, and incorporates the following fields into this record, until a further hierarchical field is encountered. If such a sub-record is not found, the program treats it as a new sub-record, and appends it to the end. This means that in the ASCII file the sub-records do not need to be arranged in the same order as in the current record. However, you can't edit fields #01 ... #06, nor introduce new sub-records into the middle of the sequence or re-arrange the existing sequence. ! When a new #00 (or the first field defined in the .CFG) is found, or the end of the file is reached, this counts as the end of the record. If no text follows the #00, then this field as such is not retained - it just signals to the program that another record is beginning. Appendix B: Instructions for a test under Windows We will describe a model installation step by step so that those with only a simple Windows PC can examine the avanti server and make themselves familiar with it. Everything will work with Windows 3.11 on a 486 with 4 Mb of RAM. For Windows 95 and NT there is a client, which is considerably easier to use. The description is also intended to help you to understand exactly how the server works. We shall start to work on the DOS level! (Windows is started up later, see 3). Assuming that: ! the normal allegro programs are on C:\ALLEGRO, preferably version 14c, but older versions will also work. ! there is a database CAT on C:\ALLEGRO\KATALOG For testing, we recommend that you make a copy of a real database, and use this! 0. If the database does not yet have any symbolic index names, put these into the file CAT.API, eg: I PER 1 "Personal names" I AUT 1 "Authors" (AUT and PER are thus equivalent!) I DIS 1D. "Dissertations (place, year, name)" I TIT 3 "Title keywords" I TAF 4 "First words of title" I SER 5 "Serial titles" R ERJ r1 "Year of publication?Limitation of period" &c. You can have up to 32 symbolic names for indexes and sections of indexes, each consisting of 3 characters. 1. Unpack the contents of AVANTI.LZH to C:\ALLEGRO: avanti.exe the server av.exe utility for passing on jobs, &c. uifsger message text for the server avanti.txt description of the server e-w.pr parameter for downloading records aj.bat for passing jobs on simply (see 7) astop.bat to stop the server allegro.ico icon for Windows 2. Start SHARE: give the command "share" at the DOS level. (Not with Windows'95) This will then enable you to use the database in a DOS window while the server is running. You can't load share within the DOS window: it must be loaded BEFORE you start Windows. 3. Start Windows (or switch back to Windows'95) 4. Make a Program Item (File/New in Program Manager . ) Description: avantiServer Command Line: C:\ALLEGRO\avanti -ka -dc:\allegro\katalog -bcat -n1 -a3 Working Directory: c:\allegro We recommend the icon ALLEGRO.ICO. 5. Open a DOS window, change to C:\ALLEGRO. 6. Set up the first job: a file with the name job and content help will do. 7. Pass this job to the server (although it is not yet running!) with aj job thus creating the file avanti.jb0. 8. Go back to the Program Manager with Alt+TAB, and start the server from there. The server window will appear. The server will take the job and do it, and then wait. 9. Return to the DOS window with Alt+space and "change to ..." and then to C:\ALLEGRO. job.dnl will now exist, and contain help on the database. The server has done its first job! 10. Now you can really get going: make a job file, with any name. You can use any of the commands in the avanti language. Pass job1, for example, to the server with aj job1 You only need to wait until job1.dnl is ready. It will contain the result set, and job1.err will contain any error messages. Recommendation: always use the same name for small, one-off jobs - something like JOB - otherwise no end of files will be produced that will have to be deleted sooner or later. For convenient testing, use the // to inactivate commands and remove the // to reactivate them. While a job is running, you can also access the database at the same time as the server with CockPit or directly with presto -a3 -dkatalog -n1. This is particularly fascinating when an upload or update is taking place, as you can then watch the index entries appearing, one after the other. This will only work if you haven't forgotten to load SHARE (see 2), AND have then started PRESTO without -S! 11. Stop the server with astop in the DOS window. 12. Go to the server window. 13. Close the server window with Alt+F4. If you have any programming experience, you can now decide whether and how to use the server in other environments. The only important thing is to make do-able job files: it doesn't matter how you make them. The jobs must be passed to the server with av, as in the model AJ.BAT. The file jobname.dnl appears when the job has been processed. What you do with it is entirely up to you: perhaps you will make a new job out of it, and send it back to the server . Implementation in Braunschweig The avanti server was incorporated into the home page of Braunschweig University Library in December '96. It is used for the WWW-OPACs, which run on a SUN workstation. Previously, these used to run with a combination of the programs qrix and srch, but this method of implementing a WWW catalogue required really long-winded parameterisation. The new method is faster and more elegant. The method is summarily described in allegro news 44 (31.12.96). All the scripts (Perl and HTML) together with detailed description can be found on both the FTP and WWW servers of Braunschweig University (file acwww25.lzh).