package bloomtime;
import java.io.RandomAccessFile;
import java.io.File;
import java.util.ArrayList;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.io.IOException;
import java.util.BitSet;
import jelectrum.TimeRecord;
import org.junit.Assert;
public class LongMappedBufferMany implements LongFile
{
//public static final long MAP_SIZE = Integer.MAX_VALUE;
public static final long MAP_SIZE = 4 * 1024 * 1024;
private ArrayList<MappedByteBuffer> map_list;
private long total_size;
private byte[] byte_mappings;
public LongMappedBufferMany(File f, long total_size)
throws IOException
{
f.mkdirs();
this.total_size = total_size;
map_list=new ArrayList<>();
long opened = 0;
while(opened < total_size)
{
File child = new File(f, "" + opened);
RandomAccessFile raf = new RandomAccessFile(child, "rw");
FileChannel chan = raf.getChannel();
long len = Math.min(total_size - opened, MAP_SIZE);
MappedByteBuffer buf = chan.map(FileChannel.MapMode.READ_WRITE, 0, len);
opened += len;
map_list.add(buf);
}
byte_mappings = new byte[8];
for(int i=0; i<8; i++)
{
BitSet bs = new BitSet(8);
bs.set(i);
byte[] b = bs.toByteArray();
byte_mappings[i]=b[0];
}
}
public synchronized void getBytes(long position, byte[] buff)
{
long t1 = System.nanoTime();
//Assert.assertTrue(position >= 0);
//Assert.assertTrue(position + buff.length <= total_size);
int to_read=buff.length;
int start_file = (int) (position / MAP_SIZE);
int start_offset = (int) (position % MAP_SIZE);
MappedByteBuffer map = map_list.get(start_file);
map.position(start_offset);
int len = Math.min(to_read, (int) (MAP_SIZE - start_offset));
map.get(buff, 0, len);
if (len < to_read)
{
map = map_list.get(start_file + 1);
map.position(0);
map.get(buff, len, to_read - len);
}
TimeRecord.record(t1, "long_map_get_bytes");
}
public synchronized void putBytes(long position, byte[] buff)
{
long t1 = System.nanoTime();
//Assert.assertTrue(position >= 0);
//Assert.assertTrue(position + buff.length <= total_size);
int to_write=buff.length;
int start_file = (int) (position / MAP_SIZE);
int start_offset = (int) (position % MAP_SIZE);
MappedByteBuffer map = map_list.get(start_file);
map.position(start_offset);
int len = Math.min(to_write, (int) (MAP_SIZE - start_offset));
map.put(buff, 0, len);
if (len < to_write)
{
map = map_list.get(start_file + 1);
map.position(0);
map.put(buff, len, to_write - len);
}
TimeRecord.record(t1, "long_map_put_bytes");
}
public void setBit(long bit)
{
long t1=System.nanoTime();
long data_pos = bit / 8;
int file = (int) (data_pos / MAP_SIZE);
int file_offset = (int) (data_pos % MAP_SIZE);
int bit_in_byte = (int)(bit % 8);
byte[] b = new byte[1];
MappedByteBuffer map = map_list.get(file);
b[0]=map.get(file_offset);
byte n = (byte)(b[0] | byte_mappings[bit_in_byte]);
if (b[0] != n)
{
map.put(file_offset, n);
}
//BitSet bs = BitSet.valueOf(b);
//if (!bs.get(bit_in_byte))
//{
// bs.set(bit_in_byte);
// b = bs.toByteArray();
// map.put(file_offset, b[0]);
//}
TimeRecord.record(t1, "long_map_set_bit");
}
}