CSE 461: Introduction to Computer Communication Networks, Autumn 2012
  CSE Home   About Us   Search   Contact Info 
Home
Overview
Course email
Anonymous feedback
View feedback
Course wiki
Home Virtual Machines
Homework Turnin
Class GoPost Forum
Gradebook
Schedule
Hw/Project List
    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.


Computer Science & Engineering
University of Washington
Box 352350
Seattle, WA  98195-2350
(206) 543-1695 voice, (206) 543-2969 FAX
[comments to zahorjan at cs.washington.edu]