Document revision date: 19 July 1999
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

OpenVMS Programming Concepts Manual


Previous Contents Index

12.6 Specifying Attributes

Generally, attributes specified through the logical name system services perform two functions: they affect the creation of logical names or govern how the system service operates, and they affect the translation of logical names and equivalence strings.

Attributes that affect the creation of the logical names are specified optionally in the attr argument of a system service call. The attr argument attributes that are available from the SYS$CRELNM system service are as follows:
Attribute Meaning
LNM$M_CONFINE Prevents this process-private logical name from being copied to subprocesses. Subprocesses are created by the DCL command SPAWN or by the run-time library LIB$SPAWN routine.
LNM$M_NO_ALIAS Prevents creation of a duplicate logical name in the specified logical name table at an outer access mode. If another logical name already exists in the table at an outer access mode, that name is deleted.

The attr argument attributes that are available from the SYS$CRELNT system service are as follows:
Attribute Meaning
LNM$M_CONFINE Prevents this process-private logical table from being copied to subprocesses. Subprocesses are created by the DCL command SPAWN or by the run-time library LIB$SPAWN routine.
LNM$M_CREATE_IF Prevents creation of a nonclusterwide logical name table if the specified table already exists at the specified access mode in the appropriate directory table. This attribute applies only to local tables.
LNM$M_NO_ALIAS Prevents creation of a logical name table at an outer access mode in a directory table if the table name already exists in the directory table.

The attr argument attributes that are available from the SYS$TRNLNM system service are as follows:
Attribute Meaning
LNM$M_CASE_BLIND Governs the translation process and causes SYS$TRNLNM to ignore uppercase and lowercase differences in letters when searching for logical names.
LNM$M_INTERLOCKED Ensures that any clusterwide logical name modifications in progress are completed before the name is translated.

The translation attributes LNM$M_CONCEALED and LNM$M_TERMINAL associated with logical names and equivalence strings are specified optionally through the LNM$_ATTRIBUTES item code in the itmlst argument of the SYS$CRELNM system service call. The equivalence name attributes for SYS$CRELNM are as follows:
Attribute Meaning
LNM$M_CONCEALED Indicates that the equivalence string at the current index value for the logical name is an OpenVMS RMS concealed device name.
LNM$M_TERMINAL Indicates that the equivalence strings cannot be translated further.

When the item code LNM$_ATTRIBUTES is specified through SYS$TRNLNM, the system returns the current attributes associated with the logical name and equivalence string at the current index value. Since a logical name can have more than one equivalence name, each equivalence name is identified by an index value. The item code LNM$_INDEX of SYS$TRNLNM searches for an equivalence name that has the specified index value.

The equivalence returned attributes for SYS$TRNLNM are as follows:
Attribute Meaning
LNM$M_CONCEALED Indicates that the equivalence string at the current index value for the logical name is an OpenVMS RMS concealed device name.
LNM$M_CONFINE Indicates that the logical name cannot be used by spawned subprocesses. Subprocesses are created by the DCL command SPAWN or by the run-time library LIB$SPAWN routine.
LNM$M_CRELOG Indicates that the logical name was created by the SYS$CRELOG system service.
LNM$M_EXISTS Indicates that the equivalence string at the specified index value exists.
LNM$M_NO_ALIAS Indicates that if the logical name already exists in the table, it cannot be created in that table at an outer access mode.
LNM$M_TABLE Indicates that the logical name is the name of a logical name table.
LNM$M_TERMINAL Indicates that the equivalence strings cannot be translated further.
LNM$V_CLUSTERWIDE Indicates that the logical name is clusterwide.

The attributes of multiple equivalence strings do not have to match. For more information about attributes, refer to the appropriate system service in the OpenVMS System Services Reference Manual.

12.7 Establishing Logical Name Table Quotas

A logical name table quota is the number of bytes allocated in memory for logical names contained in a logical name table. Logical name table quotas are established in the following instances:

Each logical name table has a quota associated with it that limits the number of bytes of memory (either process pool or system paged pool) that can be occupied by the names defined in the table. The quota for a table is established when the table is created.

If no quota is specified, the newly created table has unlimited quota. Note that this table can expand to consume all available process or system memory, and all users with write access to such a shareable table can cause the unlimited consumption of system paged pool.

12.7.1 Directory Table Quotas

When the system is initialized, unlimited quota is automatically established for the system directory table LNM$SYSTEM_DIRECTORY.

When you log in to the system, unlimited quota is automatically established for the process directory table LNM$PROCESS_DIRECTORY.

12.7.2 Default Logical Name Table Quotas

The process, group, system, clusterwide system, and clusterwide parent logical name tables have unlimited quota.

12.7.3 Job Logical Name Table Quotas

Because the job logical name table is a shareable table, and because you do not need special privileges to create logical names within it, the quota allocated to this logical name table is constrained at the time the table is created. The following three mechanisms exist to specify the quota for the job logical name table at the time of its creation:

12.7.4 User-Defined Logical Name Table Quotas

User-defined logical name tables can be created with either an explicit limited quota or no quota limit.

The presence of user-defined logical name table quotas eliminates the need for a privilege (for example, SYSNAM or GRPNAM) to control consumption of paged pool when you create logical names in a shareable table.

12.8 Interprocess Communication

Although logical names typically represent device and file names, shareable logical names can also be used to pass information among cooperating processes. When a process creates a shareable logical name, it can store up to 255 bytes of information in each equivalence name. The processes can agree to any arbitrary form for the information. Cooperating processes can translate the shareable name to retrieve the data in its eqivalence names.

The operating system ensures one process cannot change a logical name at the same time another process is either translating the name or trying to change it. In other words, the synchronization provided by OpenVMS allows multiple concurrent readers or a single writer to access shared logical names that are not clusterwide.

Each instance of OpenVMS has its own shareable logical name database. When a process creates a new shareable logical name, that name can be translated immediately by any other process in the system with access to the containing table.

On an OpenVMS cluster, each node has its own shareable logical name database. In addition, the clusterwide tables and their names are replicated on each node of the cluster. Cluster communication and replication time can delay the time when a clusterwide logical name is visible on other cluster nodes. For increased performance, the default synchronization provided by OpenVMS for clusterwide logical names allows a single writer to access shared logical names, but it does not block concurrent readers.

Synchronization provided by OpenVMS may therefore be insufficient for a given application. In particular, the following circumstances require that an application provide additional synchronization:

If you have an application where a logical name translator must be certain of getting the most recent definition of a clusterwide logical name, you should specify in the application the LNM$M_INTERLOCKED attribute in the attr argument. Use of this attribute synchronizes the translation with any pending changes to clusterwide names and ensures that the translation retrieves the most recent definition of the name. Use of this attribute to translate a local name adds a small amount of overhead but is otherwise harmless.

No logical name service provides an atomic modify of a logical name, clusterwide or local; it is thus not possible in one system service call to read the information in a logical name's equivalence names and recreate it with updated information. This means that if you have an interprocess application in which multiple processes modify a logical name, you must provide additional synchronization to create a critical section containing the SYS$TRNLNM and SYS$CRELNM calls. For example, your application could take the following steps:

  1. Call SYS$ENQ to acquire a restrictive lock on an application-specific resource name.
  2. Call SYS$TRNLNM to retrieve the current equivalence names, modify them, and call SYS$CRELNM to recreate the logical name. Use the LNM$M_INTERLOCKED attribute if the name could be clusterwide.
  3. Call SYS$DEQ to release the lock.
Because locks synchronize processes running on multiple cluster nodes, this method synchronizes processes that are running on a single node or multiple nodes.

12.9 Using Logical Name and Equivalence Name Format Conventions

The operating system uses special conventions for assigning logical names to equivalence names and for translating logical names. These conventions are generally transparent to user programs; however, you should be aware of the programming considerations involved.

If a logical name string presented in I/O services is preceded by an underscore (_), the I/O services bypass logical name translation, drop the underscore, and treat the logical name as a physical device name.

When you log in, the system creates default logical name table entries for process-permanent files. The equivalence names for these entries (for example, SYS$INPUT and SYS$OUTPUT) are preceded by a 4-byte header that contains the following information:
Byte Contents
0 ^X1B (escape character)
1 ^X00
2--3 OpenVMS RMS Internal File Identifier (IFI)

This header is followed by the equivalence name string. If any of your program applications must translate system-assigned logical names, you must prepare the program to check for the existence of this header and to use only the desired part of the equivalence string. The following program demonstrates how to do this:


 
#include <stdio.h> 
#include <lnmdef.h> 
#include <ssdef.h> 
#include <descrip.h> 
#include <ctype.h> 
#include <string.h> 
 
#define HEADER 4 
 
/* Define an item descriptor */ 
struct { 
        unsigned short buflen, item_code; 
        void *bufaddr; 
        void *retlenaddr; 
        unsigned int terminator; 
}item_lst; 
        
 
main() { 
        
        unsigned int status,len,i; 
        char resstring[LNM$C_NAMLENGTH]; 
        $DESCRIPTOR(tabdesc,"LNM$FILE_DEV"); 
        $DESCRIPTOR(logdesc,"SYS$OUTPUT"); 
 
        item_lst.buflen = LNM$C_NAMLENGTH; 
        item_lst.item_code = LNM$_STRING; 
        item_lst.bufaddr = resstring; 
        item_lst.retlenaddr = 0; 
        item_lst.terminator = 0; 
 
/* Translate the logical name */ 
        status = SYS$TRNLNM( 0,   /* attr - attributes of the logical name */ 
                  &tabdesc,       /* tabnam - logical name table */ 
                  &logdesc,       /* lognam - logical name */ 
                  0,              /* acmode - accessm mode */ 
                  &item_lst);     /* itmlst - item list */ 
        if((status & 1) != 1) 
                LIB$SIGNAL( status ); 
        
/* 
   Examine 4-byte header 
   Is first character an escape char? 
   If so, dump the header 
*/ 
        if( resstring[0] == 0x1B) { 
                printf("\nDumping the header...\n"); 
                for(i = 0; i < HEADER; i++) 
                        printf(" Byte %d: %X\n",i,resstring[i]); 
 
                printf("\nEquivalence string: %s\n",(resstring + HEADER)); 
        } 
        else 
                printf("Header not found\n"); 
                
} 
 

12.10 Using Logical Names and Logical Name Table System Services in Programs

The following sections describe by programming examples how to use SYS$CRELNM, SYS$CRELNT, SYS$DELLNM, and SYS$TRNLNM system services.

12.10.1 Using SYS$CRELNM to Create a Logical Name

To perform an assignment in a program, you must provide character-string descriptors for the name strings, select the table to contain the logical name, and use the SYS$CRELNM system service as shown in the following example. In either case, the result is the same: the logical name DISK is equated to the physical device name DUA2 in table LNM$JOB.


 
#include <stdio.h> 
#include <lnmdef.h> 
#include <descrip.h> 
#include <string.h> 
#include <ssdef.h> 
 
/* Define an item descriptor */ 
 
struct itm { 
            unsigned short buflen, item_code; 
            void *bufaddr; 
            void *retlenaddr; 
}; 
 
/* Declare an item list */ 
 
struct { 
                struct itm items2]; 
                unsigned int terminator; 
}itm_lst; 
 
main() { 
 
        static char eqvnam[] = "DUA2:"; 
        unsigned int status, lnmattr; 
        $DESCRIPTOR(logdesc,"DISK"); 
        $DESCRIPTOR(tabdesc,"LNM$JOB"); 
 
        lnmattr = LNM$M_TERMINAL; 
 
/* Initialize the item list */ 
        
        itm_lst.items[0].buflen = 4; 
        itm_lst.items[0].item_code = LNM$_ATTRIBUTES; 
        itm_lst.items[0].bufaddr = &lnmattr; 
        itm_lst.items[0].retlenaddr = 0; 
 
        itm_lst.items[1].buflen = strlen(eqvnam); 
        itm_lst.items[1].item_code = LNM$_STRING; 
        itm_lst.items[1].bufaddr = eqvnam; 
        itm_lst.items[1].retlenaddr = 0; 
        itm_lst.terminator = 0; 
 
/* Create the logical name */ 
        status = SYS$CRELNM(0,           /* attr - attributes */ 
                         &tabdesc,       /* tabnam - logical table name */ 
                         &logdesc,       /* lognam - logical name */ 
                         0,              /* acmode - access mode 0 means use the */ 
                                         /* access mode of the caller=user mode */ 
                         &itm_lst);      /* itmlst - item list */ 
        if((status & 1) != 1) 
                LIB$SIGNAL(status); 
 
} 
 
 
 

Note that the translation attribute is specified as terminal. This attribute indicates that iterative translation of the logical name DISK ends when the equivalence string DUA2 is returned. In addition, because the acmode argument was not specified, the access mode of the logical name DISK is the access mode from which the image requested the SYS$CRELNM service.

The following example shows how a process-private logical name with multiple equivalence names can be created in user mode by an image:


 
#include <stdio.h> 
#include <lnmdef.h> 
#include <ssdef.h> 
#include <descrip.h> 
 
/* Define an item  descriptor */ 
struct lst { 
            unsigned short buflen, item_code; 
            void *bufaddr; 
            void *retlenaddr; 
}; 
 
/* Declare an item list */ 
struct { 
        struct lst items[2]; 
        unsigned int terminator; 
}item_lst; 
 
/* Equivalence name strings */ 
 
static char eqvnam1[] = "XYZ"; 
static char eqvnam2[] = "DEF"; 
 
main() { 
 
        unsigned int status; 
        $DESCRIPTOR(logdesc,"ABC"); 
        $DESCRIPTOR(tabdesc,"LNM$PROCESS"); 
 
        item_lst.items[0].buflen = strlen(eqvnam1); 
        item_lst.items[0].item_code = LNM$_STRING; 
        item_lst.items[0].bufaddr = eqvnam1; 
        item_lst.items[0].retlenaddr = 0; 
 
        item_lst.items[1].buflen = strlen(eqvnam2); 
        item_lst.items[1].item_code = LNM$_STRING; 
        item_lst.items[1].bufaddr = eqvnam2; 
        item_lst.items[1].retlenaddr = 0; 
        item_lst.terminator = 0; 
 
/* Create a logical name */ 
        status = SYS$CRELNM( 0,   /* attr - attributes of logical name */ 
                  &tabdesc,       /* tabnam - name of logical name table */ 
                  &logdesc,       /* lognam - name of logical name */ 
                  0,              /* acmode - access mode 0 means use the */ 
                                  /* access mode of the caller=user mode */ 
                  &item_lst);     /* itm_lst - item list */ 
        if((status & 1) != 1) 
                LIB$SIGNAL(status); 
 
} 
 
 
 
 
 

In the preceding example, logical name ABC was created and represents a search list with two equivalence strings, XYZ and DEF. Each time the LNM$_STRING item code of the itmlst argument is invoked, an index value is assigned to the next equivalence string. The newly created logical name and its equivalence string are contained in the process logical name table LNM$PROCESS_TABLE.

The following example illustrates the creation of a logical name in supervisor mode through DCL:


$ DEFINE/SUPERVISOR_MODE/TABLE=LNM$PROCESS ABC XYZ,DEF

In the preceeding example, supervisor mode and /TABLE=LNM$PROCESS are the defaults (default mode and default table) for the DEFINE command.

12.10.2 Using SYS$CRELNT to Create Logical Name Tables

The Create Logical Name Table (SYS$CRELNT) system service creates logical name tables. Logical name tables can be created in any access mode depending on the privileges of the calling process. A user-specified logical name that identifies a process-private created logical name table is stored in the process directory table LNM$PROCESS_DIRECTORY. The name of a shareable table is stored in the system directory table LNM$SYSTEM_DIRECTORY.

The following example illustrates a call to the SYS$CRELNT system service:


 
#include <stdio.h> 
#include <ssdef.h> 
#include <lnmdef.h> 
#include <descrip.h> 
 
 
main() { 
 
        unsigned int status, tab_attr=LNM$M_CONFINE, tab_quota=5000; 
        $DESCRIPTOR(tabdesc,"LOG_TABLE"); 
        $DESCRIPTOR(pardesc,"LNM$PROCESS_TABLE"); 
        
/* Create the logical name table */ 
        status = SYS$CRELNT(&tab_attr,  /* attr - table attributes */ 
                0,                      /* resnam - logical table name */ 
                0,                      /* reslen - length of table name */ 
                &tab_quota,             /* quota - max no. of bytes allocated */ 
                                        /* for names in this table */ 
                0,                      /* promsk - protection mask */ 
                &tabdesc,               /* tabnam - name of new table */ 
                &pardesc,               /* partab - name of parent table */ 
                0);                     /* acmode - access mode */ 
        if((status & 1) != 1) { 
                LIB$SIGNAL(status); 
                
} 
 
 

In this example, a user-defined table LOG_TABLE is created with an explicit quota of 5000 bytes. The name of the newly created table is an entry in the process-private directory LNM$PROCESS_DIRECTORY. The quota of 5000 bytes is deducted from the parent table LNM$PROCESS_TABLE. Because the CONFINE attribute is associated with the logical name table, the table cannot be copied from the process to its spawned processes.


Previous Next Contents Index

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
5841PRO_035.HTML