Skip to content

Commit 12f582d

Browse files
author
James Taylor
committed
Reintroducing the Servlet interface to the cache. I rewrote it using velocity
which makes the code a little cleaner. I still would like to add a detail page for viewing the items in the cache and removing one (or perhaps more than one). Seems like a decent start. git-svn-id: https://svn.apache.org/repos/asf/jakarta/jcs/trunk@223977 13f79535-47bb-0310-9956-ffa450edef68
1 parent 0b7c13f commit 12f582d

File tree

8 files changed

+306
-4
lines changed

8 files changed

+306
-4
lines changed

build.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727

2828
</target>
2929

30+
<target name="jcs:copy-classpath-vm">
31+
<copy todir="${maven.build.dest}">
32+
<fileset dir="src/java" includes="**/*.vm"/>
33+
</copy>
34+
</target>
35+
3036
<!-- The targets people are used to -->
3137

3238
<target name="clean" depends="maven:compile"/>

project.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
maven.test.callback.pre-test.buildFile = build.xml
22
maven.test.callback.pre-test.buildTarget = jcs:test-prepare
3+
4+
maven.core.callback.post-compile.buildFile = build.xml
5+
maven.core.callback.post-compile.buildTarget = jcs:copy-classpath-vm

project.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@
111111
<version>???</version>
112112
<jar>tomcat3.2.1.jar</jar>
113113
</dependency>
114+
115+
<dependency>
116+
<name>jakarta-velocity</name>
117+
<type>required</type>
118+
<version>1.3-dev</version>
119+
<jar>velocity-1.3-dev.jar</jar>
120+
</dependency>
121+
114122
<!-- Required for the server in JCS -->
115123

116124
<dependency>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
runtime.log.logsystem.class=org.apache.velocity.runtime.log.SimpleLog4JLogSystem
2+
runtime.log.logsystem.log4j.category=org.apache.velocity.Velocity
3+
4+
resource.loader = classpath
5+
classpath.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader

src/experimental/org/apache/jcs/auxiliary/lateral/http/server/LateralCacheServletReciever.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public void service( HttpServletRequest request,
9494
try
9595
{
9696
// need to set as from lateral
97-
cache.add( item );
97+
cache.localUpdate( item );
9898
}
9999
catch ( Exception e )
100100
{

src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPListener.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@
7070
import org.apache.jcs.auxiliary.lateral.LateralElementDescriptor;
7171
import org.apache.jcs.auxiliary.lateral.behavior.ILateralCacheAttributes;
7272
import org.apache.jcs.auxiliary.lateral.behavior.ILateralCacheListener;
73-
import org.apache.jcs.engine.CacheConstants;
7473
import org.apache.jcs.engine.behavior.ICacheElement;
7574
import org.apache.jcs.engine.behavior.ICompositeCache;
7675
import org.apache.jcs.engine.control.CacheHub;
@@ -96,7 +95,7 @@ public class LateralTCPListener
9695
/** Map of available instances, keyed by port */
9796
protected final static HashMap instances = new HashMap();
9897

99-
// ---------- instance variables
98+
// ----------------------------------------------------- instance variables
10099

101100
/** The socket listener */
102101
private ListenerThread receiver;
@@ -352,7 +351,6 @@ public void run()
352351
try
353352
{
354353
ois = new ObjectInputStream( socket.getInputStream() );
355-
;
356354
}
357355
catch ( Exception e )
358356
{
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
package org.apache.jcs.servlet;
2+
3+
import java.io.IOException;
4+
import java.io.OutputStream;
5+
import java.io.ObjectOutputStream;
6+
import java.util.Arrays;
7+
import java.util.LinkedList;
8+
import java.util.Iterator;
9+
import java.util.Map;
10+
import javax.servlet.http.HttpServletRequest;
11+
import javax.servlet.http.HttpServletResponse;
12+
13+
import org.apache.jcs.engine.CacheConstants;
14+
import org.apache.jcs.engine.memory.MemoryCache;
15+
import org.apache.jcs.engine.memory.MemoryElementDescriptor;
16+
import org.apache.jcs.engine.behavior.ICache;
17+
import org.apache.jcs.engine.control.CacheHub;
18+
import org.apache.jcs.engine.control.Cache;
19+
import org.apache.velocity.Template;
20+
import org.apache.velocity.context.Context;
21+
import org.apache.velocity.servlet.VelocityServlet;
22+
23+
/**
24+
* A servlet which provides HTTP access to JCS. Allows a summary of regions
25+
* to be viewed, and removeAll to be run on individual regions or all regions.
26+
* Also provides the ability to remove items (any number of key arguments can
27+
* be provided with action 'remove'). Should be initialized with a properties
28+
* file that provides at least a classpath resource loader. Since this extends
29+
* VelocityServlet, which uses the singleton model for velocity, it will share
30+
* configuration with any other Velocity in the same JVM.
31+
*
32+
* Initialization in a webapp will look something like this:
33+
* <pre>
34+
* [servlet]
35+
* [servlet-name]JCSAdminServlet[/servlet-name]
36+
* [servlet-class]org.apache.jcs.servlet.JCSAdminServlet[/servlet-class]
37+
* [init-param]
38+
* [param-name]properties[/param-name]
39+
* [param-value]WEB-INF/conf/JCSAdminServlet.velocity.properties[/param-value]
40+
* [/init-param]
41+
* [/servlet]
42+
* </pre>
43+
*
44+
* FIXME: It would be nice to use the VelocityEngine model so this can be truly
45+
* standalone. Right now if you run it in the same container as, say,
46+
* turbine, turbine must be run first to ensure it's config takes
47+
* precedence.
48+
*
49+
* @author <a href="mailto:james@jamestaylor.org">James Taylor</a>
50+
* @version $Id$
51+
*/
52+
public class JCSAdminServlet extends VelocityServlet
53+
{
54+
private static final String DEFAULT_TEMPLATE_NAME =
55+
"/org/apache/jcs/servlet/JCSAdminServletDefault.vm";
56+
57+
// Keys for parameters
58+
59+
private static final String CACHE_NAME_PARAM = "cacheName";
60+
61+
private static final String ACTION_PARAM = "action";
62+
private static final String KEY_PARAM = "key";
63+
64+
// Possible values for 'action' parameter
65+
66+
private static final String CLEAR_ALL_REGIONS_ACTION = "clearAllRegions";
67+
private static final String CLEAR_REGION_ACTION = "clearRegion";
68+
private static final String REMOVE_ACTION = "remove";
69+
70+
private CacheHub cacheHub = CacheHub.getInstance();
71+
72+
/** @see VelocityServlet#handleRequest */
73+
protected Template handleRequest( HttpServletRequest request,
74+
HttpServletResponse response,
75+
Context context )
76+
throws Exception
77+
{
78+
String cacheName = request.getParameter( CACHE_NAME_PARAM );
79+
80+
// If an action was provided, handle it
81+
82+
String action = request.getParameter( ACTION_PARAM );
83+
84+
if ( action != null )
85+
{
86+
if ( action.equals( CLEAR_ALL_REGIONS_ACTION ) )
87+
{
88+
clearAllRegions();
89+
}
90+
else if ( action.equals( CLEAR_REGION_ACTION ) )
91+
{
92+
if ( cacheName == null )
93+
{
94+
// Not Allowed
95+
}
96+
else
97+
{
98+
clearRegion( cacheName );
99+
}
100+
}
101+
else if ( action.equals( REMOVE_ACTION ) )
102+
{
103+
String[] keys = request.getParameterValues( KEY_PARAM );
104+
105+
for ( int i = 0; i < keys.length; i++ )
106+
{
107+
removeItem( cacheName, keys[ i ] );
108+
}
109+
}
110+
}
111+
112+
// Now populate the context
113+
114+
String[] cacheNames = cacheHub.getCacheNames();
115+
116+
Arrays.sort( cacheNames );
117+
118+
LinkedList cacheInfo = new LinkedList();
119+
120+
CacheRegionInfo regionInfo;
121+
Cache cache;
122+
123+
for ( int i = 0; i < cacheNames.length; i++ )
124+
{
125+
cache = ( Cache ) cacheHub.getCache( cacheNames[ i ] );
126+
127+
regionInfo = new CacheRegionInfo();
128+
129+
regionInfo.name = cache.getCacheName();
130+
regionInfo.itemCount = cache.getSize();
131+
regionInfo.byteCount = getByteCount( cache );
132+
regionInfo.status = statusAsString( cache );
133+
134+
cacheInfo.add( regionInfo );
135+
}
136+
137+
context.put( "cacheInfoRecords", cacheInfo );
138+
139+
return getTemplate( DEFAULT_TEMPLATE_NAME );
140+
}
141+
142+
public int getByteCount( Cache cache )
143+
throws Exception
144+
{
145+
MemoryCache memCache = cache.getMemoryCache();
146+
147+
Iterator iter = memCache.getIterator();
148+
149+
CountingOnlyOutputStream counter = new CountingOnlyOutputStream();
150+
ObjectOutputStream out = new ObjectOutputStream( counter );
151+
152+
while ( iter.hasNext() )
153+
{
154+
MemoryElementDescriptor node = ( MemoryElementDescriptor )
155+
( ( Map.Entry ) iter.next() ).getValue();
156+
157+
out.writeObject( node.ce.getVal() );
158+
}
159+
160+
// 4 bytes lost for the serialization header
161+
162+
return counter.getCount() - 4;
163+
}
164+
165+
private String statusAsString( ICache cache )
166+
{
167+
int status = cache.getStatus();
168+
169+
return ( status == CacheConstants.STATUS_ALIVE ? "ALIVE"
170+
: status == CacheConstants.STATUS_DISPOSED ? "DISPOSED"
171+
: status == CacheConstants.STATUS_ERROR ? "ERROR"
172+
: "UNKNOWN" );
173+
}
174+
175+
private void clearAllRegions() throws IOException
176+
{
177+
String[] names = cacheHub.getCacheNames();
178+
179+
for ( int i = 0; i < names.length; i++ )
180+
{
181+
cacheHub.getCache( names[ i ] ).removeAll();
182+
}
183+
}
184+
185+
private void clearRegion( String cacheName ) throws IOException
186+
{
187+
cacheHub.getCache( cacheName ).removeAll();
188+
}
189+
190+
private void removeItem( String cacheName, String key ) throws IOException
191+
{
192+
cacheHub.getCache( cacheName ).remove( key );
193+
}
194+
195+
/** Stores info on a cache region for the template */
196+
public class CacheRegionInfo
197+
{
198+
String name = null;
199+
long itemCount = 0;
200+
long byteCount = 0;
201+
String status = null;
202+
203+
public String getName()
204+
{
205+
return name;
206+
}
207+
208+
public long getItemCount()
209+
{
210+
return itemCount;
211+
}
212+
213+
public long getByteCount()
214+
{
215+
return byteCount;
216+
}
217+
218+
public String getStatus()
219+
{
220+
return status;
221+
}
222+
}
223+
224+
/**
225+
* Keeps track of the number of bytes written to it, but doesn't write them
226+
* anywhere.
227+
*/
228+
private static class CountingOnlyOutputStream extends OutputStream
229+
{
230+
private int count;
231+
232+
public void write( byte[] b ) throws IOException
233+
{
234+
count += b.length;
235+
}
236+
237+
public void write( byte[] b, int off, int len ) throws IOException
238+
{
239+
count += len;
240+
}
241+
242+
public void write( int b ) throws IOException
243+
{
244+
count++;
245+
}
246+
247+
/**
248+
* The number of bytes that have passed through this stream.
249+
*/
250+
public int getCount()
251+
{
252+
return this.count;
253+
}
254+
}
255+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<h1> Cache Regions </h1>
2+
3+
<p>These are the regions which are currently defined in the cache. 'Items' and
4+
'Bytes' refer to the elements currently in memory (not spooled). You can clear
5+
all items for a region by selecting 'Remove all' next to the desired region
6+
below. You can also <a href="?action=clearAllRegions">Clear all regions</a>
7+
which empties the entire cache.</p>
8+
9+
<table border="1" cellpadding="5" >
10+
<tr>
11+
<th> Cache Name </th>
12+
<th> Items </th>
13+
<th> Bytes </th>
14+
<th> Status </th>
15+
</tr>
16+
17+
#foreach ( $record in $cacheInfoRecords )
18+
<tr>
19+
<td> $record.Name </td>
20+
<td> $record.ItemCount </td>
21+
<td> $record.ByteCount </td>
22+
<td> $record.Status </td>
23+
<td> <a href="?action=clearRegion&cacheName=${record.Name}"> Remove all </a> </td>
24+
</tr>
25+
#end
26+
27+
</table>

0 commit comments

Comments
 (0)