An Example of a Kinoko Component Script

The following is an example of a Kinoko Component Script, which describes component deployments and arrangements.

This example shows the power of expression of the Kinoko script. Usually users will not need to write a script this complicated.

/* SmallKinoko.kcom */
/* Created by Enomoto Sanshiro on 27 August 2000. */
/* Last updated by Enomoto Sanshiro on 15 May 2002. */


import KinokoCollector;
import KinokoDataFlowMeter;
import KinokoBuffer;
import KinokoRecorder;
import KinokoViewer;
import KinokoController;
import KinokoLogger;
import KinokoReporter;


string host = "localhost";
int buffer_size = 32 * 1024 * 1024;
string log_file_name = "log-smallkinoko.xml";
string report_file_name = "report-smallkinoko.xml";

string kinoko_root = getEnvironmentVariable("KINOKO_ROOT");
if (kinoko_root == "") {
    println("ERROR: environment variable KINOKO_ROOT is not defined");
    exit;
}
string script_path = kinoko_root + "/scripts";

int is_enterprise_mode = 0;
if (isOptionSpecified("--enterprise")) {
    is_enterprise_mode = 1;
}

int default_port_base = 45000;
int port_base;
string port_base_string = getEnvironmentVariable("KINOKO_SHELL_PORT_BASE");
if (port_base_string != "") {
    try {
        port_base = port_base_string;
    }
    catch {
        port_base = default_port_base;
    }
}
else {
    port_base = default_port_base;
}

int port_control = port_base;
int port_log = port_base + 1;
int port_view = port_base + 2;

string ui_control = "port: " + port_control;
string ui_log = "port: " + port_log;
string ui_view = "port: " + port_view;

execute("kinoko-control --client localhost " + port_control);
execute("kinoko-board --client localhost " + port_log);
execute("kinoko-canvas --client localhost " + port_view);


component KinokoController controller(host, ui_control);
component KinokoReporter reporter(host);
component KinokoCollector collector(host);
component KinokoBuffer buffer(host);
component KinokoRecorder recorder(host);
component KinokoDataFlowMeter flow_meter(host);
component KinokoViewer viewer(host, ui_view);
component KinokoLogger logger(host, ui_log);

string readout_script;
string readout_datasource;
string view_script;
string view_display;
string data_file;
long start_time = 0;
long stop_time = 0;
int error_count = 0;
int warning_count = 0;
int supernova_count = 0;
string error_message;
int is_constructed = 0;
int is_running = 0;


on startup()
{
    println();
    println("****************************");
    println("*  Welcome to SmallKinoko  *");
    println("****************************");
    println();

    setTimeout(10);

    logger.startLogging(log_file_name);

    if (is_enterprise_mode) {
        controller.open(script_path + "/SmallKinoko-Enterprise.kcml");
        controller.load("last.smallkinoko-enterprise.kcv");
    }
    else {
        controller.open(script_path + "/SmallKinoko.kcml");
        controller.load("last.smallkinoko.kcv");
    }

    controller.changeState("component_ready");
    connect();

    if (error_count == 0) {
        controller.changeState("stream_ready");
    }
    else {
        controller.set("message", "error: click [quit] to shutdown");
        controller.changeState("error");
    }
}

on shutdown()
{
    println();
    println("shutdown completed");
}

on controller.construct()
{
    if (is_constructed) {
        disableTimeout();
        string dicision = controller.openQueryPopup("Warning", "Yes No", "system already constructed\n-- reconstruct?");
        enableTimeout();

        if (dicision != "Yes") {
            return;
        }

        destruct();
        is_constructed = 0;
    }

    controller.changeState("constructing");
    controller.set("message", "constructing...");

    if (construct() && (error_count == 0)) {
        controller.changeState("system_ready");
        controller.set("message", "system is ready to start data acquisition");
        is_constructed = 1;
    }
    else {
        controller.changeState("stream_ready");
        controller.set("message", "system construction failed: try again.");
    }
}

on controller.start() 
{
    controller.changeState("data_taking");
    controller.set("message", "data taking...");

    start();
    is_running = 1;
}

on controller.stop() 
{
    controller.changeState("stopping");
    controller.set("message", "stopping");

    stop();
    is_running = 0;
}

on recorder.finishRecording()
{
    controller.changeState("system_ready");
    controller.set("message", "system is ready to start data acquisition");
}

on controller.clear() 
{
    viewer.reset();
}

on controller.quit()
{
    controller.changeState("shutdown");
    controller.set("message", "shutting down");

    if (is_enterprise_mode) {
        controller.save("last.smallkinoko-enterprise.kcv");
    }
    else {
        controller.save("last.smallkinoko.kcv");
    }

    if (is_constructed) {
        destruct();
    }

    disconnect();
    quit();

    exit;
}

on recorder.diskSpaceExhausted()
{
    logger.writeError("disk space exhausted");

    if (is_running) {
        controller.changeState("stopping");
        controller.set("message", "stopping");
        stop();
        is_running = 0;
    }
}

on logger.processWarning(string message)
{
    ++warning_count;
}

on logger.processError(string message)
{
    if (error_count == 0) {
        error_message = message;
        controller.openPopup("Error", "OK", message);
    }
    print("\a");
    ++error_count;
}

on logger.processPanic(string message)
{
}


void connect()
{
    buffer.setBufferSize(buffer_size);
    buffer.start();
        
    asynchronously {
        collector.setSink(buffer);
        recorder.setSource(buffer);
        flow_meter.setSourceSink(buffer, viewer);
        viewer.setSource(flow_meter);
    }
    
    asynchronously {
        collector.connect();
        recorder.connect();
        flow_meter.connect();
        viewer.connect();
    }
}

int construct()
{
    string run_name = getRegistry("control/run_name");
    string comment = getRegistry("control/comment");
    readout_script = getRegistry("control/readout_script");
    readout_datasource = "";
    view_script = getRegistry("control/view_script");
    view_display = "";
    data_file = getRegistry("control/data_file");

    if (recorder.isFileReadable(data_file)) {
        disableTimeout();
        string dicision = controller.openQueryPopup("Warning", "Yes No", "file exists: " + data_file + " -- overwrite?");
        enableTimeout();

        if (dicision != "Yes") {
            return 0;
        }
    }

    if (! recorder.isFileWritable(data_file)) {
        controller.openPopup("ERROR", "OK", "unable to create file: " + data_file);
        return 0;
    }

    reporter.open(report_file_name);
    reporter.write("run-name", run_name);
    reporter.write("comment", comment);
    reporter.write("date", localTime());
    reporter.write("log-file", log_file_name);
    reporter.write("buffer-size", buffer_size);
    reporter.write("data-file", data_file);
    reporter.write("script", readout_script, "target=collector", "type=kts");
    reporter.write("script", view_script, "target=viewer", "type=kvs");

    asynchronously {
        collector.setReadoutScript(readout_script, readout_datasource);
        viewer.setViewScript(view_script, view_display);
    }

    recorder.setDataFile(data_file);
    recorder.requireDiskSpace(1024 * 1024);

    // note that normal small-kinoko does not provide the following options
    if (getRegistry("control/prohibit_overwrite") != 1) {
        recorder.allowOverWrite();
    }
    if (getRegistry("control/set_readonly") == 1) {
        recorder.setDataFileReadOnly();
    }
    if (getRegistry("control/enable_compression") == 1) {
        recorder.enableCompression();
    }
    if (getRegistry("control/make_index") == 1) {
        recorder.enableIndex();
    }
    recorder.addHeaderEntry("RunName", run_name);
    recorder.addHeaderEntry("Comment", comment);
    
    asynchronously {
        collector.construct();
        recorder.construct();
        flow_meter.construct();
        viewer.construct();
    }

    return 1;
}

void start()
{
    start_time = time();

    reporter.write("start-time", localTime());
    reporter.write("start-unix-time", start_time);

    collector.start();
}

void stop()
{
    stop_time = time();

    viewer.saveImage("picture-smallkinoko.png");

    collector.stop();

    reporter.write("picture", "picture-smallkinoko.png", "name=viewer");
    reporter.write("stop-time", localTime());
    reporter.write("stop-unix-time", stop_time);
    reporter.write("running-time", stop_time - start_time);
}

void destruct()
{
    asynchronously {
        collector.destruct();
        recorder.destruct();
        flow_meter.destruct();
        viewer.destruct();
    }

    reporter.write("event-count", warning_count, "type=warning");
    reporter.write("event-count", error_count, "type=error");
    reporter.write("error-message", error_message);
    reporter.close();

    error_message = "";
    warning_count = 0;
    error_count = 0;
}
    
void disconnect()
{
    asynchronously {
        collector.disconnect();
        recorder.disconnect();
        flow_meter.disconnect();
        viewer.disconnect();
    }
}

void quit()
{
    asynchronously {
        collector.quit();
        recorder.quit();
        flow_meter.quit();
        viewer.quit();

        buffer.quit();
        logger.quit();
        reporter.quit();
        controller.quit();
    }
}