Squeak
  links to this page:    
View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide
GOODS
Last updated at 11:54 am UTC on 17 January 2006
GOODS is a distributed, language-neutral object database from Konstantin Knizhnik. It's available at http://www.garret.ru/~knizhnik/goods.html, along with client interfaces for C++, Java, and Perl.
I've now got a pretty usable Squeak interface to it. The full protocol is implemented, and there's a nice metadata layer that allows either transparent storage of Smalltalk objects (using GOODS), or, given some Extra GOODS Type Information, compatibility with the GOODS Java interface storage conventions, for easy sharing of object data between Squeak and Java.


Downloads:

The GOODS client is available from SqueakMap:
http://map1.squeakfoundation.org/sm/package/2653845a-4738-4fa0-9e55-0ee596dea684

A Windows binary of the GOODS server has been made available:
http://www.smalltalking.net/goodies/squeak/files/goods-bin-folder.zip

Windows users: make sure you use the latest vm (at least 3.6.2) there was a bug in older versions.

Getting started:

These instructions assume you have goodsrv running on port 6000.

The only class you should have to deal with directly is KKDatabase. Create it with the onHost:port: class side method:

db := KKDatabase onHost: 'localhost' port: 6000.


When you first open a new database, you need to set the root object:

db root: Dictionary new.
db commit.


After that, you can always access that object through #root.
For example, you can open a second session:


db2 := KKDatabase onHost: 'localhost' port: 6000.
db2 root.


GOODS uses "persistence by reachability" - any object that can be accessed from the root will get stored in the database. For example:


x := OrderedCollection new.
y := 'hello world'.
db2 root at: 'test' put: x.
db2 commit.
"the collection referenced by x is now in the db".
x add: y.
db2 commit.
"now the string referenced by y is too".


Whenever you commit, your local changes are sent to the database, and any remote changes will be sent to your image. If you just want to update your image with the remote changes, use #refresh.


db root. "won't include the collection added to db2"
db refresh.
db root. "now it will"


If two clients change the same object at the same time, you can get a commit conflict. This will raise a KKCommitFailure exception. Possible actions you might want to take are #refresh (which will throw away your conflicting changes, but keep any others), or #rollback (which will throw away all your changes since the last commit). You can then try making your changes and committing again:


(db2 root at: 'test') add: 5.
db2 commit.
[(db root at: 'test') add: 42.
db commit]
on: KKCommitFailure
do: [:ex | db rollback. ex retry]

A shorthand for this is:

db commitWithRetry: [(db root at: 'test') add: 42].


Another way to avoid conflicts is with object locking. See the "locking" protocol of KKDatabase for details - there are blocking and non blocking methods for shared (read) and exclusive locks.

As you load in large numbers of objects, you may find that performance suffers, particularly during commits. You should occasionally send #flush or the more thorough, but slower, #flushAll to the database, which will remove anything it can from the object cache. Always do this right after a successful commit or rollback, or there's a risk of losing your changes.