open-insight/FRAMEWORKS/STPROC/DATABASE_SERVICES.txt
Infineon\StieberD 7762b129af pre cutover push
2024-09-04 20:33:41 -07:00

1048 lines
47 KiB
Plaintext

Function Database_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Database_Services
Description : Handler program for all Database services.
Notes : Application errors should be logged using the Error Services module. There are a few methodological
assumptions built into way errors are managed which are important to understand in order to properly
work with Error Services:
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
History : (Date, Initials, Notes)
03/27/17 dmb Original programmer.
05/02/17 dmb Add error if WriteDatabaseRow is unable to lock row.
10/31/17 dmb Add CalculateColumn and GetTableCommuter services.
11/06/17 fjt [SRPFW-195] Added to FW v16.0.12
05/25/18 dmb Add GetUserLocks service.
05/29/18 dmb Add IsKeyIDLocked, IsKeyIDSelfLocked, and UnlockKeyID services.
10/09/18 djs Added ActivateRecord service, which sets @ID, @Record, and @DICT to enable {} shorthand.
01/22/19 fjt [SRPFW-195] Updated to include codes in error reporting
02/28/19 dmb [SRPFW-195] Add safety check in GetTableHandle to make sure the table's full
handle is still in @TABLES before using the cached handle.
03/12/19 dmb [SRPFW-270] Add ClearTableHandle service so it is easy to remove the cached
table handle when situations such as aliasing a table from a different
volume occurs.
03/12/19 dmb [SRPFW-270] Add SetTableAlias service to alias a table and call the
ClearTableHandle service if thealias was successful.
05/03/19 dmb [SRPFW-273] Initialize TableName in the CalculateColumn service to prevent
potential VNAV errors.
05/11/20 dmb [SRPFW-313] Add GetTableNames service.
06/29/20 dmb [SRPFW-282] Update the GetTableNames service to support ExcludeDictionaries and
ExcludeIndexes arguments.
08/04/20 djs Commented out UnlockKeyID service. This service causes OpenInsight to crash. Use
ReleaseKeyIDLock instead.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$insert SERVICE_SETUP
$insert VOL_TABLE_EQUATES
$insert RTI_LH_INFO_EQUATES
Declare function Memory_Services, Database_Services, SRP_Encode, RetStack, RTI_LH_Info, SRP_Path, SRP_Array
Declare subroutine Memory_Services, Database_Services, Verify_LH, SRP_Stopwatch, Btree.Extract, Update_Index, Set_Status
Declare subroutine RTI_LH_Info, Alias_Table, Push.Select, Pop.Select
GoToService else
Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' module.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// ActivateRecord
//
// TableName. The linear hash database table name. - [REQUIRED]
// KeyID. The KeyID to the database table. - [REQUIRED]
//
// Reads a data row for the indicated Key ID and database table. Sets @ID, @Record, and @DICT to enable {} shorthand.
//----------------------------------------------------------------------------------------------------------------------
Service ActivateRecord(TableName, KeyID, NotExpired, ExpirationDuration, IgnoreMFSRoutines)
If TableName NE '' AND KeyID NE '' then
@ID = KeyID
DictTable = ''
If TableName[1,5] _EQC 'DICT.' then
DictTable = TableName
TableName = TableName[-1, 'B.']
end else
DictTable = 'DICT.':TableName
end
@DICT = Database_Services('GetTableHandle', DictTable)
If Error_Services('NoError') then
@Record = Database_Services('ReadDataRow',TableName,KeyID,NotExpired,ExpirationDuration,IgnoreMFSRoutines)
If Not(Error_Services('NoError')) then
Error_Services('Add','Error reading ':KeyID:' from the ':TableName:' table in the ':Service:' service.')
end
end else
Error_Services('Add', 'Error retrieving handle for the ':TableName:' table in the ':Service:' service.')
end
end
Response = @Record
end service
//----------------------------------------------------------------------------------------------------------------------
// CalculateColumn
//
// Called directly from within a calculation column. The name of the table and column is derived from the call stack
// and the associated table commuter, if it exists, is called with the appropriate arguments.
//----------------------------------------------------------------------------------------------------------------------
Service CalculateColumn()
Response = ''
ColumnName = ''
TableName = ''
RetStack = RetStack()
For Each Item in RetStack using @FM
If Index(Item, 'DICT.MFS', 1) then
ColumnName = Item[2, \00\, 1]
CharPos = BCol2() + 1
TableHandle = Item[CharPos, GetByteSize(Item), 1]
Locate TableHandle<1, 2> in @TABLES(TAB_HANDLE$) using @FM setting fPos then
TableName = @TABLES(0)<fPos> ; // This technically returns the dictionary, but DICT. will be removed.
TableName[1, 5] = ''
end
end
Until (ColumnName NE '') OR (Item EQ '')
Next Item
If TableName NE '' then
TableCommuter = Database_Services('GetTableCommuter', TableName)
If TableCommuter NE '' then
Response = Function(@TableCommuter('CalculateColumn', ColumnName))
end
end
end service
//----------------------------------------------------------------------------------------------------------------------
// ClearTableHandle
//
// TableName. The linear hash database table name. - [REQUIRED]
//
// Clears the table handle array array from cache. This will force the GetTableHandle service to call the Open statement
// again.
//----------------------------------------------------------------------------------------------------------------------
Service ClearTableHandle(TableName)
If TableName NE '' then
ServiceKeyID = ServiceModule : '*GetTableHandle'
ServiceKeyID := '*' : TableName
Memory_Services('SetValue', ServiceKeyID, '')
end else
Error_Services('Add', 'TableName was missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// DeleteDataRow
//
// TableName. The linear hash database table name. - [REQUIRED]
// KeyID. The KeyID to the database table. - [REQUIRED]
//
// Deletes a data row for the indicated Key ID and database table.
//----------------------------------------------------------------------------------------------------------------------
Service DeleteDataRow(TableName, KeyID, IgnoreSelfLock, IgnoreMFSRoutines)
If TableName NE '' AND KeyID NE '' then
If IgnoreSelfLock NE True$ then IgnoreSelfLock = False$
If IgnoreMFSRoutines NE True$ then IgnoreMFSRoutines = False$
HaveLock = Database_Services('GetKeyIDLock', TableName, KeyID, IgnoreSelfLock)
If HaveLock EQ True$ then
TableHandle = Database_Services('GetTableHandle', TableName)
If IgnoreMFSRoutines then
MFSList = TableHandle<1, 1> ; // MFS routines are @SVM delimited.
NumMFS = DCount(MFSList, @SVM)
For MFSCnt = NumMFS to 1 Step -1
MFSRoutine = MFSList<0, 0, MFSCnt>
If (MFSRoutine NE 'SI.MFS') AND (MFSRoutine NE 'RTP57') then
MFSList = Delete(MFSList, 0, 0, MFSCnt)
end
Next MFSCnt
TableHandle<1, 1> = MFSList
end
// [SRPFW-195] Updated / Added by GAC 18 May 2018
If Error_Services('NoError') then
Delete TableHandle, KeyID then
Memory_Services('SetValue', ServiceModule : '*' : 'ReadDatarow' : '*' : TableName : '*' : KeyID, '')
end else
Error_Services('Add', 'Error deleting ' : KeyID : ' from the ' : TableName : ' table in the ' : Service : ' service. Error = ' : @File_Error<1>)
end
end
* If Error_Services('NoError') then
Database_Services('ReleaseKeyIDLock', TableName, KeyID)
* end
end else
Error_Services('Add', 'Unable to lock ' : KeyID : ' for the ' : TableName : ' table in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetKeyIDLock
//
// Attempts to perform a semaphore lock on the indicated tablename and Key ID.
//----------------------------------------------------------------------------------------------------------------------
Service GetKeyIDLock(TableName, KeyID, IgnoreSelfLock)
HaveLock = False$ ; // Assume false for now.
If TableName NE '' AND KeyID NE '' then
If IgnoreSelfLock NE True$ then IgnoreSelfLock = False$
TableHandle = Database_Services('GetTableHandle', TableName)
If Error_Services('NoError') then
Lock Tablehandle, KeyID then
HaveLock = True$
end else
If IgnoreSelfLock EQ True$ then
Status = Status()
If Status EQ 1 then
HaveLock = True$
end
end
end
end
end else
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
end
Response = HaveLock
end service
//----------------------------------------------------------------------------------------------------------------------
// GetTableCommuter
//
// Returns the name of the indicated table's commuter module if it exists. If it does not exist then an empty string
// will be returned.
//----------------------------------------------------------------------------------------------------------------------
Service GetTableCommuter(TableName)
ServiceKeyID := '*' : TableName
TableCommuter = Memory_Services('GetValue', ServiceKeyID)
If TableCommuter EQ '' then
ObjExists = False$ ; // Assume the object code for the action handler does not exist for now.
For Each AppID in @AppId
If AppID _EQC 'SYSPROG' then
SysObjKey = '$' : TableName : '_ACTIONS'
end else
SysObjKey = '$' : TableName : '_ACTIONS' : '*' : AppID
end
ObjExists = Memory_Services('KeyExists', SysObjKey)
Until ObjExists
Next AppID
If Not(ObjExists) then
For Each AppID in @AppId
If AppID _EQC 'SYSPROG' then
SysObjKey = '$' : TableName : '_ACTIONS'
end else
SysObjKey = '$' : TableName : '_ACTIONS' : '*' : AppID
end
OrigFileError = @FILE.ERROR
@FILE.ERROR = ''
BFS = 'RTP57'
// The handle to SYSOBJ is used to find object code before it gets called
ActionStatus = ''
Call @BFS(2, BFS, @FILE_SYSOBJ<1, 2>, SysObjKey, FMC, SysObjRecord, ActionStatus)
@FILE.ERROR = OrigFileError
If ActionStatus then ObjExists = True$
Until ObjExists
Next AppID
end
If (ObjExists) then
TableCommuter = TableName : '_ACTIONS'
Memory_Services('SetValue', ServiceKeyID, TableCommuter)
end
end
Response = TableCommuter
end service
//----------------------------------------------------------------------------------------------------------------------
// GetTableHandle
//
// TableName. The linear hash database table name. - [REQUIRED]
//
// Returns an array of information related to the database table being passed in.
//----------------------------------------------------------------------------------------------------------------------
Service GetTableHandle(TableName)
TableHandle = ''
If TableName NE '' then
ServiceKeyID := '*' : TableName
Locate TableName in @Tables(tab_name$) using @FM setting fPos then
If @Tables(tab_handle$)<fPos> NE '' then
// Only check for a cached handle if the table and its handle is still in @TABLES. Otherwise the handle is
// probably stale and will hang OI when utilized.
TableHandle = Memory_Services('GetValue', ServiceKeyID)
end
end
If TableHandle EQ '' then
rv = Set_Status(0)
Open TableName to TableHandle then
Memory_Services('SetValue', ServiceKeyID, TableHandle)
end else
Error_Services('Add', 'Unable to open the ' : TableName : ' table in the ' : Service : ' service. Error = ' : @File_Error<1>)
end
end
end else
Error_Services('Add', 'TableName was missing in the ' : Service : ' service.')
end
Response = TableHandle
end service
//----------------------------------------------------------------------------------------------------------------------
// GetTableNames
//
// ApplicationTablesOnly - Boolean flag to determine if only application database tables should be returned (i.e.,
// exclude SYSTEM and non-RTP57 tables). Default is True.
// ExcludeDictionaries - Boolean flag to determine if dictionary tables should be excluded. Default is False.
// ExcludeIndexes - Boolean flag to determine if index tables should be excluded. Default is False.
//
// Returns an @FM list of currently attached OpenInsight database tables.
//----------------------------------------------------------------------------------------------------------------------
Service GetTableNames(ApplicationTablesOnly=BOOLEAN, ExcludeDictionaries=BOOLEAN, ExcludeIndexes=BOOLEAN)
TableNames = '' ; // Initialize the return variable.
If ApplicationTablesOnly NE False$ then ApplicationTablesOnly = True$
If ExcludeDictionaries NE True$ then ExcludeDictionaries = False$
If ExcludeIndexes NE True$ then ExcludeIndexes = False$
TableNames = @Tables(tab_name$)
TableTypes = @Tables(tab_vol_name$)
If ApplicationTablesOnly EQ True$ then
Tables = ''
For Each TableType in TableTypes using @FM setting fPos
TableName = TableNames<fPos>
If (TableType[1, 'F*'] EQ 'RTP57') AND Not(TableType EQ 'RTP57*REVBOOT') AND Not(TableType EQ 'RTP57*O4WFILES') AND Not(TableType EQ 'RTP57*AREV_DIR') then
Tables := TableName : @FM
end
Next TableType
Tables[-1, 1] = ''
Transfer Tables to TableNames
end
If ExcludeDictionaries EQ True$ then
Tables = ''
For Each TableName in TableNames using @FM
If TableName[1, 5] NE 'DICT.' then
Tables := TableName : @FM
end
Next TableType
Tables[-1, 1] = ''
Transfer Tables to TableNames
end
If ExcludeIndexes EQ True$ then
Tables = ''
For Each TableName in TableNames using @FM
If TableName[1, 1] NE '!' then
Tables := TableName : @FM
end
Next TableType
Tables[-1, 1] = ''
Transfer Tables to TableNames
end
TableNames = SRP_Array('SortRows', TableNames, 'AL1', 'LIST', @FM, @VM)
Response = TableNames
end service
//----------------------------------------------------------------------------------------------------------------------
// GetTableProperties
//
// TableName. The linear hash database table name. - [REQUIRED]
//
// Returns an array of information related to the database table being passed in.
//----------------------------------------------------------------------------------------------------------------------
Service GetTableProperties(TableName)
TableProperties = ''
If TableName NE '' then
rv = Set_Status(0)
Locate TableName in @TABLES(tab_name$) using @FM setting fPos then
TableProperties<1> = @TABLES(tab_account$)<fPos> ; // DatabaseID
TableProperties<2> = @TABLES(tab_file_sys$)<fPos> ; // MFS/BFS List
VolumeID = @TABLES(tab_vol_name$)<fPos> ; // Volume ID
Locate VolumeID in @VOLUMES(vol_name$) using @FM setting fPos then
TableProperties<3> = @VOLUMES(vol_label$)<fPos> ; // Volume Label
TableProperties<4> = @VOLUMES(vol_location$)<fPos> ; // Volume Path
TableProperties<5> = @VOLUMES(vol_file_sys$)<fPos> ; // BFS
end
end else
Error_Services('Add', 'The ' : TableName : ' table is not attached and available to the ' : Service : ' service.')
end
end else
Error_Services('Add', 'TableName argument was missing in the ' : Service : ' service.')
end
Response = TableProperties
end service
//----------------------------------------------------------------------------------------------------------------------
// GetUserLocks
//
// Returns a dynamic array of user lock information. Note, this can only be done with the UD 5. This can also cause
// instability with the current session and may require the Task Manager to close the session.
//----------------------------------------------------------------------------------------------------------------------
Service GetUserLocks()
UserLocks = RTI_LH_Info(CMD_LOCKS_INFO$, '')
Response = UserLocks
end service
//----------------------------------------------------------------------------------------------------------------------
// IsKeyIDLocked
//
// Returns a Boolean flag of the lock status for the indicated table and Key ID.
//----------------------------------------------------------------------------------------------------------------------
Service IsKeyIDLocked(TableName, KeyID, IgnoreSelfLock=BOOLEAN)
If IgnoreSelfLock NE True$ then IgnoreSelfLock = False$
KeyIDLocked = False$ ; // Assume false for now.
If (TableName NE '') AND (KeyID NE '') then
Open TableName to hTable then
Lock hTable, KeyID then
// Able to lock Key ID. Unlock it right away.
Unlock hTable, KeyID else Null
end else
// Unable to lock Key ID. Evaluate the type of lock.
LockType = Status()
If LockType EQ 0 then
// Lock exists on another station.
KeyIDLocked = True$
end else
// Lock exists on this station. Check to see if the Ignore Self Lock flag is set.
If Not(IgnoreSelfLock) then KeyIDLocked = True$
end
end
end else
Error_Services('Add', 'Error opening the ' : TableName : ' table in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
end
Response = KeyIDLocked
end service
//----------------------------------------------------------------------------------------------------------------------
// IsKeyIDSelfLocked
//
// Returns a Boolean flag of the self-lock status for the indicated table and Key ID.
//----------------------------------------------------------------------------------------------------------------------
Service IsKeyIDSelfLocked(TableName, KeyID)
KeyIDSelfLocked = False$ ; // Assume false for now.
If (TableName NE '') AND (KeyID NE '') then
Open TableName to hTable then
Lock hTable, KeyID then
// Able to lock Key ID. Unlock it right away.
Unlock hTable, KeyID else Null
end else
// Unable to lock Key ID. Evaluate the type of lock.
LockType = Status()
If LockType EQ 1 then
// This Key ID is self-locked.
KeyIDSelfLocked = True$
end
end
end else
Error_Services('Add', 'Error opening the ' : TableName : ' table in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
end
Response = KeyIDSelfLocked
end service
//----------------------------------------------------------------------------------------------------------------------
// ReadDataColumn
//
// TableName. The linear hash database table name. - [REQUIRED]
// KeyID. The KeyID to the database table. - [REQUIRED]
// ColumnNo. The index of the column that is to be read. - [REQUIRED]
//
// Reads a data column for the indicated Key ID and database table.
//----------------------------------------------------------------------------------------------------------------------
Service ReadDataColumn(TableName, KeyID, ColumnNo, NotExpired, ExpirationDuration, IgnoreMFSRoutines)
If NotExpired NE False$ then NotExpired = True$
If (ExpirationDuration EQ '') OR (Not(Num(ExpirationDuration))) then ExpirationDuration = 0
If IgnoreMFSRoutines NE True$ then IgnoreMFSRoutines = False$
ServiceKeyID := '*' : TableName : '*' : KeyID : '*' : ColumnNo
DataColumn = Memory_Services('GetValue', ServiceKeyID, NotExpired, ExpirationDuration)
If Num(ColumnNo) AND (ColumnNo GT 0) then
If TableName NE '' AND KeyID NE '' then
If DataColumn EQ '' then
TableHandle = Database_Services('GetTableHandle', TableName)
If Error_Services('NoError') then
If IgnoreMFSRoutines then
MFSList = TableHandle<1, 1> ; // MFS routines are @SVM delimited.
NumMFS = DCount(MFSList, @SVM)
For MFSCnt = NumMFS to 1 Step -1
MFSRoutine = MFSList<0, 0, MFSCnt>
If MFSRoutine NE 'RTP57' then
MFSList = Delete(MFSList, 0, 0, MFSCnt)
end
Next MFSCnt
TableHandle<1, 1> = MFSList
end
ReadV DataColumn from TableHandle, KeyID, ColumnNo then
Memory_Services('SetValue', ServiceKeyID, DataColumn)
end else
ErrorMsg = 'Error reading ' : KeyID : ' column number ' : ColumnNo : ' from the ' |
: TableName : ' table in the ' : Service : ' service.'
Error_Services('Add', ErrorMsg)
end
end
end
end else
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'ColumnNo was not a number or was not greater than zero in the ' : Service : ' service.')
end
Response = DataColumn
end service
//----------------------------------------------------------------------------------------------------------------------
// ReadDataRow
//
// TableName - The linear hash database table name. - [REQUIRED]
// KeyID - The KeyID to the database table. - [REQUIRED]
//
// Reads a data row for the indicated Key ID and database table.
//----------------------------------------------------------------------------------------------------------------------
Service ReadDataRow(TableName, KeyID, NotExpired, ExpirationDuration, IgnoreMFSRoutines)
If NotExpired NE False$ then NotExpired = True$
If (ExpirationDuration EQ '') OR (Not(Num(ExpirationDuration))) then ExpirationDuration = 0
If IgnoreMFSRoutines NE True$ then IgnoreMFSRoutines = False$
ServiceKeyID := '*' : TableName : '*' : KeyID
DataRow = Memory_Services('GetValue', ServiceKeyID, NotExpired, ExpirationDuration)
If TableName NE '' AND KeyID NE '' then
If DataRow EQ '' then
TableHandle = Database_Services('GetTableHandle', TableName)
If Error_Services('NoError') then
If IgnoreMFSRoutines then
MFSList = TableHandle<1, 1> ; // MFS routines are @SVM delimited.
NumMFS = DCount(MFSList, @SVM)
For MFSCnt = NumMFS to 1 Step -1
MFSRoutine = MFSList<0, 0, MFSCnt>
If MFSRoutine NE 'RTP57' then
MFSList = Delete(MFSList, 0, 0, MFSCnt)
end
Next MFSCnt
TableHandle<1, 1> = MFSList
end
// [SRPFW-195]
Read DataRow from TableHandle, KeyID then
Memory_Services('SetValue', ServiceKeyID, DataRow)
end else
Error_Services('Add', 'Error reading ' : KeyID : ' from the ' : TableName : ' table in the ' : Service : ' service. Error = ' : @File_Error<1>)
end
end
end
end else
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
end
Response = DataRow
end service
//----------------------------------------------------------------------------------------------------------------------
// ReleaseKeyIDLock
//
// Attempts to release a semaphore lock on the indicated tablename and Key ID.
//----------------------------------------------------------------------------------------------------------------------
Service ReleaseKeyIDLock(TableName, KeyID)
LockReleased = False$ ; // Assume false for now.
If TableName NE '' AND KeyID NE '' then
TableHandle = Database_Services('GetTableHandle', TableName)
If Error_Services('NoError') then
UnLock Tablehandle, KeyID then
LockReleased = True$
end else
Error_Services('Add', 'Unable to unlock the ' : KeyID : ' Key ID from the ' : TableName : ' table in the ' : Service : ' service. Error = ' : @File_Error<1>)
end
end
end else
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
end
Response = LockReleased
end service
//----------------------------------------------------------------------------------------------------------------------
// SearchIndex
//
// TableName. The linear hash database table name. - [REQUIRED]
// ColumnName. The indexed column to search against. - [REQUIRED]
// SearchValue. The value being searched for. - [REQUIRED]
// UpdateIndex. Boolean flag to determine if the index for the indicated column should be updated before searching.
// - [OPTIONAL]
//
// Returns an @FM delimited list of Key IDs that match the search value.
//----------------------------------------------------------------------------------------------------------------------
Service SearchIndex(TableName, ColumnName, SearchValue, UpdateIndex)
If UpdateIndex NE True$ then UpdateIndex = False$
ServiceKeyID := '*' : TableName : '*' : ColumnName : '*' : SearchValue
ServiceKeyID = SRP_Encode(ServiceKeyID, 'BASE64')
* KeyIDList = Memory_Services('GetValue', ServiceKeyID, True$, 5)
KeyIDList = ''
If TableName NE '' AND ColumnName NE '' AND SearchValue NE '' then
If KeyIDList EQ '' then
DictTableHandle = Database_Services('GetTableHandle', 'DICT.' : TableName)
If Error_Services('NoError') then
Set_Status(0)
If UpdateIndex then Update_Index(TableName, ColumnName 0)
Set_Status(0)
Flag = ''
Btree.Extract(ColumnName : @VM : SearchValue : @FM, Tablename, DictTableHandle, KeyIDList, 'S', Flag)
If Flag EQ 0 then
Convert @VM to @FM in KeyIDList
Memory_Services('SetValue', ServiceKeyID, KeyIDList)
end else
Error_Services('Add', 'Error in Btree.Extract search from the ' : TableName : ' table in the ' : Service : ' service.')
end
end
end
end else
Error_Services('Add', 'TableName, ColumnName, or SearchValue argument was missing in the ' : Service : ' service.')
end
Response = KeyIDList
end service
//----------------------------------------------------------------------------------------------------------------------
// SetTableAlias
//
// TableName - The linear hash database table name. - [Required]
// AliasName - The alias name being set. - [Required]
// Volume - The location path or volume name where the table exists. - [Required]
// DatabaseID - Database ID of the table being aliased. Defaults to the current Database ID (@DBID) - [Optional]
//
// Attempts to create an alias for the indicated table, volume, and database. It returns a True$ if successful or a
// False$ if unsuccessful.
//----------------------------------------------------------------------------------------------------------------------
Service SetTableAlias(TableName, AliasName, Volume, DatabaseID)
Success = False$ ; // Assume not successful for now.
If (TableName NE '') AND (AliasName NE '') AND (Volume NE '') then
Set_Status(0)
If DatabaseID EQ '' then DatabaseID = @DBID
Push.Select(F1, F2, F3, F4) ; // Protect cursors in case Alias_Table fails.
Alias_Table(Volume : '', DatabaseID : '', TableName : '', AliasName : '')
Pop.Select(F1, F2, F3, F4) ; // Restore cursors.
StatusCode = ''
If Get_Status(StatusCode) then
Error_Services('Add', 'Error calling the Alias_Table routine in the ' : Service : ' service. Status Code : ' : StatusCode)
end else
// Setting an alias could changes the handle so clear the cached handle to avoid it being stale.
Success = True$
Database_Services('ClearTableHandle', AliasName)
end
Set_Status(0)
end else
Error_Services('Add', 'TableName, AliasName, or Volume argument was missing in the ' : Service : ' service.')
end
Response = Success
end service
//----------------------------------------------------------------------------------------------------------------------
// UnlockKeyID
//
// Attempts to unlock the indicated Key ID from the indicated Table Name. Note, this can only be done with the UD 5.
//----------------------------------------------------------------------------------------------------------------------
* Service UnlockKeyID(TableName, KeyID)
*
* KeyIDUnlocked = False$ ; // Assume false for now.
*
* Convert @Lower_Case to @Upper_Case in TableName
*
* If (TableName NE '') AND (KeyID NE '') then
* // First, do a sanity check to confirm that there is a lock on this Key ID.
* IsKeyIDLocked = Database_Services('IsKeyIDLocked', TableName, KeyID, False$)
* If Error_Services('NoError') AND (IsKeyIDLocked EQ False$) then
* // Key ID was not locked.
* KeyIDUnlocked = True$
* end
* If KeyIDUnlocked NE True$ then
* // Key ID is still presumed to be locked.
* VolumePath = ''
* FileName = ''
*
* // Resolve the volume path for this table.
* hTableFull = Database_Services('ReadDataRow', 'SYSTABLES', TableName)
* VolumeName = hTableFull<1>
* VolumeRow = Database_Services('ReadDataRow', 'SYSVOLUMES', VolumeName)
* VolumePath = VolumeRow[-1, 'B' : @FM]
* VolumePath = VolumePath[-1, 'B' : \0D\]
* VolumePath[1, 12] = '' ; // Strip off the preceding bytes.
* If SRP_Path('IsRelative', VolumePath) then
* VolumePath = SRP_Path('Combine', Drive(), VolumePath)
* end
* VolumePath = SRP_Path('RemoveFilename', VolumePath)
* // Make sure there is a backslash since the RTI_LH_INFO API seems to use this.
* VolumePath = SRP_Path('AddBackslash', VolumePath)
*
* // Resolve the filename for this table.
* hTableFull = Database_Services('ReadDataRow', 'SYSTABLES', TableName)
* FileName = hTableFull[-1, 'B' : @FM]
* FileName = FileName[-1, 'B' : \0D\]
* FileName = FileName[1, @VM]
* If FileName _NEC 'SYSREPOS' then FileName[1, 12] = '' ; // Strip off the preceding bytes.
* FileName = FileName[-1, 'B' : '\']
* // Make sure the filename is well formed.
* Begin Case
* Case (FileName[-3, 3] _EQC '.LK') OR (FileName[-3, 3] _EQC '.OV')
* FileName[-3, 3] = ''
* Case FileName _EQC 'SYSREPOS'
* FileName = 'REVREPOS'
* End Case
*
* If (VolumePath NE '') AND (FileName) NE '' then
* // Attempt to unlocked the Key ID.
* RTI_LH_Info(CMD_UNLOCK$, VolumePath, FileName, KeyID, FileName)
* // Confirm that the Key ID was unlocked.
* IsKeyIDLocked = Database_Services('IsKeyIDLocked', TableName, KeyID, False$)
* If Error_Services('NoError') AND (IsKeyIDLocked EQ False$) then
* // Key ID was not locked.
* KeyIDUnlocked = True$
* end else
* // Unable to unlock the Key ID which could be because it is locked by this station. Try using the
* // Unlock statement.
* hTable = Database_Services('GetTableHandle', TableName)
* Unlock hTable, KeyID then
* KeyIDUnlocked = True$
* end else
* Error_Services('Add', 'Unable to unlock ' : KeyID : ' from the ' : TableName : ' table in the ' : Service : ' service.')
* end
* end
* end else
* Error_Services('Add', 'No valid VolumePath or FileName was available in the ' : Service : ' service.')
* end
* end
* end else
* Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
* end
*
* Response = KeyIDUnlocked
*
* end service
//----------------------------------------------------------------------------------------------------------------------
// VerifyLH
//
// TableNames. One or more linear hash database tables to verify. List should be @FM delimited. - [OPTIONAL]
// SaveList. Name of a saved selection of linear hash database tables to verify. This argument will be ignored
// if TableNames is populated. - [OPTIONAL]
//
// Performs a health check against the indicated tables and returns back any issues. Note: This uses the Verify_LH
// subroutine to check for GFEs. All results are stored in the SYSLHVERIFY table with a KeyID of
// VolumeLabel*DatabaseID*TableName. Returns the list of groups that have GFEs or returns an empty string if there are
// none. The list of GFEs or empty strings will themselves be @FM delimited to correspond with the tables passed into
// this service.
//----------------------------------------------------------------------------------------------------------------------
Service VerifyLH(Tablenames, SaveList)
VerifyResults = ''
If TableNames EQ '' then
TableNames = Xlate('SYSLISTS', SaveList, '', 'X')
If Index(TableNames<1>, @TM, 1) then
// This saved select has metadata in attribute 1. Remove it.
TableNames = Delete(TableNames, 1, 0, 0)
end
end
If TableNames NE '' then
NumTables = DCount(TableNames, @FM)
For TableCnt = 1 to NumTables
TableName = TableNames<TableCnt>
TableProperties = Database_Services('GetTableProperties', TableName)
If Error_Services('NoError') then
rv = Set_Status(0)
Verify_LH('', TableName, True$, False$, False$)
Open 'SYSLHVERIFY' to hSysLHVerify then
DatabaseID = TableProperties<1>
VolumeLabel = TableProperties<3>
LHVerifyKeyID = VolumeLabel : '*' : DatabaseID : '*' : TableName
Read LHVerifyRec from hSysLHVerify, LHVerifyKeyID then
VerifyResults<TableCnt> = LHVerifyRec<2>
end
end else
Error_Services('Add', 'Error opening the SYSLHVERIFY table in the ' : Service : ' service.')
end
Begin Case
Case @File_Error NE ''
Error_Services('Add', 'Error verifying table ' : TableName : ': FS Error = ' : @File_Error<1>)
Case Get_Status()
Error_Services('Add', 'Get_Status error: ' : Get_Status())
End Case
end
Next TableCnt
end else
Error_Services('Add', 'The TableName argument was missing in the ' : Service : ' service.')
end
Response = VerifyResults
end service
//----------------------------------------------------------------------------------------------------------------------
// VerifyLHAll
//
// Performs a health check against all attached tables and returns back any issues. Returns two lists which are
// delimited by an @RM. The first list is an @FM list of attached tables. The second list is an @FM list of results
// (groups that have GFEs or an empty string if there are none). Items in each list correspond which each other based on
// their list position.
//----------------------------------------------------------------------------------------------------------------------
Service VerifyLHAll()
VerifyResults = ''
TableNames = @TABLES(0)
NumTables = DCount(TableNames, @FM)
For TableCnt = 1 to NumTables
TableName = TableNames<TableCnt>
VerifyResults := Database_Services('VerifyLH', TableName) : @FM
Next TableCnt
VerifyResults[-1, 1] = '' ; // Strip off the last @FM
Response = TableNames : @RM : VerifyResults
end service
//----------------------------------------------------------------------------------------------------------------------
// WriteDataRow
//
// TableName. The linear hash database table name. - [REQUIRED]
// KeyID. The KeyID to the database table. - [REQUIRED]
//
// Writes a data row for the indicated Key ID and database table.
//----------------------------------------------------------------------------------------------------------------------
Service WriteDataRow(TableName, KeyID, DataRow, IgnoreSelfLock, IgnoreMFSRoutines, IgnoreAllLocks)
If TableName NE '' AND KeyID NE '' then
If IgnoreSelfLock NE True$ then IgnoreSelfLock = False$
If IgnoreMFSRoutines NE True$ then IgnoreMFSRoutines = False$
If IgnoreAllLocks NE True$ then IgnoreAllLocks = False$
If IgnoreAllLocks then
HaveLock = True$
end else
HaveLock = Database_Services('GetKeyIDLock', TableName, KeyID, IgnoreSelfLock)
end
If HaveLock EQ True$ then
TableHandle = Database_Services('GetTableHandle', TableName)
If IgnoreMFSRoutines then
MFSList = TableHandle<1, 1> ; // MFS routines are @SVM delimited.
NumMFS = DCount(MFSList, @SVM)
For MFSCnt = NumMFS to 1 Step -1
MFSRoutine = MFSList<0, 0, MFSCnt>
If (MFSRoutine NE 'SI.MFS') AND (MFSRoutine NE 'RTP57') then
MFSList = Delete(MFSList, 0, 0, MFSCnt)
end
Next MFSCnt
TableHandle<1, 1> = MFSList
end
// [SRPFW-195] Updated / added by GAC 18 May 2018
If Error_Services('NoError') then
Write DataRow to TableHandle, KeyID then
Memory_Services('SetValue', ServiceModule : '*' : 'ReadDatarow' : '*' : TableName : '*' : KeyID, DataRow)
end else
ErrorMsg = Error_Services('GetMessage')
Error_Services('Add', 'Error writing ' : KeyID : ' to the ' : TableName : ' table in the ' : Service : ' service. Error message: ':ErrorMsg)
end
end
* If Error_Services('NoError') then
If IgnoreAllLocks EQ False$ then
Database_Services('ReleaseKeyIDLock', TableName, KeyID)
end
* end
end else
Error_Services('Add', 'Unable to lock ' : KeyID : ' for the ' : TableName : ' table in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// UnlockKeyID
//
// Attempts to unlock the indicated Key ID from the indicated Table Name. Note, this can only be done with the UD 5.
//----------------------------------------------------------------------------------------------------------------------
Service UnlockKeyID(TableName, KeyID)
KeyIDUnlocked = False$ ; // Assume false for now.
Convert @Lower_Case to @Upper_Case in TableName
If (TableName NE '') AND (KeyID NE '') then
// First, do a sanity check to confirm that there is a lock on this Key ID.
IsKeyIDLocked = Database_Services('IsKeyIDLocked', TableName, KeyID, False$)
If Error_Services('NoError') AND (IsKeyIDLocked EQ False$) then
// Key ID was not locked.
KeyIDUnlocked = True$
end
If KeyIDUnlocked NE True$ then
// Key ID is still presumed to be locked.
VolumePath = ''
FileName = ''
// Resolve the volume path for this table.
hTableFull = Database_Services('ReadDataRow', 'SYSTABLES', TableName)
VolumeName = hTableFull<1>
VolumeRow = Database_Services('ReadDataRow', 'SYSVOLUMES', VolumeName)
VolumePath = VolumeRow[-1, 'B' : @FM]
VolumePath = VolumePath[-1, 'B' : \0D\]
VolumePath[1, 12] = '' ; // Strip off the preceding bytes.
If SRP_Path('IsRelative', VolumePath) then
VolumePath = SRP_Path('Combine', Drive(), VolumePath)
end
VolumePath = SRP_Path('RemoveFilename', VolumePath)
// Make sure there is a backslash since the RTI_LH_INFO API seems to use this.
VolumePath = SRP_Path('AddBackslash', VolumePath)
// Resolve the filename for this table.
hTableFull = Database_Services('ReadDataRow', 'SYSTABLES', TableName)
FileName = hTableFull[-1, 'B' : @FM]
FileName = FileName[-1, 'B' : \0D\]
FileName = FileName[1, @VM]
If FileName _NEC 'SYSREPOS' then FileName[1, 12] = '' ; // Strip off the preceding bytes.
FileName = FileName[-1, 'B' : '\']
// Make sure the filename is well formed.
Begin Case
Case (FileName[-3, 3] _EQC '.LK') OR (FileName[-3, 3] _EQC '.OV')
FileName[-3, 3] = ''
Case FileName _EQC 'SYSREPOS'
FileName = 'REVREPOS'
End Case
If (VolumePath NE '') AND (FileName) NE '' then
// Attempt to unlocked the Key ID.
RTI_LH_Info(CMD_UNLOCK$, VolumePath, FileName, KeyID, FileName)
// Confirm that the Key ID was unlocked.
IsKeyIDLocked = Database_Services('IsKeyIDLocked', TableName, KeyID, False$)
If Error_Services('NoError') AND (IsKeyIDLocked EQ False$) then
// Key ID was not locked.
KeyIDUnlocked = True$
end else
// Unable to unlock the Key ID which could be because it is locked by this station. Try using the
// Unlock statement.
hTable = Database_Services('GetTableHandle', TableName)
Unlock hTable, KeyID then
KeyIDUnlocked = True$
end else
Error_Services('Add', 'Unable to unlock ' : KeyID : ' from the ' : TableName : ' table in the ' : Service : ' service.')
end
end
end else
Error_Services('Add', 'No valid VolumePath or FileName was available in the ' : Service : ' service.')
end
end
end else
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
end
Response = KeyIDUnlocked
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////