Exported recoverable storage management procedures
DSInitialize:
PUBLIC
PROC [dsPort: portT, raiseSignal:
BOOL]
RETURNS [serverID: serverIdT, tsPort, mPort, sPort: portT, sharedMemAddr: vmAddressT, seqDescList: ListOfSegmentDesc ← NIL, seqPortList: ListOfPorts, kernCode: Mach.kernReturnT ← -1] ~
TRUSTED {
Initialize the data server.
innerDSInitialize:
PROC [idsPort: portT, iserverID:
POINTER
TO serverIdT, itsPort, imPort, isPort:
POINTER
TO portT, isharedMemAddr:
POINTER
TO vmAddressT, iseqDescList:
POINTER
TO segmentDescListT, isegDescListCnt:
POINTER
TO INT, iseqPortList:
POINTER
TO portArrayT, isegPortListCnt:
POINTER
TO INT]
RETURNS [kernReturnT]~
TRUSTED
MACHINE
CODE {
"<ds.h>.DS←Initialize"
};
ZsegDescList, DsegDescList: segmentDescListT ← NIL;
ZsegDescListCnt: INT ← -1;
ZsegPortList, DsegPortList: portArrayT ← NIL;
ZsegPortListCnt: INT ← -1;
initCode: INT ← SendErrorsStart;
initCode ← innerDSInitialize[dsPort, @serverID, @tsPort, @mPort, @sPort, @sharedMemAddr, @ZsegDescList, @ZsegDescListCnt, @ZsegPortList, @ZsegPortListCnt];
IF raiseSignal AND initCode # KernSuccess THEN SIGNAL MachCall[initCode, Rope.Cat["DS←Initialize failed; code = ", IO.PutFR1["%g", IO.int[initCode]]]];
IF ZsegDescListCnt # ZsegPortListCnt AND raiseSignal THEN SIGNAL MachCall[-1, IO.PutFR["DS←Initialize failed; different number of segments and ports = %g segments and %g ports", IO.int[ZsegDescListCnt], IO.int[ZsegPortListCnt]]];
IF ZsegDescListCnt > 0
THEN
TRUSTED {
newItem:
PROC
RETURNS [lsd: ListOfSegmentDesc] ~
TRUSTED {
lsd ← LIST[[ZsegDescList.serverId, ZsegDescList.segmentId, ZsegDescList.logicalDisk, ZsegDescList.unused, ZsegDescList.highSize, ZsegDescList.lowSize]];
ZsegDescList ← ZsegDescList + UNITS[segmentDescT];
};
DsegDescList ← ZsegDescList;
seqDescList ← newItem[];
IF ZsegDescListCnt > 1
THEN {
lastItem: ListOfSegmentDesc ← seqDescList;
FOR item:
INT
IN [1..ZsegDescListCnt)
DO
lastItem.rest ← newItem[];
lastItem ← lastItem.rest;
ENDLOOP;
};
[] ← vmDeallocate[targetTask: taskSelf[], address: LOOPHOLE[DsegDescList], size: BYTES[segmentDescT]*ZsegDescListCnt, raiseSignal: TRUE];
};
IF ZsegPortListCnt > 0
THEN
TRUSTED {
newPort:
PROC
RETURNS [lp: ListOfPorts] ~
TRUSTED {
lp ← LIST[[ZsegPortList.portNumber]];
ZsegPortList ← ZsegPortList + UNITS[portT];
};
DsegPortList ← ZsegPortList;
seqPortList ← newPort[];
IF ZsegPortListCnt > 1
THEN {
lastPort: ListOfPorts ← seqPortList;
FOR item:
INT
IN [1..ZsegPortListCnt)
DO
lastPort.rest ← newPort[];
lastPort ← lastPort.rest;
ENDLOOP;
};
[] ← vmDeallocate[targetTask: taskSelf[], address: LOOPHOLE[DsegPortList], size: BYTES[portT]*ZsegPortListCnt, raiseSignal: TRUE];
};
};
DSPinObject:
PUBLIC
PROC [dsPort: portT, tid: tidT, optr: optrT, size: uInt, raiseSignal:
BOOL]
RETURNS [kernCode: Mach.kernReturnT ← -1] ~ {
Pin an object in preparation for modification.
innerDSPinObject:
PROC [idsPort: portT, itid: tidT, ioptr: optrT, isize: uInt]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<ds.h>.DS←PinObject"
};
pinCode: INT ← -1;
pinCode ← innerDSPinObject[dsPort, tid, optr, size];
IF raiseSignal AND pinCode # KernSuccess THEN SIGNAL MachCall[pinCode, Rope.Cat["DS←PinObject failed; code = ", IO.PutFR1["%g", IO.int[pinCode]]]];
RETURN[pinCode];
};
DSLogNewValue:
PUBLIC
PROC [dsPort: portT, tid: tidT, optr: optrT, newValue: pointerT, newValueCnt:
INT, raiseSignal:
BOOL]
RETURNS [kernCode: Mach.kernReturnT ← -1] ~ {
Send a new value of an object to the log.
innerDSLogNewValue:
PROC [idsPort: portT, itid: tidT, ioptr: optrT, inewValue: pointerT, inewValueCnt:
INT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<ds.h>.DS←LogNewValue"
};
logCode: INT ← -1;
logCode ← innerDSLogNewValue[dsPort, tid, optr, newValue, newValueCnt];
IF raiseSignal AND logCode # KernSuccess THEN SIGNAL MachCall[logCode, Rope.Cat["DS←LogNewValue failed; code = ", IO.PutFR1["%g", IO.int[logCode]]]];
RETURN[logCode];
};
DSLogOldValueNewValue:
PUBLIC
PROC [dsPort: portT, tid: tidT, optr: optrT, oldValue: pointerT, oldValueCnt: INT, newValue: pointerT, newValueCnt: INT, raiseSignal:
BOOL]
RETURNS [kernCode: Mach.kernReturnT ← -1] ~ {
Send a new value of an object to the log.
innerDSLogOldValueNewValue:
PROC [idsPort: portT, itid: tidT, ioptr: optrT, ioldValue: pointerT, ioldValueCnt: INT, inewValue: pointerT, inewValueCnt: INT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<ds.h>.DS←LogOldValueNewValue"
};
logCode: INT ← -1;
logCode ← innerDSLogOldValueNewValue[dsPort, tid, optr, oldValue, oldValueCnt, newValue, newValueCnt];
IF raiseSignal AND logCode # KernSuccess THEN SIGNAL MachCall[logCode, Rope.Cat["DS←LogOldValueNewValue failed; code = ", IO.PutFR1["%g", IO.int[logCode]]]];
RETURN[logCode];
};
DSPrepare:
PUBLIC
PROC [dsPort: portT, topBTid: btidT, prepareData: pointerT, prepareDataCnt:
INT, raiseSignal:
BOOL]
RETURNS [kernCode: Mach.kernReturnT ← -1] ~ {
Send a new value of an object to the log.
innerDSPrepare:
PROC [idsPort: portT, itopBTid: btidT, iprepareData: pointerT, iprepareDataCnt:
INT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<ds.h>.DS←Prepare"
};
prepareCode: INT ← -1;
prepareCode ← innerDSPrepare[dsPort, topBTid, prepareData, prepareDataCnt];
IF prepareCode # KernSuccess THEN SIGNAL MachCall[prepareCode, Rope.Cat["DS←Prepare failed; code = ", IO.PutFR1["%g", IO.int[prepareCode]]]];
RETURN[prepareCode];
};
DSQInit:
PUBLIC
PROC [sharedMemAddr: Mach.vmAddressT] ~ {
Send a new value of an object to the log.
innerDSQInit:
PROC [XsharedMemAddr: Mach.vmAddressT] ~
TRUSTED
MACHINE
CODE {
"<ds.h>.Dsq←Init"
};
innerDSQInit[sharedMemAddr];
};
DSQPreflush:
PUBLIC PROC [dsPort: Mach.portT, optr: optrT, sizeInBytes: uInt] ~ {
Preflush some dirty memory.
ERROR; -- preflush should only be used in SunOS emulation for now
};
Exported transaction management procedures
camelotStringTFromRope:
PROC [name: Rope.
ROPE]
RETURNS [camelotString:
REF camelotStringT] ~ {
oNSize: INT ← 0;
camelotString ← NEW[camelotStringT];
oNSize ← Rope.Length[name];
IF oNSize >= Camelot.CAMELOTSTRINGLENGTH THEN ERROR;
FOR index:
INT
IN [0..oNSize)
DO
camelotString[index] ← Rope.Fetch[name, index];
ENDLOOP;
camelotString[oNSize] ← 0C;
};
TAAddApplication:
PUBLIC PROC [tPort: portT, atPort: portT, authName: Rope.
ROPE, raiseSignal:
BOOL]
RETURNS [applicationID: applicationIdT, taPort: portT, kernCode: Mach.kernReturnT ← -1] ~
TRUSTED {
Initialize an application to the transaction manager.
innerTAAddApplication:
PROC [itPort: portT, iatPort: portT, iauthName: POINTER TO camelotStringT, iapplicationID:
POINTER
TO applicationIdT, itaPort:
POINTER
TO portT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<ta.h>.TApplication"
};
camString: REF camelotStringT;
camString ← camelotStringTFromRope[authName];
kernCode ← innerTAAddApplication[tPort, atPort, LOOPHOLE[camString], @applicationID, @taPort];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL MachCall[kernCode, Rope.Cat["TApplication failed; code = ", IO.PutFR1["%g", IO.int[kernCode]]]];
};
TABegin:
PUBLIC
PROC [taPort: portT, parentTid: tidT, transType: transactionTypeT, raiseSignal:
BOOL]
RETURNS [newTid: tidT, kernCode: Mach.kernReturnT ← -1] ~
TRUSTED {
Start a new transaction.
innerTABegin:
PROC [taPortInner: portT, parentTidInner: tidT, transTypeInner: transactionTypeT, newTidInner:
POINTER
TO tidT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<ta.h>.TAgin"
};
kernCode ← innerTABegin[taPort, parentTid, transType, @newTid];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL MachCall[kernCode, Rope.Cat["TAgin failed; code = ", IO.PutFR1["%g", IO.int[kernCode]]]];
};
TAEnd:
PUBLIC
PROC [taPort: portT, tid: tidT, protocolType: protocolTypeT, raiseSignal:
BOOL]
RETURNS [timestamp: timestampT, status:
INT, kernCode: Mach.kernReturnT ← -1] ~
TRUSTED {
Try to commit a transaction.
innerTAEnd:
PROC [taPortInner: portT, tidInner: tidT, protocolTypeInner: protocolTypeT, timestampInner:
POINTER
TO timestampT, statusInner:
POINTER
TO
INT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<ta.h>.TA𡤎nd"
};
kernCode ← innerTAEnd[taPort, tid, protocolType, @timestamp, @status];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL MachCall[kernCode, Rope.Cat["TA𡤎nd failed; code = ", IO.PutFR1["%g", IO.int[kernCode]]]];
};
TAKill:
PUBLIC PROC [taPort: portT, tid: tidT, status:
INT, raiseSignal:
BOOL]
RETURNS [kernCode: Mach.kernReturnT ← -1] ~
TRUSTED {
Try to abort a transaction.
innerTAKill:
PROC [taPortInner: portT, tidInner: tidT, statusInner:
INT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<ta.h>.TA←Kill"
};
kernCode ← innerTAKill[taPort, tid, status];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL MachCall[kernCode, Rope.Cat["TA←Kill failed; code = ", IO.PutFR1["%g", IO.int[kernCode]]]];
};
TSJoin:
PUBLIC
PROC [tsPort: portT, tid: tidT, raiseSignal:
BOOL]
RETURNS [kernCode: Mach.kernReturnT ← -1] ~ {
Join a server to a transaction.
innerTSJoin:
PROC [tsPortInner: portT, tidInner: tidT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<ts.h>.TS←Join"
};
kernCode ← innerTSJoin[tsPort, tid];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL MachCall[kernCode, Rope.Cat["TA←Join failed; code = ", IO.PutFR1["%g", IO.int[kernCode]]]];
};
TDAddDataServer:
PUBLIC PROC [tdPort: portT, serverID: serverIdT, sendPort: portT, raiseSignal:
BOOL]
RETURNS [rcvPort: portT, kernCode: Mach.kernReturnT ← -1] ~
TRUSTED {
Join a server to a transaction.
Initialize the data server to the transaction manager.
innerTDAddDataServer:
PROC [itdPort: portT, iserverID: serverIdT, isendPort: portT, ircvPort:
POINTER
TO portT]
RETURNS [kernReturnT]~
TRUSTED
MACHINE
CODE {
"<td.h>.TDtaServer"
};
kernCode ← innerTDAddDataServer[tdPort, serverID, sendPort, @rcvPort];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL MachCall[kernCode, Rope.Cat["TDtaServer failed; code = ", IO.PutFR1["%g", IO.int[kernCode]]]];
};
Name server
objectNameTFromRope:
PROC [name: Rope.
ROPE]
RETURNS [objectNameString:
REF objectNameT] ~ {
oNSize: INT ← 0;
objectNameString ← NEW[objectNameT];
oNSize ← Rope.Length[name];
IF oNSize >= ObjectNameLength THEN ERROR;
FOR index:
INT
IN [0..oNSize)
DO
objectNameString[index] ← Rope.Fetch[name, index];
ENDLOOP;
objectNameString[oNSize] ← 0C;
};
CSSignIn:
PUBLIC PROC [nameServerPort: Mach.portT, name: Rope.
ROPE, port: Mach.portT
, raiseSignal:
BOOL]
RETURNS [kernCode: Mach.kernReturnT] ~ {
Sign in as a data server.
innerCSSignIn:
PROC [inameServerPort: Mach.portT, iname: POINTER TO objectNameT, iport: Mach.portT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<cs.h>.CS←SignIn"
};
objectNameString: REF objectNameT;
objectNameString ← objectNameTFromRope[name];
kernCode ← innerCSSignIn[nameServerPort, LOOPHOLE[objectNameString], port];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL MachCall[kernCode, Rope.Cat["CS←SignIn failed; code = ", IO.PutFR1["%g", IO.int[kernCode]]]];
};
CSSignOut:
PUBLIC PROC [nameServerPort: Mach.portT, name: Rope.
ROPE, port: Mach.portT, raiseSignal:
BOOL]
RETURNS [kernCode: Mach.kernReturnT] ~ {
Sign out as a data server.
innerCSSignOut:
PROC [inameServerPort: Mach.portT, iname: POINTER TO objectNameT, iport: Mach.portT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<cs.h>.CS←SignOut"
};
objectNameString: REF objectNameT;
objectNameString ← objectNameTFromRope[name];
kernCode ← innerCSSignOut[nameServerPort, LOOPHOLE[objectNameString], port];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL MachCall[kernCode, Rope.Cat["CS←SignOut failed; code = ", IO.PutFR1["%g", IO.int[kernCode]]]];
};
innerLookup:
PROC [nameServerPort: Mach.portT, name: Rope.
ROPE, site: Rope.
ROPE, numberWanted:
INT, maxSeconds:
INT, raiseSignal:
BOOL, cs:
BOOL]
RETURNS [portList: Mach.ListOfPorts, kernCode: Mach.kernReturnT] ~ {
Lookup for servers.
innerCSLookup:
PROC [inameServerPort: Mach.portT, iname:
POINTER
TO objectNameT, isite:
POINTER
TO objectNameT, inumberWanted:
INT, imaxSeconds:
INT, iportList:
POINTER
TO portArrayT, iportListCnt:
POINTER
TO
INT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<cs.h>.CS←Lookup"
};
innerCALookup:
PROC [inameServerPort: Mach.portT, iname:
POINTER
TO objectNameT, isite:
POINTER
TO objectNameT, inumberWanted:
INT, imaxSeconds:
INT, iportList:
POINTER
TO portArrayT, iportListCnt:
POINTER
TO
INT]
RETURNS [kernReturnT] ~
TRUSTED
MACHINE
CODE {
"<ca.h>.CA←Lookup"
};
objectNameString: REF objectNameT;
siteString: REF objectNameT;
ZportList, DportList: portArrayT ← NIL;
ZportListCnt: INT ← -1;
objectNameString ← objectNameTFromRope[name];
siteString ← objectNameTFromRope[site];
IF cs
THEN
TRUSTED {
kernCode ← innerCSLookup[nameServerPort, LOOPHOLE[objectNameString], LOOPHOLE[siteString], numberWanted, maxSeconds, @ZportList, @ZportListCnt];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL MachCall[kernCode, Rope.Cat["CS←Lookup failed; code = ", IO.PutFR1["%g", IO.int[kernCode]]]];
}
ELSE
TRUSTED {
kernCode ← innerCALookup[nameServerPort, LOOPHOLE[objectNameString], LOOPHOLE[siteString], numberWanted, maxSeconds, @ZportList, @ZportListCnt];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL MachCall[kernCode, Rope.Cat["CA←Lookup failed; code = ", IO.PutFR1["%g", IO.int[kernCode]]]];
};
IF ZportListCnt > 0
THEN
TRUSTED {
newPort:
PROC
RETURNS [lp: ListOfPorts] ~
TRUSTED {
lp ← LIST[[ZportList.portNumber]];
ZportList ← ZportList + UNITS[portT];
};
DportList ← ZportList;
portList ← newPort[];
IF ZportListCnt > 1
THEN {
lastPort: ListOfPorts ← portList;
FOR item:
INT
IN [1..ZportListCnt)
DO
lastPort.rest ← newPort[];
lastPort ← lastPort.rest;
ENDLOOP;
};
[] ← vmDeallocate[targetTask: taskSelf[], address: LOOPHOLE[DportList], size: BYTES[portT]*ZportListCnt, raiseSignal: TRUE];
};
};
CSLookup:
PUBLIC PROC [nameServerPort: Mach.portT, name: Rope.
ROPE, site: Rope.
ROPE, numberWanted:
INT, maxSeconds:
INT, raiseSignal:
BOOL]
RETURNS [portList: Mach.ListOfPorts, kernCode: Mach.kernReturnT] ~ {
Lookup for servers.
[portList, kernCode] ← innerLookup[nameServerPort, name, site, numberWanted, maxSeconds, raiseSignal, TRUE];
};
CALookup:
PUBLIC PROC [nameServerPort: Mach.portT, name: Rope.
ROPE, site: Rope.
ROPE, numberWanted:
INT, maxSeconds:
INT, raiseSignal:
BOOL]
RETURNS [portList: Mach.ListOfPorts, kernCode: Mach.kernReturnT] ~ {
Lookup for applications.
[portList, kernCode] ← innerLookup[nameServerPort, name, site, numberWanted, maxSeconds, raiseSignal, FALSE];
};
Exported lock procedures (if we are going to use CamLib)
Lock: PUBLIC PROC [tid: tidT, lockName: LockName, lockMode: lockModeT] ~ {
Obtain the lock for this transaction.
innerLOCK: PROC [lockNameInner: LockName, lockModeInner: lockModeT] ~ TRUSTED MACHINE CODE {
"LOCK"
};
MakeThisThreadPartOfTransaction[tid];
innerLOCK[lockName, lockMode];
};
TryLock: PUBLIC PROC [tid: tidT, lockName: LockName, lockMode: lockModeT] ~ {
Obtain the lock for this transaction if immediately available.
innerTryLock: PROC [lockNameInner: LockName, lockModeInner: lockModeT] ~ TRUSTED MACHINE CODE {
"TRY←LOCK"
};
MakeThisThreadPartOfTransaction[tid];
innerTryLock[lockName, lockMode];
};
Unlock: PUBLIC PROC [tid: tidT, lockName: LockName] ~ {
Release lock for this transaction.
innerUnlock: PROC [lockNameInner: LockName] ~ TRUSTED MACHINE CODE {
"UNLOCK"
};
MakeThisThreadPartOfTransaction[tid];
innerUnlock[lockName];
};
DemoteLock: PUBLIC PROC [tid: tidT, lockName: LockName] ~ {
Demote write lock to a read lock for this transaction.
innerDemoteLock: PROC [lockNameInner: LockName] ~ TRUSTED MACHINE CODE {
"UNLOCK"
};
MakeThisThreadPartOfTransaction[tid];
innerDemoteLock[lockName];
};