Outils pour utilisateurs

Outils du site


issue107:tutoriel1

Ceci est une ancienne révision du document !


In the early days of computers, a company called Digital Equipment Corporation (DEC) created its 32-bit VAX computer using openVMS as its operating system. Because a VAX/VMS computer is so reliable, there are today - after more than 25 years - still a large number of them in use. But in the end, even these reliable computers will have to be replaced. As described in part 1, you could migrate from VAX/VMS to Linux because the way Linux works is largely compatible with VAX/VMS. If you use Pascal as your programming language, you will find that Lazarus/Free Pascal is a good replacement. But there are technical functions used in VMS with no apparent replacement in Linux. In this article, I will describe how I replace logicals. File-system philosophy? To understand logicals, I have to explain the philosophy behind the file-system of VMS. In Linux there is one “device” ('/') and all physical devices are mounted to become a virtual folder (the mounting points). VMS uses a totally opposite approach: Devices are separate items, and you are allowed to create a new (virtual or pseudo) device pointing to a folder.

Au début des ordinateurs, une société appelée Digital Equipment Corporation (DEC) créa son ordinateur 32-bit VAX avec open VMS comme système d'exploitation. Puisqu'un ordinateur VAS/VMS est vraiment fiable, aujourd'hui, après plus de 25 ans, ils sont encore très nombreux à être en service. Mais, à la longue, mêmes ces ordinateurs fiables devront être remplacés. Comme décrit dans la Partie 1, vous pourriez migrer de VAX/VMS vers Linux, car le fonctionnement de Linux est en large partie compatible avec VAX/VMS. Si votre langage de programmation est Pascal, vous trouverez que Lazarus/Free Pascal est une bonne alternative. Mais il y a des fonctions techniques dans VMS sans remplacement évident sous Linux. Dans cet article, je décrira comment je remplace des « logicals ».

La philosophie du système de fichiers ?

Pour comprendre les « logicals », je dois vous expliquer la philosophie derrière le système de fichiers de VMS. Sous linux, il y a un « dispositif » ('/') et tous les dispositifs physiques sont monter pour devenir un dossier virtuel (les points de montage). VMS utilise une approche diamétralement opposée : les dispositifs sont des éléments sépar“s et vous avez le droit de créear un nouveau dispositif (virtuel ou pseudo) qui pointe vers un dossier.

As an example, this is how you would address a file in VMS: DEVICE:[DIRECTORY.SUBDIR1.SUBDIR2]FILENAME.EXT;123 The same file in Linux would look like: /mountingpoint/directory/subdir1/subdir2/filename.ext Note all the uppercase characters in VMS, and the number at the end (the file version, described in part 4). What are logicals? A logical is a name/value pair maintained by the system, consisting of strings of up to 255 characters. As with eventflags, the reason why they are important is they are used consistently throughout the entire system in VMS. Whenever you access a device, the system will first look if the device name you specified is a logical. If so, the device name is replaced with the value of the logical (in VMS we say: the logical is translated), and that process is repeated up to 10 times (to prevent loops).

Par exemple, voici le chemin d'un fichier dans VMS :

DEVICE:[DIRECTORY.SUBDIR1.SUBDIR2]FILENAME.EXT;123

Le même fichier dans Linux serait :

/mountingpoint/directory/subdir1/subdir2/filename.ext

Remarquez les majuscules dans VMS et le numéro à la fin (la version du fichier, décrite dans la Partie 4).

Que sont les logicals ?

Un logical est une paire nom/valeur maintenu par le système, composé de chaînes contenant jusqu'à 255 caractères. Comme pour les eventflags, ils sont important parce qu'ils sont utilisés régulièrement partout dans le système VMS. Chaque fois que vous accéderez à un dispositif, le système regardera d'abord si le nom du dispositif que vous avez spécifiez est un logical. Si c'est le cas, le nom du dispositif est remplacé par la valeur du logical (dans VMS, nous disons que le logical est traduit) et ce procédé est répété jusqu'à 10 fois (pour empêcher des boucles).

This mechanism is very versatile. You can influence what device is accessed by changing the corresponding logical (give it another value), and the value can contain more information than just a device: it can also contain the path to a folder (directory), or other information like TRUE, FALSE, OPEN, CLOSED, etc, etc. More than one translation. The value is not limited to one string. You are allowed to specify more than one string, separated by a comma to get a search list. If the system does not find the file in the folder resulting from the first “translation”, it will continue the search by following the second “translation”, and the third, and so on. Though very useful, be warned: this can have a nasty side-effect. If you access a file through a search list, and you don't have permission to access the file (due to file protection, root is the owner, etc), the system will continue the search, but does not find it in the other folders. Then it reports to you the FINAL error of “file not found”. But you can see the file and you will think: is that computer crazy or am I? Luckily, neither; the fault is in the message. It should be “access denied” (VMS: “file protection violation”), and I thought VMS was perfect!

Ce mécanisme est très versatile. Vous pouvez modifier le dispositif auquel vous accédez en changeant le logical correspondant (lui onner une autre valeur), et la valeur peut contenir plus d'informations qu'un simple dispositif : il peut aussi contenir le chemin vers un dossier (répertoire) ou d'autres informations comme TRUE, FALSE, OPEN, CLOSED, etc., etc.

Plus d'une traduction.

La valeur n'est pas limitée à une seule chaîne. Vous pouvez spécifier plus d'une chaîne, séparée par une virgule pour avoir une liste de choses à rechercher. Si le système ne trouve pas le fichier dans le dossier qui résulte de la première « traduction », il continuera sa recherche en suivant la seconde « traduction », puis la troisième et ainsi de suite. Quoique très utile, soyez prévenu : cela peut avoir un effet secondaire désagréable. Si vous accédez à un fichier au moyen d'une liste de choses à rechercher, et que vous n'avez pas les droits pour accéder au fichier (il est protégé, son propriétaire est root, etc.) le système continuera sa recherche, mais ne le trouvera pas dans les autres dossiers. Puis il vous indique l'erreur FINAL de « file not found » (fichier introuvable). Mais vous voyez le fichier et vous vous demandez, est-ce moi ou l'ordinateur qui est fou ? Ni l'un ni l'autre heureusement ; la faute est dans le message d'erreur. Cela devrait être « Accès non autorisé » (VMS : « file protection violation » (violation de la protection du fichier)) et dire que je pensais que VMS était parfait !

In part 1, I mentioned that I have had bad experiences with frequent, but random, errors on Charon-VAX. These errors involved the translation of a logical which contained a search list. One in every hundred or so translations failed. It was impossible to find what was wrong, because the next time the same logical was translated, there was no error. It was because of the randomness of the error that we decided not to use Charon-VAX on our production computers, only the development computers were emulated.

Not as simple as it sounds…

The implementation of logicals in VMS is very complex: a logical is part of a table and there are many different tables. Which tables and the order in which the system looks for the logical is specified in yet another logical. I will not try to explain all of this – it would be outside the scope of this article. Let me only mention that the most used tables are process, job (session), group (GID) and system tables, and they are searched in that order. This makes it possible to create a pointer to a folder for your group in the group table, and temporarily create the same pointer to a different folder for test purposes in your job or process table for your own use - without disturbing the other users or services, as would be the case when using hard links.

Examples of use

To clarify this complex instrument I will show some examples of how logicals are or could be used:

• In Linux, the system is located on '/'; in VMS the system is on disk “SYS$SYSDEVICE”.

• In VMS, the logical “TT” points to the terminal you work on. This could be a physical terminal (TTAxxx), a network terminal using the LAT protocol (LTAxxx), a telnet terminal (TNAxxx), an Xterm terminal (FTAxxx), or a remote terminal using the DecNet protocol (RTAxxx). Your program does not need to know which device started the program; it just reads from and writes to “TT:” (note the colon, this signals that TT is a device, not a file). Do not confuse this with stdin and stdout. These are file handles and they open the file “TT:”.

• Suppose you made a process that reads files with file-type XML from 3 folders (placed there by 3 other process), and put the result in another. You could define 2 group logicals pointing to these folders:

define/group INPUT_FOLDER SYS$DISK3:[QUEUES.FROM_PROCESS_1],SYS$DISK3:[QUEUES.FROM_PROCESS_2],SYS$DISK3:[QUEUES.FROM_PROCESS_3]

define/group OUTPUT_FOLDER SYS$DISK4:[PROCESSED_DATA]

Then your process would look for input using the file specification INPUT_FOLDER:*.XML, and write the result to OUTPUT_FOLDER:RESULT_'DATE'_'TIME'.DAT

Now you made a change to your process and want to test it. Reading files from the input folder(s) would interfere with your system, so you define 2 new logicals at job level:

define/job INPUT_FOLDER MYDISK0:[TEST_QUEUE]

define/job OUTPUT_FOLDER MYDISK0:[RESULTS]

Now you can run the new process and test it by copying files to MYDISK0:[TEST_QUEUE] and examine the resulting files in MYDISK0:[RESULTS].

• Suppose you measure the weight of your product with an old scale, and then you purchase a new scale. In the first few weeks, you want to be able to switch between the scales. You could have 2 different executables, and stop the process that reads the scale and restart it using the other executable when you want to switch scale, or you could put the following code in your program:

new_scale := $TRNLNM (“NEW_SCALE”); (TRNLNM = translate logical name)

if new_scale = 'ACTIVE' then weight := read_new_scale() else weight := read_old_scale();

You could use the following terminal command to use the new scale:

define/system NEW_SCALE ACTIVE

and, to use the old scale:

define/system NEW_SCALE INACTIVE (or 'FALSE' or 'USE_OLD_SCALES' or anything else)

To use version control, I create a new folder tree for every version and use a logical to specify which version is active. As an example: My current version is 7.2, so I create the folder APP$DISK:[V7-02] and the sub-folders DATA and EXEC: APP$DISK:[V7-02.EXEC] and APP$DISK:[V7-02.DATA] The logical KW21 used as pointer to the current version is created with:

define/group KW21 APP$DISK:[V7-02.]/translation=concealed (note the dot at the end!)

The switch “translation=concealed” makes the logical KW21 a pseudo device, so the sub-folders can be addressed with KW21:[EXEC] and KW21:[DATA].

To use version 7.3, I would create APP$DISK:[V7-03.EXEC] and APP$DISK:[V7-03.DATA] and define KW21 as APP$DISK:[V7-03.] – without changing anything in my applications.

The only drawback of this method is that you have to use KW21:[000000] if you want to address the folder where the logical KW21 is pointing to.

There is a lot more to tell about logicals. If you want to read more about logicals and have some time on your hands, try google with “VMS logicals”.

How to handle logicals?

I tried replacing the logicals using hard links, but that works only for logicals with only 1 translation. And - as with eventflags - you can ask the system what the value of a logical is – a feature that cannot be implemented with hard links. This way, you could also define a kind of “system parameters” to be used by running processes. This makes it possible to implement software changes that can be switched on and off by changing the value of a logical instead of stopping a process and restarting it using a different executable. Or changing to or from daylight saving time without setting the clock. The list of other possible uses in VMS is long.

For the search list, you can use environment variables (PATH), but these are valid within only one process and cannot be changed by another process. Also not an option…

My solution

To use logicals on Linux, I created a few procedures in my library to replace the VMS functions to define, delete (“deassign”) and translate logicals. In VMS, the logicals are part of the kernel and located in the kernel's “paged memory”. This part of the kernel’s memory can grow in size and can be temporarily swapped out (VMS: paged out). As my solution is created in user-space, without the kernel controlling which process has access to which table, I decided to take a different approach: I placed the tables in separate data files.

Upon program start, the shared tables (system, group and job) are opened (or created if necessary), and mapped into shared memory, so they can be accessed directly. This happens only as soon as any of the logical-library routines is called for the first time. Any changes due to (re)defining or removing of logicals are written back to the corresponding file and are immediately visible by other processes as it's mapped into shared memory. The process local table (LNM_PROCESS) is created and also mapped into memory, but not shared. And here lies a little problem:

LNM_PROCESS is not a table. It's a logical pointing to another table containing the process ID (pid) in its name to separate the many process tables from each other. The behavior of Linux concerning process ID's is different from that of VMS (I will go into more detail on this in part 5 about DCL). DCL (Digital Command Language) is a real shell: it wraps around a process, and every time an executable (“image” in VMS) is started, it runs within this shell, within the same memory, with the same logicals and symbols (environment variables) and with the same process ID. Bash is called a shell, but it is NOT! It is a CLI (Command Line Interpreter). Every time an executable is started in Linux, it's started in a new subprocess. Besides the greater overhead of the creation of a new process, it also gets a new process ID. And therein is the problem: A different process ID means a different process table. In VMS, you can define a process logical and then start an executable that would use this logical. In Linux, the defined process logical will be gone on exit of the program defining the logical.

To circumvent this problem I decided to use the process ID of the parent instead. This will be the same every time you start a new executable from the same terminal. Because this causes a different problem (having the same process table) when starting several background (“detached” in VMS) programs from a single terminal or program, I created the program “RunDetached” to do this for you. This again causes all programs to use process ID 1 from the init program, but that is easily detected. In that case its own process ID minus 1 is used.

As mentioned before, logicals are used consistently throughout the entire system in VMS. This means that whenever you want to access a device, VMS will first try to translate the name of the device. To get the same behavior, I created a library function named OPEN to substitute the file access function of VAX-pascal, but this works only for TEXT handles. If another type of file handle is used, than it will be used to determine the file attributes (like record size), and I cannot mimic that. In this case the best solution is to manually replace the OPEN statement by a sequence of: • Call to “translate name” to get the VMS behavior; • Call to ASSIGN to open the file, while specifying the correct file handle. I am hoping that I can incorporate this into my conversion software later on.

The above mentioned functions (“define”, etc.) can also be accomplished from the terminal, so I created the three corresponding programs too. They are – of course – available as open source just like RunDetached.

Next month: In the next article I will go more in-depth about other functions such as mailboxes (IPC), what you MUST know about the difference in the way VAX-pascal and Free Pascal handle “PACKED ARRAY OF CHAR” (strings), and how to deal with file version numbers.

issue107/tutoriel1.1460566280.txt.gz · Dernière modification : 2016/04/13 18:51 de auntiee