Memra

Part 1 recap: events, parsing, exceptions, serialize & restore

The non-concurrent half: parameterized events, parsing examples*.txt with Scanner + regex, a custom ControllerException, an orderly shutdown that logs to error.log, serializing the whole controller to dump.out, and a Restore that resumes from it via a Fixable factory.

What Part 1 adds to the skeleton

The starter GreenhouseControls hard-codes its schedule. Part 1 turns it into a real, fault-tolerant program by adding six things, each a topic from earlier modules made concrete.

1. Parameterized events The starter Bell rings once. Part 1 makes it ring rings times — and the event files declare it: Event=Bell,time=9000,rings=5 (see examples2.txt). So Bell gains a second constructor argument and a loop in action():

public class Bell extends Event {
    private int rings;
    public Bell(long delayTime, int rings) {
        super(delayTime);
        this.rings = rings;
    }
    public void action() {
        for (int i = 0; i < rings; i++) System.out.println("Bing!");
    }
}

examples2.txt also introduces FansOn / FansOff — proving the framework extends by adding an inner Event subclass, never by editing the controller.

2. Parse the event file with Scanner + regex Each line looks like Event=LightOn,time=2000 (optionally ,rings=5). You read the file with a Scanner and pull the fields with a capturing regex (Module 4): a group for the event name, a group for the time, an optional group for rings. The captured name string is what later (Part 2) feeds reflection.

Pattern p = Pattern.compile("Event=(\\w+),time=(\\d+)(?:,rings=(\\d+))?");
Matcher m = p.matcher(line);
if (m.matches()) {
    String name = m.group(1);
    long time = Long.parseLong(m.group(2));
    // m.group(3) is null when ,rings= is absent
}

3. A custom checked exception A fault — a stuck window, a power cut — is a recoverable condition the caller must handle, so it is a checked exception (extends Exception, Module 3):

public class ControllerException extends Exception {
    public ControllerException(String why) { super(why); }
}

The new fault events throw it: WindowMalfunction and PowerOut (added in examples3.txt / examples4.txt) throw new ControllerException(...) from action().

4. Orderly shutdown that logs When run() catches a ControllerException, it does not crash — it calls shutdown(), which records the failure to error.log (append mode + a timestamp, Module 8) and then exits cleanly. This is the fault half of the project.

5. Serialize the whole controller GreenhouseControls is made Serializable, so on certain faults the program can write its entire object graph — controller, event list, current state — to dump.out with an ObjectOutputStream (Module 8). The clock-related fields are marked transient (absolute times are meaningless after a reload).

6. Restore from the dump Run with -d dump.out and a Restore path deserializes that file with an ObjectInputStream, calls start() on each surviving event to re-base its time onto now, and resumes the run() loop — the program picks up where it crashed.

The Fixable factory ties it together Faults map to fixes through an interface used as a factory (Module 2.3). A Fixable declares fix() and log(); a getFixable(int errorcode) method returns the right Fixable for each error code — so adding a new fault is adding a case, not rewriting the recovery logic:

public interface Fixable {
    void fix();
    void log();
}

How it runs java GreenhouseControls -f examples3.txt parses the file into events, runs them in time order, and when WindowMalfunction fires it throws ControllerException; run() catches it, shutdown() logs to error.log and serializes to dump.out; later java GreenhouseControls -d dump.out restores and continues.

-f examples3.txtScanner + regex build the eventsWindowMalfunctionthrows ControllerExceptionrun() catches itno crashshutdown()error.log + dump.out-d dump.outstart() re-bases each event
One run, end to end. The fault does not crash the program: it becomes a checked exception the run loop catches, and shutdown() leaves behind both the log and the object graph a later -d run resumes from.
~/memra/learn/comp-308/part-1-recap