Working with Geosoft Databases
Opening and Locking a Database
An important distinction exists in Oasis montaj between a database (DB) and an edited database (EDB). An EDB is what the user sees on the screen – it is a representation of the data (the DB) which exists somewhere on disk. With the EDB object is possible to do a number of things, including looking at, loading or unloading channels of data, creating profiles, and marking ranges of data. The one thing that cannot be done with the EDB is retrieve or change data, or select individual lines for processing. To do this, the database must be made exclusively available to the individual user. This is performed by locking the database to other users. The locking function returns the DB handle, which can be used to access the data directly:
// --- Get database --- Edata = Current_EDB(); Data = Lock_EDB(Edata); // --- Access data using the DB handle "Data" .... . . . // --- Release the database --- UnLock_EDB(Edata);
Selecting Lines for Processing
Many processes access the database one line of data at a time. This is performed using a loop structure and the FirstSelLine_DB and NextSelLine_DB functions, which allow the process to step through all the selected lines in the database:
Line = FirstSelLine_DB(Data); while (iIsLineValid_DB(Data,Line)) { // --- Process the line --- . . . // --- Advance to the next line --- Line = NextSelLine_DB(Data, Line); iLines++; // increment a counter for the progress bar }
Within the variable declaration section, declare a DB_SELECT object. This will be a handle to the current selection list within the database; because it already exists, it is not an object that must be “Created” or Destroyed”.Line selection is usually done from the OASIS interface by using the selection tool.
A common GX dialog option, found, for instance, in data export GXs, allows the user to process all the lines, just the selected lines, or the currently displayed line. The following annotated example, excerpted from the EXPDB GX, shows how this selection process is implemented within a GX.
DB_SELECT Select; // current selection mode
The line selection choice is retrieved from the workspace parameter block, and the selection is verified and interpreted as one of the line selection options.
GetString_SYS("EXPDB","LINE",sLine); if (iChar_STR(sLine) == iChar_STR("D")) iLine = DU_LINES_DISPLAYED; else if (iChar_STR(sLine) == iChar_STR("S")) iLine = DU_LINES_SELECTED; else if (iChar_STR(sLine) == iChar_STR("A")) iLine = DU_LINES_ALL; else Abort_SYS("Line selection invalid");
The identity of the currently viewed line is determined from the edited database (EDB) object.
Edata = Current_EDB(); // --- Get the name of the currently selected line --- GetCurLine_EDB(Edata,sCurLine);
Get a database handle by locking the current database, then perform the selection; if the user wishes to use all the selected lines, nothing needs to be done before processing begins. The selection list handle is obtained using the GetSelect_DB function.
Data = Lock_EDB(Edata); if(iLine != DU_LINES_SELECTED) { Select = GetSelect_DB(Data); if (iLine == DU_LINES_DISPLAYED) { Select_DB(Data,"",DB_LINE_SELECT_EXCLUDE); Select_DB(Data,sCurLine,DB_LINE_SELECT_INCLUDE); } else if (iLine == DU_LINES_ALL) Select_DB(Data,"",DB_LINE_SELECT_INCLUDE); }
Now that the correct set of lines is selected, do the processing. Finally, return the line selection list to its original state.
// --- process the data --- . . . // --- reset starting selections if (iLine != DU_LINES_SELECTED) SetSelect_DB(Data,Select);
Locking and Unlocking Lines and Channels
The OASIS database is currently designed for a single-user environment, but contains features that will smooth transition to a multi-user environment in future. For this reason, you are required to lock and unlock certain database objects for use.
For example, if you are filtering the lines in a database, you require an input channel (with read status) and an output channel (with read/write status). When you are reading and writing to a channel, the system requires that you lock it, perform the reading or writing process and unlock it. This prevents the data from being altered by another process or user while you alter some of the data.
For certain operations, such as applying math expressions, the same requirements apply. However, when you look at sample code, you will notice that channels are not locked or unlocked. Because the locking and unlocking can be quite complex for math expressions, the system is designed to manage this task for you.
The following examples of locking and unlocking lines and channels are from the COPY GX, shown above.
Creating a line or channel symbol using the DupSymb_DB function automatically locks it. (The CreateSymb_DB function does not lock the new symbols.) In the following code, if the output channel doesn’t already exist, it is created from an already existing symbol using the DupSymb_DB function. Since it will be locked later, the lock should be temporarily “undone”. It is possible to lock an object more than once, but care should be taken that an equal number of unlock operations have been performed upon completion.
// --- Does the Output Channel Exist? --- if (!iExistSymb_DB(Data,sOutCh,DB_SYMB_CHAN)) { OutCh = DupSymb_DB(Data,InCh,sOutCh); // Create it UnLockSymb_DB(Data,OutCh); } else OutCh = FindSymb_DB(Data,sOutCh,DB_SYMB_CHAN); // --- Does the Output Channel Exist? --- if (!iExistSymb_DB(Data,sOutCh,DB_SYMB_CHAN)) { OutCh = DupSymb_DB(Data,InCh,sOutCh); // Create it UnLockSymb_DB(Data,OutCh); } else OutCh = FindSymb_DB(Data,sOutCh,DB_SYMB_CHAN);
The same channels are locked throughout the line-by-line processing, so it makes sense to lock them just once, outside the loop. Notice that the input channel is locked “READONLY”, since no changes will be made to it. It is a wise practice never to give more access to an object than the process requires.
// --- Lock the channel symbols --- if (InCh != OutCh) LockSymb_DB(Data,InCh,DB_LOCK_READONLY,DB_WAIT_INFINITY); LockSymb_DB(Data,OutCh,DB_LOCK_READWRITE,DB_WAIT_INFINITY);
Within the line loop, the line symbols are locked momentarily in order to determine the line name for use in the progress bar. (See the important note about line locks below).
// --- Update the Progress Bar --- LockSymb_DB(Data,Line,DB_LOCK_READONLY,DB_WAIT_INFINITY); GetSymbName_DB(Data,Line,sTemp); UnLockSymb_DB(Data,Line); Strcpy_STR(sLabel,"Copy line: "); Strcat_STR(sLabel,sTemp); ProgName_SYS(sLabel,0); ProgUpdate_SYS( (int) ((real) iLines / (real) iTotLines * 100.0) );
Finally, after the loop is completed, unlock the channel.
// --- Unlock the Channel Symbol --- if (InCh != OutCh) UnLockSymb_DB(Data,InCh); UnLockSymb_DB(Data,OutCh);
Note: It is necessary to lock a line only when accessing information about the line symbol itself (as in the example above, where the line name is retrieved). However, a lock is not required when accessing line data itself, for instance in the calls to Decimate_DU and SetFid_DB in the COPY GX above, even though these functions take the line handle as an argument. It is possible that in the future, if Oasis montaj becomes truly multi-user capable, that this ‘hole” will be filled and a line lock will be required for all functions taking the line symbol as an argument. We strongly recommend that in new code that the line lock and unlock statements be placed to enclose all functions using the line symbol to access data to within the loop structure, as in the following example:
while (iIsLineValid_DB(Data,Line)) { // --- Lock the line --- LockSymb_DB(Data,Line,DB_LOCK_READONLY,DB_WAIT_INFINITY); // --- Update the Progress Bar --- . . . // --- Process the line --- . . . // --- Unlock the line --- UnLockSymb_DB(Data,Line); // --- Advance to the next line --- Line = NextSelLine_DB(Data, Line ); iLines++; // increment a counter for the progress bar }