DIRECTORY DB USING [ Aborted, Error, Failure ], -- Cheery interface, in't it? DBEnvironment USING [ ErrorCode ], GVBasics, IO, Nuthatch, NuthatchLog, NuthatchDB, NuthatchUpdater, Rope, BasicTime, Thrush; NuthatchUpdaterImpl: CEDAR MONITOR IMPORTS DB, IO, NuthatchLog, NuthatchDB, Rope EXPORTS NuthatchUpdater = { OPEN NuthatchDB, NuthatchUpdater; ROPE: TYPE = Rope.ROPE; DoLogEntries: PUBLIC ENTRY PROC [nuthatchUserHandle: Nuthatch.NuthatchUserHandle, close: BOOL] = TRUSTED { ENABLE UNWIND => NULL; cTrans: REF ANY_NIL; cWhat: ATOM_NIL; cInfo: ROPE_NIL; cCode: DBEnvironment.ErrorCode; cError: BOOL_FALSE; TRUSTED { ENABLE { NuthatchLog.Error => SELECT code FROM aborted => RETRY; failed => NULL; -- Communication failure or other environmental problem. give up. ENDCASE; DB.Aborted => { cTrans _ trans; RETRY; }; DB.Error => { cCode _ code; cError _ TRUE; GOTO Failed; }; DB.Failure => { cTrans _ trans; cWhat _ what; cInfo_info; GOTO Failed; }; }; logEntryStream: IO.STREAM; token: Rope.ROPE; userName: GVBasics.RName; tuneNumber: INT; recordedTime: BasicTime.GMT; referenceCount: INT; samples: INT; startingSample: INT; encryptionKeyRope: Rope.ROPE; type: Rope.ROPE; voiceFileID: Nuthatch.VoiceFileID; refIDType: ROPE; refID: ROPE; DoProc: SAFE PROC[ voiceFileID:Nuthatch.VoiceFileID, refIDType: Nuthatch.IDType, refID: Nuthatch.ID, user: GVBasics.RName, close: BOOL ]; doType: NAT_0; IF cTrans#NIL THEN NuthatchDB.AbortTransaction[]; cTrans _ NIL; NuthatchLog.SetLogIndex[nuthatchUserHandle]; DO IF ([logEntryStream,] _ NextEntryStream[nuthatchUserHandle]).endOfLog THEN EXIT; token _ IO.GetCedarTokenRope[logEntryStream].token; SELECT TRUE FROM token.Equal["Catalog"] => doType_3; token.Equal["Create"] => { doType_1; DoProc_NuthatchDB.MakeInterestEntry; }; token.Equal["AddRef"] => { doType_1; DoProc_NuthatchDB.AddInterest; }; token.Equal["AddUserRef"] => { doType_2; DoProc_NuthatchDB.AddInterest; }; token.Equal["LoseRef"] => { doType_1; DoProc_NuthatchDB.LoseInterest; }; token.Equal["LoseUserRef"] => { doType_2; DoProc_NuthatchDB.LoseInterest; }; token.Equal["RemoveRef"] => { doType_1; DoProc_NuthatchDB.RemoveInterestEntry; }; token.Equal["RemoveUserRef"] => { doType_2; DoProc_NuthatchDB.RemoveInterestEntry; }; ENDCASE; SELECT doType FROM 1 => { voiceFileID _ GetVoiceFileID[logEntryStream]; logEntryStream _ NextEntryStream[nuthatchUserHandle].s; userName _GetUserName[logEntryStream]; [refIDType, refID] _ GetRefIDS[nuthatchUserHandle]; DoProc[voiceFileID, refIDType, refID, userName, FALSE] }; 2 => { userName _ GetUserName[logEntryStream]; [refIDType, refID] _ GetRefIDS[nuthatchUserHandle]; DoProc[NIL, refIDType, refID, userName, FALSE]; }; 3 => { voiceFileID _ GetVoiceFileID[logEntryStream]; logEntryStream _ NextEntryStream[nuthatchUserHandle].s; userName _GetUserName[logEntryStream]; tuneNumber _IO.GetInt[logEntryStream]; recordedTime_logEntryStream.GetTime[]; logEntryStream _ NextEntryStream[nuthatchUserHandle].s; referenceCount_IO.GetInt[logEntryStream]; samples_IO.GetInt[logEntryStream]; startingSample_IO.GetInt[logEntryStream]; encryptionKeyRope _ IO.PutFR["%bB %bB", IO.card[IO.GetCard[logEntryStream]], IO.card[IO.GetCard[logEntryStream]]]; type_IO.GetCedarTokenRope[logEntryStream].token; [] _ NuthatchDB.CatalogVoiceFile[ msg: voiceFileID, tuneNumber: tuneNumber, recordTime: recordedTime, creator: userName, samples: samples, startSample: startingSample, encryptionKeyRope: encryptionKeyRope, type: type, referenceCount: referenceCount, close: FALSE ]; }; ENDCASE => ERROR; ENDLOOP; NuthatchDB.MarkTransaction[]; -- be sure that updated read point is truth NuthatchLog.UpdateLogIndex[nuthatchUserHandle]; -- If aborts, it's before getting new val. NuthatchDB.SetReadPoint[nuthatchUserHandle, close]; -- Aborted retry does only this EXITS Failed => { NuthatchDB.AbortTransaction[]; IF cError THEN DB.Error[cCode] ELSE DB.Failure[cTrans, cWhat, cInfo]; }; }; }; GetVoiceFileID: PROC[s: IO.STREAM] RETURNS [voiceFileID: ROPE] = { []_s.SkipWhitespace[]; -- flush blanks -- voiceFileID _s.GetLineRope[]; }; NextEntryStream: PROC[nuthatchUserHandle: Nuthatch.NuthatchUserHandle] RETURNS [s: IO.STREAM_NIL, endOfLog: BOOL] = { logEntryRope: ROPE; [logEntryRope, endOfLog] _ NuthatchLog.ReadLogEntry[nuthatchUserHandle]; RETURN[IO.RIS[logEntryRope], endOfLog]; }; GetRefIDS: PROC[nuthatchUserHandle: Nuthatch.NuthatchUserHandle] RETURNS [refIDType, refID: ROPE_NIL] = { s: IO.STREAM = NextEntryStream[nuthatchUserHandle].s; refIDType _ s.GetCedarTokenRope[].token; []_s.SkipWhitespace[]; -- flush blanks refID _ s.GetLineRope[]; -- rest of line is ID }; GetUserName: PROC[stream: IO.STREAM] RETURNS [userName: Rope.ROPE] = { RETURN[stream.GetTokenRope[IO.IDProc].token]; }; }. ÐNuthatchUpdaterImpl.mesa Contents: Process to read from a nuthatch log and call the appropriate Nuthatch database routines to effect the updates. The log reads and database writes will occur under a Cypress transaction. Last Edited by: Lia, September 30, 1983 11:52 am Last Edited by: Swinehart, July 11, 1985 12:14:26 pm PDT The updater process should: 1. Opens a readonly transaction on the Nuthatch segment and the user's Nuthatch log. Under the same transaction, examine the log to get its length, and compare it against the user's log-read-point information in the database. If they're the same, no updating is necessary. Otherwise, 2. Prepare to update the database according to the log. Upgrade the transaction to read-write the database. (Still readonly for the log.) For each line in the log between the read point and the end, . parse it into a valid database update command, . call the Nuthatch DB routine to perform the update. Update the read-point. . mark the transaction 3. Close the transaction. The Cypress memorial collection of signal arguments Transaction aborted; restart loop, but completed actions are OK. In either case, the reservation that SetLogIndex makes has been cancelled. Ê·˜J™J™yJ™KJ™0J™8J˜šÏk ˜ JšœœÏc˜CJšœœ˜"J˜ Jšœ˜J˜ J˜ J˜ J˜J˜J˜ J˜—šœœ˜"š˜Jšœ ˜&—Jšœ˜Jšœœ˜"J˜J™J™J™žJ™J™Ê™J™1Jšœœ7™NJ™J™—J™J™Jšœœœ˜—J˜š Ïn œœœœ:œœ˜jJšœœœ˜J™3Jšœœœœ˜Jšœœœ˜Jšœœœ˜J˜Jšœœœ˜Jšœ˜ šœ˜šœœ˜%šœ œ˜Jšž@™@—šœ œžA˜QJ™J—Jšœ˜—Jšœœ˜)Jšœ#œœ ˜:Jšœ8œ ˜IJ˜—Jšœœœ˜Jšœ œ˜J˜Jšœ œ˜Jšœœ˜Jšœœ˜Jšœ œ˜ Jšœœ˜Jšœœ˜Jšœ œ˜J˜"Jšœ œ˜Jšœœ˜ šŸœœœ˜Jšœ!˜!Jšœ˜Jšœœ˜Jšœ˜Jšœ˜ Jšœ˜—Jšœœ˜Jšœœœ˜1Jšœ œ˜ J˜,š˜JšœDœœ˜PJšœœ)˜3šœœ˜Jšœ#˜#JšœL˜LJšœF˜FJšœJ˜JJšœH˜HJšœL˜LJšœQ˜QJšœU˜UJšœ˜—šœ˜˜Jšœ-˜-Jšœ7˜7Jšœ&˜&Jšœ3˜3Jšœ0œ˜6J˜—šœ˜J˜'Jšœ3˜3Jšœœœ˜/J˜—˜Jšœ-˜-Jšœ7˜7J˜&Jšœ œ˜&J˜&Jšœ7˜7Jšœœ˜)Jšœœ˜"Jšœœ˜)Jš œœœœœœ˜rJšœœ)˜0˜!J˜J˜J˜J˜J˜J˜J˜%J˜ J˜Jšœ˜ J˜—J˜—Jšœœ˜—Jšœ˜—Jšœž+˜IJšœ0ž*˜ZJšœ4ž˜Sš˜˜ J˜Jš œœœœœ˜EJ˜——J˜Jšœ˜—J˜š Ÿœœœœœœ˜BJšœž˜*Jšœ˜J˜—J˜šŸœœ1˜FJš œœœœ œ˜.Jšœœ˜JšœH˜HJšœœœ˜'J˜—J˜šŸ œœ1˜@Jšœœœ˜(Jšœœœ)˜5Jšœ(˜(Jšœž˜'Jšœž˜.J˜J˜—š Ÿ œœ œœœœ˜FJšœ'˜-Jšœ˜J˜—šœ˜J˜J˜——…—|