Updating the Vision Network

Overview

There are two basic types of update that can be performed: Global Updates which can create and change any object or message and Private User Updates which can only create and change objects in a particular object space. The dbadmin user code usually performs global updates. Other users can perform private user updates within their object space. A utility is available that allows non-dbadmin users to submit changes for global update.

Within any Vision session, any user can create new classes or instances, define or modify methods, and create or update property values. During your session, you can safely modify classes and instances that you do not control (i.e., shared object space 3 objects), since these changes will only impact your session. Any definitions or modifications made during your session will apply throughout your session and will disappear when you exit the session without saving your changes.

An update is really just a Vision session whose actions are committed to the permanent database. Although any user can change shared objects during a session, only the dbadmin can save the changes as a permanent part of the database. Global (i.e., dbadmin) updates can affect objects in one or more object spaces. Private users can permanently save changes made to objects that they own. Private user updates commit changes to a single object space.

When Vision saves changes to the network, new segments are created. Private saves will create segments in the top level object space only. Global updates may create segments in several object spaces.

If you choose to commit a Vision session to the permanent database, Vision will attempt to do a global update if the following conditions are met:

  • The user code appears in the file /localvision/network/NDF.GURL.
  • The session has the VisionAdm environment variable set.
If both of these conditions are not met, Vision will perform a private user update.

The NDF.GURL file contains a list of user codes that have permission to perform global updates. By default, this file contains only the dbadmin user code. You can edit this file to contain any number of users, one per line: however, it is usually preferable to limit the number of users with global update rights.

All updates to the Vision network are recorded in the NDF.JOURNAL file located in /localvision/network. Minimally, this Ascii file lists the segments created with each update. When you use the dbSubmit utility and the database network maintenance tools, additional annotations will be placed in this file for each update. The NDF.JOURNAL and related tools are described further in the section, Network Administration Tools


Saving A Session

Unless you are creating a new object space, all Vision updates are performed using a specific object space as the top-level. The dbadmin user can specify any object space as its top level, depending on the nature of the update. This is usually object space 3 for general maintenance activities. The object space defined for a private user should be specified for private updates.

If you are going to update the network, you should start your Vision session with an explicit object space number or set the UserOSI environment variable. For example, the dbadmin user would start a session in object space 3 using:

  vision -U3
The session should look identical to any other Vision session. You should execute whatever Vision code is needed to define or modify Vision objects. It is good practice to test all changes interactively in a session that you are not planning to commit. You can then create a single file of Vision code which can be loaded, executed, and saved.

There are several ways to commit an update to the database. You can explicitly save your session using the expression:

  Utility updateNetwork ;
If you are the dbadmin, you should see the message:
  >>> Object Network Updated. <<<
If you are a private user, you should the message:
  >>> User Space Updated. <<<
To include a comment with the save, use the form:
  Utility updateNetworkWithAnnotation: "This is an important save." ;
This is the most direct way to commit a set of changes to the Vision network. Private users can use this approach; however, it is recommended that global (dbadmin) updates are managed using one of the approaches described below.

Saving Your Session on Exit

If you are the dbadmin user and you use the Vision Editor, this first option is available to you. Otherwise, you should use the dbSubmit option.

After you have made all your changes, exit from your session in the normal way. Before finishing, Vision will ask if you wish to update the shared network with your changes. Type the single character y to indicate that you want to commit your changes. You will then be prompted for a password. This password is normally distinct from the dbadmin password, since not all users who are allowed to perform some database activities (e.g., tape loading) should be allowed to change the shared network. Type your password, followed by a carriage return. If you do not provide the correct password after three tries, Vision will terminate without saving your changes.

After you have supplied the correct password, you will be prompted for your initials. Your changes will then be saved as part of the shared network. You will be informed when the save has successfully completed. In addition to confirmation, you will be provided with a log file number which corresponds to a log of your entire session which is saved in the directory $DBUpdateLogs.

Note that for this option to work, you must have a user code named dbupdate set up. The password for this user code is the password you should use for the save. This user code should be set up to run the /bin/passwd program as its shell.

By convention, updates installed in this manner are read in from files maintained in the directory /localvision/source/changes directory. Master files which contain a logical grouping of class and message definition are often maintained in the /localvision/source/latest directory. For example, if you used the file DEFcompany to define all your company messages initially and need to modify a specific method, you could create a Vision script named changes.company.1 that just includes the modification, update the Vision database with this script, and edit the DEFcompany file to reflect this change. The DEFcompany file becomes the unofficial master of all company methods.


Note:
This is a convention that requires cooperation among all updaters. There is no guarantee that the code in this file is the latest version. The only way to be sure you have the latest code for a particular method is to check within the Vision database itself.

The dbSubmit Utility

The previous approach is adequate for installations that have a single user who performs shared updates. Environments that have several users who need to make global changes and/or the environments which have production update processing throughout the day are better served by the dbSubmit utility.

The dbSubmit utility is a Unix script that accepts a file containing Vision code from any user and submits it for update by the dbadmin user. Requests submitted in this manner are validated for basic syntax errors, then added to a batch queue for later processing. This batch queue can be processed as often as every minute, depending on your organization's needs.

To submit Vision code for update type:

  dbSubmit
at the Unix prompt. You will be prompted as follows:
  Input File:                     #-  enter name of file of Vision code

  Run in Space [3]:               #-  carriage return or alternative
                                  #-  space number

  Test File Before Submitting?    #- Yes/No
If the supplied file is okay, you will see a message of the form:
  ***  File Update Pending.  File: update.xyz.nn

  where  xyz  is your user code
  and nn is the next available number for your user code
The actual processing of this file is described in more detail in the next section.

Processing Submitted Updates

Updates that have been submitted with the dbSubmit utility that are waiting to be processed are stored in the directory:
  $transArea/pending
Updates that have already been processed are stored in the directory:
  $transArea/posting
and serve as an audit trail of changes made to the database over time. The directory
  $transArea/logs
contains daily log files that indicate which updates were committed on a particular day and any output generated by these updates.

The script that processes any submitted jobs is:

  $transArea/scripts/processUpdate
This script performs the following functions:
  • Creates a token $tokens/manual. in Progress which prevents other updates from starting.
  • Starts a Vision session in the correct object space, executes the next pending script, and updates the network.
  • Moves the pending script from the pending to the posted directory.
  • Processes the next pending script.
There are several different options for running this script.

If an automated daemon is not running at your installation, you can execute the following:

  cd $transArea/scripts
  processUpdate
To start the daemon manually, execute:
  $adminArea/restart.manual
This starts a job in background that periodically looks for pending files and processes them.

If the daily. daemon is running at your installation, any pending files will be executed as part of the standard production cycle.


New Object Spaces

Note that if you do not start Vision with a top level space and you are the dbadmin, Vision will create a new object space if you perform an update. Although this is a way to create a new space, it is not recommended because you will not run any of the procedures used to make the space easily accessible to other users. If desired, the following steps can be used to bypass the installSpace script to create a new space and run the initialization procedures:
  • Start a Vision session without the -U option
            vision
    
  • Execute the method:
      Environment MaintenanceTools
      setupSpaceFor: "code"
      as: "type"
      description: "description of space"
    
      where:
      code            a code indicating a short name for the space
      type            "DBA", "DB", or "User" indicating space's function
      description     a string describing the function
    
    For example, to set up a general administration space, use the Vision expression:
      Environment MaintenanceTools
      setupSpaceFor: "General"
                 as: "DBA"
        description: "Miscellaneous Admin Tools"
    
    The object space number assigned to General will be displayed.

  • Save the session.
      Utility updateNetwork
    

Note:
In general there is no reason to use this approach since the installSpace script performs these steps and generates a centralized audit file.

Private Workspace Extensions

Private updates can be used to store:
  • Variables defining frequently used names or constants.
  • Variables defining lists of entities that are frequently used.
  • Private classes and the messages and instances of these classes.
Since you cannot make permanent changes to classes you do not own, several messages have been defined that allow individual users to define and maintain extensions to the core entity classes that can be saved in private workspaces. If you changed objects that you do not own during your session, the save will be successful in most cases; however, any changes you made to objects that you do not own will not actually be saved. For example, suppose you define and use a temporary property at the shared class Security and create some methods at Object and List. You can use these new messages to update data in your private classes. When you save your session, the messages you defined at Security, Object, and List will be ignored and the new data in your private classes and extensions will be saved.

One common use for private spaces is to store lists of entities that are frequently needed. For example:

  !canadaList <- Security masterList select: [ country isCanada ] ;
This list is available throughout your session. If you save your session prior to exiting, this list will have the same contents when you start your next session. You can save additional information for the elements in this list using extensions. For example:
  !canadaList <- Security masterList select: [ country isCanada ] .
  extendBy: [ !item1 <- sales * 2 ; ] ;
If you save this session, and start a new one, you will still be able to access the value item1 for the elements of this list. Note that if additional securities have been added since this list was created, they will not be in the list. The variable canadaList refers to the list that was created when your session was saved. You can define a method that you can run at startup that always updates this list. For example:
  ^global
  defineMethod:
  [ | runStartup |
  ^global defineFixedProperty: 'canadaList' ;
  ^global :canadaList <-
  Security masterList select: [ country isCanada ] .
  extendBy: [ !item1 <- sales * 2 ] ;
  ] ;
Save the session in which you defined this method. When you start a new session and execute runStartup, a new version of canadaList will be defined.

You can also create your own subclasses, messages, and instances. Private subclasses of Object, Entity, or Dictionary can be created using the specializeAs: message. You should send this message to the class MyObject, MyEntity, or MyDictionary. For example, to create a private set of industries that reference a shared sector use the following expressions:

  MyEntity specializeAs: "MyIndustry" ;
  MyIndustry newAs: "ind1" . setNameTo: "Industry 1" ;
  MyIndustry newAs: "ind2" . setNameTo: "Industry 2" ;
  MyIndustry defineFixedProperty: 'sector' ;
  Named MyIndustry ind1 :sector <- Named Sector Retail ;
  Named MyIndustry ind2 :sector <- Named Sector Finance ;
If you save this session, the class MyIndustry with its two instances and the property values set for sector will be saved.

Although private users can save references to shared objects in properties of their private objects (as illustrated in the last example), they cannot make permanent changes to classes that they do not own. Most of the core entity classes are shared by all users. Users have "read" access to these classes and can make any modifications desired during their sessions; however, these modifications cannot be saved as part of the permanent database. Several methods have been defined that allow individual users to define and maintain additional information about shared objects in their private workspaces. Other users will be able to access this data in the same manner used to access data in external database classes.

To create a private extension in which to define additional messages for a core entity class, you send the createPrivateStructure message to the class. For example, to create a structure for maintaining private data about securities use:

  Security createPrivateStructure
This creates a private class named SecurityRecord in your private space. This class can be thought of as an extension to the Security class and gives you a place to define messages that you can save. Although you can reference the class directly as SecurityRecord in your private space, a direct access path from Security instances to SecurityRecord instances is automatically defined. This path is available to all users independent of their top-level object space. The code defined when the space was created defines this path. For example, if the code name for this object space is xyz, the expression:
  Named Security IBM xyzData
will return xyz's private data about IBM if it has been defined. The expression:
  Security xyzData = SecurityRecord
will return TRUE when executed in user xyz's private space.

To create a private data record for each security that does not currently have one, use the expression:

  Security xyzData createMissingLinksForClass
This will create an instance in your local class for every "real" Security. The first time you run this, you will get an instance for each Security. If you know that you will never track data for any security that is not a US security, you can restrict the creation to this subset using:
  Security xyzData createMissingLinksForList:
  (Security masterList select: [ country isUS ] );
When you save your session, the private security instances will be saved. When you start a new session and execute:
  Security xyzData createMissingLinksForClass
you will only create new private instances for shared securities that have been created since your last private save.

You can define properties and methods for your private class using:

  Security xyzData
  defineFixedProperty: 'fp' .
  define: 'ts' .
  defineMethod:
  [ | m1 |
  "fp: " print; fp printNL ;
  "ts: " print ; :ts count printNL ;
  :ts displayAll
  ] ;
The message entity is defined at the private class to return the corresponding entity in the shared class. You can use this entity to update the private properties. For example:
  Security xyzData instanceList
  do: [ 
       :fp <- entity sector ;
       90 to: 92 by: 1 years .
       evaluate: [ :ts put: entity sales ] ;
      ] ;
To access this data for a specific Security, use the expression:
  Named Security IBM xyzData :ts displayAll ;
To find all securities that do have xyz data but do not have a value for fp, use the expression:
  Security masterList select: [ xyzData isntDefault ] .
  select: [ xyzData fp isNA ] .
  do: [ # your code goes here
      ] ;
Note that the xyzData message needs to execute several lookups to link the security to the private data. If you are planning to do a number of operations in a list that reference xyzData, you will find it is faster to create a local variable inside your do: or extend: block. For example:
  Security masterList
  do: [ !xyz <- xyzData ;
        !calc1 <- xyz fp1 + xyz fp2 + xyz ts1 ;
        !calc2 <- calc1 - xyz calc1 ;
        #---
      ] ;
When you save your session, any new private entity instances, messages, and property values are saved. This data can be accessed by any user via the xyzData message but can only be updated if you start with the correct object space and have write permission for this space.

In summary, to create private records that extend shared entity classes, use the expression:

  Security createPrivateStructure createMissingLinksForClass
to create the private structure and initial instances. This is normally done once for each class and saved. Each time you start a session you can execute the expression:
  Security xyzData createMissingLinksForClass
to create private instances for any security that has been added since your last save.

Error Messages

When a save is successful, you will see the message:
  >>> Object Network Updated. <<<
or
  >>> User Space Updated. <<<
There are several situations that can prevent a private save from completing successfully. In most cases, it is because a private user has defined something at a shared class that is needed in order to make the private save meaningful. For example, the expressions:
  Security newAs: "12345610" ;
  Security xyzData createMissingLinksForClass ;
can be used to create a new shared security and a private extension that is linked to it. The property entity for the object Named Security \12345610 xyzData will return the new security (i.e., Named Security \12345610). When you try to save this session, you will see the message:
  >>> Local Update Would Disrupt Network Integrity  <<<
When Vision tries to save your SecurityRecord, it discovers that the entity property references something that cannot be saved and the save is aborted.

Related Topics