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

com.gc.iotools.stream.store.ThresholdStore Maven / Gradle / Ivy

Go to download

EasyStream is a small set of utilities for dealing with streams (InputStreams and OutputStreams). The aim is to ease the use of pipes when they're required. Main features are: * "Convert" an OutputStream to an InputStream. * Count the number of bytes read or wrote to a given stream. * While reading the data from an InputStream copy it to a supplied OutputStream. * Read the content of an InputStream multiple times or seek to a definite position

The newest version!
package com.gc.iotools.stream.store;

/*
 * Copyright (c) 2008, 2015 Gabriele Contini. This source code is released
 * under the BSD License.
 */

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gc.iotools.stream.utils.LogUtils;

/**
 * Store that puts data in memory until threshold size is reach. At that point
 * data is written to the disk.
 * 
 * @author dvd.smnt
 * @since 1.2.0
 * @version $Id: ThresholdStore.java 463 2013-01-21 23:54:17Z
 *          [email protected] $
 */
public class ThresholdStore implements SeekableStore {
	private static final int BUF_SIZE = 8192;

	private static final Logger LOG = LoggerFactory
			.getLogger(ThresholdStore.class);

	private RandomAccessFile fileAccess;
	private File fileStorage;
	private final String instantiationPath;
	private final MemoryStore ms = new MemoryStore();
	private long position = 0;
	private long size = 0;

	private final int treshold;

	/**
	 * 

* Constructor for ThresholdStore. *

* * @param treshold * a int. */ public ThresholdStore(final int treshold) { this.treshold = treshold; this.instantiationPath = LogUtils.getCaller(ThresholdStore.class, 5); } /** *

* Constructor for ThresholdStore. *

* * @param treshold * a int. * @param file * a {@link java.io.File} object. */ public ThresholdStore(final int treshold, final File file) { this.treshold = treshold; this.fileStorage = file; this.instantiationPath = LogUtils.getCaller(ThresholdStore.class, 5); } /** {@inheritDoc} */ @Override public void cleanup() { this.size = 0; this.position = 0; this.ms.cleanup(); if (this.fileAccess != null) { try { this.fileAccess.close(); } catch (final IOException e) { ThresholdStore.LOG.warn( "Exception in closing the temporary " + "stream associated to file [" + this.fileStorage.getName() + "] it " + "is possible to continue but some" + " resources are not released.", e); } this.fileAccess = null; } if (this.fileStorage != null) { // FileCleaningTracker ftc=new FileCleaningTracker(); // ftc.exitWhenFinished() final boolean deleted = this.fileStorage.delete(); if (deleted) { this.fileStorage = null; } else { this.fileStorage.deleteOnExit(); ThresholdStore.LOG.warn("Temporary file [" + this.fileStorage.getName() + "] was not deleted. It " + "is possible to continue but some" + " resources are not released. Instantiation path [" + this.instantiationPath + "]"); } } } /** * {@inheritDoc} Clean up the temporary files eventually open. */ @Override protected void finalize() throws Throwable { cleanup(); } /** {@inheritDoc} */ @Override public int get(final byte[] bytes, final int offset, final int length) throws IOException { int result; if (this.size < this.treshold) { result = this.ms.get(bytes, offset, length); } else { if (this.position != this.fileAccess.getFilePointer()) { this.fileAccess.seek(this.position); } result = this.fileAccess.read(bytes, offset, length); } this.position += Math.max(result, 0); return result; } /** *

* Getter for the field size. *

* * @return a long. */ public long getSize() { return this.size; } /** *

* Getter for the field treshold. *

* * @return a int. */ public int getTreshold() { return this.treshold; } /** {@inheritDoc} */ @Override public void put(final byte[] bytes, final int offset, final int length) throws IOException { if (length <= 0) { throw new IllegalArgumentException("lenght = [" + length + "]"); } if (this.size + length < this.treshold) { this.ms.put(bytes, offset, length); } else { if (this.size < this.treshold) { // empty the memory buffer and init the file buffer if (this.fileStorage == null) { this.fileStorage = File.createTempFile("iotools-storage", ".tmp"); } this.fileAccess = new RandomAccessFile(this.fileStorage, "rw"); final byte[] buffer = new byte[ThresholdStore.BUF_SIZE]; this.ms.seek(0); int len; while ((len = this.ms.get(buffer, 0, buffer.length)) > 0) { this.fileAccess.write(buffer, 0, len); } this.ms.cleanup(); } else { final long fp = this.fileAccess.getFilePointer(); if (fp != this.size) { this.fileAccess.seek(this.size); } } this.fileAccess.write(bytes, offset, length); } this.size += length; } /** {@inheritDoc} */ @Override public void seek(final long position) throws IOException { // if already in place do nothing. if (this.position != position) { this.position = position; if (position <= this.size) { if (this.size < this.treshold) { this.ms.seek(position); } else { final long fp = this.fileAccess.getFilePointer(); if (fp != position) { this.fileAccess.seek(position); } } } else { // seek outside the buffer throw new IOException("Seek at posiotion [" + position + "]outside buffer size[" + this.size + "]"); } } } /** *

* Setter for the field position. *

* * @param position * a long. */ public void setPosition(final long position) { this.position = position; } /** * {@inheritDoc} Provides a String representation of the state of the * Store for debugging purposes. */ @Override public String toString() { String str = this.getClass().getSimpleName() + "[pos=" + this.position + ",size=" + this.size; if (this.fileStorage != null) { str += ",file=" + this.fileStorage; } else { str += ",ms=" + this.ms; } if (this.fileAccess != null) { try { str += ",fp=" + this.fileAccess.getFilePointer(); } catch (final IOException e) { // do nothing... here for debugging. } } return str + "]"; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy