CSE 461: Introduction to Computer Communication Networks, Spring 2012
  CSE Home   About Us   Search   Contact Info 
 
Course Home
  Home
Administration
  Overview
  Course email
  Anonymous feedback
  View feedback
 
Assignment Utilities
  Home Virtual Machines
  Homework Turnin
  Class GoPost Forum
  Gradebook
 
Most Everything
  Schedule
  Hw/Project List
    Project 5: SNetDB461

Preface

Many of the facilities mentioned here are implemented in the superclasses of an 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 alos the key field of table. The second is an integer count of the number of times this photo appears in the community table, as either a myPhoto or chosenPhoto entry. It supports garbage collection of photo table records. Your code is responsible for maintaining the reference count, and for deleting the record when the 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.

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 are record type are public, and it's intended that client code manipulate them directly. The only public method they support is toString().

Table Operations

SNetDB461 itself provides almost no operations. Instead, table classes 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.)

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 name of the file will be <fullDDNSname>snet.db, e.g., jz.cse461.snet.db. (Except for the root, the full DDNS name ends with a '.'.)

There's no easy way for the caller to tell if a database already existed or a new one was created. Because of that, when you create the first SNetDB461 object (e.g., in onCreate()) you should simply call the registerMember(String member) method mentioned on the main assignment page to make sure the community table contains records for both the user (whose name is the full DDNS name of the system) and the root (whose name is the null string).

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. Note that this will reset your own generation number to 0, though, and so other clients might essentially ignore you until you modify your gallery enough times to bring your generation number up to a new all-time high (or until you artificially set it high).

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]