'From Squeak3.1alpha of 4 February 2001 [latest update: #3500] on 5 February 2001 at 9:38:08 am'! !Utilities class methodsFor: 'fetching updates' stamp: 'tk 2/5/2001 09:36'! readServer: serverList updatesThrough: maxNumber saveLocally: saveLocally updateImage: updateImage "Scan the update server(s) for unassimilated updates. If maxNumber is not nil, it represents the highest-numbered update to load. This makes it possible to update only up to a particular point. If saveLocally is true, then save local copies of the update files on disc. If updateImage is true, then absorb the updates into the current image." "Utilities readServer: Utilities serverUrls updatesThrough: 828 saveLocally: true updateImage: true" | urls failed loaded docQueue this nextDoc docQueueSema str | Cursor wait showWhile: [ urls _ self newUpdatesOn: (serverList collect: [:url | url, 'updates/']) throughNumber: maxNumber. loaded _ 0. failed _ nil. "send downloaded documents throuh this queue" docQueue := SharedQueue new. "this semaphore keeps too many documents from beeing queueed up at a time" docQueueSema := Semaphore new. 5 timesRepeat: [ docQueueSema signal ]. "fork a process to download the updates" self retrieveUrls: urls ontoQueue: docQueue withWaitSema: docQueueSema. "process downloaded updates in the foreground" [ this _ docQueue next. nextDoc _ docQueue next. nextDoc = #failed ifTrue: [ failed _ this ]. (failed isNil and: [ nextDoc ~= #finished ]) ] whileTrue: [ failed ifNil: [ nextDoc reset; text. nextDoc size = 0 ifTrue: [ failed _ this ]. ]. failed ifNil: [ nextDoc peek asciiValue = 4 "pure object file" ifTrue: [failed _ this]]. "Must be fileIn, not pure object file" failed ifNil: [ "(this endsWith: '.html') ifTrue: [doc _ doc asHtml]." "HTML source code not supported here yet" updateImage ifTrue: [ChangeSorter newChangesFromStream: nextDoc named: (this findTokens: '/') last]. saveLocally ifTrue: [self saveUpdate: nextDoc onFile: (this findTokens: '/') last]. "if wanted" loaded _ loaded + 1]. docQueueSema signal]. ]. failed ~~ nil & (urls size - loaded > 0) ifTrue: [ str _ loaded printString ,' new update file(s) processed.'. str _ str, '\Could not load ' withCRs, (urls size - loaded) printString ,' update file(s).', '\Starting with "' withCRs, failed, '".'. self inform: str]. ^ Array with: failed with: loaded ! ! !Utilities class methodsFor: 'fetching updates' stamp: 'tk 2/5/2001 09:37'! readServerUpdatesThrough: maxNumber saveLocally: saveLocally updateImage: updateImage "Scan the update server(s) for unassimilated updates. If maxNumber is not nil, it represents the highest-numbered update to load. This makes it possible to update only up to a particular point. If saveLocally is true, then save local copies of the update files on disc. If updateImage is true, then absorb the updates into the current image. A file on the server called updates.list has the names of the last N update files. We look backwards for the first one we do not have, and start there" "* To add a new update: Name it starting with a new two-digit code. * Do not use %, /, *, space, or more than one period in the name of an update file. * The update name does not need to have any relation to the version name. * Figure out which versions of the system the update makes sense for. * Add the name of the file to each version's category below. * Put this file and the update file on all of the servers. * * To make a new version of the system: Pick a name for it (no restrictions) * Put # and exactly that name on a new line at the end of this file. * During the release process, fill in exactly that name in the dialog box. * Put this file on the server." "Utilities readServerUpdatesThrough: 828 saveLocally: false updateImage: true" "Utilities readServerUpdatesThrough: 828 saveLocally: true updateImage: true" | failed loaded str res servers triple tryAgain | Utilities chooseUpdateList ifFalse: [^ self]. "ask the user which kind of updates" servers _ Utilities serverUrls copy. [servers isEmpty] whileFalse: [ triple _ self readServer: servers updatesThrough: maxNumber saveLocally: saveLocally updateImage: updateImage. "report to user" failed _ triple first. loaded _ triple second. tryAgain _ false. failed ifNil: ["is OK" loaded = 0 ifTrue: ["found no updates" servers size > 1 ifTrue: ["not the last server" res _ PopUpMenu withCaption: 'No new updates on the server ', servers first, ' Would you like to try the next server? (Normally, all servers are identical, but sometimes a server won''t let us store new files, and gets out of date.)' chooseFrom: 'Stop looking\Try next server'. res = 2 ifFalse: [^ self] ifTrue: [servers _ servers allButFirst. "try the next server" tryAgain _ true]]]]. tryAgain ifFalse: [ str _ loaded printString ,' new update file(s) processed.'. ^ self inform: str]. ].! ! !Utilities class methodsFor: 'fetching updates' stamp: 'tk 2/4/2001 14:47'! retrieveUrls: urls ontoQueue: queue withWaitSema: waitSema "download the given list of URLs. The queue will be loaded alternately with url's and with the retrieved contents. If a download fails, the contents will be #failed. If all goes well, a special pair with an empty URL and the contents #finished will be put on the queue. waitSema is waited on every time before a new document is downloaded; this keeps the downloader from getting too far ahead of the main process" "kill the existing downloader if there is one" | doc canPeek front | UpdateDownloader ifNotNil: [UpdateDownloader terminate]. "fork a new downloading process" UpdateDownloader _ [urls do: [:url | waitSema wait. queue nextPut: url. doc _ HTTPSocket httpGet: url accept: 'application/octet-stream'. doc class == String ifTrue: [queue nextPut: #failed. UpdateDownloader _ nil. Processor activeProcess terminate] ifFalse: [canPeek _ 120 min: doc size. front _ doc next: canPeek. doc skip: -1 * canPeek. (front beginsWith: '