DIRECTORY
Arpa USING [Address, nullAddress],
Atom USING [GetPName, MakeAtom],
Basics USING [HFromCard16, LowHalf],
Convert USING [ArpaAddressFromRope],
IO USING [rope, PutFR1],
LoganBerry,
LoganBerryClass USING [Class, ClassObject, Register],
LoganBerrySunRPC,
LoganBerrySunRPCClient,
RefID USING [Seal, Unseal],
Rope USING [Concat, Find, FromRefText, Length, Replace, ROPE, Substr],
SunPMap USING [ipProtocolUDP, udpPort],
SunPMapClient USING [GetPort],
SunRPC USING [Error, Handle],
SunRPCOnUDP USING [Create, SetRemote],
SunRPCAuth USING [Initiate],
SunYPAgent USING [Error, Handle, Match, ObtainHandle, ReleaseHandle, Tokenize];
~
BEGIN
ROPE: TYPE = Rope.ROPE;
Conv: TYPE ~ LoganBerry.Conv;
OpenDB: TYPE ~ LoganBerry.OpenDB;
AttributeType: TYPE ~ LoganBerry.AttributeType;
AttributeValue: TYPE ~ LoganBerry.AttributeValue;
Entry: TYPE ~ LoganBerry.Entry;
EntryProc: TYPE ~ LoganBerry.EntryProc;
Cursor: TYPE ~ LoganBerry.Cursor;
CursorDirection: TYPE ~ LoganBerry.CursorDirection;
LogID: TYPE ~ LoganBerry.LogID;
activityLog: LogID ~ LoganBerry.activityLog;
SchemaInfo: TYPE ~ LoganBerry.SchemaInfo;
nilconv: INT = 0;
OpenDBInfo: TYPE = REF OpenDBRecord;
OpenDBRecord:
TYPE =
MONITORED RECORD [
h: SunRPC.Handle ¬ NIL,
db: CARD32
];
CursorInfo: TYPE = REF CursorRecord;
CursorRecord:
TYPE =
RECORD[
dbinfo: OpenDBInfo,
cursor: CARD32
];
Class methods
Open:
PROC [conv: Conv ¬
NIL, dbName:
ROPE]
RETURNS [db: OpenDB] ~ {
ENABLE {
SunRPC.Error => PostSunError[code];
LoganBerrySunRPCClient.Error => ERROR LoganBerry.Error[Atom.MakeAtom[ec], explanation];
};
accept: BOOLEAN;
server, nameOnServer: ROPE;
dbinfo: OpenDBInfo;
addr: Arpa.Address;
port: CARD;
[accept, server, nameOnServer] ¬ CheckName[dbName];
IF NOT accept THEN RETURN[LoganBerry.nullDB];
dbinfo ¬ NEW[OpenDBRecord];
addr ¬ SunYPNameToAddress[server];
IF ( addr = Arpa.nullAddress )
THEN
ERROR LoganBerry.Error[$CantOpenSchema, IO.PutFR1["Unknown server: %g.", IO.rope[server]]];
dbinfo.h ¬ SunRPCOnUDP.Create[addr, Basics.HFromCard16[SunPMap.udpPort]];
port ¬ SunPMapClient.GetPort[dbinfo.h, SunRPCAuth.Initiate[], 390905, 1, SunPMap.ipProtocolUDP ! SunRPC.Error => ERROR LoganBerry.Error[$CantOpenSchema, IO.PutFR1["Can't contact remote server: %g.", IO.rope[server]]]];
IF port = 0
THEN
ERROR LoganBerry.Error[$CantOpenSchema, IO.PutFR1["LoganBerry not exported on server: %g.", IO.rope[server]]];
dbinfo.h ¬ SunRPCOnUDP.SetRemote[dbinfo.h, addr, Basics.HFromCard16[Basics.LowHalf[port]]];
dbinfo.db ¬ LoganBerrySunRPCClient.Open[dbinfo.h, nilconv, nameOnServer];
RETURN[RefID.Seal[dbinfo]];
};
ReadEntry:
PROC [conv: Conv ¬
NIL, db: OpenDB, key: AttributeType, value: AttributeValue]
RETURNS [entry: Entry, others:
BOOLEAN] ~ {
ENABLE {
SunRPC.Error => PostSunError[code];
LoganBerrySunRPCClient.Error => ERROR LoganBerry.Error[Atom.MakeAtom[ec], explanation];
};
dbinfo: OpenDBInfo ¬ GetInfo[db];
[entry, others] ¬ ReadEntryI[dbinfo, key, value];
RETURN[entry, others];
};
ReadEntryI:
PUBLIC
ENTRY
PROC [dbinfo: OpenDBInfo, key: AttributeType, value: AttributeValue]
RETURNS [entry: Entry, others:
BOOLEAN] ~ {
ENABLE UNWIND => NULL;
srEntry: LoganBerrySunRPC.Entry;
[srEntry, others] ¬ LoganBerrySunRPCClient.ReadEntry[dbinfo.h, nilconv, dbinfo.db, Atom.GetPName[key], value];
entry ¬ SrToEntry[srEntry];
};
EnumerateEntries:
PROC [db: OpenDB, key: AttributeType, start: AttributeValue ¬
NIL, end: AttributeValue ¬
NIL, proc: EntryProc]
RETURNS [] ~ {
entry: Entry;
c: Cursor ¬ GenerateEntries[NIL, db, key, start, end];
entry ¬ NextEntry[NIL, c];
WHILE entry #
NIL
DO
IF NOT proc[entry] THEN EXIT;
entry ¬ NextEntry[NIL, c];
ENDLOOP;
EndGenerate[NIL, c];
};
GenerateEntries:
PROC [conv: Conv ¬
NIL, db: OpenDB, key: AttributeType, start: AttributeValue ¬
NIL, end: AttributeValue ¬
NIL]
RETURNS [cursor: Cursor] ~ {
ENABLE {
SunRPC.Error => PostSunError[code];
LoganBerrySunRPCClient.Error => ERROR LoganBerry.Error[Atom.MakeAtom[ec], explanation];
};
cinfo: CursorInfo;
dbinfo: OpenDBInfo ¬ GetInfo[db];
cinfo ¬ GenerateEntriesI[dbinfo, key, start, end];
RETURN[RefID.Seal[cinfo]];
};
GenerateEntriesI:
PUBLIC
ENTRY
PROC [dbinfo: OpenDBInfo, key: AttributeType, start: AttributeValue ¬
NIL, end: AttributeValue ¬
NIL]
RETURNS [cinfo: CursorInfo] ~ {
ENABLE UNWIND => NULL;
cinfo ¬ NEW[CursorRecord];
cinfo.dbinfo ¬ dbinfo;
cinfo.cursor ¬ LoganBerrySunRPCClient.GenerateEntries[dbinfo.h, nilconv, dbinfo.db, Atom.GetPName[key], start, end];
};
NextEntry:
PROC [conv: Conv ¬
NIL, cursor: Cursor, dir: CursorDirection ¬ increasing]
RETURNS [entry: Entry] ~ {
ENABLE {
SunRPC.Error => PostSunError[code];
LoganBerrySunRPCClient.Error => ERROR LoganBerry.Error[Atom.MakeAtom[ec], explanation];
};
cinfo: CursorInfo ¬ GetCursorInfo[cursor];
entry ¬ NextEntryI[cinfo.dbinfo, cinfo, dir];
RETURN[entry];
};
NextEntryI:
PUBLIC
ENTRY
PROC [dbinfo: OpenDBInfo, cinfo: CursorInfo, dir: CursorDirection ¬ increasing]
RETURNS [entry: Entry] ~ {
ENABLE UNWIND => NULL;
srEntry: LoganBerrySunRPC.Entry;
srEntry ¬ LoganBerrySunRPCClient.NextEntry[cinfo.dbinfo.h, nilconv, cinfo.cursor, IF dir=increasing THEN increasing ELSE decreasing];
entry ¬ SrToEntry[srEntry];
};
EndGenerate:
PROC [conv: Conv ¬
NIL, cursor: Cursor]
RETURNS [] ~ {
ENABLE {
SunRPC.Error => PostSunError[code];
LoganBerrySunRPCClient.Error => ERROR LoganBerry.Error[Atom.MakeAtom[ec], explanation];
};
cinfo: CursorInfo ¬ GetCursorInfo[cursor];
EndGenerateI[cinfo.dbinfo, cinfo];
};
EndGenerateI:
PUBLIC
ENTRY
PROC [dbinfo: OpenDBInfo, cinfo: CursorInfo]
RETURNS [] ~ {
ENABLE UNWIND => NULL;
LoganBerrySunRPCClient.EndGenerate[cinfo.dbinfo.h, nilconv, cinfo.cursor];
};
WriteEntry:
PROC [conv: Conv ¬
NIL, db: OpenDB, entry: Entry, log: LogID ¬ activityLog, replace:
BOOLEAN ¬
FALSE]
RETURNS [] ~ {
ENABLE {
SunRPC.Error => PostSunError[code];
LoganBerrySunRPCClient.Error => ERROR LoganBerry.Error[Atom.MakeAtom[ec], explanation];
};
dbinfo: OpenDBInfo ¬ GetInfo[db];
WriteEntryI[dbinfo, entry, log, replace];
};
WriteEntryI:
PUBLIC
ENTRY
PROC [dbinfo: OpenDBInfo, entry: Entry, log: LogID ¬ activityLog, replace:
BOOLEAN ¬
FALSE]
RETURNS [] ~ {
ENABLE UNWIND => NULL;
LoganBerrySunRPCClient.WriteEntry[dbinfo.h, nilconv, dbinfo.db, EntryToSr[entry], log, replace];
};
DeleteEntry:
PROC [conv: Conv ¬
NIL, db: OpenDB, key: AttributeType, value: AttributeValue]
RETURNS [deleted: Entry] ~ {
ENABLE {
SunRPC.Error => PostSunError[code];
LoganBerrySunRPCClient.Error => ERROR LoganBerry.Error[Atom.MakeAtom[ec], explanation];
};
dbinfo: OpenDBInfo ¬ GetInfo[db];
deleted ¬ DeleteEntryI[dbinfo, key, value];
RETURN[deleted];
};
DeleteEntryI:
PUBLIC
ENTRY
PROC [dbinfo: OpenDBInfo, key: AttributeType, value: AttributeValue]
RETURNS [deleted: Entry] ~ {
ENABLE UNWIND => NULL;
srEntry: LoganBerrySunRPC.Entry;
srEntry ¬ LoganBerrySunRPCClient.ReadEntry[dbinfo.h, nilconv, dbinfo.db, Atom.GetPName[key], value].entry;
LoganBerrySunRPCClient.DeleteEntry[dbinfo.h, nilconv, dbinfo.db, Atom.GetPName[key], value];
deleted ¬ SrToEntry[srEntry];
};
Close:
PROC [conv: Conv ¬
NIL, db: OpenDB]
RETURNS [] ~ {
ENABLE {
SunRPC.Error => PostSunError[code];
LoganBerrySunRPCClient.Error => ERROR LoganBerry.Error[Atom.MakeAtom[ec], explanation];
};
dbinfo: OpenDBInfo ¬ GetInfo[db];
CloseI[dbinfo];
};
CloseI:
PUBLIC
ENTRY
PROC [dbinfo: OpenDBInfo]
RETURNS [] ~ {
ENABLE UNWIND => NULL;
LoganBerrySunRPCClient.Close[dbinfo.h, nilconv, dbinfo.db];
};
BuildIndices:
PROC [conv: Conv ¬
NIL, db: OpenDB]
RETURNS [] ~ {
ENABLE {
SunRPC.Error => PostSunError[code];
LoganBerrySunRPCClient.Error => ERROR LoganBerry.Error[Atom.MakeAtom[ec], explanation];
};
dbinfo: OpenDBInfo ¬ GetInfo[db];
BuildIndicesI[dbinfo];
};
BuildIndicesI:
PUBLIC
ENTRY
PROC [dbinfo: OpenDBInfo]
RETURNS [] ~ {
ENABLE UNWIND => NULL;
LoganBerrySunRPCClient.BuildIndices[dbinfo.h, nilconv, dbinfo.db];
};
CompactLogs:
PROC [conv: Conv ¬
NIL, db: OpenDB]
RETURNS [] ~ {
ENABLE {
SunRPC.Error => PostSunError[code];
LoganBerrySunRPCClient.Error => ERROR LoganBerry.Error[Atom.MakeAtom[ec], explanation];
};
dbinfo: OpenDBInfo ¬ GetInfo[db];
CompactLogsI[dbinfo];
};
CompactLogsI:
PUBLIC
ENTRY
PROC [dbinfo: OpenDBInfo]
RETURNS [] ~ {
ENABLE UNWIND => NULL;
LoganBerrySunRPCClient.CompactLogs[dbinfo.h, nilconv, dbinfo.db];
};
Describe:
PROC [conv: Conv ¬
NIL, db: OpenDB]
RETURNS [info: SchemaInfo] ~ {
ENABLE {
SunRPC.Error => PostSunError[code];
LoganBerrySunRPCClient.Error => ERROR LoganBerry.Error[Atom.MakeAtom[ec], explanation];
};
dbinfo: OpenDBInfo ¬ GetInfo[db];
info ¬ DescribeI[dbinfo];
RETURN[info];
};
DescribeI:
PUBLIC
ENTRY
PROC [dbinfo: OpenDBInfo]
RETURNS [info: SchemaInfo] ~ {
ENABLE UNWIND => NULL;
srInfo: LoganBerrySunRPC.SchemaInfo;
srInfo ¬ LoganBerrySunRPCClient.Describe[dbinfo.h, nilconv, dbinfo.db];
info ¬ SrToSchemaInfo[srInfo];
};
IsLocal:
PROC [db: LoganBerry.OpenDB]
RETURNS [local:
BOOL ¬
TRUE] = {
RETURN[FALSE];
};
PostSunError:
PROC [code:
ATOM]
RETURNS [] ~ {
Simply turn SUN RPC errors into LoganBerry errors.
ERROR LoganBerry.Error[$CallFailed
, IO.PutFR1["SUN RPC stub problem - %g.", IO.rope[
SELECT code
FROM
$timeout, $unreachable => "server unreachable",
$protocolError => "protocol error",
$wrongRPCVersion, $wrongProgram, $wrongProgramVersion, $wrongProc => "using wrong program, version, or procedure",
ENDCASE => "unknown error"
]]];
};