package com.neocoretechs.bigsack.io;
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import com.neocoretechs.bigsack.DBPhysicalConstants;
/*
* Copyright (c) 2003, NeoCoreTechs
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* Neither the name of NeoCoreTechs nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* Memory mapped file I/O. Somewhat bound to our block-oriented tables
* by the Fextend, which guarantees a block<br>
* For pool, there are one of these per tablespace and pointers use the
* first 3 bits for tablespace so our theoretical max per tablespace is
* 2,305,843,009,213,693,952 bytes * 8 tablespaces
* @see IoInterface
* @author Groff
*/
public final class MmapIO implements IoInterface {
private static boolean DEBUG = false;
private boolean fisopen, fisnew;
private File WO;
private FileOutputStream FO;
private FileChannel FC;
private LinkedMappedByteBuffer linkedMappedByteBuff;
private ByteBuffer bPageBuff =
ByteBuffer.allocate(DBPhysicalConstants.DBLOCKSIZ);
private RandomAccessFile RA;
public MmapIO() {
}
public MmapIO(String fname, boolean create) throws IOException {
Fopen(fname, create);
}
/** create is true for 'create if not existing' */
public boolean Fopen(String fname, boolean create) throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fopen "+fname+" "+create);
WO = new File(fname);
if (!WO.exists()) {
if (create) {
// create if not existing
FO = new FileOutputStream(WO);
FO.close();
RA = new RandomAccessFile(WO, "rw");
fisnew = true;
} else {
fisopen = false;
return false;
}
} else { // exists?
//
RA = new RandomAccessFile(WO, "rw");
fisnew = false;
}
FC = RA.getChannel();
long iSize;
if (FC.size() == 0L)
iSize =
DBPhysicalConstants.DBLOCKSIZ * DBPhysicalConstants.DBUCKETS;
else
iSize = FC.size();
// map the mem
//linkedMappedByteBuff = FC.map(FileChannel.MapMode.READ_WRITE, 0, iSize);
linkedMappedByteBuff = new LinkedMappedByteBuffer(FC, iSize);
fisopen = true;
return true;
}
// re-open file
public void Fopen() throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fopen "+WO);
RA = new RandomAccessFile(WO, "rw");
FC = RA.getChannel();
long iSize;
if (FC.size() == 0L) {
iSize =
DBPhysicalConstants.DBLOCKSIZ * DBPhysicalConstants.DBUCKETS;
fisnew = true;
} else {
iSize = FC.size();
fisnew = false;
}
//linkedMappedByteBuff = FC.map(FileChannel.MapMode.READ_WRITE, 0, iSize);
linkedMappedByteBuff = new LinkedMappedByteBuffer(FC, iSize);
fisopen = true;
}
/**
* Invoke about every flush of every associated buffer imaginable
* lots of opinions but this way just seems to have to work
*/
public void Fclose() throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fopen "+WO);
if (fisopen) {
Fforce();
FC.close();
RA.close();
fisopen = false;
}
}
public long Ftell() throws IOException {
if( DEBUG )
System.out.println("MMapIO.Ftell "+linkedMappedByteBuff.position());
return linkedMappedByteBuff.position();
}
public void Fseek(long offset) throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fseek "+offset+" pos:"+linkedMappedByteBuff.position());
linkedMappedByteBuff.position((int) offset);
}
public long Fsize() throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fsize "+linkedMappedByteBuff.capacity());
return linkedMappedByteBuff.capacity();
}
public void Fset_length(long newlen) throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fset_length NEW LENGTH:"+newlen);
if (newlen < FC.size()) {
linkedMappedByteBuff.force();
linkedMappedByteBuff = null;
System.gc();
FC.truncate(newlen);
FC.force(false);
//linkedMappedByteBuff = FC.map(FileChannel.MapMode.READ_WRITE, 0, newlen);
linkedMappedByteBuff = new LinkedMappedByteBuffer(FC, newlen);
} else if (newlen > FC.size())
Fextend(newlen);
}
public void Fforce() throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fforce ATTEMPTING FORCE");
linkedMappedByteBuff.force();
FC.force(true);
RA.getFD().sync();
}
/**
* Position file at newSize - 1 block, and write blank block
* @param newSize
* @throws IOException
*/
private void Fextend(long newSize) throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fextend "+newSize);
FC.position(newSize - DBPhysicalConstants.DBLOCKSIZ);
FC.write(bPageBuff);
bPageBuff.rewind();
FC.force(false);
}
/**
* Extend by 1 block by writing page buffer if position is at capacity value
* @throws IOException
*/
@SuppressWarnings("unused")
private void Fextend() throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fextend ");
long fPos = linkedMappedByteBuff.position();
if (fPos == linkedMappedByteBuff.capacity()) {
FC.write(bPageBuff);
bPageBuff.rewind();
FC.force(false);
}
}
// writing..
public void Fwrite(byte[] obuf) throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fwrite @"+linkedMappedByteBuff.position()+" bytes:"+obuf.length);
try {
linkedMappedByteBuff.put(obuf);
} catch (Exception bue) {
throw new IOException(bue.toString());
}
}
public void Fwrite(byte[] obuf, int osiz) throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fwrite @"+linkedMappedByteBuff.position()+" bytes:"+obuf.length+" size:"+osiz);
try {
linkedMappedByteBuff.put(obuf, 0, osiz);
} catch (Exception bue) {
throw new IOException(bue.toString());
}
}
public void Fwrite_int(int obuf) throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fwrite int @"+linkedMappedByteBuff.position()+" val:"+obuf);
try {
linkedMappedByteBuff.putInt(obuf);
} catch (Exception bue) {
throw new IOException(bue.toString());
}
}
public void Fwrite_long(long obuf) throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fwrite long @"+linkedMappedByteBuff.position()+" val:"+obuf);
try {
linkedMappedByteBuff.putLong(obuf);
} catch (Exception bue) {
throw new IOException(bue.toString());
}
}
public void Fwrite_short(short obuf) throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fwrite short @"+linkedMappedByteBuff.position()+" val:"+obuf);
try {
linkedMappedByteBuff.putShort(obuf);
} catch (Exception bue) {
throw new IOException(bue.toString());
}
}
// reading...
public int Fread(byte[] b, int osiz) throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fread @"+linkedMappedByteBuff.position()+" buf:"+b.length+" size:"+osiz);
try {
linkedMappedByteBuff.get(b, 0, osiz);
return osiz;
} catch (Exception bue) {
throw new IOException(bue.toString());
}
}
public int Fread(byte[] b) throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fread @"+linkedMappedByteBuff.position()+" buf:"+b.length);
try {
linkedMappedByteBuff.get(b);
return b.length;
} catch (Exception bue) {
throw new IOException(bue.toString());
}
}
public int Fread_int() throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fread int @"+linkedMappedByteBuff.position());
try {
return linkedMappedByteBuff.getInt();
} catch (Exception bue) {
throw new IOException(bue.toString());
}
}
public long Fread_long() throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fread long @"+linkedMappedByteBuff.position());
try {
return linkedMappedByteBuff.getLong();
} catch (Exception bue) {
throw new IOException(bue.toString());
}
}
public short Fread_short() throws IOException {
if( DEBUG )
System.out.println("MMapIO.Fread short @"+linkedMappedByteBuff.position());
try {
return linkedMappedByteBuff.getShort();
} catch (Exception bue) {
throw new IOException(bue.toString());
}
}
public String FTread() throws IOException {
if( DEBUG )
System.out.println("MMapIO.FTread @"+linkedMappedByteBuff.position());
return RA.readLine();
}
public void FTwrite(String ins) throws IOException {
if( DEBUG )
System.out.println("MMapIO.FTwrite @"+linkedMappedByteBuff.position()+" len:"+ins.length());
RA.writeBytes(ins);
}
public void Fdelete() {
if( DEBUG )
System.out.println("MMapIO.FDelete");
WO.delete();
}
public String Fname() {
return WO.getName();
}
public boolean isopen() {
return fisopen;
}
public boolean iswriteable() {
return true;
}
public boolean isnew() {
return fisnew;
}
public Channel getChannel() {
if( DEBUG )
System.out.println("MMapIO.getChannel:"+FC);
return FC;
}
}