Package org.geotools.data.shapefile.files

Source Code of org.geotools.data.shapefile.files.MemoryMapCache

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2008, Open Source Geospatial Foundation (OSGeo)
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation;
*    version 2.1 of the License.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*/
package org.geotools.data.shapefile.files;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geotools.data.DataUtilities;
import org.geotools.resources.NIOUtilities;
import org.geotools.util.SoftValueHashMap;
import org.geotools.util.SoftValueHashMap.ValueCleaner;
import org.geotools.util.logging.Logging;

/**
* A cache for memory mapped buffers, used to avoid generating over and over
* read only memory mapped buffers. Mapping a file is a synchronized operation,
* plus by generating light copies the same buffer can be shared by various threads
* @author Andrea Aime - OpenGeo
*
*/
class MemoryMapCache {
 
  static final Logger LOGGER = Logging.getLogger(MemoryMapCache.class);

    SoftValueHashMap<MappingKey, MappedByteBuffer> buffers = new SoftValueHashMap<MappingKey, MappedByteBuffer>(0, new BufferCleaner());
   
  MappedByteBuffer map(FileChannel wrapped, URL url, MapMode mode, long position, long size) throws IOException {
    if(mode != MapMode.READ_ONLY) {
      return wrapped.map(mode, position, size);
    }
   
    File file = DataUtilities.urlToFile(url).getCanonicalFile();
    MappingKey mk = new MappingKey(file, position, size);
    MappedByteBuffer buffer = buffers.get(mk);
    if(buffer == null) {
      synchronized (this) {
        buffer = buffers.get(mk);
        if(buffer == null) {
          buffer = wrapped.map(mode, position, size);
          buffers.put(mk, buffer);
          if(LOGGER.isLoggable(Level.FINE)) {
            LOGGER.log(Level.FINE, "Mapping and caching " + file.getAbsolutePath());
          }
        }
      }
    } else {
      if(LOGGER.isLoggable(Level.FINE)) {
        LOGGER.log(Level.FINE, "Using cached map for " + file.getAbsolutePath());
      }
    }
   
    return (MappedByteBuffer) buffer.duplicate();
  }
 
  /**
   * Cleans up all memory mapped regions for a specified file. It is necessary to call this
   * method before any attempt to open a file for writing on Windows
   * @param file
   */
  void cleanFileCache(URL url) {
      try {
          final File rawFile = DataUtilities.urlToFile(url);
          if(rawFile == null) {
              // not a local file
              return;
          }
            File file = rawFile.getCanonicalFile();
          List<MappingKey> keys = new ArrayList<MappingKey>(buffers.keySet());
          for (MappingKey key : keys) {
                if(key.file.equals(file)) {
                    MappedByteBuffer buffer = buffers.remove(key);
                    NIOUtilities.clean(buffer, true);
                    if(LOGGER.isLoggable(Level.FINE)) {
                LOGGER.log(Level.FINE, "Removed mapping for " + file.getAbsolutePath());
                    }
                }
            }
      } catch(Throwable t) {
          LOGGER.log(Level.WARNING, "An error occurred while trying to clean the memory map cache", t);
      }
  }
 
  void clean() {
    List<MappingKey> keys = new ArrayList<MappingKey>(buffers.keySet());
      for (MappingKey key : keys) {
            MappedByteBuffer buffer = buffers.remove(key);
            NIOUtilities.clean(buffer, true);
            if(LOGGER.isLoggable(Level.FINE)) {
        LOGGER.log(Level.FINE, "Removed mapping for " + key.file.getAbsolutePath());
            }
        }
  }
 
  /**
   * Tracks a memory mapped region of a certain file
   */
  static class MappingKey {
    File file;
    long position;
    long size;
   
    public MappingKey(File file, long position, long size) {
      super();
      this.file = file;
      this.position = position;
      this.size = size;
    }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((file == null) ? 0 : file.hashCode());
            result = prime * result + (int) (position ^ (position >>> 32));
            result = prime * result + (int) (size ^ (size >>> 32));
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            MappingKey other = (MappingKey) obj;
            if (file == null) {
                if (other.file != null)
                    return false;
            } else if (!file.equals(other.file))
                return false;
            if (position != other.position)
                return false;
            if (size != other.size)
                return false;
            return true;
        }
  }
 
  /**
   * Cleans up the buffers before the soft reference gets deallocated
   * @author Andrea Aime
*
*
* @source $URL$
   */
  public class BufferCleaner implements ValueCleaner {

        public void clean(Object key, Object object) {
            MappedByteBuffer buffer = (MappedByteBuffer) object;
            NIOUtilities.clean(buffer, true);
        }

    }


}
TOP

Related Classes of org.geotools.data.shapefile.files.MemoryMapCache

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.