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 }