Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* COOS - Connected Objects Operating System (www.connectedobjects.org).
*
* Copyright (C) 2009 Telenor ASA and Tellu AS. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
* You may also contact one of the following for additional information:
* Telenor ASA, Snaroyveien 30, N-1331 Fornebu, Norway (www.telenor.no)
* Tellu AS, Hagalokkveien 13, N-1383 Asker, Norway (www.tellu.no)
*/
package org.coos.javaframe;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.coos.actorframe.application.Container;
import org.coos.actorframe.application.Session;
import org.coos.actorframe.messages.AFConstants;
import org.coos.javaframe.messages.AFPropertyMsg;
import org.coos.javaframe.messages.ActorMsg;
import org.coos.javaframe.messages.ActorRouterRegMsg;
import org.coos.javaframe.messages.ActorRouterUnRegMsg;
import org.coos.javaframe.messages.JFConstants;
import org.coos.javaframe.messages.Message;
import org.coos.javaframe.messages.RouterMsg;
import org.coos.util.serialize.AFClassLoader;
/**
* Specifies an general simulator that is extended to a specific application. It
* is used to keep the reference to the different state machines. It has a
* message queue that is used to send actor message between actors. The queue is
* a FIFO queue.
*
* @author Geir Melby, Tellu AS
*/
public class SchedulerImpl implements Scheduler, Runnable, AFConstants, AFClassLoader {
/**
* SchedulerData contains common instance date for a set of actors. It is
* configured at the start up of the system
*/
private SchedulerData schedulerData;
/**
* If true all logged information logged and stored
*/
boolean traceOn = true;
boolean traceError = true;
/**
* Contains the actor instances belonging to this scheduler
*/
public Hashtable mySchedulables;
protected static Logger logger = LoggerFactory.getLogger("org.coos.javaframe.Scheduler");
private TraceObject trace = new TraceObject(); // trace output on the
// screen;
// object use to synchronized access to non reentrent code in different
// threads (ServerUDP, SenderUDP)
public static Object semafor = new Object();
private boolean running = true;
private int threads = 1;
private String name = "default";
private Thread thread;
protected AFClassLoader classLoader;
/**
* Default constructor
*/
public SchedulerImpl() {
mySchedulables = new Hashtable();
}
/**
* @param name
* - the name of the constructor
*/
public SchedulerImpl(String name) {
mySchedulables = new Hashtable();
}
/**
* @param schedulerData
* - the system data that the scheduler is initialized with, i.e.
* all the actors in this system
*/
public SchedulerImpl(SchedulerData schedulerData) {
this.schedulerData = schedulerData;
if (schedulerData.getDefaultScheduler() == null) {
schedulerData.setDefaultScheduler(this);
}
mySchedulables = new Hashtable();
}
/**
* @param name
* - the name of the scheduler
* @param schedulerData
* the system data that the scheduler is initialized with, i.e.
* all the actors in this system
*/
public SchedulerImpl(String name, SchedulerData schedulerData) {
this.schedulerData = schedulerData;
if (schedulerData.getDefaultScheduler() == null) {
schedulerData.setDefaultScheduler(this);
}
mySchedulables = new Hashtable();
}
public SchedulerData getSchedulerData() {
return schedulerData;
}
public void setSchedulerData(SchedulerData schedulerData) {
this.schedulerData = schedulerData;
if (schedulerData.getDefaultScheduler() == null) {
schedulerData.setDefaultScheduler(this);
}
}
/**
* Adds an instance of a state machine to the schedulers list of created
* state machines. The hash key is the string representation of actor
* address as "ping@Ping".
*
* @param sm
* is the state machine to be added
* @param aa
* is the actor address of the state machine
*/
public void addSchedulable(Schedulable sm, ActorAddress aa) {
schedulerData.getMySystem().put(aa.keyWithOutPortAndRole(), sm);
mySchedulables.put(aa.keyWithOutPortAndRole(), sm);
sm.setScheduler(this);
if (aa.key().indexOf(".") == -1) {
sm.init(); // Initiate State machine added instead of call to
// sm.ejbcreate
}
}
public void remove(ActorAddress aa) {
schedulerData.getMySystem().remove(aa.keyWithOutPortAndRole());
mySchedulables.remove(aa.keyWithOutPortAndRole());
}
/**
* Adds the router to the scheduler. This used when the router shal be run
* as part of a scheduler,
*
* @param session
*/
public void addRouter(Session session) {
schedulerData.setTheRouterSession(session);
session.setScheduler(this);
}
/**
* Adds the router to the scheduler. This used when the router shal be run
* as part of a scheduler,
*/
public void removeRouter() {
schedulerData.setTheRouterSession(null);
}
/**
* This method is used to configure the types of scedulable object that this
* scheduler will handle
*
* @param objectType
* of the scedulable object
*/
public void configure(String objectType) {
schedulerData.getSchedulerConfig().put(objectType, this);
}
public void start() {
this.thread = new Thread(this, this.name);
thread.start();
}
/**
* The run method that the thread starts with
*/
public void run() {
this.execute();
}
/**
* the infinite loop for execution of scedulable objects. It waits for
* messages in the mailbox queue. If no messages it calls the "wait" until
* it's notified that a message is placed in the mailbox
*/
void execute() {
Schedulable sm = null;
ActorMsg msg = null;
trace.traceOut(TraceConstants.tlInfo, "Thread " + getName() + " is started using " + getThreads() + " threads");
while (running) {
Enumeration en = mySchedulables.elements();
// Iterate alle schedulables
while (en.hasMoreElements()) {
Object o = en.nextElement();
if (o instanceof Schedulable) {
sm = (Schedulable) o;
// remove the first message of the schedulable
msg = (ActorMsg) sm.getMailbox().removeFirst(); // remove
// the
// message
// read
// If it is not null process it
if (msg != null) {
if (msg.getReceiverRole().isValied()) {
processMessage(msg, sm);
} else {
if (isTraceOn()) {
trace.traceError("execute: Error in receiver role, message dropped!"
+ msg.getReceiverRole());
}
}
}
}
}
// The first message of all schedulables attached to this scheduler
// is now processed,
// now we have to check if the queues contains more messages to be
// processed
synchronized (this) {
boolean emptyqueues = true;
Enumeration enum1 = mySchedulables.elements();
while (enum1.hasMoreElements()) {
Object ob = enum1.nextElement();
if (ob instanceof Schedulable) {
sm = (Schedulable) ob;
// One of the queues is not empty
if (!sm.getMailbox().isEmpty()) {
emptyqueues = false;
}
}
}
// If all queues are empty the scheduler waits
if (emptyqueues) {
try {
wait();
} catch (InterruptedException e) {
if (isTraceOn()) {
trace.traceOut(TraceConstants.tlInfo, "Thread " + getName() + " is stopped");
}
}
}
}
}
}
protected boolean processMessage(ActorMsg msg, Schedulable sm) {
boolean ok = sm.processMessage(msg);
if (sm.isReadyToBeDeleted()) {
remove(sm.getMyActorAddress());
if (isTraceOn()) {
logger.log(TraceConstants.tlInfo, "execute: ActorStateMachine deleted: " + sm);
}
}
return ok;
}
/**
* Check if the state machine with address aa is already created
*
* @param aa
* is the address of the state machine
* @return true if the actor exists already
*/
private boolean isActorCreated(ActorAddress aa) {
return schedulerData.getMySystem().get(aa.keyWithOutPortAndRole()) != null;
}
/**
* If the message is an Router message, a new actor message ia created out
* of the payload of the router message. Then the out method of the
* scheduler is called that puts the message into the mailbox of the
* receiving actor
*
* @param rm
* is the message
* @param curfsm
* reference to the schedulable caller
* @throws IOException
*/
public void postMessageToScheduler(Message rm, Schedulable curfsm) throws IOException {
ActorMsg msg;
if (rm instanceof RouterMsg) {
msg = ((RouterMsg) rm).deSerializeMessage(classLoader);
} else {
msg = (ActorMsg) rm;
}
// store the last received message to avoid sending the same message
// back,
// discard the message
schedulerData.setLastMsgFromRouter(msg);
// Special handling of RESTART message, send it to all state machines
if (msg.equals(JFConstants.ROLE_RESTART_MSG)) {
if (msg.getReceiverRole() == null) {
// broadcast it to all state machines
Enumeration en = getSchedulerData().getMySystem().elements();
while (en.hasMoreElements()) {
Object o = en.nextElement();
if (o instanceof StateMachine) {
StateMachine sm = (StateMachine) o;
ActorAddress address = sm.getMyActorAddress();
ActorMsg am = msg.getCopy(getClassLoader());
am.setReceiverRole(address);
out(am, curfsm);
}
}
return;
}
}
out(msg, curfsm);
}
/**
* Post the message to the input queue of the receiving scheduable.
*
* @param sig
* is the output signal to be send
* @param curfsm
* is a reference to the state machine
*/
public boolean output(ActorMsg sig, Schedulable curfsm) {
boolean ok = out(sig, curfsm);
if (ok && curfsm != null ) {
if (isTraceOn() && !sig.getMsgId().equals(JFConstants.TIMER_ID)) {
curfsm.getScheduler().getTraceObject().traceOutput(sig);
}
}
return ok;
}
/**
* The output method that every schedulable object must call in order to
* send messages to other schedulable objects. The trace is special here,
* because this method is static, the traceobject of the running scheduable
* instance has to be used curfsm.getScheduler().getTraceObject()
*
* @param sig
* the message
* @param curfsm
* the schedulable object
*/
protected final boolean out(ActorMsg sig, Schedulable curfsm) {
ActorAddress receiver = sig.getReceiverRole();
if (receiver == null || !receiver.isValied()) {
if (isTraceOn())
trace.traceError("Scheduler.out: Illegal receiver address: " + receiver);
return false;
}
// check if the sig is an create message and the
boolean created = isActorCreated(receiver);
if (!created && isCreateMsg(sig) && (sig.getProperty("targetActor") == null)) {
// The message is either a RolePlay or a RoleCreate message
Scheduler sched = (Scheduler) schedulerData.getSchedulerConfig().get(sig.getReceiverRole().getActorType());
if (sched == null) {
sched = schedulerData.getDefaultScheduler();
}
StateMachine sm = sched.createActor(sig, curfsm);
if (sm != null) {
// the message is send as part of the create actor mthod
sched.notifyScheduler();
return true;
} else {
if (isTraceOn())
trace.traceError("Scheduler.out: ERROR Creation of actor Failed: " + receiver.getActorType());
}
return false;
}
// Send all other messages if the receiver exists
// check if mySystem contains the state machine
Object o = schedulerData.getMySystem().get(sig.getReceiverRole().keyWithOutPortAndRole());
if (o != null) {
Schedulable sm = (Schedulable) o;
if (sm != null) {
sm.getMailbox().addMessage(sig);
sm.getScheduler().notifyScheduler();
return true;
}
} else {
if (schedulerData == null
|| schedulerData.getTheRouterSession() == null
|| !schedulerData.getContainer().isRouterRunning()) {
if ((curfsm != null) && isTraceOn()) {
trace.traceError("Scheduler.out: Router is not available, theRouterSession = null");
}
return false;
}
synchronized (schedulerData.getTheRouterSession().getScheduler()) {
if (schedulerData.getLastMsgFromRouter() == null || schedulerData.getLastMsgFromRouter() != sig) {
// the last message i send from the local actor
// schedulerData, it safe to send it to the router
if (sig.getReceiverRole().getProxyAddress() != null) {
ActorAddress aa = sig.getReceiverRole().getProxyAddress();
ActorAddress target = sig.getReceiverRole();
sig.setReceiverRole(aa);
sig.getReceiverRole().setProxyAddress(target);
}
boolean ok = schedulerData.getTheRouterSession().processMessage(sig);
if (!ok && isTraceOn()) {
trace.traceError("SchedulerImpl.out: failed to send " + sig);
}
return ok;
} else {
if (isTraceOn()) {
trace.traceError("Scheduler.out: circulating message is skipped:" + sig);
}
}
}
}
return false;
}
/**
* Used to check if the incomming message is a message that shall create an
* new state machine instance, before the transition is executed. This
* routine is overrided by the sub class. Default is set to false, which
* will disable the possiblillity to create new instances.
*
* @param msg
* is the message to checked if it is a RoleCreateMsg
*/
/*
* protected boolean isCreateMsg(ActorMsg msg) { return false; }
*/
protected static boolean isCreateMsg(ActorMsg msg) {
if (msg instanceof AFPropertyMsg) {
AFPropertyMsg am = (AFPropertyMsg) msg;
return (am.equals(AFConstants.ROLE_CREATE_MSG) || am.equals(AFConstants.ROLE_PLAY_MSG));
} else {
return false;
}
}
static final String title = "ActorStateMachine creation: ";
/**
* creates an new actor instance.
*
* @param curfsm
* @return the actor state machine
*/
public StateMachine createActor(ActorMsg rsm, Schedulable curfsm) {
String className = null;
ActorSpec as = getSchedulerData().getApplicationSpec().getActorSpec(rsm.getReceiverRole().getActorType());
if ((as != null) && rsm instanceof AFPropertyMsg) {
className = as.getActorClassName();
}
if ((className == null) || className.equals("")) {
if (isTraceOn()) {
trace.traceError(title + "failed, Class name: " + className);
}
return null;
} else {
// creates the state machine
StateMachine sm = null;
try {
sm = createClass(className);
if (sm != null) {
// this variables has to be set before the state machine is
// inititated, instance created and added
// to the mySystem, which contains all state machine
// instances
String actorType = rsm.getReceiverRole().getActorType();
sm.setMyActorId(rsm.getReceiverRole().getActorID());
sm.setMyActorType(actorType);
sm.setMyActorDomain(schedulerData.getActorDomainName());
sm.setCurrentMessage(rsm);
sm.trace = this.trace;
sm.setVisible(rsm.getBoolean(ROLE_CREATE_MSG_VISIBLE));
sm.setTraceLevel(rsm.getInt(TRACE_LEVEL_PROP));
if (isTraceOn()) {
logger.log(TraceConstants.tlInfo, title + "Success: " + "ActorStateMachine: " + sm
+ " Scheduler: " + getName() + " Class: " + className);
}
this.addSchedulable(sm, rsm.getReceiverRole());
sm.mailbox.addMessage(rsm);
}
} catch (InstantiationException e) {
if (isTraceOn()) {
if (isTraceOn()) {
trace.traceError(title + "failed, InstantiationException occurred" + " Class: " + className);
}
}
} catch (IllegalAccessException e) {
if (isTraceOn()) {
trace.traceError("failed, IllegalAccessException occurred" + " Class: " + className);
}
} catch (ClassNotFoundException e) {
// the class was not found, could be an error
if (isTraceOn()) {
trace.traceError(title + "failed, class name: " + className + " not found");
}
}
return sm;
}
}
protected StateMachine createClass(String className) throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Class clazz = classLoader.loadClass(className);
if (clazz != null) {
return (StateMachine) clazz.newInstance();
}
return null;
}
/**
* Return those actors that has its flag to be visible in the router system
*
* @return a vector of actor address
*/
public Vector getVisibleStateMachines() {
Vector v = new Vector();
Enumeration en = schedulerData.getMySystem().elements();
while (en.hasMoreElements()) {
Object o = en.nextElement();
if (o instanceof StateMachine) {
// check if the state machine is visible
StateMachine sm = (StateMachine) o;
if (sm.isVisible()) {
v.addElement(sm.getMyActorAddress());
}
}
}
return v;
}
/**
* Sends an ActorStateMachine Reg message to the local router, to update the
* router with visble actors
*
* @param sm
* is the actor
*/
public void upDateVisibleActors(StateMachine sm) {
ActorRouterRegMsg arrm = new ActorRouterRegMsg(getVisibleStateMachines(), 0);
arrm.setReceiverRole(schedulerData.getApplicationSpec().getRouterAddress()); // set
// the
// senderAddress
// of
// this
// message
if (sm != null) {
arrm.setSenderRole(new ActorAddress(sm.myActorId, sm.myActorType)); // set
// the
// senderAddress
// of
// this
} else {
arrm.setSenderRole(new ActorAddress("null", "null")); // set dumy
// actor
// address
// (is is
// not used)
}
Session rs = schedulerData.getTheRouterSession();
if (rs != null ) {
schedulerData.getTheRouterSession().processMessage(arrm);
}
// out(arrm, sm);
}
/**
* Sends an ActorStateMachine Reg message to the local router, to update the
* router with visble actors
*
* @param aa
* is the actor
*/
public void unRegVisibleActor(ActorAddress aa) {
Vector v = new Vector();
v.addElement(aa.clone());
ActorRouterUnRegMsg arrm = new ActorRouterUnRegMsg(v, 0);
arrm.setReceiverRole(schedulerData.getApplicationSpec().getRouterAddress()); // set
// the
// senderAddress
// of
// this
// message
arrm.setSenderRole(aa); // set the senderAddress of this
Session rs = schedulerData.getTheRouterSession();
if (rs != null && schedulerData.getContainer().isRouterRunning()) {
rs.processMessage(arrm);
}
}
/**
* Cheks if the statemachine that is equal to the actor address
*
* @param aa
* the actor address of the state machine to be checked
* @return true if the state machine exists
*/
public boolean containsStateMachine(ActorAddress aa) {
if (schedulerData.getMySystem().containsKey(aa.key())) {
return true;
}
return false;
}
/**
* All threads has to be deleted. All actors are also called to enable the
* actors to stop local threads
*/
public void stop() {
// all threads are stopped first
Enumeration en = schedulerData.getMySystem().elements();
while (en.hasMoreElements()) {
Schedulable sched = (Schedulable) en.nextElement();
sched.destroy();
}
setStopFlag();
interrupt();
}
public void interrupt() {
this.thread.interrupt();
}
public void setStopFlag() {
running = false;
}
/**
* uases all scheduable components. This method is called each time the
* container calls the destroy method
*/
public void pauseApp() {
Enumeration en = schedulerData.getMySystem().elements();
while (en.hasMoreElements()) {
Schedulable sched = (Schedulable) en.nextElement();
sched.pause();
}
// todo pause all threads here
}
public void addStateMachine(StateMachine sm, String type) {
// To change body of implemented methods use File | Settings | File
// Templates.
}
public TraceObject getTraceObject() {
return trace;
}
public void clearLastMsgFromRouter() {
schedulerData.setLastMsgFromRouter(null);
}
public int getThreads() {
return threads;
}
public void setThreads(int threads) {
this.threads = threads;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setClassLoader(Container classLoader) {
this.classLoader = classLoader;
}
public AFClassLoader getClassLoader() {
return classLoader;
}
public Class loadClass(String className) throws ClassNotFoundException {
return classLoader.loadClass(className);
}
public boolean isTraceOn() {
return traceOn;
}
public void setTrace(boolean on) {
traceOn = on;
}
public boolean isTraceError() {
return traceError;
}
public void setTraceError(boolean on) {
traceError = on;
}
public synchronized void notifyScheduler() {
notify();
}
}