DIRECTORY Basics USING [bytesPerWord], BasicTime USING [GMT, Now, nullGMT, ToPupTime], BcdDefs USING [BCD, NullVersion, VersionStamp], Commander USING [CommandProc, Register], DFUtilities USING [Date, RemoveVersionNumber], FS USING [Error, FileInfo, minimumStreamBufferParms, Open, OpenFile, StreamFromOpenFile, StreamOpen], FSBackdoor USING [EnumerateCacheForInfo, InfoProc], GenerateDFClosure USING [ActionProc, ClosureInfo, GenerateClosureToProc], IFSFile USING [Close, Completer, Error, FileHandle, Finalize, FSInstance, Initialize, Login, Logout, Open, Problem, StartRead, UnableToLogin], IO USING [Close, EndOfStream, GetIndex, GetTokenRope, IDProc, PutChar, PutF, PutFR, PutRope, RIS, SetIndex, SetLength, STREAM, UnsafeGetBlock], MessagesOut USING [PutRopes], PriorityQueue USING [Insert, Predict, Ref, Remove, Size, SortPred], Process USING [Pause, SecondsToTicks], ProcessExtras USING [CheckForAbort], Rope USING [Concat, Equal, Fetch, Find, Flatten, FromProc, Index, Length, Match, ROPE, Run, Size, SkipTo, Substr], UserCredentials USING [Get], VersionMap USING [FillInShortNames, Map, MapEntry, MapList, MapRep, MyStamp, Range, RangeList, RangeToEntry, RestoreMapFromFile, SaveMapToFile, ShortNameToRanges, VersionToName], ViewerIO USING [CreateViewerStreams]; VersionMapFromDFImpl: CEDAR MONITOR LOCKS myData USING myData: MyData IMPORTS BasicTime, Commander, DFUtilities, FS, FSBackdoor, GenerateDFClosure, IFSFile, IO, MessagesOut, PriorityQueue, Process, ProcessExtras, Rope, UserCredentials, VersionMap, ViewerIO SHARES IO, VersionMap = BEGIN BCD: TYPE = BcdDefs.BCD; bytesPerWord: NAT = Basics.bytesPerWord; Date: TYPE = DFUtilities.Date; LORA: TYPE = LIST OF REF ANY; PQ: TYPE = PriorityQueue.Ref; GMT: TYPE = BasicTime.GMT; Map: TYPE = VersionMap.Map; MapList: TYPE = VersionMap.MapList; MapEntry: TYPE = VersionMap.MapEntry; MapRep: TYPE = VersionMap.MapRep; MyStamp: TYPE = VersionMap.MyStamp; NullStamp: MyStamp = LOOPHOLE[NullVersion]; MyStampAsHex: TYPE = PACKED ARRAY [0..12) OF [0..16); ROPE: TYPE = Rope.ROPE; RopeList: TYPE = LIST OF ROPE; STREAM: TYPE = IO.STREAM; VersionStamp: TYPE = BcdDefs.VersionStamp; NullVersion: VersionStamp = BcdDefs.NullVersion; FileEntry: TYPE = REF FileEntryRep; FileEntryRep: TYPE = RECORD [ name: ROPE, date: Date, version: VersionStamp, from: ROPE]; NameSeq: TYPE = REF NameSeqRep; NameSeqRep: TYPE = RECORD [ SEQUENCE len: NAT OF NameEntry]; NameEntry: TYPE = RECORD [hasPrefix: BOOL, name: ROPE]; MyData: TYPE = REF MyDataRep; MyDataRep: TYPE = MONITORED RECORD [ sourceQueue: PQ _ NIL, objectQueue: PQ _ NIL, objectFiles,sourceFiles: INT _ 0, oldObjectMap: MapList _ NIL, oldSourceMap: MapList _ NIL, prefix: ROPE _ NIL, errs: STREAM _ NIL, remoteHandle: IFSFile.FSInstance _ NIL, remoteHandleServer: ROPE _ NIL, remoteHandleReleased: CONDITION, which: {source, object, both} _ both, checkRemote: BOOL _ TRUE, remoteHandleOwned: NAT _ 0, abortRequested: BOOL _ FALSE ]; EachFile: GenerateDFClosure.ActionProc = { myData: MyData _ NARROW[data]; CheckAbort[myData]; SELECT kind FROM file => { needsVersion: BOOL _ FALSE; isBcd: BOOL _ FALSE; entry: FileEntry _ NEW[FileEntryRep _ [ name: name, date: date, version: NullVersion, from: from]]; triesLeft: NAT _ 10; -- must be >= 1 IF Rope.Match["*!*", name] THEN isBcd _ Rope.Match["*.symbols!*", name, FALSE] OR Rope.Match["*.bcd!*", name, FALSE] ELSE isBcd _ Rope.Match["*.symbols", name, FALSE] OR Rope.Match["*.bcd", name, FALSE]; IF myData.prefix = NIL AND NOT Rope.Match["[]*", name] THEN { pos: INT _ Rope.Find[name, ">"]; IF pos > 0 THEN myData.prefix _ Rope.Flatten[name, 0, pos+1]; }; IF myData.prefix # NIL THEN IF Rope.Run[myData.prefix, 0, name, 0, FALSE] # Rope.Length[myData.prefix] THEN MessagesOut.PutRopes[ myData.errs, "Prefix warning: ", name, "\n from: ", from]; DO ENABLE FS.Error => { SELECT error.code FROM $serverInaccessible => { MessagesOut.PutRopes[myData.errs, "Server glitch: ", name]; IF (triesLeft _ triesLeft - 1) # 0 THEN LOOP; }; ENDCASE; MessagesOut.PutRopes[ myData.errs, "File not found: ", name, IO.PutFR["\n from: %g\n reason: %g\n", [rope[from]], [rope[error.explanation]]]]; IF error.group # bug THEN EXIT ELSE REJECT; }; IF isBcd THEN SELECT myData.which FROM object,both => FillInObjectVersion[myData, entry, myData.checkRemote]; ENDCASE ELSE SELECT myData.which FROM source,both => FillInSourceVersion[myData, entry, myData.checkRemote]; ENDCASE; EXIT; ENDLOOP; }; ENDCASE; }; FillInSourceVersion: PROC [myData: MyData, entry: FileEntry, checkRemote: BOOL _ TRUE] = { created: BasicTime.GMT _ entry.date.gmt; full: ROPE _ entry.name; attached: ROPE _ NIL; version: VersionStamp; useFileSystem: BOOL _ FALSE; IF entry.date.format = explicit AND created # BasicTime.nullGMT THEN { version _ [0, 0, BasicTime.ToPupTime[created]]; IF checkRemote THEN { IF myData.oldSourceMap = NIL THEN useFileSystem _ TRUE ELSE { full _ VersionMap.VersionToName[myData.oldSourceMap, version].name; IF full = NIL THEN {useFileSystem _ TRUE; full _ entry.name}; }; }; } ELSE { useFileSystem _ TRUE; created _ BasicTime.nullGMT; checkRemote _ TRUE; }; IF useFileSystem THEN { IF created = BasicTime.nullGMT THEN full _ DFUtilities.RemoveVersionNumber[full]; [created: created, fullFName: full, attachedTo: attached] _ FS.FileInfo[ name: full, wantedCreatedTime: created, remoteCheck: checkRemote]; version _ [0, 0, BasicTime.ToPupTime[created]]; }; entry.date _ [format: explicit, gmt: created]; entry.version _ version; IF attached # NIL THEN entry.name _ attached ELSE entry.name _ full; PriorityQueue.Insert[myData.sourceQueue, entry]; myData.sourceFiles _ myData.sourceFiles + 1; }; FillInObjectVersion: PROC [myData: MyData, entry: FileEntry, checkRemote: BOOL _ TRUE] = { outerCreated: BasicTime.GMT _ entry.date.gmt; full: ROPE _ entry.name; attached: ROPE _ NIL; valid: BOOL _ FALSE; -- indicates validity of version stamp IF entry.date.format # explicit THEN { outerCreated _ BasicTime.nullGMT; full _ DFUtilities.RemoveVersionNumber[full]; }; [created: outerCreated, fullFName: full, attachedTo: attached] _ FS.FileInfo[ name: full, wantedCreatedTime: outerCreated, remoteCheck: checkRemote]; entry.date _ [format: explicit, gmt: outerCreated]; IF attached # NIL THEN full _ attached; entry.name _ full; [valid, entry.version] _ FindShortObjectName[myData, full]; IF NOT valid THEN { cacheChecker: FSBackdoor.InfoProc = { IF outerCreated = created AND bytes > 0 THEN { full _ fullGName; inCache _ TRUE; RETURN [FALSE]; }; RETURN [TRUE]; }; inCache: BOOL _ FALSE; FSBackdoor.EnumerateCacheForInfo[cacheChecker, NIL, full]; IF inCache THEN { file: FS.OpenFile _ FS.Open[ name: full, lock: read, wantedCreatedTime: outerCreated, remoteCheck: FALSE]; stream: STREAM _ FS.StreamFromOpenFile[ openFile: file, streamBufferParms: FS.minimumStreamBufferParms]; TRUSTED { ENABLE UNWIND => IO.Close[stream]; versionOffset: NAT = bytesPerWord*SIZE[CARDINAL]; versionBytes: NAT = bytesPerWord*SIZE[VersionStamp]; IO.SetIndex[stream, versionOffset]; [] _ IO.UnsafeGetBlock[ stream, [LOOPHOLE[@entry.version], 0, versionBytes]]; }; IO.Close[stream]; } ELSE { serverPos: INT = Rope.SkipTo[full, 1, "]"]; server: ROPE = Rope.Flatten[full, 1, serverPos-1]; rest: ROPE = Rope.Flatten[full, serverPos+1]; IF AcquireRemoteHandle[myData, server] THEN { {ENABLE UNWIND => ReleaseRemoteHandle[myData]; [valid, entry.version] _ VersionStampFromRemoteHandle[ myData, server, rest, outerCreated]; }; ReleaseRemoteHandle[myData]; IF NOT valid THEN { MessagesOut.PutRopes[myData.errs, "File not found: ", full]; RETURN; }; } ELSE { RETURN; }; }; }; PriorityQueue.Insert[myData.objectQueue, entry]; myData.objectFiles _ myData.objectFiles + 1; }; EntrySortPred: PriorityQueue.SortPred = TRUSTED { xx: MyStamp = LOOPHOLE[LOOPHOLE[x, FileEntry].version]; yy: MyStamp = LOOPHOLE[LOOPHOLE[y, FileEntry].version]; IF xx.num # yy.num THEN RETURN [xx.num < yy.num]; IF xx.hi # yy.hi THEN RETURN [xx.hi < yy.hi]; RETURN [xx.lo < yy.lo]; }; VersionSortPred: PROC [xx,yy: MyStamp] RETURNS [BOOL] = TRUSTED { IF xx.num # yy.num THEN RETURN [xx.num < yy.num]; IF xx.hi # yy.hi THEN RETURN [xx.hi < yy.hi]; RETURN [xx.lo < yy.lo]; }; VersionMapFromPQ: PROC [pq: PQ, prefix: ROPE, myData: MyData] RETURNS [map: Map] = { currentName: ROPE _ prefix _ Rope.Flatten[prefix]; prefixLen: NAT = Rope.Size[prefix]; pos: INT _ prefixLen+1; entries: NAT = PriorityQueue.Size[pq]; seq: NameSeq _ NEW[NameSeqRep[entries]]; entryIndex: NAT _ 0; subPos: NAT _ 0; subLim: NAT _ prefixLen; lastPos: INT _ 0; lag: FileEntry _ NIL; getChar: PROC [] RETURNS [c: CHAR] = { IF subPos < subLim THEN { c _ currentName.Fetch[subPos]; subPos _ subPos + 1; RETURN; }; c _ '\n; IF entryIndex < entries THEN { nameEntry: NameEntry _ seq[entryIndex]; currentName _ nameEntry.name; subLim _ Rope.Length[currentName]; IF nameEntry.hasPrefix THEN subPos _ prefixLen ELSE subPos _ 0; entryIndex _ entryIndex + 1; }; }; ProcessExtras.CheckForAbort[]; map _ NEW[MapRep[entries]]; FOR i: NAT IN [0..entries) DO entry: FileEntry = NARROW[PriorityQueue.Remove[pq]]; name: ROPE = entry.name; hasPrefix: BOOL = Rope.Run[name, 0, prefix, 0, FALSE] = prefixLen; seq[i] _ [hasPrefix, name]; map[i] _ [stamp: LOOPHOLE[entry.version], index: pos]; pos _ pos + Rope.Length[name] + 1; IF hasPrefix THEN pos _ pos - prefixLen; IF lag # NIL AND lag.version = entry.version THEN { MessagesOut.PutRopes[myData.errs, "Warning, duplicate versions for", IO.PutFR["\n %g\n from: %g", [rope[lag.name]], [rope[lag.from]]], IO.PutFR["\n %g\n from: %g", [rope[entry.name]], [rope[entry.from]]] ]; }; lag _ entry; ENDLOOP; map.names _ Rope.FromProc[pos, getChar, 4040]; VersionMap.FillInShortNames[map]; }; WriteMapToFile: PROC [map: Map, name: ROPE] = { prefix: ROPE _ NIL; st: IO.STREAM _ FS.StreamOpen[name, create]; count: NAT _ map.len; names: ROPE _ map.names; firstCR: INT _ names.Index[0, "\n"]; ProcessExtras.CheckForAbort[]; prefix _ names.Flatten[0, firstCR]; IO.PutRope[st, prefix]; IO.PutRope[st, "\n"]; FOR i: NAT IN [0..map.len) DO entry: MapEntry _ map[i]; index: INT _ entry.index; stamp: MyStamp _ entry.stamp; PutStampAsHex[st, stamp]; IO.PutRope[st, " "]; DO c: CHAR _ names.Fetch[index]; index _ index + 1; IO.PutChar[st, c]; IF c = '\n THEN EXIT; ENDLOOP; ENDLOOP; IO.PutRope[st, "\n"]; IO.SetLength[st, IO.GetIndex[st]]; -- force goddamm truncation already!!! IO.Close[st]; }; IndexToShortName: PROC [map: Map, index: INT] RETURNS [ROPE] = { names: ROPE _ map.names; end: INT _ names.SkipTo[index, "!\n"]; pos: INT _ end; WHILE pos > index DO SELECT names.Fetch[pos] FROM '/, '], '> => EXIT; ENDCASE; pos _ pos - 1; ENDLOOP; RETURN [names.Substr[pos, end-pos]]; }; PutStampAsHex: PROC [st: IO.STREAM, stamp: MyStamp] = { hex: MyStampAsHex _ LOOPHOLE[stamp]; FOR index: CARDINAL IN [0..12) DO x: CARDINAL [0..15] _ hex[index]; c: CHAR _ IF x IN [0..9] THEN '0 + x ELSE 'A + (x-10); st.PutChar[c]; ENDLOOP; }; ScanName: PROC [name: ROPE] RETURNS [pos,bang,dot: INT] = { len: INT = Rope.Length[name]; pos _ bang _ dot _ len; WHILE pos > 0 DO posM: INT = pos-1; SELECT Rope.Fetch[name, posM] FROM '! => bang _ dot _ posM; '. => dot _ posM; '>, '/, '] => RETURN; ENDCASE; pos _ posM; ENDLOOP; }; CheckAbort: ENTRY PROC [myData: MyData] = { ENABLE UNWIND => myData.abortRequested _ TRUE; IF myData.abortRequested THEN RETURN WITH ERROR ABORTED; ProcessExtras.CheckForAbort[]; }; CheckAbortInternal: INTERNAL PROC [myData: MyData] = { ENABLE UNWIND => myData.abortRequested _ TRUE; IF myData.abortRequested THEN RETURN WITH ERROR ABORTED; ProcessExtras.CheckForAbort[]; }; AcquireRemoteHandle: ENTRY PROC [myData: MyData, server: ROPE] RETURNS [ok: BOOL _ TRUE] = { ENABLE UNWIND => myData.abortRequested _ TRUE; fs: IFSFile.FSInstance _ NIL; problem: IFSFile.Problem _ ok; CheckAbortInternal[myData]; IF myData.remoteHandle # NIL THEN IF NOT Rope.Equal[myData.remoteHandleServer, server, FALSE] THEN TRUSTED { WHILE myData.remoteHandleOwned # 0 DO CheckAbortInternal[myData]; WAIT myData.remoteHandleReleased; ENDLOOP; fs _ myData.remoteHandle; myData.remoteHandle _ NIL; IF fs # NIL THEN IFSFile.Logout[fs]; }; IF myData.remoteHandle = NIL THEN TRUSTED { userName,password: ROPE; [userName,password] _ UserCredentials.Get[]; fs _ IFSFile.Login[server, userName, password ! IFSFile.UnableToLogin => { why: ROPE _ "Remote access failed for "; SELECT problem FROM credentials => why _ "Invalid credentials for "; io => why _ "Server not found: "; ENDCASE; MessagesOut.PutRopes[myData.errs, why, server]; GO TO notGood; }]; myData.remoteHandle _ fs; myData.remoteHandleServer _ server; }; myData.remoteHandleOwned _ myData.remoteHandleOwned + 1; EXITS notGood => ok _ FALSE; }; NotOwned: ERROR = CODE; ReleaseRemoteHandle: ENTRY PROC [myData: MyData] = { ENABLE UNWIND => myData.abortRequested _ TRUE; IF myData.remoteHandleOwned = 0 THEN RETURN WITH ERROR NotOwned; myData.remoteHandleOwned _ myData.remoteHandleOwned - 1; CheckAbortInternal[myData]; }; FinalizeRemoteHandle: ENTRY PROC [myData: MyData] = TRUSTED { ENABLE UNWIND => myData.abortRequested _ TRUE; fs: IFSFile.FSInstance _ NIL; WHILE myData.remoteHandleOwned # 0 DO WAIT myData.remoteHandleReleased; ENDLOOP; fs _ myData.remoteHandle; myData.remoteHandle _ NIL; IF fs # NIL THEN IFSFile.Logout[fs]; IFSFile.Finalize[]; CheckAbortInternal[myData]; }; VersionStampFromRemoteHandle: PROC [myData: MyData, server,name: ROPE, created: GMT] RETURNS [valid: BOOL _ FALSE, stamp: VersionStamp] = TRUSTED { ENABLE UNWIND => myData.abortRequested _ TRUE; completed: CONDITION; problem: IFSFile.Problem _ ok; OnCompletion: IFSFile.Completer = TRUSTED { problem _ outcome; NoteCompleted[myData]; }; NoteCompleted: ENTRY PROC [myData: MyData] = TRUSTED { BROADCAST completed; }; WaitForCompleted: ENTRY PROC [myData: MyData] = TRUSTED { WAIT completed; }; bcd: BCD; ifsFile: IFSFile.FileHandle _ NIL; bcd.version _ NullVersion; ProcessExtras.CheckForAbort[]; FOR pause: NAT IN [2..7] DO ifsFile _ IFSFile.Open[myData.remoteHandle, name ! IFSFile.Error => {problem _ reason; CONTINUE}]; IF problem = ok THEN EXIT; MessagesOut.PutRopes[myData.errs, "File open glitch: [", server, "]", name]; Process.Pause[Process.SecondsToTicks[pause/2]]; ENDLOOP; IF problem = ok THEN { FOR pause: NAT IN [2..7] DO IFSFile.StartRead[ ifsFile, 0, SIZE[BCD]*bytesPerWord, LOOPHOLE[LONG[@bcd]], OnCompletion, NIL]; WaitForCompleted[myData]; IF problem = ok THEN EXIT; MessagesOut.PutRopes[myData.errs, "File access glitch: [", server, "]", name]; Process.Pause[Process.SecondsToTicks[pause/2]]; ENDLOOP; IFSFile.Close[ifsFile]; valid _ problem = ok; stamp _ bcd.version; }; }; ShortName: PROC [full: ROPE] RETURNS [ROPE] = { pos: INT _ Rope.Length[full]; lim: INT _ pos; WHILE pos > 0 DO c: CHAR = Rope.Fetch[full, pos_pos-1]; SELECT c FROM '! => lim _ pos; '>, '] => {pos _ pos + 1; EXIT}; ENDCASE; ENDLOOP; RETURN [Rope.Flatten[full, pos, lim-pos]]; }; FindShortObjectName: PROC [myData: MyData, full: ROPE] RETURNS [valid: BOOL _ FALSE, stamp: VersionStamp] = { IF myData.oldObjectMap # NIL THEN { short: ROPE = ShortName[full]; rangeList: VersionMap.RangeList _ VersionMap.ShortNameToRanges[myData.oldObjectMap, short]; WHILE rangeList # NIL DO range: VersionMap.Range _ rangeList.first; rangeList _ rangeList.rest; WHILE range.len # 0 DO name: ROPE; stamp: VersionStamp; [name, stamp, range] _ VersionMap.RangeToEntry[range]; IF Rope.Equal[full, name, FALSE] THEN RETURN [TRUE, stamp]; ENDLOOP; ENDLOOP; valid _ FALSE; }; }; warningList: RopeList _ LIST["[Indigo]*", "[Ivy]*"]; GenMap: Commander.CommandProc = { ris: STREAM = IO.RIS[cmd.commandLine]; token: ROPE _ "CurrentCedar"; dump: BOOL _ TRUE; dumpDebug: BOOL _ TRUE; namesOnly: BOOL _ FALSE; remoteOpened: BOOL _ FALSE; pos,bang,dot: INT _ 0; inName,sourceName,objectName,outPrefix: ROPE _ NIL; command: ROPE _ cmd.command; forkers: NAT _ 0; results: GenerateDFClosure.ClosureInfo; myData: MyData; sourceMap: Map _ NIL; objectMap: Map _ NIL; checkRemote: BOOL _ TRUE; inLog,outLog: STREAM _ NIL; genMaps: BOOL _ FALSE; -- gen regular version maps if TRUE trustOld: BOOL _ FALSE; -- trust old version maps if TRUE token _ IO.GetTokenRope[ris, IO.IDProc ! IO.EndOfStream => CONTINUE].token; [pos,bang,dot] _ ScanName[inName _ token]; IF bang = Rope.Size[inName] -- no version stuff AND (bang-dot # 3 OR Rope.Run[inName, dot, ".df", 0, FALSE] # 3) -- no DF extension THEN inName _ Rope.Concat[token, ".df"]; inName _ FS.FileInfo[inName ! FS.Error => IF error.group # bug THEN { IO.PutF[ cmd.out, "\nCan't open %g\n %g\n", [rope[inName]], [rope[error.explanation]]]; GO TO quit; }; ].fullFName; [inLog,outLog] _ ViewerIO.CreateViewerStreams[ "VersionMapBuilder.log", NIL, "VersionMapBuilder.log", FALSE]; [pos,bang,dot] _ ScanName[inName]; outPrefix _ Rope.Flatten[inName, pos, dot-pos]; IO.PutF[outLog, "\nVersion Map Builder started at %g", [time[BasicTime.Now[]]]]; IO.PutF[outLog, "\n\nInput from: %g\n", [rope[inName]]]; sourceName _ Rope.Concat[outPrefix, ".sourceMap"]; objectName _ Rope.Concat[outPrefix, ".objectMap"]; TRUSTED {IFSFile.Initialize[]}; {ENABLE UNWIND => { FinalizeRemoteHandle[myData]; }; SELECT TRUE FROM Rope.Equal[command, "TestMap", FALSE] => { forkers _ 0; }; Rope.Equal[command, "TestMap1", FALSE] => { forkers _ 1; }; Rope.Equal[command, "TestMap2", FALSE] => { forkers _ 2; }; Rope.Equal[command, "TestMap3", FALSE] => { forkers _ 3; }; Rope.Equal[command, "TestMap4", FALSE] => { forkers _ 4; }; Rope.Equal[command, "TestMap8", FALSE] => { forkers _ 8; }; Rope.Equal[command, "GenMap", FALSE] => { forkers _ 2; genMaps _ TRUE; }; Rope.Equal[command, "MergeMap", FALSE] => { forkers _ 2; trustOld _ genMaps _ TRUE; }; Rope.Equal[command, "GenCedarMap", FALSE] => { forkers _ 2; genMaps _ TRUE; outPrefix _ "Cedar"; }; Rope.Equal[command, "MergeCedarMap", FALSE] => { forkers _ 2; trustOld _ genMaps _ TRUE; outPrefix _ "Cedar"; }; ENDCASE; myData _ NEW[MyDataRep _ [ sourceQueue: PriorityQueue.Predict[2000, EntrySortPred], objectQueue: PriorityQueue.Predict[1500, EntrySortPred], errs: outLog, checkRemote: checkRemote ]]; IF genMaps THEN { sourceName _ Rope.Concat[outPrefix, "Source.VersionMap"]; objectName _ Rope.Concat[outPrefix, "Symbols.VersionMap"]; }; IF trustOld THEN { IO.PutRope[outLog, "\nReading old maps."]; myData.oldSourceMap _ LIST[ VersionMap.RestoreMapFromFile[sourceName ! FS.Error => { IO.PutRope[outLog, "\nWarning, can't read "]; IO.PutRope[outLog, sourceName]; CONTINUE}] ]; myData.oldObjectMap _ LIST[ VersionMap.RestoreMapFromFile[objectName ! FS.Error => { IO.PutRope[outLog, "\nWarning, can't read "]; IO.PutRope[outLog, objectName]; GO TO exit}] ]; EXITS exit => {}; }; CheckAbort[myData]; myData.which _ both; IO.PutRope[outLog, "\nGenerating DF closure."]; results _ GenerateDFClosure.GenerateClosureToProc[ inName, outLog, EachFile, myData, [toFork: forkers]]; }; FinalizeRemoteHandle[myData]; IO.PutF[outLog, "\n\n%g DF files, %g source files, %g object files.\n", [integer[results.dfFiles]], [integer[myData.sourceFiles]], [integer[myData.objectFiles]]]; IO.PutRope[outLog, "\nMaking short name index for source map."]; sourceMap _ VersionMapFromPQ[myData.sourceQueue, myData.prefix, myData]; CheckAbort[myData]; IO.PutRope[outLog, "\n\nWriting "]; IO.PutRope[outLog, sourceName]; IO.PutRope[outLog, "\n"]; IF genMaps THEN VersionMap.SaveMapToFile[sourceMap, sourceName] ELSE WriteMapToFile[sourceMap, sourceName]; IO.PutRope[outLog, "\nMaking short name index for object map."]; objectMap _ VersionMapFromPQ[myData.objectQueue, myData.prefix, myData]; CheckAbort[myData]; IO.PutRope[outLog, "\n\nWriting "]; IO.PutRope[outLog, objectName]; IO.PutRope[outLog, "\n"]; IF genMaps THEN VersionMap.SaveMapToFile[objectMap, objectName] ELSE WriteMapToFile[objectMap, objectName]; IO.PutF[outLog, "\n\nVersion maps built at %g\n\n", [time[BasicTime.Now[]]]]; IO.Close[inLog]; IO.Close[outLog]; EXITS quit => {}; }; Commander.Register["GenMap", GenMap]; Commander.Register["MergeMap", GenMap]; Commander.Register["GenCedarMap", GenMap]; Commander.Register["MergeCedarMap", GenMap]; END. VersionMapFromDFImpl.mesa Russ Atkinson, December 12, 1983 1:33 pm T Y P E S Single file processing [data: REF, kind: {file, notFound, syntaxError}, name: ROPE, date: Date, from: ROPE] We need to establish the remote prefix Check file for prefix occurence, give warning if missing There is an explicit date in the DF file We have been instructed to verify the DF file date, either through the remote server OR through the old source version map. We have been instructed to TRUST the old map (if the file is present) For a non-explicit date, we can't trust anything. At this point, created = BasicTime.nullGMT if we are supposed to check the rremote file server. If this check fails, it is the caller's responsibility to handle the error. At this point, created # BasicTime.nullGMT, and the full name is presumed correct (although attached may take precedence as the 'real' name). So it is time to insert this file entry into the priority queue. Read the version number from the BCD. Too bad we have to get the whole file! For object files we are not sure whether we can trust the version number, so we MUST ask the file system. We use the resulting full file name as the truth when searching the old object map. As a side effect, the date in the entry is now explicit. We have to check the file itself, rather than trust the old symbols map [fullGName: ROPE, created: BasicTime.GMT, bytes: INT, keep: CARDINAL] RETURNS [continue: BOOLEAN] We can afford to open the file on the local disk, since this is better than trying to open the remote file. We should try to use the remote server for this file. We could not find the file, so give a message and return We could NOT get to the server, a message has been produced by AcquireRemoteHandle, so we can just return? [x: Item, y: Item, data: REF _ NIL] RETURNS [BOOL] Warn the user that there are duplicate versions Display the entry. Return the name without the prefix or version ... puts out the given ropes to the MessageWindow. This is an entry procedure to keep the message in the MessageWindow consistent. ... puts out the given ropes to the MessageWindow. This is an entry procedure to keep the message in the MessageWindow consistent. RemoteHandle stuff (to avoid races in using it) We have a server open, but it is the wrong one, so close it. Notice that we have limited remote handle ownership to one per process by this approach, since if the current process already owns the wrong server, we will never exit this loop. This is OK, since each process handles only one file at a time when using IFSFile. There is no remote handle, so open one Routines to use the old maps for verification of names At this point we did NOT get a match, so flake out! Main command routine [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] Setup the old maps (if any); also make an index for the object map. stores to *Source.VersionMap & *Symbols.VersionMap stores to *Source.VersionMap & *Symbols.VersionMap stores to CedarSource.VersionMap & CedarSymbols.VersionMap stores to CedarSource.VersionMap & CedarSymbols.VersionMap ÊÞ˜šœ™Jšœ(™(—J˜šÏk ˜ Jšœœ˜Jšœ œœ˜/Jšœœœ˜/Jšœ œ˜(Jšœ œ˜.šœ˜Jšœ\˜\—Jšœ œ#˜3Jšœœ2˜Išœ˜ Jšœ€˜€—šœ˜JšœTœœ˜†—Jšœ œ ˜Jšœœ0˜CJšœœ˜&Jšœœ˜$šœ˜ JšœFœ˜g—Jšœœ˜šœ ˜Jšœ¡˜¡—Jšœ œ˜%J˜—šœœ˜#Jšœœ˜!š˜Jšœ#œ*œa˜²—Jšœœ ˜Jšœ˜J˜—šœ ™ J˜Jšœœ œ˜Jšœœ˜(Jšœœ˜Jš œœœœœœ˜Jšœœ˜Jšœœ œ˜Jšœœ˜Jšœ œ˜#Jšœ œ˜%Jšœœ˜!šœ œ˜#Jšœœ˜+—Jš œœœœ œ ˜5Jšœœœ˜Jš œ œœœœ˜Jšœœœœ˜šœœ˜*Jšœ0˜0—J˜Jšœ œœ˜#šœœœ˜Jšœœ+œ˜;J˜—Jšœ œœ ˜šœ œœ˜Jšœœœ ˜ —Jš œ œœ œœ˜7J˜Jšœœœ ˜šœ œ œœ˜$Jšœ œœ˜Jšœ œœ˜Jšœœ˜!Jšœœ˜Jšœœ˜Jšœœœ˜Jšœœœ˜Jšœ#œ˜'Jšœœœ˜Jšœ œ˜ J˜%Jšœ œœ˜Jšœœ˜Jšœœ˜Jšœ˜J˜——™J™šœ*˜*Jšœœ-œœ™TJšœœ˜Jšœ˜šœ˜šœ ˜ Jšœœœ˜Jšœœœ˜šœœ˜'Jšœ;˜;—Jšœ œÏc˜%šœ˜š˜šœ(œ˜.Jšœœ˜%——š˜šœ&œ˜,Jšœœ˜$———š œœœœœ˜=Jšœ&™&Jšœœ˜ Jšœ œ.˜=J˜—šœœ˜Jšœ8™8šœ%œ˜Jšœ˜Jšœ;˜;———š˜š˜šœ ˜ šœ ˜šœ˜Jšœ;˜;Jšœ!œœ˜-J˜—Jšœ˜—šœ˜Jšœ&˜&šœ&˜(Jšœ*˜*——Jš œœœœœ˜+J˜——šœ˜š˜šœ˜JšœF˜FJš˜——š˜šœ˜JšœF˜FJšœ˜———Jšœ˜Jšœ˜—J˜—Jšœ˜—Jšœ˜J˜—šÏnœ˜Jšœ0œœ˜@Jšœœ˜(Jšœœ˜Jšœ œœ˜Jšœ˜Jšœœœ˜šœœ˜?šœ˜Jšœ!œ™(Jšœ/˜/šœ œ˜Jšœ&œ-œ$™{šœ˜Jšœ˜šœ˜JšœE™EJšœC˜CJšœœœœ˜=J˜——J˜—J˜—šœ˜Jšœ1™1Jšœœ˜Jšœ˜Jšœœ˜J˜——J™Jšœ¬™¬šœœ˜Jšœœ.˜Qšœ<œ ˜HJšœB˜B—Jšœ/˜/J˜—J™JšœÏ™ÏJšœ.˜.Jšœ˜Jšœ œœœ˜DJšœ0˜0Jšœ,˜,J˜J˜—šŸœ˜Jšœ0œœ˜@JšœM™MJšœœ˜-Jšœœ˜Jšœ œœ˜Jšœœœž&˜Jšœœœ˜.Jšœ œ˜Jšœ˜šœ"œ˜+Jšœ˜Jšœ˜J˜—šŸ œœœœ˜6Jš œ ˜Jšœ˜—šŸœœœœ˜9Jšœ ˜J˜—Jšœœ˜ Jšœœ˜"J˜Jšœ˜šœœœ˜šœ0˜0Jšœ&œ˜1—Jšœœœ˜JšœL˜LJšœ/˜/Jšœ˜—šœœ˜šœœœ˜šœ˜Jš œ œœœœœ˜M—Jšœ˜Jšœœœ˜JšœN˜NJšœ/˜/Jšœ˜—Jšœ˜Jšœ˜Jšœ˜J˜—J˜J˜——šœ6™6J˜—šŸ œ˜Jšœœœœ˜Jšœœ˜Jšœœ˜šœ ˜Jšœœ˜&šœ˜ J˜Jšœœ˜ Jšœ˜—Jšœ˜—Jšœ$˜*J˜J˜—šŸœ˜Jš œœœ œœ˜Sšœœœ˜#Jšœœ˜šœ!˜!Jšœ9˜9—šœ œ˜Jšœ*˜*Jšœ˜šœ˜Jšœœ˜ J˜Jšœ6˜6Jš œœœœœ ˜;Jšœ˜—Jšœ˜—Jšœ3™3Jšœœ˜J˜—J˜J˜—šœ™J˜Jšœœ˜;J˜šœ!˜!Jš œœ œœœœ™:Jšœœœœ˜&Jšœœ˜Jšœœœ˜Jšœ œœ˜Jšœ œœ˜Jšœœœ˜Jšœœ˜Jšœ(œœ˜3Jšœ œ˜Jšœ œ˜Jšœ'˜'J˜Jšœœ˜Jšœœ˜Jšœ œœ˜Jšœœœ˜Jšœ œœž#˜:Jšœ œœž!˜9J˜Jš œœœ œœ˜KJšœ*˜*šœž˜/Jšœœ!œž˜TJšœ$˜(—šœ œ˜šœœ ˜ šœœ˜šœ˜Jšœ#˜#Jšœ+˜+—Jšœœ˜ J˜——Jšœ ˜ —J˜šœ.˜.Jšœœœ˜>—Jšœ"˜"Jšœ/˜/JšœN˜PJšœ6˜8Jšœ2˜2Jšœ2˜2Jšœ˜šœ˜šœ˜ Jšœ˜J˜—šœœ˜šœœ˜*Jšœ ˜ Jšœ˜—šœ œ˜+Jšœ ˜ J˜—šœ œ˜+Jšœ ˜ J˜—šœ œ˜+Jšœ ˜ J˜—šœ œ˜+Jšœ ˜ J˜—šœ œ˜+Jšœ ˜ J˜—šœœ˜)Jšœ ˜ Jšœ œ˜J˜—šœ œ˜+Jšœ ˜ Jšœœ˜J˜—šœ#œ˜.Jšœ ˜ Jšœ œ˜Jšœ˜J˜—šœ%œ˜0Jšœ ˜ Jšœœ˜Jšœ˜J˜—Jšœ˜—šœ œ˜Jšœ8˜8Jšœ8˜8Jšœ ˜ J˜Jšœ˜—šœ œ˜Jšœ9˜9Jšœ:˜:J˜—šœ œ˜JšœC™CJšœ(˜*šœœ˜šœ(˜(šœœ ˜Jšœ+˜-Jšœ˜Jšœ˜ ——Jšœ˜—šœœ˜šœ(˜(šœœ ˜Jšœ+˜-Jšœ˜Jšœœ˜ ——J˜—Jšœ ˜J˜—J˜Jšœ˜Jšœ˜Jšœ-˜/šœ2˜2Jšœ5˜5—J˜—Jšœ˜šœE˜GJšœZ˜Z—Jšœ>˜@JšœH˜HJšœ˜Jšœ!˜#Jšœ˜Jšœ˜šœ˜ Jšœ0˜4Jšœ'˜+—Jšœ>˜@JšœH˜HJšœ˜Jšœ!˜#Jšœ˜Jšœ˜šœ˜ Jšœ0˜4Jšœ'˜+—JšœK˜MJšœ˜Jšœ˜J˜Jšœ ˜Jšœ˜J˜—šœ%˜%Jšœ2™2—šœ'˜'Jšœ2™2—šœ*˜*Jšœ:™:—šœ,˜,Jšœ:™:——J˜Jšœ˜J˜—…—N`vT