Mercurial > hg > digilib-old
comparison servlet/src/digilib/io/DocuDirCache.java @ 290:5d0c0da080ec gen2 scaleable_1
digilib servlet version 2 ("scaleable digilib")
- first stab at using thread pools to limit resource use
- using Dug Leas util.concurrent
- doesn't mix with tomcat :-(
author | robcast |
---|---|
date | Thu, 21 Oct 2004 20:53:37 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
289:9f7b864f955f | 290:5d0c0da080ec |
---|---|
1 /* | |
2 * DocuDirCache.java | |
3 * | |
4 * Digital Image Library servlet components | |
5 * | |
6 * Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify it | |
9 * under the terms of the GNU General Public License as published by the Free | |
10 * Software Foundation; either version 2 of the License, or (at your option) | |
11 * any later version. | |
12 * | |
13 * Please read license.txt for the full details. A copy of the GPL may be found | |
14 * at http://www.gnu.org/copyleft/lgpl.html | |
15 * | |
16 * You should have received a copy of the GNU General Public License along with | |
17 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | |
18 * Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 * Created on 03.03.2003 | |
21 */ | |
22 | |
23 package digilib.io; | |
24 | |
25 import java.io.File; | |
26 import java.util.HashMap; | |
27 import java.util.Iterator; | |
28 import java.util.LinkedList; | |
29 import java.util.List; | |
30 import java.util.Map; | |
31 | |
32 import org.apache.log4j.Logger; | |
33 | |
34 import digilib.servlet.DigilibConfiguration; | |
35 | |
36 /** | |
37 * @author casties | |
38 */ | |
39 public class DocuDirCache { | |
40 | |
41 /** general logger for this class */ | |
42 Logger logger = Logger.getLogger(this.getClass()); | |
43 | |
44 /** HashMap of directories */ | |
45 Map map = null; | |
46 | |
47 /** names of base directories */ | |
48 String[] baseDirNames = null; | |
49 | |
50 /** array of allowed file classes (image/text) */ | |
51 private int[] fileClasses = null; | |
52 | |
53 /** number of files in the whole cache (approximate) */ | |
54 long numFiles = 0; | |
55 | |
56 /** number of cache hits */ | |
57 long hits = 0; | |
58 | |
59 /** number of cache misses */ | |
60 long misses = 0; | |
61 | |
62 /** use safe (but slow) indexing */ | |
63 boolean safeDirIndex = false; | |
64 | |
65 /** the root directory element */ | |
66 public static Directory ROOT = null; | |
67 | |
68 /** | |
69 * Constructor with array of base directory names and file classes. | |
70 * | |
71 * @param bd | |
72 * base directory names | |
73 */ | |
74 public DocuDirCache(String[] bd, int[] fileClasses, | |
75 DigilibConfiguration dlConfig) { | |
76 baseDirNames = bd; | |
77 map = new HashMap(); | |
78 this.fileClasses = fileClasses; | |
79 safeDirIndex = dlConfig.getAsBoolean("safe-dir-index"); | |
80 } | |
81 | |
82 /** | |
83 * Constructor with array of base directory names. | |
84 * | |
85 * @param bd | |
86 * base directory names | |
87 */ | |
88 public DocuDirCache(String[] bd) { | |
89 baseDirNames = bd; | |
90 map = new HashMap(); | |
91 // default file class is CLASS_IMAGE | |
92 fileClasses = new int[1]; | |
93 fileClasses[0] = FileOps.CLASS_IMAGE; | |
94 } | |
95 | |
96 /** | |
97 * The number of directories in the cache. | |
98 * | |
99 * @return | |
100 */ | |
101 public int size() { | |
102 return (map != null) ? map.size() : 0; | |
103 } | |
104 | |
105 /** | |
106 * Add a DocuDirectory to the cache. | |
107 * | |
108 * @param newdir | |
109 */ | |
110 public void put(DocuDirectory newdir) { | |
111 String s = newdir.getDirName(); | |
112 if (map.containsKey(s)) { | |
113 logger.warn("Duplicate key in DocuDirCache.put -- ignoring!"); | |
114 } else { | |
115 map.put(s, newdir); | |
116 numFiles += newdir.size(); | |
117 } | |
118 } | |
119 | |
120 /** | |
121 * Add a directory to the cache and check its parents. | |
122 * | |
123 * @param newDir | |
124 */ | |
125 public synchronized void putDir(DocuDirectory newDir) { | |
126 put(newDir); | |
127 String parent = FileOps.parent(newDir.getDirName()); | |
128 if (parent != "") { | |
129 // check the parent in the cache | |
130 DocuDirectory pd = (DocuDirectory) map.get(parent); | |
131 if (pd == null) { | |
132 // the parent is unknown | |
133 pd = new DocuDirectory(parent, this); | |
134 putDir(pd); | |
135 } | |
136 newDir.setParent(pd); | |
137 } | |
138 } | |
139 | |
140 /** | |
141 * Get a list with all children of a directory. | |
142 * | |
143 * Returns a List of DocuDirectory's. Returns an empty List if the directory | |
144 * has no children. If recurse is false then only direct children are | |
145 * returned. | |
146 * | |
147 * @param dirname | |
148 * @param recurse | |
149 * find all children and their children. | |
150 * @return | |
151 */ | |
152 public List getChildren(String dirname, boolean recurse) { | |
153 List l = new LinkedList(); | |
154 for (Iterator i = map.keySet().iterator(); i.hasNext();) { | |
155 String n = (String) i.next(); | |
156 DocuDirectory dd = (DocuDirectory) map.get(n); | |
157 if (recurse) { | |
158 if (dd.getDirName().startsWith(dirname)) { | |
159 l.add(dd); | |
160 } | |
161 } else { | |
162 if (FileOps.parent(dd.getDirName()).equals(dirname)) { | |
163 l.add(dd); | |
164 } | |
165 } | |
166 } | |
167 return l; | |
168 } | |
169 | |
170 /** | |
171 * Returns the DocuDirent with the pathname <code>fn</code> and the index | |
172 * <code>in</code> and the class <code>fc</code>. | |
173 * | |
174 * If <code>fn</code> is a file then the corresponding DocuDirent is | |
175 * returned and the index is ignored. | |
176 * | |
177 * @param fn | |
178 * digilib pathname | |
179 * @param in | |
180 * file index | |
181 * @param fc | |
182 * file class | |
183 * @return | |
184 */ | |
185 public DocuDirent getFile(String fn, int in, int fc) { | |
186 DocuDirectory dd; | |
187 // file number is 1-based, vector index is 0-based | |
188 int n = in - 1; | |
189 // first, assume fn is a directory and look in the cache | |
190 dd = (DocuDirectory) map.get(fn); | |
191 if (dd == null) { | |
192 // cache miss | |
193 misses++; | |
194 /* | |
195 * see if fn is a directory | |
196 */ | |
197 File f = new File(baseDirNames[0], fn); | |
198 if (f.isDirectory()) { | |
199 dd = new DocuDirectory(fn, this); | |
200 if (dd.isValid()) { | |
201 // add to the cache | |
202 putDir(dd); | |
203 } | |
204 } else { | |
205 /* | |
206 * maybe it's a file | |
207 */ | |
208 // get the parent directory string (like we store it in the | |
209 // cache) | |
210 String d = FileOps.parent(fn); | |
211 // try it in the cache | |
212 dd = (DocuDirectory) map.get(d); | |
213 if (dd == null) { | |
214 // try to read from disk | |
215 dd = new DocuDirectory(d, this); | |
216 if (dd.isValid()) { | |
217 // add to the cache | |
218 putDir(dd); | |
219 } else { | |
220 // invalid path | |
221 return null; | |
222 } | |
223 } else { | |
224 // it was not a real cache miss | |
225 misses--; | |
226 } | |
227 // get the file's index | |
228 n = dd.indexOf(f.getName(), fc); | |
229 } | |
230 } else { | |
231 // cache hit | |
232 hits++; | |
233 } | |
234 dd.refresh(); | |
235 if (dd.isValid()) { | |
236 try { | |
237 return dd.get(n, fc); | |
238 } catch (IndexOutOfBoundsException e) { | |
239 } | |
240 } | |
241 return null; | |
242 } | |
243 | |
244 /** | |
245 * Returns the DocuDirectory indicated by the pathname <code>fn</code>. | |
246 * | |
247 * If <code>fn</code> is a file then its parent directory is returned. | |
248 * | |
249 * @param fn | |
250 * digilib pathname | |
251 * @return | |
252 */ | |
253 public DocuDirectory getDirectory(String fn) { | |
254 DocuDirectory dd; | |
255 // first, assume fn is a directory and look in the cache | |
256 dd = (DocuDirectory) map.get(fn); | |
257 if (dd == null) { | |
258 // cache miss | |
259 misses++; | |
260 // see if it's a directory | |
261 File f = new File(baseDirNames[0], fn); | |
262 if (f.isDirectory()) { | |
263 dd = new DocuDirectory(fn, this); | |
264 if (dd.isValid()) { | |
265 // add to the cache | |
266 putDir(dd); | |
267 } | |
268 } else { | |
269 // maybe it's a file | |
270 if (f.canRead()) { | |
271 // try the parent directory in the cache | |
272 dd = (DocuDirectory) map.get(f.getParent()); | |
273 if (dd == null) { | |
274 // try to read from disk | |
275 dd = new DocuDirectory(f.getParent(), this); | |
276 if (dd.isValid()) { | |
277 // add to the cache | |
278 putDir(dd); | |
279 } else { | |
280 // invalid path | |
281 return null; | |
282 } | |
283 } else { | |
284 // not a real cache miss then | |
285 misses--; | |
286 } | |
287 } else { | |
288 // it's not even a file :-( | |
289 return null; | |
290 } | |
291 } | |
292 } else { | |
293 // cache hit | |
294 hits++; | |
295 } | |
296 dd.refresh(); | |
297 if (dd.isValid()) { | |
298 return dd; | |
299 } | |
300 return null; | |
301 } | |
302 | |
303 /** | |
304 * @return String[] | |
305 */ | |
306 public String[] getBaseDirNames() { | |
307 return baseDirNames; | |
308 } | |
309 | |
310 /** | |
311 * @return long | |
312 */ | |
313 public long getNumFiles() { | |
314 return numFiles; | |
315 } | |
316 | |
317 /** | |
318 * Sets the baseDirNames. | |
319 * | |
320 * @param baseDirNames | |
321 * The baseDirNames to set | |
322 */ | |
323 public void setBaseDirNames(String[] baseDirNames) { | |
324 this.baseDirNames = baseDirNames; | |
325 } | |
326 | |
327 /** | |
328 * @return long | |
329 */ | |
330 public long getHits() { | |
331 return hits; | |
332 } | |
333 | |
334 /** | |
335 * @return long | |
336 */ | |
337 public long getMisses() { | |
338 return misses; | |
339 } | |
340 | |
341 /** | |
342 * @return | |
343 */ | |
344 public int[] getFileClasses() { | |
345 return fileClasses; | |
346 } | |
347 | |
348 /** | |
349 * @param fileClasses | |
350 */ | |
351 public void setFileClasses(int[] fileClasses) { | |
352 this.fileClasses = fileClasses; | |
353 } | |
354 | |
355 } |