Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/scoja/server/target/FileLRUCache.java


1   
2   package org.scoja.server.target;
3   
4   import org.scoja.util.LRUShell;
5   import org.scoja.util.ExpiringLRUCache;
6   import org.scoja.util.TransientMap;
7   import org.scoja.common.PriorityUtils;
8   import org.scoja.server.core.EventContext;
9   import org.scoja.server.source.Internal;
10  
11  /**
12   * Es una caché de ficheros abiertos.
13   * Está implementada con un {@link ExpiringLRUCache}, así que hereda
14   * de ella tanto sus capacidades (control por tamaño y tiempo) como su
15   * idiosincrasia de uso (todos los accesos son a través del método
16   * {@link #get(String)}).
17   * <p><b>Forma de uso</b>
18   * Si <code>fileCache</code> contiene un FileLRUCache,
19   * <code><pre>
20   * final FileShell file = fileCache.get(filename, env);
21     if (file != null) {
22         try {
23             final OutputStream out = file.getOutputStream();
24             .....
25         } catch (IOException e) {
26             System.err.println("UGGS: " + e.getMessage());
27         } finally {
28             file.release();
29         }
30     }
31   * </pre></code>
32   * El método {@link #get(String)} devuelve <code>null</code> si no 
33   * pudo abrir el fichero; además produce un evento interno con level
34   * {@link PriorityUtils#CRIT}; por tanto, no es necesario producir
35   * ningún mensaje en el sitio de uso.
36   * Para que un error de apertura no provoque una cantidad
37   * desproporcianada de mensajes de error y de intentos de apertura (lo
38   * que redudaría muy negativamente en el rendimiento de Scoja),
39   * se mantiene una tabla con los ficheros que han fallado.
40   */
41  public class FileLRUCache 
42      implements TransientMap.Graveyard {
43  
44      public static final int DEFAULT_OPEN_MAX_SIZE = 500;
45      public static final long DEFAULT_OPEN_MAX_INACTIVITY = 5*60*1000;
46      public static final int DEFAULT_FAILED_MAX_SIZE = 50000;
47      public static final long DEFAULT_FAILED_MAX_INACTIVITY = 5*60*1000;
48  
49      protected final ExpiringLRUCache openCache;
50      protected final TransientMap failedCache;
51      
52      public FileLRUCache() {
53          openCache = new ExpiringLRUCache(DEFAULT_OPEN_MAX_SIZE,
54                                           DEFAULT_OPEN_MAX_INACTIVITY);
55          failedCache = new TransientMap(DEFAULT_FAILED_MAX_INACTIVITY);
56          failedCache.setGraveyard(this);
57      }
58      
59      public void setSize(final int maxSize) {
60          openCache.setSize(maxSize);
61      }
62      
63      public void setInactivity(final long maxInactivity) {
64          openCache.setInactivity(maxInactivity);
65      }
66      
67      public void setFailedMemory(final long maxMemory) {
68          failedCache.setFadingOut(maxMemory);
69      }
70      
71      /**
72       * Busca el fichero <code>filename</code> en esta caché.
73       * Si no lo encuentra y recuerda haber fallado en esta operación 
74       * hace poco, devuelve <code>null</code>.
75       * Si no lo encuentra y no recuerda haber fallado en esta
76       * operación hace poco, intenta abrirlo.
77       * Si falla en la operación de abrirlo, genera un mensaje
78       * {@link Internal#crit} y devuelve <code>null</code>.
79       * En cualquier otro caso, el resultado es distinto de
80       * <code>null</code> y ya contiene el fichero abierto.
81       * <b>No se debe olvidar hacer un <code>release()</code> sobre el
82       * resultado una vez que ya se ha terminado de usar.</b>
83       */
84      public FileShell get(final String filename,
85                           final EventContext env) {
86          final LRUShell shell = openCache.get(filename);
87          FileShell file = (FileShell)shell.getValue();
88          if (file == null) {
89              final Object name = failedCache.get(filename);
90              if (name == null) {
91                  try {
92                      file = new FileShell(filename, shell);
93                      Internal.notice(env, "File \"" +filename+ "\""
94                                      + " added to the open files cache");
95                      shell.put(file);
96                  } catch (Throwable e) {
97                      shell.release();
98                      failedCache.put(filename, filename);
99                      Internal.crit(env, "Error " + e.getMessage()
100                                   + " while trying open file " + filename
101                                   + " to write " + env.getEvent());
102                 }
103             } else {
104                 if (PriorityUtils.DEBUG <= Internal.LOG_DETAIL) {
105                     Internal.debug(env, "Ignoring request to open file \""
106                                    +filename+"\" because recently failed");
107                 }
108             }
109         } else {
110             if (PriorityUtils.DEBUG <= Internal.LOG_DETAIL) {
111                 Internal.debug(env, "File \"" +filename+ "\""
112                                + " found in the open file cache");
113             }
114         }
115         return file;
116     }
117     
118     public void died(final Object key, final Object value) {
119         Internal.notice("Forgetting that opening file \"" +key+ "\" failed."
120                         + " I will try to open it at next request.");
121     }
122 }