package com.alimama.mdrill.buffer;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.lucene.store.Directory;
import org.apache.solr.core.SolrResourceLoader.PartionKey;
import org.apache.solr.request.uninverted.GrobalCache;
import com.alimama.mdrill.utils.UniqConfig;
public class BlockBufferMalloc {
private static ArrayList<blockData> freeByteBlocks = new ArrayList<blockData>();
public static AtomicLong mallocTimes = new AtomicLong(0l);
public static AtomicLong reusedTimes = new AtomicLong(0l);
public static Object lock=new Object();
private static blockData getByteBlock(int asize) {
synchronized (lock) {
final int size = freeByteBlocks.size();
final blockData b;
if (0 == size) {
b = new blockData(new byte[BlockBufferInput.BLOCK_SIZE], asize);
mallocTimes.incrementAndGet();
} else {
b = freeByteBlocks.remove(size - 1);
reusedTimes.incrementAndGet();
}
return b;
}
}
private static void recycleByteBlocks(blockData data) {
synchronized (lock) {
int allowsize = UniqConfig.getBlockBufferSize() - freeByteBlocks.size();
if (allowsize > 0) {
freeByteBlocks.add(data);
}
}
}
public static blockData malloc(int asize) {
blockData rtn = getByteBlock(asize);
rtn.setSize(asize);
return rtn;
}
public static void freeData(blockData d) {
if (d != null) {
recycleByteBlocks(d);
}
}
public static class block implements GrobalCache.ILruMemSizeKey{
private long index;
private String flushkey="";
public block(Directory dir,String filename,long pos,PartionKey p) {
super();
this.index = pos;
String[] filelist=new String[]{filename};
flushkey=dir.getCacheKey(filelist);
}
@Override
public String toString() {
return "block [index=" + index + ", flushkey=" + flushkey + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((flushkey == null) ? 0 : flushkey.hashCode());
result = prime * result + (int) (index ^ (index >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
block other = (block) obj;
if (flushkey == null) {
if (other.flushkey != null)
return false;
} else if (!flushkey.equals(other.flushkey))
return false;
if (index != other.index)
return false;
return true;
}
}
public static class blockData implements GrobalCache.ILruMemSizeCache{
byte[] buff;
int size;
@Override
public String toString() {
return "blockData [buff=" + buff.length+ ", size="
+ size + ", allowFree=" + allowFree + ", lasttime="
+ lasttime + "]";
}
public void setSize(int size) {
this.size = size;
}
public blockData(byte[] buff,int size) {
super();
this.buff = buff;
this.size=size;
}
public AtomicInteger allowFree=new AtomicInteger(0);
long lasttime=System.currentTimeMillis();
public long getLasttime() {
return lasttime;
}
public void updateLasttime() {
this.lasttime = System.currentTimeMillis();
}
@Override
public long memSize() {
if(buff==null)
{
return Integer.SIZE/8;
}
return buff.length+Integer.SIZE/8;
}
@Override
public void LRUclean() {
BlockBufferMalloc.freeData(this);
}
}
}