View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs.cache;
18  
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  import org.apache.commons.collections.map.AbstractLinkedMap;
23  import org.apache.commons.collections.map.LRUMap;
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.commons.vfs.FileName;
27  import org.apache.commons.vfs.FileObject;
28  import org.apache.commons.vfs.FileSystem;
29  import org.apache.commons.vfs.FileSystemException;
30  import org.apache.commons.vfs.VfsLog;
31  import org.apache.commons.vfs.util.Messages;
32  
33  /***
34   * This implementation caches every file using {@link LRUMap}.<br>
35   * The default constructor uses a LRU size of 100 per filesystem.
36   *
37   * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
38   * @version $Revision: 480428 $ $Date: 2006-11-29 07:15:24 +0100 (Mi, 29 Nov 2006) $
39   */
40  public class LRUFilesCache extends AbstractFilesCache
41  {
42      /***
43       * The logger to use.
44       */
45      private Log log = LogFactory.getLog(LRUFilesCache.class);
46  
47      private final Map filesystemCache = new HashMap(10);
48      private final int lruSize;
49  
50      private class MyLRUMap extends LRUMap
51      {
52          final FileSystem filesystem;
53  
54          public MyLRUMap(final FileSystem filesystem, int size)
55          {
56              super(size, true);
57              this.filesystem = filesystem;
58          }
59  
60          protected boolean removeLRU(final AbstractLinkedMap.LinkEntry linkEntry)
61          {
62              synchronized (LRUFilesCache.this)
63              {
64              	FileObject file = (FileObject) linkEntry.getValue();
65              	
66                  // System.err.println(">>> " + size() + " check removeLRU:" + linkEntry.getKey().toString());
67  
68                  if (file.isAttached() || file.isContentOpen())
69                  {
70                      // do not allow open or attached files to be removed
71                      // System.err.println(">>> " + size() + " VETO removeLRU:" + linkEntry.getKey().toString() + " (" + file.isAttached() + "/" + file.isContentOpen() + ")");
72                      return false;
73                  }
74  
75                  // System.err.println(">>> " + size() + " removeLRU:" + linkEntry.getKey().toString());
76                  if (super.removeLRU(linkEntry))
77                  {
78                      try
79                      {
80                          // force detach
81                          file.close();
82                      }
83                      catch (FileSystemException e)
84                      {
85                          VfsLog.warn(getLogger(), log, Messages.getString("vfs.impl/LRUFilesCache-remove-ex.warn"), e);
86                      }
87  
88                      Map files = (Map) filesystemCache.get(filesystem);
89                      if (files.size() < 1)
90                      {
91                          filesystemCache.remove(filesystem);
92                      }
93  
94                      return true;
95                  }
96  
97                  return false;
98              }
99          }
100     }
101 
102     /***
103      * Default constructor. Uses a LRU size of 100 per filesystem.
104      */
105     public LRUFilesCache()
106     {
107         this(100);
108     }
109 
110     /***
111      * Set the desired LRU size.
112      *
113      * @param lruSize the LRU size
114      */
115     public LRUFilesCache(int lruSize)
116     {
117         this.lruSize = lruSize;
118     }
119 
120     public void putFile(final FileObject file)
121     {
122         synchronized (this)
123         {
124             Map files = getOrCreateFilesystemCache(file.getFileSystem());
125 
126             // System.err.println(">>> " + files.size() + " put:" + file.toString());
127 
128             files.put(file.getName(), file);
129         }
130     }
131 
132     public FileObject getFile(final FileSystem filesystem, final FileName name)
133     {
134         synchronized (this)
135         {
136             Map files = getOrCreateFilesystemCache(filesystem);
137 
138             // FileObject fo = (FileObject) files.get(name);
139             // System.err.println(">>> " + files.size() + " get:" + name.toString() + " " + fo);
140 
141             return (FileObject) files.get(name);
142         }
143     }
144 
145     public void clear(final FileSystem filesystem)
146     {
147         synchronized (this)
148         {
149             // System.err.println(">>> clear fs " + filesystem);
150 
151             Map files = getOrCreateFilesystemCache(filesystem);
152             files.clear();
153 
154             filesystemCache.remove(filesystem);
155         }
156     }
157 
158     protected Map getOrCreateFilesystemCache(final FileSystem filesystem)
159     {
160         Map files = (Map) filesystemCache.get(filesystem);
161         if (files == null)
162         {
163             // System.err.println(">>> create fs " + filesystem);
164 
165             files = new MyLRUMap(filesystem, lruSize);
166             filesystemCache.put(filesystem, files);
167         }
168 
169         return files;
170     }
171 
172     public void close()
173     {
174         super.close();
175 
176         synchronized (this)
177         {
178             // System.err.println(">>> clear all");
179 
180             filesystemCache.clear();
181         }
182     }
183 
184     public void removeFile(final FileSystem filesystem, final FileName name)
185     {
186         synchronized (this)
187         {
188             Map files = getOrCreateFilesystemCache(filesystem);
189 
190             // System.err.println(">>> " + files.size() + " remove:" + name.toString());
191 
192             files.remove(name);
193 
194             if (files.size() < 1)
195             {
196                 filesystemCache.remove(filesystem);
197             }
198         }
199     }
200 
201     public void touchFile(final FileObject file)
202     {
203         // this moves the file back on top
204         getFile(file.getFileSystem(), file.getName());
205     }
206 }