File: DBImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Purpose: Monitored interface to DB, to keep only one client in database system at a time. Contains one ENTRY per DB procedure (except those that need not be monitored, like Eq). The procs simply call the internal procs in the DBModel*Impls.
Created by Haugeland and Cattell, April 1982
Last edited by:
Rick Cattell on November 2, 1983 10:13 am
Willie-Sue, February 22, 1985 9:20:26 am PST
Donahue, March 10, 1986 8:49:40 am PST
Widom, September 13, 1985 2:56:52 pm PDT
DIRECTORY
AlpineEnvironment,
Atom,
DB,
DBCommon,
DBDefs,
DBModel,
DBStats,
Rope;
DBImpl: CEDAR MONITOR
IMPORTS DBModel, DBStats, DB
EXPORTS DB =
BEGIN OPEN DBCommon, DBDefs;
ROPE: TYPE = Rope.ROPE;
Part 1: Global top-level operations
Initialize: PUBLIC ENTRY PROC[nCachePages: NAT, cacheFileName: ROPE] =
{ ENABLE UNWIND => NULL;
DBModel.Initialize[nCachePages, cacheFileName];
RETURN};
OpenTransaction: PUBLIC ENTRY PROC[segment: Segment, useTrans: TransactionHandle] RETURNS[trans: TransactionHandle, schemaInvalid: BOOL] =
{ ENABLE UNWIND => DBStats.Stopping[OpenTransaction];
DBStats.Starting[OpenTransaction];
[trans, schemaInvalid] ← DBModel.OpenTransaction[segment, useTrans];
DBStats.Stopping[OpenTransaction] };
MarkTransaction: PUBLIC ENTRY PROC[trans: TransactionHandle] = {
ENABLE UNWIND => DBStats.Stopping[MarkTransaction];
DBModel.MarkTransaction[trans];
DBStats.Stopping[MarkTransaction] };
AbortTransaction: PUBLIC ENTRY PROC[trans: TransactionHandle] = {
ENABLE UNWIND => DBStats.Stopping[AbortTransaction];
DBModel.AbortTransaction[trans];
DBStats.Stopping[AbortTransaction] };
CloseTransaction: PUBLIC ENTRY PROC[trans: TransactionHandle] = {
ENABLE UNWIND => DBStats.Stopping[CloseTransaction];
DBModel.CloseTransaction[trans];
DBStats.Stopping[CloseTransaction] };
DeclareSegment: PUBLIC ENTRY PROC[filePath: ROPE, segment: Segment, number: SegmentIndex, lock: AlpineEnvironment.LockOption, readonly: BOOL, createIfNotFound: BOOL, nPagesInitial, nPagesPerExtent: INT] =
{ ENABLE UNWIND => NULL;
DBModel.DeclareSegment[filePath, segment, number, lock, readonly, createIfNotFound, nPagesInitial, nPagesPerExtent] };
EraseSegment: PUBLIC ENTRY PROC[segment: Segment, useTrans: TransactionHandle] RETURNS [trans: TransactionHandle] =
Open a new transaction onto an empty database
{ ENABLE UNWIND => NULL;
RETURN[DBModel.OpenTransaction[segment: segment, useTrans: useTrans, eraseAfterOpen: TRUE].trans] };
GetSegmentInfo: PUBLIC ENTRY PROC[segment: Segment] RETURNS [filePath: ROPE, readOnly: BOOL] =
{ ENABLE UNWIND => NULL;
[filePath, readOnly] ← DBModel.GetSegmentInfo[segment] };
SegmentsForTransaction: PUBLIC PROC[trans: TransactionHandle] RETURNS [segments: SegmentList] =
{ segments ← IF trans = NIL THEN NIL ELSE trans.segments };
Part 2: Schema-definition and -interrogation operations
DeclareDomain: PUBLIC ENTRY PROC [name: ROPE, segment: Segment] RETURNS [d: Domain] = {
ENABLE UNWIND => DBStats.Stopping[DeclareDomain];
IF NOT DBModel.initialized THEN ERROR Error[DatabaseNotInitialized];
d ← DBModel.DeclareDomain[name, segment];
DBStats.Stopping[DeclareDomain] };
LookupDomain: PUBLIC ENTRY PROC [name: ROPE, segment: Segment] RETURNS [d: Domain] = {
ENABLE UNWIND => DBStats.Stopping[LookupDomain];
IF NOT DBModel.initialized THEN ERROR Error[DatabaseNotInitialized];
d ← DBModel.LookupDomain[name, segment];
DBStats.Stopping[LookupDomain] };
DestroyDomain: PUBLIC ENTRY PROC [d: Domain] = {
ENABLE UNWIND => DBStats.Stopping[DestroyDomain];
DBModel.DestroyDomain[d];
DBStats.Stopping[DestroyDomain] };
DomainInfo: PUBLIC ENTRY PROC[d: Domain] RETURNS[name: ROPE, segment: DBCommon.Segment] = TRUSTED {
ENABLE UNWIND => NULL;
IF d.key # DBModel.CacheKey[d.segment] THEN ERROR Error[IllegalDomain];
segment ← d.segment;
name ← d.name };
DomainsByName: PUBLIC ENTRY PROC [segment: Segment, lowName, highName: ROPE, start: FirstLast] RETURNS[ds: DomainSet] = {
ENABLE UNWIND => NULL;
ds ← DBModel.DomainsByName[segment, lowName, highName, start] };
NextDomain: PUBLIC ENTRY PROC [ds: DomainSet] RETURNS [d: Domain] = {
ENABLE UNWIND => NULL;
d ← DBModel.NextDomain[ds] };
PrevDomain: PUBLIC ENTRY PROC [ds: DomainSet] RETURNS [d: Domain] = {
ENABLE UNWIND => NULL;
d ← DBModel.PrevDomain[ds] };
ReleaseDomainSet: PUBLIC ENTRY PROC [ds: DomainSet] =
{ ENABLE UNWIND => NULL; DBModel.ReleaseDomainSet[ds] };
DeclareSubType: PUBLIC ENTRY PROC [of, is: Domain] =
{ ENABLE UNWIND => NULL; DBModel.DeclareSubType[of, is] };
DestroySubType: PUBLIC ENTRY PROC [of, is: Domain] =
{ ENABLE UNWIND => NULL; DBModel.DestroySubType[of, is] };
SuperType: PUBLIC ENTRY PROC [d: Domain] RETURNS[super: Domain] =
{ ENABLE UNWIND => NULL; RETURN[DBModel.SuperType[d]] };
SubTypes: PUBLIC ENTRY PROC [d: Domain] RETURNS[subs: DomainSet] =
{ ENABLE UNWIND => NULL; RETURN[DBModel.SubTypes[d]] };
TypeForDomain: PUBLIC ENTRY PROC[d: Domain] RETURNS[type: TypeCode] =
{ ENABLE UNWIND => NULL; RETURN[DBModel.TypeForDomain[d]] };
DeclareRelation: PUBLIC ENTRY PROC [name: ROPE, segment: Segment, fields: DB.FieldSpec, keys: LIST OF Index] RETURNS [r: Relation] = {
ENABLE UNWIND => DBStats.Stopping[DeclareRelation];
DBStats.Starting[DeclareRelation];
r ← DBModel.DeclareRelation[name, segment, fields, keys];
DBStats.Stopping[DeclareRelation] };
LookupRelation: PUBLIC ENTRY PROC [name: ROPE, segment: Segment] RETURNS [r: Relation] = {
ENABLE UNWIND => DBStats.Stopping[LookupRelation];
DBStats.Starting[LookupRelation];
r ← DBModel.LookupRelation[name, segment];
DBStats.Stopping[LookupRelation] };
DestroyRelation: PUBLIC ENTRY PROC [r: Relation] = {
ENABLE UNWIND => DBStats.Stopping[DestroyRelation];
DBStats.Starting[DestroyRelation];
DBModel.DestroyRelation[r];
DBStats.Stopping[DestroyRelation] };
RelationInfo: PUBLIC ENTRY PROC [r: Relation] RETURNS[name: ROPE, segment: DBCommon.Segment] = TRUSTED {
ENABLE UNWIND => NULL;
IF r.key # DBModel.CacheKey[r.segment] THEN ERROR Error[IllegalRelation];
segment ← r.segment;
name ← r.name };
RelationsByName: PUBLIC ENTRY PROC [segment: Segment, lowName, highName: ROPE, start: FirstLast] RETURNS[rs: RelationSet] = {
ENABLE UNWIND => NULL;
rs ← DBModel.RelationsByName[segment, lowName, highName, start] };
NextRelation: PUBLIC ENTRY PROC [rs: RelationSet] RETURNS [r: Relation] = {
ENABLE UNWIND => NULL;
r ← DBModel.NextRelation[rs] };
PrevRelation: PUBLIC ENTRY PROC [rs: RelationSet] RETURNS [r: Relation] = {
ENABLE UNWIND => NULL;
r ← DBModel.PrevRelation[rs] };
ReleaseRelationSet: PUBLIC ENTRY PROC [rs: RelationSet] =
{ ENABLE UNWIND => NULL; DBModel.ReleaseRelationSet[rs] };
NameToField: PUBLIC ENTRY PROC [r: Relation, name: ROPE] RETURNS[exists: BOOL, pos: CARDINAL] =
{ ENABLE UNWIND => NULL; [exists, pos] ← DBModel.NameToField[r: r, name: name] };
FieldCount: PUBLIC ENTRY PROC[r: Relation] RETURNS[count: CARDINAL] = {
ENABLE UNWIND => NULL; count ← DBModel.FieldCount [r: r] };
FieldInfo: PUBLIC ENTRY PROC [r: Relation, pos: CARDINAL] RETURNS [field: DB.Field] = {
ENABLE UNWIND => NULL;
field ← DBModel.FieldInfo[r, pos] };
DeclareIndex: PUBLIC ENTRY PROC [r: Relation, index: Index] = {
ENABLE UNWIND => DBStats.Stopping[DeclareIndex];
DBStats.Starting[DeclareIndex];
DBModel.DeclareIndex[r, index];
DBStats.Stopping[DeclareIndex] };
DestroyIndex: PUBLIC ENTRY PROC [r: Relation, index: Index] = {
ENABLE UNWIND => DBStats.Stopping[DestroyIndex];
DBStats.Starting[DestroyIndex];
DBModel.DestroyIndex[r, index];
DBStats.Stopping[DestroyIndex] };
Keys: PUBLIC ENTRY PROC[r: Relation] RETURNS[keys: LIST OF Index] = {
keys ← DBModel.Keys[r] };
Indices: PUBLIC ENTRY PROC[r: Relation] RETURNS[indices: LIST OF Index] = {
indices ← DBModel.Indices[r] };
Part 3: Primitive operations
DeclareEntity: PUBLIC ENTRY PROC[d: Domain, name: ROPE] RETURNS[e: Entity] =
{ ENABLE UNWIND => DBStats.Stopping[DeclareEntity];
DBStats.Starting[DeclareEntity];
e ← DBModel.DeclareEntity[d, name];
DBStats.Stopping[DeclareEntity]};
LookupEntity: PUBLIC ENTRY PROC[d: Domain, name: ROPE] RETURNS[e: Entity] =
{ ENABLE UNWIND => DBStats.Stopping[LookupEntity];
DBStats.Starting[LookupEntity];
e ← DBModel.LookupEntity[d, name];
DBStats.Stopping[LookupEntity] };
CreateRelship: PUBLIC ENTRY PROC[r: Relation, init: ValueSequence] RETURNS[t: Relship] =
{ ENABLE UNWIND => DBStats.Stopping[CreateRelship];
DBStats.Starting[CreateRelship];
t ← DBModel.CreateRelship[r, init];
DBStats.Stopping[CreateRelship] };
LookupRelship: PUBLIC ENTRY PROC[r: Relation, key: Index, val: ValueSequence] RETURNS[t: Relship] =
{ ENABLE UNWIND => DBStats.Stopping[LookupRelship];
DBStats.Starting[LookupRelship];
t ← DBModel.LookupRelship[r, key, val];
DBStats.Stopping[LookupRelship] };
oneLittleValueSequence: ValueSequence ← NEW[ValueSequenceObject[1]];
LookupWithSimpleKey: PUBLIC ENTRY PROC[r: Relation, key: Index, val: Value] RETURNS[t: Relship] = TRUSTED {
ENABLE UNWIND => DBStats.Stopping[LookupRelship];
DBStats.Starting[LookupRelship];
IF key.fields.count # 1 THEN ERROR DB.Error[MismatchedAttributeValueType];
oneLittleValueSequence[0] ← val;
t ← DBModel.LookupRelship[r, key, oneLittleValueSequence];
DBStats.Stopping[LookupRelship] };
DestroyEntity: PUBLIC ENTRY PROC[e: Entity] = {
ENABLE UNWIND => DBStats.Stopping[DestroyEntity];
DBStats.Starting[DestroyEntity];
DBModel.DestroyEntity[e];
DBStats.Stopping[DestroyEntity] };
DestroyRelship: PUBLIC ENTRY PROC[t: Relship] = {
ENABLE UNWIND => DBStats.Stopping[DestroyRelship];
DBStats.Starting[DestroyRelship];
DBModel.DestroyRelship[t];
DBStats.Stopping[DestroyRelship] };
SetF: PUBLIC ENTRY PROC[t: Relship, field: CARDINAL, v: Value] = {
ENABLE UNWIND => DBStats.Stopping[SetF];
DBStats.Starting[SetF];
DBModel.SetF[t, field, v];
DBStats.Stopping[SetF] };
GetF: PUBLIC ENTRY PROC[t: Relship, field: CARDINAL] RETURNS [v: Value ← [null[]]] = TRUSTED {
ENABLE UNWIND => DBStats.Stopping[GetF];
DBStats.Starting[GetF];
v ← DBModel.GetF[t, field];
DBStats.Stopping[GetF] };
SetP: PUBLIC ENTRY PROC[e: Entity, r: Relation, field: CARDINAL, v: Value] = {
ENABLE UNWIND => DBStats.Stopping[SetP];
DBStats.Starting[SetP];
DBModel.SetP[e, r, field, v];
DBStats.Stopping[SetP] };
GetP: PUBLIC ENTRY PROC[e: Entity, r: Relation, field: CARDINAL] RETURNS[v: Value← [null[]]] = TRUSTED {
ENABLE UNWIND => DBStats.Stopping[GetP];
DBStats.Starting[GetP];
v ← DBModel.GetP[e, r, field];
DBStats.Stopping[GetP] };
DomainEq: PUBLIC PROC [d1, d2: Domain] RETURNS[BOOL] = {
RETURN[DBModel.DomainEq[d1, d2]] };
RelationEq: PUBLIC PROC [r1, r2: Relation] RETURNS[BOOL] = {
RETURN[DBModel.RelationEq[r1, r2]] };
AttributeEq: PUBLIC PROC [a1, a2: Attribute] RETURNS[BOOL] = {
RETURN[DBModel.AttributeEq[a1, a2]] };
NullDomain: PUBLIC PROC [d: Domain] RETURNS[BOOLEAN] = {
RETURN[DBModel.NullDomain[d]] };
NullRelation: PUBLIC PROC [r: Relation] RETURNS[BOOLEAN] = {
RETURN[DBModel.NullRelation[r]] };
EntityInfo: PUBLIC ENTRY PROC [e: Entity] RETURNS [name: ROPE, domain: Domain] =
{ ENABLE UNWIND => NULL;
[name, domain] ← DBModel.EntityInfo[e] };
RelationOf: PUBLIC ENTRY PROC[t: Relship] RETURNS [Relation] =
{ ENABLE UNWIND => NULL;
RETURN[DBModel.RelationOf[t]] };
Part 4: Aggregate operations
RelationSubset: PUBLIC ENTRY PROC[r: Relation, index: Index, constraint: Constraint, start: FirstLast] RETURNS [rs: RelshipSet] = {
ENABLE UNWIND => DBStats.Stopping[RelationSubset];
DBStats.Starting[RelationSubset];
rs ← DBModel.RelationSubset[r, index, constraint, start];
DBStats.Stopping[RelationSubset] };
NextRelship: PUBLIC ENTRY PROC[rs: RelshipSet] RETURNS [t: Relship] =
{ ENABLE UNWIND => DBStats.Stopping[NextRelship];
DBStats.Starting[NextRelship];
t ← DBModel.NextRelship[rs];
DBStats.Stopping[NextRelship] };
PrevRelship: PUBLIC ENTRY PROC[rs: RelshipSet] RETURNS [t: Relship] =
{ ENABLE UNWIND => DBStats.Stopping[PrevRelship];
DBStats.Starting[PrevRelship];
t ← DBModel.PrevRelship[rs];
DBStats.Stopping[PrevRelship] };
ReleaseRelshipSet: PUBLIC ENTRY PROC [rs: RelshipSet] =
{ENABLE UNWIND => NULL; DBModel.ReleaseRelshipSet[rs]};
DomainSubset: PUBLIC ENTRY PROC[d: Domain, lowName, highName: ROPE, start: FirstLast] RETURNS [es: EntitySet] = {
ENABLE UNWIND => DBStats.Stopping[DomainSubset];
DBStats.Starting[DomainSubset];
es ← DBModel.DomainSubset[d, lowName, highName, start];
DBStats.Stopping[DomainSubset];
RETURN[es] };
NextEntity: PUBLIC ENTRY PROC[es: EntitySet] RETURNS [e: Entity] =
{ ENABLE UNWIND => DBStats.Stopping[NextEntity];
DBStats.Starting[NextEntity];
e ← DBModel.NextEntity[es];
DBStats.Stopping[NextEntity];
};
PrevEntity: PUBLIC ENTRY PROC[es: EntitySet] RETURNS [e: Entity] =
{ ENABLE UNWIND => DBStats.Stopping[PrevEntity];
DBStats.Starting[PrevEntity];
e ← DBModel.PrevEntity[es];
DBStats.Stopping[PrevEntity];
};
ReleaseEntitySet: PUBLIC ENTRY PROC[es: EntitySet] =
{ ENABLE UNWIND => NULL; DBModel.ReleaseEntitySet[es]};
RelshipsForEntity: PUBLIC ENTRY PROC [e: Entity] RETURNS [rs: RelshipSet] =
{ ENABLE UNWIND => NULL; RETURN[DBModel.RelshipsForEntity[e]] };
RelshipsWithEntityField: PUBLIC ENTRY PROC[r: Relation, field: CARDINAL, val: Entity] RETURNS[rs: RelshipSet] = {
ENABLE UNWIND => NULL; RETURN[DBModel.RelshipsWithEntityField[r, field, val]] };
RelationsOf: PUBLIC ENTRY PROC[d: Domain] RETURNS[rs: RelationSet] =
{ ENABLE UNWIND => NULL; rs ← DBModel.RelationsOf[d] };
Miscellaneous operations
L2VS: PUBLIC PROC[vals: LIST OF Value] RETURNS[seq: ValueSequence] = TRUSTED {
length: CARDINAL ← 0;
IF vals = NIL THEN RETURN[NIL];
FOR vL: LIST OF Value ← vals, vL.rest UNTIL vL = NIL DO
length ← length + 1
ENDLOOP;
seq ← NEW[ValueSequenceObject[length]];
length ← 0;
FOR vL: LIST OF Value ← vals, vL.rest UNTIL vL = NIL DO
seq[length] ← vL.first;
length ← length + 1
ENDLOOP
};
L2FS: PUBLIC PROC[vals: LIST OF DB.Field] RETURNS[seq: DB.FieldSpec] = TRUSTED {
length: CARDINAL ← 0;
IF vals = NIL THEN RETURN[NIL];
FOR vL: LIST OF DB.Field ← vals, vL.rest UNTIL vL = NIL DO
length ← length + 1
ENDLOOP;
seq ← NEW[DB.FieldSpecObject[length]];
length ← 0;
FOR vL: LIST OF DB.Field ← vals, vL.rest UNTIL vL = NIL DO
seq[length] ← vL.first;
length ← length + 1
ENDLOOP
};
L2F: PUBLIC PROC[vals: LIST OF CARDINAL] RETURNS[seq: FieldSequence] = TRUSTED {
length: CARDINAL ← 0;
IF vals = NIL THEN RETURN[NIL];
FOR vL: LIST OF CARDINAL ← vals, vL.rest UNTIL vL = NIL DO
length ← length + 1
ENDLOOP;
seq ← NEW[FieldSequenceObject[length]];
length ← 0;
FOR vL: LIST OF CARDINAL ← vals, vL.rest UNTIL vL = NIL DO
seq[length] ← vL.first;
length ← length + 1
ENDLOOP
};
L2C: PUBLIC PROC[vals: LIST OF ValueConstraint] RETURNS[seq: Constraint] = TRUSTED {
length: CARDINAL ← 0;
IF vals = NIL THEN RETURN[NIL];
FOR vL: LIST OF DBDefs.ValueConstraint ← vals, vL.rest UNTIL vL = NIL DO
length ← length + 1
ENDLOOP;
seq ← NEW[ConstraintObject[length]];
length ← 0;
FOR vL: LIST OF ValueConstraint ← vals, vL.rest UNTIL vL = NIL DO
seq[length] ← vL.first;
length ← length + 1
ENDLOOP
};
Errors
Error: PUBLIC SIGNAL [code: DB.ErrorCode] = CODE;
Aborted: PUBLIC ERROR = CODE;
Failure: PUBLIC ERROR [what: ATOM, info: ROPE] = CODE;
InternalError: PUBLIC ERROR = CODE;
Initialization
{ DBStats.Initialize[] }
END.