IIIA-Example for Join Point Subtyping from Berkeley DB

The following example shows a potential application of the join point subtyping capabilities of IIIA.

For this we revisit the logging example from Exposing Local Variables with Explicit Annoucement, where we extraced a Logging feature from Berkeley DB, where trace calls like the following were scattered all over the application:

Original Berkeley DB Code (Excerpt)

public class Tree {
	public long insert(LeafNode ln, byte[] key, ...) { 
		BottomNode bin = findBINForInsert(key, ...);
		long position = ln.log(key, ...);
		bin.updateEntry(ln, position, key);
		bin.clearKnownDeleted();
		traceInsert(Level.FINER, bin, ln, position);
		//...
	}
}

IIIA Implementation

In the IIIA implementation we created a join point type with all 4 parameters and created an explicit join point to expose the local variables.
joinpointtype Trace {
	Level logLevel;
}
joinpointtype TraceInsert extends Trace {
	BottomNode bin;
	LeafNode ln;
	long position;
}
public class Tree exhibits TraceInsert {
	public long insert(LeafNode ln, byte[] key , ... ) { //...
		bin.clearKnownDeleted();
		exhibit new TraceInsert(Level.FINER, bin, ln, position) {};
		// ...
	}
}
public aspect TreeLogging advises TraceInsert {
	after(TraceInsert t){
		traceInsert(t.logLevel, t.bin, t.ln, t.position);
	}
	//...
}

Join Point Type Subtyping

Note, we used join point subtyping and created an abstract join point type Trace that was not directly used in this example. However, we can reuse this abstract join point type, for other necessary join point types that are needed to expose different context information as the following:

joinpointtype TraceDelete extends Trace {
	BottomNode bin;
	Object oldValue;
}
joinpointtype TraceEnvironment extends Trace {
	EnvironmentImpl environment;
}
joinpointtype TraceDatabaseOpen extends Trace {
aspect CriticalErrorAlert advises Trace, TraceInsert {
	declare precedence: CriticalErrorAlert, Tracer;
	after(Trace t) {
		if (t.logLevel==Level.SEVERE) {
			playSound(ERROR_SOUND);
			flashMessage("A severe error has occurred in Berkeley DB. Consult the log file for more information");
		}
	}
	
	private final static String ERROR_SOUND="error.wav";
	private void playSound(String fileName){
		System.out.println("playing "+fileName);
	}
	private void flashMessage(String msg){
		// open window for 3 seconds and flash a message
		System.out.println("Flash Message: "+msg);
	}
}
	DatabaseImpl database;
}

Application

Though, most logging join points in Berkeley DB are heterogeneous - i.e. they occur only in a single position in the source code, and for every join point there is a slightly different advice needed to handle the specific context - we can use the subtyping and advise the abstract join point type as in this example:
aspect CriticalErrorAlert advises Trace, ... {
	after(Trace t) {
		if (t.logLevel==Level.SEVERE) {
			playSound(ERROR_SOUND);
			flashMessage("A severe error has occurred in Berkeley DB. Consult the log file for more information");
		}
	}
}

Back to main page