arlut.csd.ganymede
Class GanymedeBuilderTask

java.lang.Object
  |
  +--arlut.csd.ganymede.GanymedeBuilderTask
All Implemented Interfaces:
java.lang.Runnable

public abstract class GanymedeBuilderTask
extends java.lang.Object
implements java.lang.Runnable

This class provides a template for code to be attached to the server to handle propagating data from the Ganymede object store into the wide world, via NIS, DNS, NIS+, LDAP, JNDI, JDBC, X, Y, Z, etc.

Subclasses of GanymedeBuilderTask need to implement builderPhase1() and builderPhase2(). builderPhase1() is run while a dumpLock is established on DBStore, guaranteeing a transaction-consistent database state. builderPhase1() should do whatever is required to write out files or otherwise propagate data out from the database. If builderPhase1() returns true, the dump lock is released and builderPhase2() is run. This method is intended to run external scripts and/or code that can process the files/data written out by builderPhase1() without needing the database to remain locked.

All subclasses of GanymedeBuilderTask need to be registered in the Ganymede database via the task object type. GanymedeBuilderTasks registered to be run on database commit will automatically be issued by the GanymedeScheduler when transactions commit. The GanymedeScheduler is designed so that it will not re-issue a specific task while a previous instance of the task is still running, so you don't have to worry about builderPhase2() taking a fair amount of time. builderPhase1() should be as fast as possible, however, as no additional transactions will be able to be committed until builderPhase1() completes.


Field Summary
private static java.util.Hashtable backupsBusy
          This hashtable maps directory paths to an Integer counting the number of tasks that are currently copying backup files to it.
private static java.lang.String basePath
           
private static java.lang.String currentBackUpDirectory
           
private static boolean debug
           
private static boolean firstRun
           
private  boolean forceAllBases
          If this flag is true, baseChanged() will always return true, as a way of forcing consideration of all databases that might be examined by GanymedeBuilderTask subclasses.
private static int id
           
protected  java.util.Date lastRunTime
           
(package private)  arlut.csd.ganymede.DBDumpLock lock
           
private static java.lang.String oldBackUpDirectory
           
protected  java.util.Date oldLastRunTime
           
(package private)  java.util.Vector optionsCache
           
private static int phase1Count
          Count of the number of builder tasks currently running in phase 1.
private static int phase2Count
          Count of the number of builder tasks currently running in phase 1.
private static long rolloverTime
           
private static long rollunderTime
           
(package private)  arlut.csd.ganymede.GanymedeSession session
           
protected  arlut.csd.ganymede.Invid taskDefObjInvid
          Must be protected so subclasses in a different package can set this.
 
Constructor Summary
GanymedeBuilderTask()
           
 
Method Summary
protected  boolean baseChanged(short baseid)
          This method is used by subclasses of GanymedeBuilderTask to determine whether a particular base has had any modifications made to it since the last time this builder task was run.
abstract  boolean builderPhase1()
          This method is intended to be overridden by subclasses of GanymedeBuilderTask.
abstract  boolean builderPhase2()
          This method is intended to be overridden by subclasses of GanymedeBuilderTask.
private static int busyCount(java.lang.String path)
           
private static void cleanBackupDirectory()
           This static method is run before the first time a builder task writes any file on server start-up.
private static void decBusy(java.lang.String path)
           
(package private) static void decPhase1(boolean update)
           
(package private) static void decPhase2(boolean update)
           
protected  java.util.Enumeration enumerateObjects(short baseid)
          This method is used by subclasses of GanymedeBuilderTask to obtain a list of DBObject references of the requested type.
protected  java.lang.String getLabel(arlut.csd.ganymede.Invid invid)
          This method is used by subclasses of GanymedeBuilderTask to obtain the label for an object.
protected  arlut.csd.ganymede.DBObject getObject(arlut.csd.ganymede.Invid invid)
          This method is used by subclasses of GanymedeBuilderTask to obtain a reference to a DBObject matching a given invid.
(package private)  java.util.Vector getOptionStrings()
          This method returns the Vector of option strings registered for this task object in the Ganymede database, or null if no option strings are defined.
protected  java.lang.String getOptionValue(java.lang.String option)
          This method retrieves the value associated with the provided option name if this builder task was registered with taskDefObjInvid set by a subclass whose constructor takes an Invid parameter and which sets taskDefObjInvid in GanymedeBuilderTask.
static int getPhase1Count()
          This is public for GanymedeSession.openTransaction(), as a hack to support proper updating of the client's status icon on client connect.
static int getPhase2Count()
          This is public for GanymedeSession.openTransaction(), as a hack to support proper updating of the client's status icon on client connect.
private static void incBusy(java.lang.String path)
           
(package private) static void incPhase1(boolean update)
           
(package private) static void incPhase2(boolean update)
           
protected  boolean isOptionSet(java.lang.String option)
          This method looks in the optionStrings field in the task object associated with this task and determines whether the given option name is present in the field.
private static void openBackupDirectory(java.lang.String filename)
          This method is called before the server's builder tasks are run and creates a backup directory for files to be copied to.
protected  java.io.PrintWriter openOutFile(java.lang.String filename)
          This method opens the specified file for writing out a text stream.
protected  java.io.PrintWriter openOutFile(java.lang.String filename, java.lang.String taskName)
          This method opens the specified file for writing out a text stream.
 void run()
          This method is the main entry point for the GanymedeBuilderTask.
 void run(java.lang.Object[] options)
          This method is the main entry point for the GanymedeBuilderTask.
(package private) static void updateBuildStatus()
          This method is called by the GanymedeBuilderTask base class to record that the server is processing a build.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

debug

private static final boolean debug
See Also:
Constant Field Values

currentBackUpDirectory

private static java.lang.String currentBackUpDirectory

oldBackUpDirectory

private static java.lang.String oldBackUpDirectory

backupsBusy

private static java.util.Hashtable backupsBusy

This hashtable maps directory paths to an Integer counting the number of tasks that are currently copying backup files to it. If the current day's directory path changes and this count goes to zero, the old directory will be zipped up and deleted.


basePath

private static java.lang.String basePath

rollunderTime

private static long rollunderTime

rolloverTime

private static long rolloverTime

firstRun

private static boolean firstRun

id

private static int id

phase1Count

private static int phase1Count

Count of the number of builder tasks currently running in phase 1.


phase2Count

private static int phase2Count

Count of the number of builder tasks currently running in phase 1.


lastRunTime

protected java.util.Date lastRunTime

oldLastRunTime

protected java.util.Date oldLastRunTime

session

arlut.csd.ganymede.GanymedeSession session

lock

arlut.csd.ganymede.DBDumpLock lock

optionsCache

java.util.Vector optionsCache

forceAllBases

private boolean forceAllBases

If this flag is true, baseChanged() will always return true, as a way of forcing consideration of all databases that might be examined by GanymedeBuilderTask subclasses.


taskDefObjInvid

protected arlut.csd.ganymede.Invid taskDefObjInvid

Must be protected so subclasses in a different package can set this.

Constructor Detail

GanymedeBuilderTask

public GanymedeBuilderTask()
Method Detail

run

public final void run()

This method is the main entry point for the GanymedeBuilderTask. It is responsible for setting up the environment for a builder task to operate under, and for actually invoking the builder method.

Specified by:
run in interface java.lang.Runnable

run

public final void run(java.lang.Object[] options)

This method is the main entry point for the GanymedeBuilderTask. It is responsible for setting up the environment for a builder task to operate under, and for actually invoking the builder method.


baseChanged

protected final boolean baseChanged(short baseid)

This method is used by subclasses of GanymedeBuilderTask to determine whether a particular base has had any modifications made to it since the last time this builder task was run.

Parameters:
baseid - The id number of the base to be checked

enumerateObjects

protected final java.util.Enumeration enumerateObjects(short baseid)

This method is used by subclasses of GanymedeBuilderTask to obtain a list of DBObject references of the requested type.

Note that the Enumeration returned by this method MUST NOT be used after builderPhase1() returns. This Enumeration is only valid while the base in question is locked with the global dumpLock obtained before builderPhase1() is run and which is released after builderPhase1() returns.

Parameters:
baseid - The id number of the base to be listed
Returns:
An Enumeration of DBObject references

getObject

protected final arlut.csd.ganymede.DBObject getObject(arlut.csd.ganymede.Invid invid)

This method is used by subclasses of GanymedeBuilderTask to obtain a reference to a DBObject matching a given invid.

Parameters:
invid - The object id of the object to be viewed

getLabel

protected final java.lang.String getLabel(arlut.csd.ganymede.Invid invid)

This method is used by subclasses of GanymedeBuilderTask to obtain the label for an object.


builderPhase1

public abstract boolean builderPhase1()

This method is intended to be overridden by subclasses of GanymedeBuilderTask.

This method runs with a dumpLock obtained for the builder task.

Code run in builderPhase1() can call enumerateObjects() and baseChanged(). Note that the Enumeration of objects returned by enumerateObjects() is only valid and should only be consulted while builderPhase1 is running.. as soon as builderPhase1 returns, the dumpLock used to make the enumerateObjects() call safe to use is relinquished, and any Enumerations obtained will then be unsafe to depend on.

Returns:
true if builderPhase1 made changes necessitating the execution of builderPhase2.

builderPhase2

public abstract boolean builderPhase2()

This method is intended to be overridden by subclasses of GanymedeBuilderTask.

This method runs after this task's dumpLock has been relinquished. This method is intended to be used to finish off a build process by running (probably external) code that does not require direct access to the database.

For instance, for an NIS builder task, builderPhase1() would scan the Ganymede object store and write out NIS-compatible source files. builderPhase1() would return, the run() method drops the dump lock so that other transactions can be committed, and then builderPhase2() can be run to turn those on-disk files written by builderPhase1() into NIS maps. This generally involves executing an external Makefile, which can take an indeterminate period of time.

By releasing the dumpLock before we get to that point, we minimize contention for users of the system.

As a result of having dropped the dumpLock, enumerateObjects() cannot be called by this method.

builderPhase2 is only run if builderPhase1 returns true.


isOptionSet

protected boolean isOptionSet(java.lang.String option)

This method looks in the optionStrings field in the task object associated with this task and determines whether the given option name is present in the field. This works only if this builder task was registered with taskDefObjInvid set by a subclass whose constructor takes an Invid parameter and which sets taskDefObjInvid in GanymedeBuilderTask.

That is, if the task object for this task has an option strings vector with the following contents:

  useMD5
  useShadow
 

then a call to isOptionSet with 'useMD5' or 'useShadow', of any capitalization, will return true. Any other parameter provided to isOptionSet() will cause null to be returned.


getOptionValue

protected java.lang.String getOptionValue(java.lang.String option)

This method retrieves the value associated with the provided option name if this builder task was registered with taskDefObjInvid set by a subclass whose constructor takes an Invid parameter and which sets taskDefObjInvid in GanymedeBuilderTask.

getOptionValue() will search through the option strings for the task object associated with this task and return the substring after the '=' character, if the option name is found on the left.

That is, if the task object for this task has an option strings vector with the following contents:

  useMD5
  buildPath=/var/ganymede/schema/NT
  useShadow
 

then a call to getOptionValue() with 'buildPath', of any capitalization, as the parameter will return '/var/ganymede/schema/NT'.

Any other parameter provided to getOptionValue() will cause null to be returned.


getOptionStrings

final java.util.Vector getOptionStrings()

This method returns the Vector of option strings registered for this task object in the Ganymede database, or null if no option strings are defined.


openOutFile

protected java.io.PrintWriter openOutFile(java.lang.String filename)
                                   throws java.io.IOException
This method opens the specified file for writing out a text stream. If the files have not yet been backed up this run time, openOutFile() will cause the files in Ganymede's output directory to be zipped up before overwriting any files.

java.io.IOException

openOutFile

protected java.io.PrintWriter openOutFile(java.lang.String filename,
                                          java.lang.String taskName)
                                   throws java.io.IOException
This method opens the specified file for writing out a text stream. If the files have not yet been backed up this run time, openOutFile() will cause the files in Ganymede's output directory to be zipped up before overwriting any files.

Parameters:
filename - The name of the file to open
taskName - The name of the builder task that is writing this file. Used to create a unique name (across tasks) for the backup copy of the file when we overwrite an existing file.
java.io.IOException

incBusy

private static void incBusy(java.lang.String path)

decBusy

private static void decBusy(java.lang.String path)

busyCount

private static int busyCount(java.lang.String path)

openBackupDirectory

private static void openBackupDirectory(java.lang.String filename)
                                 throws java.io.IOException

This method is called before the server's builder tasks are run and creates a backup directory for files to be copied to.

java.io.IOException

cleanBackupDirectory

private static void cleanBackupDirectory()
                                  throws java.io.IOException

This static method is run before the first time a builder task writes any file on server start-up. It is responsible for sweeping through the system backup directory and zipping up any day directories that are lingering from earlier runs.

java.io.IOException

getPhase1Count

public static int getPhase1Count()

This is public for GanymedeSession.openTransaction(), as a hack to support proper updating of the client's status icon on client connect.


getPhase2Count

public static int getPhase2Count()

This is public for GanymedeSession.openTransaction(), as a hack to support proper updating of the client's status icon on client connect.


incPhase1

static void incPhase1(boolean update)

decPhase1

static void decPhase1(boolean update)

incPhase2

static void incPhase2(boolean update)

decPhase2

static void decPhase2(boolean update)

updateBuildStatus

static void updateBuildStatus()

This method is called by the GanymedeBuilderTask base class to record that the server is processing a build.