org.nustaq.offheap.bytez.malloc.MMFBytez Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fst Show documentation
Show all versions of fst Show documentation
A fast java serialization drop in-replacement and some serialization based utils such as Structs and OffHeap Memory.
/*
* Copyright 2014 Ruediger Moeller.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.nustaq.offheap.bytez.malloc;
import sun.misc.Cleaner;
import sun.nio.ch.FileChannelImpl;
import java.io.File;
import java.io.RandomAccessFile;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.channels.FileChannel;
/**
* Bytez allocated inside a memory mapped file. Some Mmap file stuff handling is copied from OpenHFT library (too big to depend on for fst),
* a great tool for all kind of binary/low level java stuff. Check it out at github.
*/
public class MMFBytez extends MallocBytez {
private File file;
private FileChannel fileChannel;
private Cleaner cleaner;
public MMFBytez(String filePath, long length, boolean clearFile) throws Exception {
super(0, 0);
init( filePath, length, clearFile );
}
protected void init(String file, long length, boolean clearFile) throws Exception {
File f = new File(file);
if ( f.exists() && clearFile ) {
f.delete();
}
this.file = f;
if ( f.exists() ) {
length = f.length();
}
RandomAccessFile raf = new RandomAccessFile(f, "rw");
raf.setLength(length); // FIXME: see stackoverflow. does not work always
FileChannel fileChannel = raf.getChannel();
this.fileChannel = raf.getChannel();
this.baseAdress = map0(fileChannel, imodeFor(FileChannel.MapMode.READ_WRITE), 0L, length);
this.length = length;
this.cleaner = Cleaner.create(this, new Unmapper(baseAdress, length, fileChannel));
}
public void freeAndClose() {
cleaner.clean();
}
/**
* hack to update underlying file in slices handed out to app
*/
public void _setMMFData(File file, FileChannel fileChannel,Cleaner cleaner) {
this.file = file; this.fileChannel = fileChannel; this.cleaner = cleaner;
}
public File getFile() {
return file;
}
public FileChannel getFileChannel() {
return fileChannel;
}
public Cleaner getCleaner() {
return cleaner;
}
/**
* stuff copied from OpenHFT library (too big to depend on for fst) ...
*
* Copyright 2013 Peter Lawrey
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @param fileChannel
* @param imode
* @param start
* @param size
* @return
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
private static final int MAP_RO = 0;
private static final int MAP_RW = 1;
private static final int MAP_PV = 2;
private static long map0(FileChannel fileChannel, int imode, long start, long size) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Method map0 = fileChannel.getClass().getDeclaredMethod("map0", int.class, long.class, long.class);
map0.setAccessible(true);
return (Long) map0.invoke(fileChannel, imode, start, size);
}
private static void unmap0(long address, long size) throws Exception {
Method unmap0 = FileChannelImpl.class.getDeclaredMethod("unmap0", long.class, long.class);
unmap0.setAccessible(true);
unmap0.invoke(null, address, size);
}
private static int imodeFor(FileChannel.MapMode mode) {
int imode = -1;
if (mode == FileChannel.MapMode.READ_ONLY)
imode = MAP_RO;
else if (mode == FileChannel.MapMode.READ_WRITE)
imode = MAP_RW;
else if (mode == FileChannel.MapMode.PRIVATE)
imode = MAP_PV;
assert (imode >= 0);
return imode;
}
static class Unmapper implements Runnable {
private final long size;
private final FileChannel channel;
private volatile long address;
Unmapper(long address, long size, FileChannel channel) {
assert (address != 0);
this.address = address;
this.size = size;
this.channel = channel;
}
public void run() {
if (address == 0)
return;
try {
unmap0(address, size);
address = 0;
if (channel.isOpen()) {
channel.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy