If somebody knows what happens, please advise.
I implemented a classroom management (turnin/grading) system for Mark Guzdial's class, and recently we discovered the following problem (I am skipping hours of raiding for the lost shark):
Large turnins (i.e., for which text instance variable is >16384 bytes) could not be recovered from a DataStream. Running a debugger revealed that the error occurred after the text (that was supposed to be over 16K long) was recovered into an empty String. However, the error was raised only when the next instance variable was being read: DataStream raised 'Expected start of object but found 0' error.
It is my understanding that the text instance variable (containing a String at the time of save) was written as ByteArray (because it was longer than 16384 bytes). However, when it was read from DataStream, it did not recover correctly (tried to read as String?).
Bolot Kerimbaev
PS. I am using Mark Guzdial's FileDictionary, which provides a Dictionary like access to data in a PositionableDataStream (which extends DataStream with position, position:, and setToEnd methods).
This is a message I sent to Mark and his TAs.
---------- Forwarded message ---------- Date: Thu, 28 May 1998 17:16:15 -0400 (EDT) From: Bolot Kerimbaev bolot@cc.gatech.edu To: CS 2390 Admin cs2390-ta@cc.gatech.edu Subject: saga: root of problems
New theory:
When a Turnin is saved to disk, it iterates through its instance variables and tries to save each of them. Since code is-a String, it is subject to the 16384 byte limitation (DataStream>>writeString), i.e., instead of trying to save it as a String, DataStream saves that large chunk of code as a ByteArray. But ByteArray and String use 4 and 2 bytes to save length respectively. In other words, they are different.
Now, when that Turnin is read from the disk, Turnin tries to restore code (which is in Turnin's text instVar). But for some reason (have not figured out how exactly), it stores '' (at least on my test runs) in text, and then chokes on Timestamp. Apparently, it does not correctly process text instVar, which messes up its DataStream position counter, and then tries to read Timestamp from an incorrect position!
I reproduced the problem using 'bare' FileDictionary:
| sqFD data | data := Turnin new initialize; text: (String new: 17000 withAll: $a). sqFD := FileDictionary fileNamed: 'test'. sqFD open. sqFD at: 'fred' put: data. sqFD close.
and then to read (and crash):
| sqFD data | sqFD := FileDictionary fileNamed: 'test'. sqFD open. [data := sqFD at: 'fred' ] ifError: [:msg :rec | Transcript show: 'This is the error! Trying to read Timestamp, but Turnin instVar>>text was not properly handled'; cr. sqFD close]. sqFD close. " you won't get here " data inspect.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Bolot Kerimbaev (bolot@cc.gatech.edu) ------------------------------------- The difficult -- we'll do immediately. The impossible will take a bit longer.
Folks, Bolot is right about the bug in how DataStream stores large strings on the disk. There was one bug in reading of strings between 192 and 16384 long, and another in reading strings >16384. You can tell this was not used much.... I sent him a permanent fix, and it will be in an update soon. --Ted.
Ted Kaehler, Walt Disney Imagineering, R&D (home) 3415 Cork Oak Way, Palo Alto, CA 94303. voice (650) 424-1070 http://www.webPage.com/~kaehler2/ Give me your old Macintosh! I will put it in a first grade classroom.
squeak-dev@lists.squeakfoundation.org