All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.nc2.iosp.netcdf3.N3nioMMap.save Maven / Gradle / Ivy

Go to download

The NetCDF-Java Library is a Java interface to NetCDF files, as well as to many other types of scientific data formats.

There is a newer version: 4.3.22
Show newest version
/*
 * Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
 *
 * Portions of this software were developed by the Unidata Program at the
 * University Corporation for Atmospheric Research.
 *
 * Access and use of this software shall impose the following obligations
 * and understandings on the user. The user is granted the right, without
 * any fee or cost, to use, copy, modify, alter, enhance and distribute
 * this software, and any derivative works thereof, and its supporting
 * documentation for any purpose whatsoever, provided that this entire
 * notice appears in all copies of the software, derivative works and
 * supporting documentation.  Further, UCAR requests that the user credit
 * UCAR/Unidata in any publications that result from the use of this
 * software or in any product that includes this software. The names UCAR
 * and/or Unidata, however, may not be used in any advertising or publicity
 * to endorse or promote any products or commercial entity unless specific
 * written permission is obtained from UCAR/Unidata. The user also
 * understands that UCAR/Unidata is not obligated to provide the user with
 * any support, consulting, training or assistance of any kind with regard
 * to the use, operation and performance of this software nor to provide
 * the user with any updates, revisions, new versions or "bug fixes."
 *
 * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
 */
package ucar.nc2.iosp.netcdf3;

import ucar.ma2.*;
import ucar.nc2.iosp.Indexer;

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.net.URL;
import java.util.*;


/**
 * Use memmory mapping to do bulk read/write.
 */

class N3nioMMap extends N3iosp  {

  private MappedByteBuffer source;
  protected FileChannel channel;

  // used for writing
  private int minIncrement = 10000000; // minimum file increment size 10M

  //////////////////////////////////////////////////////////////////////////////////////
  // read existing file


  public void open(ucar.unidata.io.RandomAccessFile raf, ucar.nc2.NetcdfFile ncfile,
                   ucar.nc2.util.CancelTask cancelTask) throws IOException {
    super.open( raf, ncfile, cancelTask);
    channel = raf.getRandomAccessFile().getChannel();
    source = channel.map( readonly ? FileChannel.MapMode.READ_ONLY : FileChannel.MapMode.READ_WRITE, (long) 0, channel.size());
    if (debug) System.out.println ("Opened file to read:'" + raf.getLocation()+ "', size=" + channel.size());
  }

   /**
    * Read data subset from file for a variable, create primitive array.
    * @param beginOffset: variable's beginning byte offset in file.
    * @param index handles skipping around in the file.
    * @param source from this buye buffer
    * @param dataType dataType of the variable
    * @return primitive array with data read in
    */
  protected Object readData( int beginOffset, Indexer index, DataType dataType) {
    int offset = 0;
    int chunk = index.getChunkSize();
    int size = index.getTotalSize();

    if ((dataType == DataType.BYTE) || (dataType == DataType.CHAR)) {
      byte[] buff = new byte[size];
      while (index.hasNext()) {
        source.position( beginOffset + index.next());
        source.get(buff, offset, chunk);
        offset += chunk;
      }
      return (dataType == DataType.BYTE) ? buff : (Object) convertByteToChar( buff);

    } else if (dataType == DataType.SHORT) {
      short[] buff = new short[size];
      while (index.hasNext()) {
        source.position( beginOffset + index.next());
        ShortBuffer cb = source.asShortBuffer();
        cb.get(buff, offset, chunk);
        offset += chunk;
      }
      return buff;

    } else if (dataType == DataType.INT) {
      int[] buff = new int[size];
      while (index.hasNext()) {
        source.position( beginOffset + index.next());
        IntBuffer cb = source.asIntBuffer();
        cb.get(buff, offset, chunk);
        offset += chunk;
      }
     return buff;

    } else if (dataType == DataType.FLOAT) {
      float[] buff = new float[size];
      while (index.hasNext()) {
        source.position( beginOffset + index.next());
        FloatBuffer cb = source.asFloatBuffer();
        cb.get(buff, offset, chunk);
        offset += chunk;
      }
     return buff;

    } else if (dataType == DataType.DOUBLE) {
      double[] buff = new double[size];
      while (index.hasNext()) {
        source.position( beginOffset + index.next());
        DoubleBuffer cb = source.asDoubleBuffer();
        cb.get(buff, offset, chunk);
        offset += chunk;
      }
      return buff;
    }

    throw new IllegalStateException();
  }

  public void create(String filename, ucar.nc2.NetcdfFile ncfile, boolean fill) throws IOException {
    super.create( filename, ncfile, fill);
    channel = raf.getChannel();
    source = channel.map(FileChannel.MapMode.READ_WRITE, (long) 0, recStart);
    if (debug) out.println ("Opened file to write:'" + filename+ "', size=" + channel.size());
    flush();
  }

  protected void setNumrecs(int n) throws IOException {
    if (n <= numrecs) return;
    super.setNumrecs(n);

    // gotta grow the mapBuffer
    long need = recStart + n * recsize;
    if (debugSize) System.out.println("gotta grow the mapBuffer to = "+need);
    source = channel.map(FileChannel.MapMode.READ_WRITE, (long) 0, need);
  }

  /**
    * Write data subset to file for a variable, create primitive array.
    * @param beginOffset: variable's beginning byte offset in file.
    * @param index handles skipping around in the file.
    * @param source from this buye buffer
    * @param dataType dataType of the variable
    * @return primitive array with data read in
    */
  protected void writeData( Array aa, int beginOffset, Indexer index, DataType dataType) {
    int offset = 0;
    int chunk = index.getChunkSize();

    if ((dataType == DataType.BYTE) || (dataType == DataType.CHAR)) {
      byte[] buff;
      if (dataType == DataType.BYTE)
         buff = (byte[]) aa.getStorage();
      else {
        char[] cbuff = (char[]) aa.getStorage();
        buff = convertCharToByte( cbuff);
      }
      while (index.hasNext()) {
        source.position( beginOffset + index.next());
        source.put(buff, offset, chunk);
        offset += chunk;
      }
      return;

    } else if (dataType == DataType.SHORT) {
      short[] buff = (short[]) aa.getStorage();
      while (index.hasNext()) {
        source.position( beginOffset + index.next());
        ShortBuffer cb = source.asShortBuffer();
        cb.put(buff, offset, chunk);
        offset += chunk;
      }
      return;

    } else if (dataType == DataType.INT) {
      int[] buff = (int[]) aa.getStorage();
      while (index.hasNext()) {
        source.position( beginOffset + index.next());
        IntBuffer cb = source.asIntBuffer();
        cb.put(buff, offset, chunk);
        offset += chunk;
      }
      return;

    } else if (dataType == DataType.FLOAT) {
      float[] buff = (float[]) aa.getStorage();
      while (index.hasNext()) {
        source.position( beginOffset + index.next());
        FloatBuffer cb = source.asFloatBuffer();
        cb.put(buff, offset, chunk);
        offset += chunk;
      }
      return;

    } else if (dataType == DataType.DOUBLE) {
      double[] buff = (double[]) aa.getStorage();
      while (index.hasNext()) {
        source.position( beginOffset + index.next());
        DoubleBuffer cb = source.asDoubleBuffer();
        cb.put(buff, offset, chunk);
        offset += chunk;
      }
      return;
   }

    throw new IllegalStateException();
  }

  public void flush() throws IOException {
    channel.force( false);
  }

  public void close() throws IOException {
    if (!readonly) flush();
    if (channel != null)
      channel.close();
    super.close();
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy