EMMA Coverage Report (generated Mon Mar 20 21:27:43 EST 2006)
[all classes][com.webhydra.slug.process]

COVERAGE SUMMARY FOR SOURCE FILE [AbstractProcessRunner.java]

nameclass, %method, %block, %line, %
AbstractProcessRunner.java100% (1/1)100% (12/12)94%  (283/301)97%  (79.6/82)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AbstractProcessRunner100% (1/1)100% (12/12)94%  (283/301)97%  (79.6/82)
freeProcess (String, String): void 100% (1/1)85%  (28/33)93%  (8.4/9)
cleanSession (String): void 100% (1/1)89%  (48/54)97%  (13.5/14)
findProcess (String, String): SluggishProcess 100% (1/1)90%  (19/21)83%  (5/6)
save (SluggishProcess, String): String 100% (1/1)92%  (55/60)98%  (10.7/11)
AbstractProcessRunner (): void 100% (1/1)100% (8/8)100% (3/3)
cancelProcess (String, String): SluggishProcess 100% (1/1)100% (21/21)100% (7/7)
checkProcess (String, String): ProcessStatus 100% (1/1)100% (18/18)100% (6/6)
clear (): void 100% (1/1)100% (22/22)100% (6/6)
consumeProcess (String, String): SluggishProcess 100% (1/1)100% (19/19)100% (6/6)
count (): long 100% (1/1)100% (32/32)100% (8/8)
prepare (): void 100% (1/1)100% (8/8)100% (3/3)
release (): void 100% (1/1)100% (5/5)100% (3/3)

1/*
2 * @(#) $Id: AbstractProcessRunner.java,v 1.1.1.1 2006/03/19 06:09:42 rossen Exp $
3 *
4 * Copyright (c) 2006, WebHydra.com
5 * All rights reserved.
6 * 
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 
10 *     * Redistributions of source code must retain the above copyright notice,
11 *       this list of conditions and the following disclaimer.
12 *     * Redistributions in binary form must reproduce the above copyright
13 *       notice, this list of conditions and the following disclaimer in the
14 *       documentation and/or other materials provided with the distribution.
15 *     * Neither the name of the WebHydra.com nor the names of its contributors
16 *       may be used to endorse or promote products derived from this software
17 *       without specific prior written permission.
18 * 
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 
32package com.webhydra.slug.process;
33 
34import com.webhydra.slug.SlugInitializationException;
35import java.security.InvalidParameterException;
36import java.util.ArrayList;
37import java.util.Date;
38import java.util.HashMap;
39import java.util.Iterator;
40import java.util.List;
41import java.util.Map;
42 
43/**
44 * Abstract Scheduler of the <code>SluggishProcess</code>es.
45 * @author rossen
46 */
47public abstract class AbstractProcessRunner extends AbstractSlugService implements ISlugRunner
48{
49 
50    /**
51     * Active Process List (APL)<br>
52     * Holds map of <code>session</code>s and a map of their running processes.
53     * The user's <code>session</code> is used as a key to the a map of
54     * <code>PID</code>s and the corresponding <code>SluggishProces</code>.
55     */
56    protected Map apl;
57 
58    /**
59     * Creates a new instance of AbstractProcessRunner
60     */
61    protected AbstractProcessRunner()
62    {
63        apl = new HashMap();
64    }
65 
66    /**
67     * Find <code>SluggishProcess</code> in the Active Process List (APL)
68     * @param session current user session ID
69     * @param pid running Process ID (PID)
70     * @return <code>SluggishProcess</code> if found, otherwise - <code>null</code>.
71     */
72    private SluggishProcess findProcess(String session, String pid)
73    {
74        if ((session == null) || (pid == null))
75        {
76            return null;
77        }
78        Map pidSessions = (Map) apl.get(session);
79        if (pidSessions == null)
80        {
81            // session not found!
82            return null;
83        }
84 
85        return (SluggishProcess) pidSessions.get(pid);
86    }
87 
88    /**
89     * Checks process status
90     * @param session current user session ID.
91     * @param pid running Process ID (PID)
92     * @return current porcess status if process with provided <code>PID</code> exist in current <code>session</code>.
93     * If no process can be found then <code>null</code> is returned.
94     */
95    public ProcessStatus checkProcess(String session, String pid)
96    {
97        if ((session == null) || (pid == null))
98        {
99            return null;
100        }
101        SluggishProcess sp = findProcess(session, pid);
102        if (sp == null)
103        {
104            // process not found
105            return null;
106        }
107        return sp.getProcessStatus();
108    }
109 
110    /**
111     * Remove specified process from the Active Process List (APL).
112     * If this is the last process for provided session then this session is removed from APL too.
113     * @param session current user session ID.
114     * @param pid Process ID (PID) to be removed.
115     * @return removed process or <code>null</code> if <code>PID</code> is not found.
116     */
117    public SluggishProcess consumeProcess(String session, String pid)
118    {
119        if ((session == null) || (pid == null))
120        {
121            return null;
122        }
123        SluggishProcess sp = findProcess(session, pid);
124        if (sp != null)
125        {
126            freeProcess(session, pid);
127        }
128        return sp;
129    }
130 
131    /**
132     * Cancel process
133     * Proces is signalled using SluggishProcess.cancel() and is removed from Active Process List (APL).
134     * @param session current user session ID.
135     * @param pid Process ID (PID) to be canceled.
136     * @return process or <code>null</code> if <code>PID</code> is not found.
137     */
138    public SluggishProcess cancelProcess(String session, String pid)
139    {
140        if ((session == null) || (pid == null))
141        {
142            return null;
143        }
144        SluggishProcess sp = findProcess(session, pid);
145        if (sp != null)
146        {
147            sp.cancel();
148            freeProcess(session, pid);
149        }
150        return sp;
151    }
152 
153    /**
154     * Free Active Process List (APL) map from current PID.
155     * If this is the last <code>PID</code> for this <code>session</code> the <code>session</code> is removed too.
156     * @param session current user session ID.
157     * @param pid Process ID (PID) to be canceled.
158     */
159    private void freeProcess(String session, String pid)
160    {
161        if (session != null)
162        {
163            synchronized (session)
164            {
165                Map pidSessions = (Map) apl.get(session);
166                if (pidSessions != null)
167                {
168                    pidSessions.remove(pid);
169                    if (pidSessions.isEmpty())
170                        cleanSession(session);
171                }
172            }
173        }
174    }
175 
176    /**
177     * Remove all processes for specified session.
178     * @param session user's session ID to cleanup.
179     */
180    public void cleanSession(String session)
181    {
182        if (session != null)
183        {
184            synchronized (apl)
185            {
186                Map sessionPids = (Map) apl.get(session);
187                if ((sessionPids != null) && !sessionPids.isEmpty())
188                {
189                    for (Iterator j = sessionPids.keySet().iterator(); j.hasNext();)
190                    {
191                        // try to safely cancel all processess if possible
192                        Object pid = j.next();
193                        try
194                        {
195                            SluggishProcess sp = (SluggishProcess) sessionPids.get(pid);
196                            sp.cancel();
197                        }
198                        catch (Throwable t) {} // ignore it
199                        j.remove();
200                    }
201                }
202                apl.remove(session);
203            }
204        }
205    }
206 
207    /**
208     * Save a new SluggishProcess in to the Active Process List (<code>APL</code>).
209     * @param proc process to be executed.
210     * @param session current user session ID.
211     * @return Proccess ID (<code>PID</code>) assigned to provided process/session pair.
212     * @exception InvalidParameterException if any of the provided parameters is null.
213     */
214    protected String save(SluggishProcess proc, String session) throws InvalidParameterException
215    {
216        if ((proc == null) || (session == null))
217        {
218            throw new InvalidParameterException("Not null " + ((proc == null) ? "process" : "session" + " is required!"));
219        }
220        String pid = PidGenerator.newPid();
221        synchronized (apl)
222        {
223            Map sessionPids = (Map) apl.get(session);
224            if (sessionPids == null)
225            {
226                sessionPids = new HashMap();
227            }
228            sessionPids.put(pid, proc);
229            apl.put(session, sessionPids);
230        }
231        return pid;
232    }
233 
234    /**
235     * Returns estimated total number of sluggish processes in this runner instance.
236     * Since the execution of this method may take considerable time it is not synchronized
237     * and as a result the returned count is an estimate and may vary from the real
238     * process count at the moment.
239     * Another factor is the underlaying Map implementation which size() method
240     * returns Integer.MAX_VALUE when it has more than Integer.MAX_VALUE elements.
241     * @return the estimated count of all running and completed processes
242     * accomodated in this instance.
243     * @see java.util.Map#size()
244     */
245    public long count()
246    {
247        long cnt = 0;
248        if (!apl.isEmpty())
249        {
250            for (Iterator i = apl.keySet().iterator(); i.hasNext();)
251            {
252               Map m = (Map) apl.get(i.next());
253               if (m != null)
254                   cnt += m.size();
255            }
256        }
257        return cnt;
258    }
259 
260    /**
261     * Cancels all running processes and removes them from this instance.
262     */
263    public synchronized void clear()
264    {
265        List sessions = new ArrayList(apl.keySet());
266        for (Iterator i = sessions.iterator();  i.hasNext();)
267        {
268            String sessionKey = (String) i.next();
269            cleanSession(sessionKey);
270        }
271    }
272 
273    /**
274     * Default implementation.
275     * Si,pyt invoces <code>clean()</code>.
276     * @see #clear()
277     */
278    public void release() {
279        super.release();
280        clear();
281    }
282 
283    /**
284     * Initialize the <code>APL</code> map
285     * @exception SlugInitializationException not really thrown
286     */
287    public void prepare() throws SlugInitializationException {
288        super.prepare();
289        apl = new HashMap();
290    }
291}

[all classes][com.webhydra.slug.process]
EMMA 2.0.5312 (C) Vladimir Roubtsov