/* * Copyright 2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.rioproject.examples.workflow; import net.jini.core.entry.Entry; import net.jini.core.lease.Lease; import net.jini.core.transaction.Transaction; import net.jini.core.transaction.TransactionFactory; import net.jini.core.transaction.server.TransactionManager; import net.jini.space.JavaSpace; import org.rioproject.impl.associations.AssociationProxyUtil; import org.rioproject.annotation.PreAdvertise; import org.rioproject.servicebean.ServiceBeanContext; import org.rioproject.watch.Calculable; import org.rioproject.impl.watch.CounterWatch; import org.rioproject.impl.watch.PeriodicWatch; import org.rioproject.impl.watch.StopWatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.PreDestroy; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * A basic JavaSpace worker */ @SuppressWarnings("unused") public class Worker { private JavaSpace space; private TransactionManager tranMgr; private WorkflowEntry template; private ExecutorService service; public static final String COMPONENT = "workflow"; private long timeout; private Logger logger = LoggerFactory.getLogger(COMPONENT); String name; private boolean shutdown = false; private CounterWatch rate; private ThroughputWatch throughput; private StopWatch meanTime; private ServiceBeanContext context; public void setJavaSpace(JavaSpace space) { this.space = space; } public void setServiceBeanContext(ServiceBeanContext context) { this.context = context; name = context.getServiceElement().getName(); } public void setTransactionManager(TransactionManager tranMgr) { this.tranMgr = AssociationProxyUtil.getService(tranMgr); } public void setParameters(Map<String, Object> parms) { String tmpl = (String)parms.get("template"); State state = State.valueOf(tmpl); template = new WorkflowEntry(state); } @PreAdvertise public void startup() { if(space==null) throw new IllegalStateException("The JavaSpace should have been injected prior to this method being called"); logger.info("PRE_ADVERTISE {}", context.getServiceElement().getName()); rate = new CounterWatch("rate"); throughput = new ThroughputWatch("throughput"); meanTime = new StopWatch("meanTime"); timeout = 1000*10; int workerTasks = 1; service = Executors.newFixedThreadPool(workerTasks); service.submit(new SpaceProcessor()); context.getWatchRegistry().register(rate); context.getWatchRegistry().register(meanTime); context.getWatchRegistry().register(throughput); } @PreDestroy public void cleanup() { shutdown = true; throughput.stop(); if (service != null) service.shutdownNow(); } class SpaceProcessor implements Runnable { public void run() { while (!shutdown) { try { Transaction tx = null; if (tranMgr != null) { tx = TransactionFactory.create(tranMgr, Lease.FOREVER).transaction; } WorkflowEntry entry = (WorkflowEntry)space.takeIfExists(template, tx, timeout); if (entry == null && tx != null) { tx.abort(); } else { if(entry!=null) { logger.info("Worker [{}] processing task: {}", name, entry); meanTime.startTiming(); Entry result = entry.execute(); meanTime.stopTiming(); space.write(result, tx, timeout); if(tx != null) tx.commit(); rate.increment(); throughput.increment(); } } } catch (InterruptedException e) { logger.info("SpaceProcessor InterruptedException, exiting"); break; } catch (Exception e) { logger.warn("Worker [{}] processing task", name, e); break; } } } } public class ThroughputWatch extends PeriodicWatch { private int numberOfCalls = 0; public ThroughputWatch(String id) { super(id); super.setPeriod(1000); } public void checkValue() { super.addWatchRecord(new Calculable("taux", numberOfCalls / (getPeriod() / 1000))); numberOfCalls = 0; } public void increment() { numberOfCalls++; } } }