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

net.algart.arrays.DataFile Maven / Gradle / Ivy

Go to download

Open-source Java libraries, supporting generalized smart arrays and matrices with elements of any types, including a wide set of 2D-, 3D- and multidimensional image processing and other algorithms, working with arrays and matrices.

There is a newer version: 1.4.23
Show newest version
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2007-2024 Daniel Alievsky, AlgART Laboratory (http://algart.net)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package net.algart.arrays;

import java.nio.*;

/**
 * 

Some "data file" (usually disk file) that supports file-mapping operation. * Used by the {@link LargeMemoryModel large memory model}.

* *

The instances of this class are returned by methods of {@link DataFileModel} interface.

* *

Note: all implementations of this interface from this package do not override standard * equals and hashCode methods of Object class. * Illegal overriding these methods may lead to losing some file instances by * {@link DataFileModel#allTemporaryFiles()} method.

* *

Objects implementing this interface may be not immutable * and not thread-safe, but must be thread-compatible * (allow manual synchronization for multithreading access).

* * @author Daniel Alievsky */ public interface DataFile { /** * Possible results of {@link DataFile#open(boolean)} method. */ enum OpenResult { /** * Returned by link {@link DataFile#open(boolean)} method if the data file existed before the method call. */ OPENED, /** * Returned by link {@link DataFile#open(boolean)} method if its argument is false * and the data file was created by the method call. */ CREATED } /** * Returns the byte order in all byte buffers returned by {@link #map(Range, boolean)} * method. * *

This method never throws exceptions. * * @return the byte order in all returned byte buffers. */ ByteOrder byteOrder(); /** * Opens the data file. Does nothing if it is already opened. * Must be called before any calls of {@link #map(Range, boolean)}, * {@link #length()}, {@link #length(long)}, * {@link BufferHolder#unmap(boolean)}, {@link BufferHolder#flush(boolean)} methods. * It is not necessary to call this method before deletion the file * by {@link DataFileModel#delete(DataFile)} method. * *

If readOnly argument is true, this file * will be used only for reading data. * In particular, the {@link #length(long)} method will not be called. * The read-only mode will be actual until {@link #close() closing} file; * the next open method may change this mode. * *

If the file does not exist yet, then behavior of this method depends on * readOnly argument. If it is false (read/write mode), * this method tries to create it at the position theModelWhichCreatedThisFile.{@link * DataFileModel#getPath(DataFile) getPath}(thisFile). * If it is true (read-only mode), this method just throws * IOError with the corresponding cause (usually FileNotFoundException). * In the first case, the length of the newly created file is always 0. * *

This method returns {@link OpenResult#CREATED} if and only if * readOnly argument is false and the data file was successfully created. * In all other cases this method returns {@link OpenResult#OPENED}. * * @param readOnly if true, the file data will be read but will not be changed. * @return {@link OpenResult#CREATED} if this method has successfully created the new file, * {@link OpenResult#OPENED} in all other cases. * @see #close() * @throws java.io.IOError in a case of some disk errors or if the argument is true * and there is no file with the given position. */ OpenResult open(boolean readOnly); /** * Closes data file. Does nothing if it is already closed. * It disables all other further operations, besides {@link #open(boolean)} * and {@link DataFileModel#delete(DataFile)} methods. * *

Please note that there are no guarantees that this method * completely releases all system resources, associated with this data file. * Please see comments to classes {@link DefaultDataFileModel} and {@link StandardIODataFileModel} * about behavior of this method in that data file models. * * @see #open(boolean) * @throws java.io.IOError in a case of some disk errors. */ void close(); /** * Tries to write any updates of this data file to the storage device that contains it. */ void force(); /** * Returns the argument passed to last {@link #open(boolean)} method. * *

This method never throws exceptions. * * @return true if the file is opened in read-only mode. */ boolean isReadOnly(); /** * Maps a region of this data file directly into memory. * It is an analog (usually a wrapper) of standard * {@link java.nio.channels.FileChannel#map} method. * The mapping mode (read-write or read-only) may depend on * the argument of the previous call of the {@link #open(boolean)} method. * *

This method is used by this package in very restricted manner. * If you implement this method in your own {@link DataFileModel}, you can be sure that * the arguments the following conditions are true: *

    *
  1. range.position()=bankSize*k, where bankSize is the result of * {@link DataFileModel#recommendedBankSize(boolean)} method of your data file model * and k is some non-negative integer; *
  2. range.length()<=bankSize; *
  3. the same positions are never mapped 2 or more times simultaneously for one file: * {@link BufferHolder#unmap(boolean)} method is always called before the same * position will be mapped again. *
*

In particular, it means that the regions mapped by this package * never overlap. * *

If notLoadDataFromFile argument is true, this method * may ignore the current data in this data file. This method is called by this package with * notLoadDataFromFile==true if the returned buffer will be immediately * filled by some values, not depending on the previous file content. * * @param range the position within the file at which the mapped region * starts and the size of the region to be mapped. * In current version, the region size ({@link Range#length() range.length()} * must not be greater than Integer.MAX_VALUE. * @param notLoadDataFromFile if true, this method may discard the previous content * of the specified region of the data file. * @return an object allowing to access mapped data. * @throws java.io.IOError in a case of some disk errors. */ BufferHolder map(Range range, boolean notLoadDataFromFile); /** * Returns the current length of the data file. * * @return the current length of the data file. * @throws java.io.IOError in a case of some disk errors. */ long length(); /** * Resizes the data file. * * @param newLength new length of data file. * @throws java.io.IOError in a case of some disk errors. */ void length(long newLength); /** *

Pair of 2 long values position * and length, describing the range position..position+length-1 * of linear addresses in some {@link DataFile data file}.

* *

This class is immutable and thread-safe.

* * @see DataFile#map(Range, boolean) */ final class Range implements Comparable { private final long position; private final long length; private Range(long position, long length) { if (position < 0) throw new IllegalArgumentException("Negative position argument: " + position); if (length < 0) throw new IllegalArgumentException("Negative length argument: " + position); this.position = position; this.length = length; } /** * Creates new range position..position+length-1. * @param position the starting range position. * @param length the length of range. * @return new range instance. * @throws IllegalArgumentException of position or length is negative. */ public static Range valueOf(long position, long length) { return new Range(position, length); } /** * Returns the starting range position. * * @return the starting range position. */ public long position() { return this.position; } /** * Returns the range length. * * @return the range length. */ public long length() { return this.length; } /** * Returns -1 if the starting position of this range is less than the starting position of the argument, * 1 if it is greater and 0 if they are equal. * * @param o another range. * @return -1 if the starting position of this range is less than the starting position of the argument, * 1 if it is greater and 0 if they are equal. */ public int compareTo(Range o) { return position < o.position ? -1 : position > o.position ? 1 : 0; } /** * Returns a brief string description of this factory. * *

The result of this method may depend on implementation. * * @return a brief string description of this object. */ public String toString() { return Long.toHexString(position) + "h..+" + Long.toHexString(length) + "h"; } /** * Returns the hash code for this range. * * @return the hash code for this range. */ public int hashCode() { int v1 = (int)(position >>> 32) * 37 + (int)position; int v2 = (int)(length >>> 32) * 37 + (int)length; return v1 * 37 + v2; } /** * Indicates whether some other range is equal to this one, i.e. it * contains the same starting position and length. * * @param obj some another range. * @return true if the passed object is an instance of this class and * contains the same starting position and length. */ public boolean equals(Object obj) { if (!(obj instanceof Range r)) { return false; } return r.position == position && r.length == length; } } /** *

An object allowing to access mapped data, returned by the {@link DataFile#map} method.

* *

Objects implementing this interface may be not immutable * and not thread-safe, but must be thread-compatible * (allow manual synchronization for multithreading access).

* */ interface BufferHolder { /** * Returns the mapped region within the file, in bytes. * The result is identical to the first argument of {@link DataFile#map(Range, boolean)} method, * which was called to create this instance. * * @return the mapped region within the file, in bytes. */ Range range(); /** * Returns the mapped data. Usually returns MappedByteBuffer/ * *

This method never throws exceptions. * * @return the mapped data. */ ByteBuffer data(); /** * Returns the object which deallocation by the garbage collector allows all * manipulations with the source mappable object, including deletion and * any resizing. Usually returns the same result as {@link #data()}. * *

Used by implementation of AlgART arrays with * {@link net.algart.finalizing.Finalizer#invokeOnDeallocation} method. * *

This method never throws exceptions. * * @return the object which deallocation allows all manipulations with the source mappable object. */ Object mappingObject(); /** * Makes an effort to ensure that this buffer's content will be resident in physical memory. * In other words, this method tries to preload the content of this buffer into RAM * to provide fastest access to its content in the nearest future. */ void load(); /** * Forces any changes made to this buffer's content to be written to the * storage device containing the mapped object. * *

This method may not perform immediate writing data to the storage devices. * But it guarantees that any changes in the buffer's content will not be lost. * More precisely, it guarantees that:

    *
  • this data will be correctly read by * possible next call of {@link DataFile#map} method;
  • *
  • and, for non-temporary files (i.e. for any instances of {@link DataFile} * which were not created by {@link DataFileModel#createTemporary} method), * the data will be really stored in the file and will be able to be loaded * by another software, at least, after shutting down JVM. * (There is no this guarantee for temporary files: * such files are used by this application only and automatically deleted * while JVM shutdown.) *
* *

If the forcePhysicalWriting argument is true, this * method tries to write data to the storage device immediately. * For data file models implemented in this package, * it means that the data will be really stored on the disk and will be immediately * available for reading by another applications. * * @param forcePhysicalWriting is it necessary to try forcing physical writing all associated resources * to the external device. * @throws java.io.IOError in a case of some disk errors. */ void flush(boolean forcePhysicalWriting); /** * Unmaps the data: releases all system resources associated with this mapping. * *

This method always performs, at least, the same actions as {@link #flush(boolean) * flush(forcePhysicalWriting)} method with the same forcePhysicalWriting argument. * *

This method may do not actual unmapping. For example, its implementation * for {@link DefaultDataFileModel} does not unmap the data. * *

After calling this method, this instance must not be used, excepting calling methods * {@link #mappingObject()}, {@link #isLoadedFromCache()} and toString(). * In particular, this method must not be called twice. * Moreover, behavior of the ByteBuffer returned by the last call of {@link #data()} method * becomes undefined. * * @param forcePhysicalWriting is it necessary to try forcing physical writing all associated resources * to the external device. * @throws java.io.IOError in a case of some disk errors. */ void unmap(boolean forcePhysicalWriting); /** * This method either performs the same actions as {@link #unmap(boolean) unmap(false)} method * and returns true, * or performs some reduced form of unmapping (or even does nothing) and returns false. * *

This method is called by AlgART array manager for temporary data files * when we are absolutely sure that the this buffer's content will never be useful in future * and may be lost. Namely, it is called while array finalization and while * system shutdown. (In all other cases, {@link #unmap(boolean)} method is called instead.) * *

So, the implementation of this method should release all external resources, * if there are such resources associated with this mapping buffer, but may not to force writing * buffer's content to external device, if it requires long time. * *

In {@link DefaultDataFileModel}, this method is equivalent to * {@link #unmap(boolean) unmap(false)}} and always * returns true. If {@link StandardIODataFileModel} (that does not associate * any resources with every buffer), this method does nothing and always returns false. * *

After calling this method, this instance must not be used, excepting calling methods * {@link #mappingObject()}, {@link #isLoadedFromCache()} and toString(). * In particular, this method must not be called twice. * Moreover, behavior of the ByteBuffer returned by the last call of {@link #data()} method * becomes undefined. * * @return true if this method has performed all actions that are performed by * {@link #unmap(boolean) unmap(false)}. * If (and only if) the result is true, we can be sure that the same data * will be loaded by next call {@link DataFile#map} method. * * @throws java.io.IOError in a case of some disk errors. */ boolean dispose(); // Result of dispose() method is ignored in current implementation of AlgART arrays. /** * Returns true if this object was not actually read from the file by * {@link DataFile#map(Range, boolean)} method, but was quickly loaded from some cache. * *

This method is used only for debugging (logging). * *

This method never throws exceptions. * * @return true if this object was quickly loaded from some cache. */ boolean isLoadedFromCache(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy