Project 5: SNetDB461
Preface
Many of the facilities mentioned here are implemented in the superclasses of
SNetDB461. Those superclasses implement a reasonably general, cross-platform
implementation of record-based files; only the SNetDB461 component knows about the
specific format of the SNet tables. This documentation ignores where functionality
is actually implemented, and just talks about what is available from an SNetDB461
object. It also ignores the code in the superclasses intended to provide generality
beyond SNet.
Tables
An SNetDB461 object provides read/write access to two tables, COMMUNITYTABLE
and PHOTOTABLE. The former holds information about community members,
the latter about photos:
Each record of the community table describes a single member of the SNet
community. Records have five fields.
The Name field is a String giving the fully qualified DDNS name
of the member. It is also the key field of the table.
The Generation is an integer, as are the two photo columns; the latter hold the hash of the
photo's data bytes. A value of 0 is used to indicate "none." (It is very unlikely
that some actual photo will hash to 0. It would also be very unfortunate.)
The isFriend field is a boolean, true if the member is a friend,
and false otherwise.
Each record of the photo table describes a single SNet photo.
Records have three fields. The first is an integer giving the hash of the photo's data.
It is also the key field of table.
The second is a reference count - an integer count of the number of times this photo
appears in the community table, as either a myPhoto or chosenPhoto entry.
The reference count supports garbage collection of photo table records.
Your code is responsible for maintaining the reference count, and for
deleting both the record and the disk file for the photo it describes when the reference
count goes to zero.
The final field is a String giving the absolute (full) path name of the local file storing
the photo's bytes. A value of null indicates that there is no local copy.
It is intended that every photo mentioned in the community table should have a record in the
photo table.
It's important to realize that SNetDB461 doesn't really know anything about
the SNet application. It only knows that it has two tables, and what types of
values are stored in the fields of each. This means it never tries to enforce any
application semantics. All it can do is read and write rows of the two tables.
Records
SNetDB461 defines a record class for each table. A record object represents
a record of a table.
public class PhotoRecord extends Record {
public int hash;
public int refCount;
public File file;
}
public class CommunityRecord extends Record {
public String name;
public int generation;
public int myPhotoHash;
public int chosenPhotoHash;
public boolean isFriend;
}
All instance variables of each record type are public,
and it's intended that client code manipulate them directly.
The only public method they implement is toString().
You do not new up records; they are created by methods
on classes representing their tables.
Table Operations
SNetDB461 itself provides almost no operations. Instead, table classes
(CommunityTable and PhotoTable)
expose methods that allow clients to manipulate them.
SNetDB461 tables provide only very simple operations: read one record, read all records, write one record, and delete a record. The detailed method signatures are given in the
code, but here's a summary.
- Record readOne(key)
If the table contains a record with the given key, it is returned.
Example:
SNetDB461 db = new SNetDB461();
CommunityRecord cRec = db.COMMUNITYTABLE.readOne("foo.cse461.");
PhotoRecord pRec = db.PHOTOTABLE.readOne(1278493845);
- RecordSet<Record> readAll()
Returns all records in the table, as a RecordSet, which is basically
a typed Vector.
Example:
RecordSet<CommunityRecord> cRecVec = db.COMMUNITYTABLE.readAll();
- write(record)
Puts the record in the table, replacing any existing table record containing the same key.
Example:
PhotoRecord pRec = db.PHOTOTABLE.readOne(1278493845);
pRec.generation++;
db.PHOTOTABLE.write(pRec);
- delete(key)
Deletes the table record with the key given in the argument Record.
If there is no such record, does nothing.
Example:
db.PHOTOTABLE.delete(pRec);
You use SNetDB461 mainly by calling methods on the two tables it contains to read a record,
then modify the record in memory, and then write it back. You don't try to modify the tables
directly, using SQL, even if you know SQL and even if the some methods not mentioned here
are public. (Okay, you can do what you want, but there's no support for those things.)
In addition to the above operations, the table classes expose a createRecord() method
used to create a new record to then be initialized and written to the table.
Operations on an SNetDB461 Object
Creation
When you new SNetDB461() it will look for an existing SQLite database
for the SNet application. If it doesn't find one, it will create one.
An SQLite database is simply a file.
The component creating the SNetDB461 (usually an SNetController
object) determines the directory in which to create the DB file, and the name of the file.
Using an SNetDB461
SNetDB461 is built on SQLite. In Android, only the thread that opens an
SQLite database can access the database. This means you need to be careful. The
easiest thing to do is to create an SNetDB461 object when you first need
it, use it so long as you're sure the code is being executed by a single thread,
and forget it when that thread returns to the original caller.
The general form of the code is this:
SNetDB461 db = null;
try {
db = new SNetDB461();
...
} finally {
if ( db != null ) db.discard();
}
fixDB()
The only other method provided by the SNetDB461 class
is fixDB(), which applies heuristics that try to bring the tables
into a sensible state. This method understands the meaning of the data in the tables. None
of the other methods do. As mentioned elsewhere in the documentation, it is destructive.
In the worst case, where the tables have become hopelessly confused, find and delete the
file storing the SQLite database.
The Photo Utility Class
SNetDB461.java also provides a useful utility class, Photo,
not very strongly related
to its main goal (of providing a table abstraction). A Photo object's constructor
takes a Java File object as an argument. The Photo object has
two fields. mPhotoFile is a copy of the constructor's argument. mHash
is the hash value of the file's contents. It's computed automatically when the Photo
object is constructed.
|