Wiki

Clone wiki

javarosa / DaemonProposal

Dæmon Subsystem Proposal

This document outlines a proposal for a new JavaRosa subsystem. This system would be used to keep track of a new entity in the JavaRosa universe of concepts, a 'daemon'.

Dæmons

Daemons, whose name and concept are lifted straight from classic Unix language, are independent processes that run in the background of an application, and provide feature-specific interaction to the Shell. An example of a Daemon is a process which keeps track of whether there are reminders that need to be displayed to the user, or a process which listens for a text message, and reports in some way when a special one is received.

Daemons deserve to be though of, and treated as, a unique entity in JavaRosa. These are not services, because they are still within the JavaRosa framework, and are not Activities, because they take place synchronously with the main user interface and other Daemons.

General Dæmon Interface

As in Unix systems, I propose that daemons have three basic methods, '''start()''', '''stop()''', and '''resume()'''. In addition, I think that a general '''getName()''' method would be helpful for managing what daemons are running, and an isRunning method to identify if a thread is active.

The interface would look like

    public interface IDaemon {
        public String getName();
        public void start();
        public void stop();
        public void restart();
        public boolean isRunning();
    }

JRSP Support

Daemons potentially need to be accessible to many different entities in JavaRosa. Modules will need to create and start them, property rules will need to be able to trigger their activation level. One way to support this is by declaring Daemon's to be static. There are a lot of reasons why this is sub-optimal.

  • Static classes can't usefully be referenced via an interface, so Daemon's can't be handled generically
  • There can only ever be one instance of a Daemon running at one time

I propose that daemons are registered in the JRSP in a manner similar to services. A Daemon is registered with a hashtable of services in the JRSP indexed by name. A module would register a Daemon by saying

    JavaRosaServiceProvider.instance().registerDaemon(new SMSDaemon(), SMSDaemon.getName());

Afterward, Daemons could be retrieved similarly to Services

    IDaemon daemon = JavaRosaServiceProvider.instance().getDaemon(SMSDaemon.getName());
    daemon.restart();

Then shells could interact with existing daemons, and the daemon could be started and stopped by generic calls attached to property rules sets.

Best Practices

Keeping a low overhead for Daemon processes is fairly essential. Threads consume a fair amount of resources, so it is fairly vital to design threads conservatively.

Daemons should essentially be considered wrappers for some background service. IE, a poor way to make a daemon would be

    public class StrawManDaemon implements IDaemon {

        static boolean running;
        
        public StrawManDaemon() {
            // start the actual thread
            Runnable runner= new Runnable() {
                public void run() {
                    while(true) { // Poll until app exits.
                        wait(10000); //Only poll every 10 seconds
                        if(running) { 
                            //perform some polling action
                            //that this daemon is for
                        }
                        else {
                            //do nothing, we're stopped.
                        }
                    }
                }
            }
            new Thread(runner).start();
        }

        public String getName() {
            return "Straw Man Daemon";
        }
        public void start() {
            running = true;
        }
        public void stop() {
            running = false;
        }
        public void restart() {
            running = true;
        }
        public boolean isRunning() {
            return running;
        }
    }

This is obviously a mocked up example, but the basic idea is made apparent. Threads should be running as little as possible. A daemon is a wrapper for a background service that controls when it is running, rather than a thread that is actively doing something or not. A better daemon might look like

    public class ActualProcess extends Thread {
        private boolean killed = false;
        
        public void run() {
            while(!killed) {
                //Do cool stuff!
                wait(10000); //Wait for 10 second between polls.
            }
        } 
        public void kill() {
            killed = true;
        }
    }

    public class ImprovedDaemon implements IDaemon {

        private ActualProcess thread;
        
        public ImprovedDaemon () {
        }

        public String getName() {
            return "Improved Daemon";
        }
        public void start() {
            thread = new ActualProcess();
            thread.start();
        }
        public void stop() {
            thread.kill();
            thread = null;
        }
        public void restart() {
            if(isRunning) {
                stop();
            }
            start();
        }
        public boolean isRunning() {
           return thread != null;
        }
    }

This design affords many advantages, but the most important of these are that when the background process is deactivated, it is actually not running. By using Timers, it is possible to lower this overhead even further. The goal should be for the background process to be taking up as little memory and time as possible.

Updated