mdj wrote:
On Apr 28, 3:28 pm, "Michael J. Mahon" <mjma...@aol.com> wrote:Michael J. Mahon wrote:Michael J. Mahon wrote:I'm getting close to releasing this, so I thought I'd provide a few updates...<brazen preannouncement>I'm finishing up a file server for NadaNet that is written in Applesoft BASIC running under ProDOS, in less than 300 lines, with Applesoft client-side code of about 15 lines. ;-)It handles all the BASIC.SYSTEM commands that make sense from a remote machine (BSAVE, BLOAD, BRUN, SAVE, RUN, CREATE, DELETE, LOCK, UNLOCK, RENAME, and VERIFY), with all the legal parameters. After each command is completed by the server, it posts to the client the result code (with error code, if any), the AUX TYPE, and the EOF of the file if data was transferred.This allows any machine on a NadaNet to use the filesystem on the server using an invoking interface like:RQ$ = "bload myprog,a$2000":gosub 10000Of course, the request string can be formed by concatenating any variable parameter values, etc., as desired.Errors can be handled in-line by setting EH=1 prior to the GOSUB and then examining the value of RC after the GOSUB. (If EH=0, then any error results in an error message and a STOP.)The current implementation is geared to a network of more than two machines, and uses a message server to queue the requests. The server and client code are easily modified for a two-machine network that forgoes queueing (since one client can't have more than one request in the queue at a time anyway) and so doesn't need the message server.The client machine queues a request (prefixed with its machine ID) by doing a &PUTMSG to the predetermined file server queue number, then idles in a &SERVE() loop polling the result code after each network transaction handled by the client. When it finds a result, it returns from the GOSUB and continues execution.The file server idles polling its input queue with a &GETMSG, and, when it finds a request, it parses it, sets up any required parameters that were not supplied, and executes the command on the local file system.If a data transfer is required, it is &PEEKed and BSAVEd or BLOADed and &POKEd in chunks up to some maximum (like 4KB, to keep network latency reasonable). When the command is complete, the result code, and any address and EOF information, is &POKEd to the requester, and the server goes on to the next request in its queue.Performance seems to be quite good, limited primarily by device latency and/or network bandwidth (>10KB/sec).After I get a little further down the road (and get back from a short trip) I'll complete testing and do some performance characterization.After doing some performance measurement of v1.0, I found that my Applesoft code for scanning requests and their parameters was slower than I thought (I'm too used to my Zip Chip ;-). For a typical request, it was taking about 1.5 seconds on a 1MHz machine! It's hard to afford structure in Applesoft.So I recoded the scanner to use Applesoft's DATA statement scanner, and that speeded up request scanning by a factor of three--good enough for government work. ;-) Version 1.1 works quite efficiently.When that's satisfactory, I'll be writing it up and posting it on my web site for people to play with, or just take a look at. I think there is some value in publishing code that implements modest network functionality concisely.</brazen preannouncement>I expect to finish up within the next week--now all I need are some NadaNet users. ;-) (Bill Garber still has some NadaNet adapters for anyone who'd rather buy than build...)OK, it's out there. ;-) It's linked prominently from my main page, as well as from new "mentions" in several of the other articles. There is a pretty complete performance section, with comparisons to local floppy and local CFFA access.Very cool Michael :-)
Thanks--it was fun to do! Having a file server opens up a huge category of applications to 'Crate machines. Since they have no local I/O, putting a file server on the network gives them a much richer environment. In the past, I've tended to "set up" the 'Crate machines from the master machine, then just "start"ed them up. It's now possible to load them with a very small program launcher (think of it as a high- level "boot"), and then let them "get their own stuff together". ;-) If greater control over synchrony is needed, they can all rendezvous or wait for a broadcast signal from the master. Making the application programs be responsible for loading up their environments makes an application much more readable than having the "initialization" part in a separate program running on the master.
I particularly like the use of the Applesoft DATA statements in the servers' command lexical scanner/parser. A little obtuse, but nonetheless an elegant optimisation and an excellent performance/ maintainability engineering tradeoff. It must've been very tempting just to recode the critical section in assembly ;-)
Ironically, as I was coding the original nested-GOSUB Applesoft parser, I was always thinking on the side about how sweet it could be in assembly--the 6502 is a *great* scanning machine! You'll note that I couldn't resist in the case of folding the request to upper case in Applesoft. Since that was the only character-by- character processing remaining (hex excepted), I wrote a snippet of code to fold the whole request in less time than it takes Applesoft to do one statement. ;-) -michael NadaNet file server for Apple II computers! Home page: http://members.aol.com/MJMahon/ "The wastebasket is our most important design tool--and it's seriously underused."