public class JcacheContext {
	
	private static ThreadLocal<Map<Object,Object>> local = new ThreadLocal<>();
	
	/**
	 * 内存池
	 */
	private static Slabs slabPool;
	
	/**
	 * item 访问器
	 */
	private static ItemsAccessManager itemsAccessManager = new ItemsAccessManager();

	/**
	 * item 访问器
	 */
	private static CrawlersAccessManager crawlersAccessManager = new CrawlersAccessManager();
	
	/**
	 * hashtable
	 */
	private static Assoc assoc;
	
	/**
	 * hash
	 */
	private static Hash hash = new HashImpl(Hash_func_type.JENKINS_HASH);
	
	/**
	 * 分段锁
	 */
	private static Segment segment;
	
	/**
	 * worker threads
	 */
	private static ExecutorService executor;
	
	/* Locks for cache LRU operations */
	private final static AtomicBoolean[] lru_locks = new AtomicBoolean[Settings.POWER_LARGEST];
	
	/* Lock for global stats */
	private final static AtomicBoolean stats_lock = new AtomicBoolean(false);
	
	static {
       for(int i=0; i<lru_locks.length; i++){
    	   lru_locks[i] = new AtomicBoolean(false);
       }
    }
	
	public static AtomicBoolean getLRU_Lock(int id){
		if(id>(lru_locks.length-1)||id<0){
			return null;
		}
		return lru_locks[id];
	}
	
	public static AtomicBoolean getStatsLock(){
		return stats_lock;
	}

	
	public static Hash getHash() {
		return hash;
	}

	public static void setHash(Hash hash) {
		JcacheContext.hash = hash;
	}

	public static Slabs getSlabPool() {
		return slabPool;
	}

	public static void setSlabPool(Slabs slabPool) {
		JcacheContext.slabPool = slabPool;
	}

	public static ItemsAccessManager getItemsAccessManager() {
		return itemsAccessManager;
	}

	public static void setItemsAccessManager(ItemsAccessManager itemsAccessManager) {
		JcacheContext.itemsAccessManager = itemsAccessManager;
	}

	public static CrawlersAccessManager getCrawlersAccessManager() {
		return crawlersAccessManager;
	}
	
	public static void setItemsAccessManager(CrawlersAccessManager crawlersAccessManager) {
		JcacheContext.crawlersAccessManager = crawlersAccessManager;
	}
	
	public static Assoc getAssoc(){
		return assoc;
	}
	
	public static void setAssoc(Assoc assoc){
		JcacheContext.assoc = assoc;
	}

	public static Segment getSegment() {
		return segment;
	}

	public static void setSegment(Segment segment) {
		JcacheContext.segment = segment;
	}

	public static ExecutorService getExecutor() {
		return executor;
	}

	public static void setExecutor(ExecutorService executor) {
		JcacheContext.executor = executor;
	}
	
	public static int hashsize(long n){
		return 1<<n;
	}
	
	public static int hashmask(long n){
		return hashsize(n) - 1;
	}

	public static Object getLocal(Object key) {
		return local.get().get(key);
	}

	public static void setLocal(Object key,Object value) {
		Map<Object,Object> map = local.get();
		if(map==null){
			map = new HashMap<>();
			local.set(map);
		}
		map.put(key, value);
	}
}
 public class Stats {
    public volatile static AtomicLong total_items = new AtomicLong(0);
    public volatile static AtomicLong total_conns = new AtomicLong(0);
    public volatile static AtomicLong rejected_conns = new AtomicLong(0);
    public volatile static AtomicLong malloc_fails = new AtomicLong(0);
    public volatile static AtomicLong listen_disabled_num = new AtomicLong(0);
    public volatile static AtomicLong slabs_moved = new AtomicLong(0);       /* times slabs were moved around */
    public volatile static AtomicLong slab_reassign_rescues = new AtomicLong(0); /* items rescued during slab move */
    public volatile static AtomicLong slab_reassign_evictions_nomem = new AtomicLong(0); /* valid items lost during slab move */
    public volatile static AtomicLong slab_reassign_inline_reclaim = new AtomicLong(0); /* valid items lost during slab move */
    public volatile static AtomicLong slab_reassign_chunk_rescues = new AtomicLong(0); /* chunked-item chunks recovered */
    public volatile static AtomicLong slab_reassign_busy_items = new AtomicLong(0); /* valid temporarily unmovable */
    public volatile static AtomicLong lru_crawler_starts = new AtomicLong(0); /* Number of item crawlers kicked off */
    public volatile static AtomicLong lru_maintainer_juggles = new AtomicLong(0); /* number of LRU bg pokes */
    public volatile static AtomicLong time_in_listen_disabled_us = new AtomicLong(0);  /* elapsed time in microseconds while server unable to process new connections */
    public volatile static AtomicLong log_worker_dropped = new AtomicLong(0); /* logs dropped by worker threads */
    public volatile static AtomicLong log_worker_written = new AtomicLong(0); /* logs written by worker threads */
    public volatile static AtomicLong log_watcher_skipped = new AtomicLong(0); /* logs watchers missed */
    public volatile static AtomicLong log_watcher_sent = new AtomicLong(0); /* logs sent to watcher buffers */
    public volatile static AtomicLong maxconns_entered = new AtomicLong(0);  /* last time maxconns entered */

}
 public class StatsState {
    public volatile static AtomicLong curr_items = new AtomicLong(0);
    public volatile static AtomicLong curr_bytes = new AtomicLong(0);
    public volatile static AtomicLong curr_conns = new AtomicLong(0);
    public volatile static AtomicLong hash_bytes = new AtomicLong(0);       /* size used for hash tables */
    public volatile static AtomicLong conn_structs = new AtomicLong(0);
    public volatile static AtomicLong reserved_fds = new AtomicLong(0);
    public volatile static AtomicLong hash_power_level = new AtomicLong(0); /* Better hope it's not over 9000 */
    public volatile static AtomicBoolean hash_is_expanding = new AtomicBoolean(false); /* If the hash table is being expanded */
    public volatile static AtomicBoolean accepting_conns = new AtomicBoolean(false);  /* whether we are currently accepting */
    public volatile static AtomicBoolean slab_reassign_running = new AtomicBoolean(false); /* slab reassign in progress */
    public volatile static AtomicBoolean lru_crawler_running = new AtomicBoolean(false); /* crawl in progress */
}
 public enum MOVE_STATUS {
    MOVE_PASS,
    MOVE_FROM_SLAB,
    MOVE_FROM_LRU,
    MOVE_BUSY,
    MOVE_LOCKED
} public interface Items {
	
	static final int  LRU_PULL_EVICT = 1;
	static final int LRU_PULL_CRAWL_BLOCKS = 2;
	static final int LARGEST_ID = Settings.POWER_LARGEST;
	
	
	default int CLEAR_LRU(int id){
		return id & ~(3<<6);
	}
	
	long get_cas_id();
	
	long do_item_alloc(String key,int nkey,int flags,long exptime,int nbytes);
	
	void item_free(long it);
	
	boolean item_size_ok(int nkey,int flags,int nbytes);
	
	boolean do_item_link(long it,long hv);
	
	void do_item_unlink(long it,long hv);
	
	void do_item_unlink_nolock(long it,long hv);
	
	void do_item_remove(long it);
	
	void do_item_update(long it);
	
	void do_item_update_nolock(long it);
	
	boolean do_item_replace(long it,long new_it,long hv);
	
	boolean item_is_flushed(long it);
	
	void do_item_linktail_q(long it);
	
	void do_item_unlinktail_q(long it);
	
	long do_item_crawl_q(long it);
	
	long item_cachedump(int slabs_clsid, int limit, long bytes);
//	void item_stats(ADD_STAT add_stats, void *c);
	void do_item_stats_add_crawl(int i,long reclaimed,
			long unfetched, long checked);
//	void item_stats_totals(ADD_STAT add_stats, void *c);
	/*@null@*/
//	void item_stats_sizes(ADD_STAT add_stats, void *c);
	void item_stats_sizes_init();
//	void item_stats_sizes_enable(ADD_STAT add_stats, void *c);
//	void item_stats_sizes_disable(ADD_STAT add_stats, void *c);
	void item_stats_sizes_add(long it);
	void item_stats_sizes_remove(long it);
	boolean item_stats_sizes_status();
	
	long do_item_get(String key,int nkey,long hv,Connection conn);
	
	long do_item_touch(String key,int nkey,long exptime,long hv,Connection conn);
	
	void item_stats_reset();
	
	int start_lru_maintainer_thread();
	
	int stop_lru_maintainer_thread();
	
	int init_lru_maintainer();
	
	void lru_maintainer_pause();
	
	void lru_maintainer_resume();
	
	void lru_maintainer_crawler_check(CrawlerExpiredData cdata );
	
	int lru_maintainer_juggle(int slabs_clsid);
}
 public final class JcacheGlobalConfig {
	
	/**
	 * 默认reactor pool 大小
	 */
	public static int defaulePoolSize = Runtime.getRuntime().availableProcessors();
	
	/**
	 * 默认 reactor pool 绑定地址
	 */
	public static final String defaultPoolBindIp = "0.0.0.0";
	
	/**
	 * 默认 reactor 选择策略
	 */
	public static final String defaultReactorSelectStrategy = "ROUND_ROBIN";
	
	/**
	 * 
	 */
	public static final int defaultMaxAcceptNum = 10000;
	
	/**
	 * 默认字符编码
	 */
	public static final String defaultCahrset = "UTF-8";
	
	/** Maximum length of a key */
	public static final int KEY_MAX_LENGTH = 250;


	/** Maximum length of a value */
	public static final long VALUE_MAX_LENGTH=1024*1024;
	
	/** current version */
	public static final String version = "0.5.0";
	
	/** How long an object can reasonably be assumed to be locked before
    	harvesting it on a low memory condition. Default: disabled. */
	public static final int TAIL_REPAIR_TIME_DEFAULT = 0;
	
	/** Size of an incr buf. */
	public static final int INCR_MAX_STORAGE_LEN = 24;
	
}
 public enum ItemFlags {
	ITEM_LINKED((byte)1),
	ITEM_CAS((byte)2),
	/* temp */
	ITEM_SLABBED((byte)4),   /* 存在于slab 中,没有被引用    */
	/* Item was fetched at least once in its lifetime */
	ITEM_FETCHED((byte)8),
	/* Appended on fetch, removed on LRU shuffling */
	ITEM_ACTIVE((byte)16),
	/* If an item's storage are chained chunks. */
	ITEM_CHUNKED((byte)32), 
	ITEM_CHUNK((byte)64);
	
	private byte flags;
	
	private ItemFlags(byte flags) {
		this.flags = flags;
	}

	public byte getFlags() {
		return flags;
	} 
} public enum REASSIGN_RESULT_TYPE {
	REASSIGN_OK,
	REASSIGN_RUNNING,
	REASSIGN_BADCLASS,
	REASSIGN_NOSPARE,
	REASSIGN_SRC_DST_SAME
}
 @SuppressWarnings("restriction")
public class Settings {
	public static boolean useCas = true;
	public static String access = "0700";
	public static int port = 11211;
	public static int udpport = 11211;
	public static int redis_port=6378;
	public static String inter = null;
	
	public static long maxbytes = VM.maxDirectMemory()>0?VM.maxDirectMemory():64*1024*1024; //64M
	public static int maxConns = 1024;
	public static short verbose = 2;
	public static long oldestLive = 0;
	public static long oldestCas = 0;
	public static short evictToFree = 1;  /* push old items out of cache when memory runs out */
	public static String socketPath = null;
	public static boolean prealloc = true;
	public static double factor = 1.25;
	public static int chunkSize = 48;
	public static int numThreads = 4; /* N workers */
	public static int numThreadsPerUdp = 0;
	public static String prefixDelimiter = ":";
	public static boolean detailEnabled = false;
	public static int reqsPerEvent = 20;
	public static int backLog = 1024;
	public static Protocol binding_protocol = Protocol.negotiating;
	public static int itemSizeMax = 1024*1024; /* The famous 1MB upper limit. */
	public static int slabPageSize = 1024 * 1024; /* chunks are split from 1MB pages. */
	public static int slabChunkSizeMax = slabPageSize;
	public static boolean sasl = false;  /* SASL on/off */
	public static boolean maxConnsFast = false;
	public static boolean lruCrawler = false;
	public static int lruCrawlerSleep = 100;
	public static int lruCrawlerTocrawl = 0;
	public static boolean lruMaintainerThread = false; /* LRU maintainer background thread */
	public static int hotLruPct = 32;
	public static int warmLruPct = 32;
	public static boolean expireZeroDoesNotEvict = false;
	public static int idleTimeout = 0;
	public static int hashpower_default = 16; /* Initial power multiplier for the hash table */
	public static int hashPowerInit = hashpower_default;
	public static boolean slabReassign = false; /* Whether or not slab reassignment is allowed */
	public static short slabAutoMove = 0; /* Whether or not to automatically move slabs */
	public static boolean shutdownCommand = false; /* allow shutdown command */
	public static long tailRepairTime = JcacheGlobalConfig.TAIL_REPAIR_TIME_DEFAULT; /* LRU tail refcount leak repair time */
	public static boolean flushEnabled = true; /* flush_all enabled */
	public static int crawlsPerSleep = 1000;  /* Number of seconds to let connections idle */
	public static int loggerWatcherBufSize = 1024; /* size of logger's per-watcher buffer */
	public static int loggerBufSize = 1024; /* size of per-thread logger buffer */
	
	public static boolean lru_crawler = false;
	public static int lru_crawler_sleep = 100;
	public static int lru_crawler_tocrawl = 0;
	public static boolean lru_maintainer_thread = false;
	public static long current_time = new Date().getTime();
	
	public static String hash_algorithm; //PigBrother hash algorithm

	/*
	 * We only reposition items in the LRU queue if they haven't been repositioned
	 * in this many seconds. That saves us from churning on frequently-accessed
	 * items.
	 */
	public static int ITEM_UPDATE_INTERVAL= 60 * 1000;
	
	public static int hashsize;  //临时参数
	
	public static String mapfile; // MappedByteBuffer 内存映射文件地址
	
	public static long process_started = System.currentTimeMillis();
	

	
	
	public static final int MAX_NUMBER_OF_SLAB_CLASSES = 64;
	public static final int POWER_SMALLEST = 1;
	public static final int POWER_LARGEST = 256;
	public static final int CHUNK_ALIGN_BYTES = 8;
	public static final int SLAB_GLOBAL_PAGE_POOL = 0; /* magic slab class for storing pages for reassignment */
	public static final int ITEM_HEADER_LENGTH = 52;   /* item header length */
	public static final int MAX_MAINTCRAWL_WAIT = 60 * 60;
	public static final int slab_automove = 0;
	public static final boolean expirezero_does_not_evict = false;
}
 @SuppressWarnings("restriction")
/* Header when an item is actually a chunk of another item. */
public class ItemChunkUtil {
	
	private static int ntotal = 41; 
	/* points within its own chain. */
	private static final byte next=0;
	/* can potentially point to the head. */
	private static final byte prev=8;
	/* always points to the owner chunk */
	private static final byte head=16;
	/* available chunk space in bytes */
	private static final byte size=24;
	/* chunk space used */
	private static final byte used=28;
	/* used. */
	private static final byte nbytes=32;
	
	private static final byte refcount=36;
	/* unused */
	private static final byte nsuffix=38;
	/* ITEM_* above. */
	private static final byte it_flags=39;
	/* Same as above. */
	private static final byte slabs_clsid=40;
	
	private static final byte data = 41;

	public static int getNtotal() {
		return ntotal;
	}

	public static long getNext(long addr) {
		return UnSafeUtil.getLong(addr+next);
	}
	
	public static void setNext(long addr,long value){
		UnSafeUtil.putAddress(addr+next, value);
	}

	public static long getPrev(long addr) {
		return UnSafeUtil.getLong(addr+prev);
	}
	
	public static void setPrev(long addr,long value){
		UnSafeUtil.putAddress(addr+prev, value);
	}

	public static long getHead(long addr) {
		return UnSafeUtil.getLong(addr+head);
	}
	
	public static void setHead(long addr,long value){
		UnSafeUtil.putAddress(addr+head, value);
	}

	public static int getSize(long addr) {
		return UnSafeUtil.getInt(addr+size);
	}
	
	public static void setSize(long addr,int value){
		UnSafeUtil.putInt(addr+size, value);
	}

	public static int getUsed(long addr) {
		return UnSafeUtil.getInt(addr+used);
	}
	
	public static void setUsed(long addr,int value){
		UnSafeUtil.putInt(addr+used, value);
	}
	
	public static void incrUsed(long addr,int value){
		UnSafeUtil.unsafe.getAndAddInt(null, addr+used, value);
	}
	
	public static void descUsed(long addr,int value){
		UnSafeUtil.unsafe.getAndAddInt(null, addr+used, -value);
	}

	public static int getNbytes(long addr) {
		return UnSafeUtil.getInt(addr+nbytes);
	}
	
	public static void setNbytes(long addr,int value){
		UnSafeUtil.putInt(addr+nbytes, value);
	}

	public static short getRefcount(long addr) {
		return UnSafeUtil.getShort(addr+refcount);
	}
	
	public static void setRefcount(long addr,short value){
		UnSafeUtil.putShort(addr+refcount, value);
	}

	public static byte getNsuffix(long addr) {
		return UnSafeUtil.getByte(addr+nsuffix);
	}
	
	public static void setNsuffix(long addr,byte value){
		UnSafeUtil.putByte(addr+nsuffix, value);
	}

	public static byte getItFlags(long addr) {
		return UnSafeUtil.getByte(addr+it_flags);
	}
	
	public static void setItFlags(long addr,byte value){
		UnSafeUtil.putByte(addr+it_flags, value);
	}

	public static byte getSlabsClsid(long addr) {
		return UnSafeUtil.getByte(addr+slabs_clsid);
	}
	
	public static void setSlabsClsid(long addr,byte value){
		UnSafeUtil.putByte(addr+slabs_clsid, value);
	}

	public static void setData(long addr,byte[] datas) {
		UnSafeUtil.setBytes(addr+data, datas, 0, datas.length);;
	}
	
	public static long getDataAddr(long addr) {
		return UnSafeUtil.getLong(addr+data);
	}
}
 public class ItemUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(ItemUtil.class);

	
	public static String ItemToString(long addr){
		return "{prev =" + getPrev(addr)+",next = "+getNext(addr)+",hnext = "+getHNext(addr)+", flushtime = "
			   + getTime(addr)+", exptime = "+getExpTime(addr)+", nbytes = "+getNbytes(addr)+", refcount = "
			   + getRefCount(addr)
			   +", slabsclsid = " + getSlabsClsid(addr)+", itlags = "
			   + getItflags(addr)+",nsuffix = " + getNsuffix(addr)+",nskey = " + getNskey(addr)+", key = "
			   + getKey(addr)+",suffix = " + new String(getSuffix(addr))+",value = " + new String(getValue(addr)) +"}";
	}

	/**
	 * PigBrother
	 * 字段偏移
	 */
	private static final byte PREV=0;
	private static final byte NEXT=8;
	private static final byte HNEXT=16;
	private static final byte FLUSHTIME=24;
	private static final byte EXPTIME=32;
	private static final byte NBYTES=40;
	private static final byte REFCOUNT=44;
	private static final byte SLABSCLISD=48;
	private static final byte IT_FLAGS=49;
	private static final byte NSUFFIX=50;
	private static final byte NSKEY=51;
	private static final byte CAS=52;
//	private static final byte KEY=58;
//	private static final byte SUFFER=0;这两个字段偏移是动态的
//	private static final byte VALUE=0;
	
	private static AtomicLong cas_id = new AtomicLong(0);
	
	public static long REALTIME_MAXDELTA = 60*60*24*30*1000L;


	////////////////////////////////// header begin ////////////////////////////////////////////////
	/**
	 * 获取 /记录上一个item的地址,主要用于LRU链和freelist链   
	 * @param item
	 * @return
	 */
	/**
	 * This place had huge bug ,  byte  didn't enough to contain the information the address
	 * This place must be long
	 * @author PigBrother
	 * @param addr
	 * @return
     */
	public static long getPrev(long addr){
		return UnSafeUtil.getLongVolatile(addr+PREV);
	}

	/**
	 * This place had huge bug ,  byte  didn't enough to contain the information the address
	 * This place must be long
	 * @author PigBrother
	 * @param addr
	 * @return
	 */
	public static void setPrev(long addr,long prev){
		//This place used Volatile is not necessary.
		//after codes didn't  use   Volatile
		// setNest()
		UnSafeUtil.putLongVolatile(addr+PREV, prev);
	}
	
	/**
	 * 记录下一个item的地址,主要用于LRU链和freelist链
	 * @param //item
	 * @return
	 */
	public static long getNext(long addr){
		//return UnSafeUtil.getByte(addr+1);
		return UnSafeUtil.getLongVolatile(addr+NEXT);
	}
	/**
	 * This place had huge bug ,  byte  didn't enough to contain the information the address
	 * This place must be long
	 * @author PigBrother
	 * @param addr
	 * @return
	 */
	public static void setNext(long addr,long next){
		///UnSafeUtil.putByte(addr+1, next);   old
		//PigBrother
		UnSafeUtil.putLongVolatile(addr+NEXT, next);
	}
	
	/**
	 * 记录HashTable的下一个Item的地址 
	 * @param item
	 * @return
	 */
	/**
	 * This place had huge bug ,  byte  didn't enough to contain the information the address
	 * This place must be long
	 * @author PigBrother
	 * @param addr
	 * @return
	 */
	public static long getHNext(long addr){
		//return UnSafeUtil.getByte(addr+2);
//		throw new RuntimeException();
//		logger.debug("addr=========== : {}",addr);  TODO  test  为什么一直在执行
		return UnSafeUtil.getLongVolatile(addr+HNEXT);
	}
	// fixed setHNext(long addr, long next)
	//PigBrohter
	public static void setHNext(long addr,long hnext){
		UnSafeUtil.putLongVolatile(addr+HNEXT, hnext);
	}
	/**
	          最近访问的时间，只有set/add/replace等操作才会更新这个字段
	 * 当执行flush命令的时候，需要用这个时间和执行flush命令的时间相比较，来判断是否失效  
	 * typedef unsigned int rel_time_t;
	 * Time relative to server start. Smaller than time_t on 64-bit systems. 
	 * @param //item
	 * @return
	 */
	public static long getTime(long addr){
		//PigBrother
		//return UnSafeUtil.getInt(addr+3);
		return UnSafeUtil.getLongVolatile(addr+FLUSHTIME);
	}

	public static void setTime(long addr,long time){
		UnSafeUtil.lazySetLong(addr+FLUSHTIME, time);
	}

	/**
	 * 缓存的过期时间。设置为0的时候，则永久有效。
	 * 如果Memcached不能分配新的item的时候，设置为0的item也有可能被LRU淘汰
	 * typedef unsigned int rel_time_t;
	 * Time relative to server start. Smaller than time_t on 64-bit systems.
	 * @param //item
	 * @return
	 */
	public static long getExpTime(long addr){
		//PigBrother
		//return UnSafeUtil.getLong(addr+7);
		return UnSafeUtil.getLongVolatile(addr+EXPTIME);
	}
	
	public static void setExpTime(long addr,long expTime){
		UnSafeUtil.putLongVolatile(addr+EXPTIME, expTime);
	}
	
	/**
	 * value数据大小
	 * @param //item
	 * @return
	 */
	public static int getNbytes(long addr){
		//PigBrother
		//return UnSafeUtil.getInt(addr+11);
		return UnSafeUtil.getIntVolatile(addr+NBYTES);
	}
	
	public static void setNbytes(long addr,int nbytes){
		UnSafeUtil.putIntVolatile(addr+NBYTES,nbytes);
	}
	
	/**
	 * 引用的次数。通过这个引用的次数，可以判断item是否被其它的线程在操作中。
	 * 也可以通过refcount来判断当前的item是否可以被删除，只有refcount -1 = 0的时候才能被删除  
	 * @param //
	 * item
	 * @return
	 */
	public static int getRefCount(long addr){
		//PigBrother
		//return UnSafeUtil.getShort(addr+15);
		return UnSafeUtil.getIntVolatile(addr+REFCOUNT);
	}
	
    /**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public static int incrRefCount(long addr) {
        return UnSafeUtil.incrementAndGetInt(addr+REFCOUNT);
    }

    /**
     * Atomically decrements by one the current value.
     *
     * @return the updated value
     */
    public static int decrRefCount(long addr) {
        return UnSafeUtil.decrementAndGetInt(addr+REFCOUNT);
    }
    
    public static void setRefCount(long addr,int value){
    	UnSafeUtil.putInt(addr+REFCOUNT, value);
    }
	
	/**
	 * which slab class we're in 标记item属于哪个slabclass下
	 * @param //item
	 * @return
	 */
	public static byte getSlabsClsid(long addr){
		//PigBrother
		//return UnSafeUtil.getByte(addr+17);
		return UnSafeUtil.getByteVolatile(addr+SLABSCLISD);
	}
	
	public static void setSlabsClsid(long addr,byte clsid){
		// PigBrother
		// /UnSafeUtil.putByte(addr+17, clsid);
		UnSafeUtil.putByteVolatile(addr+SLABSCLISD, clsid);
	}
	
	/**
	 * ITEM_* above
	 * @param //item
	 * @return
	 */
	public static byte getItflags(long addr){
		// PigBrother
		// 这个memcached里 是一个int  用 byte表示是否够了？
		// /return UnSafeUtil.getByte(addr+18);
		return UnSafeUtil.getByteVolatile(addr+IT_FLAGS);
	}
	
	public static void setItflags(long addr,byte flags){
		// PigBrother
		//UnSafeUtil.putByte(addr+18,flags);
		UnSafeUtil.putByteVolatile(addr+IT_FLAGS,flags);
	}
	
	/**
	 * length of flags-and-length string
	 * @param //item
	 * @return
	 */
	public static byte getNsuffix(long addr){
		// PigBrother
		//return UnSafeUtil.getByte(addr+19);
		return UnSafeUtil.getByteVolatile(addr+NSUFFIX);
	}
	
	
	public static void setNsuffix(long addr,byte nsuffix){
		UnSafeUtil.putByteVolatile(addr+NSUFFIX,nsuffix);
	}
	
	/**
	 * length of flags-and-length string
	 * @param //item
	 * @return
	 */
	public static byte getNskey(long addr){
		// PigBrother
		//return UnSafeUtil.getByte(addr+20);
		return UnSafeUtil.getByteVolatile(addr+NSKEY);
	}
	
	
	public static void setNskey(long addr,byte nkey){
		UnSafeUtil.putByteVolatile(addr+NSKEY,nkey);
	}
	
	public static long getHeaderEnd(long addr){
		return addr + CAS;
	}
	
	////////////////////////////////// header end ////////////////////////////////////////////////
	
	//PigBrother
	/**
	 * length of CAS
	 * @param //item
	 * @return
	 */
	public static long getCAS(long addr){
		return UnSafeUtil.getLongVolatile(getHeaderEnd(addr));
	}
	//PigBrother
	/**
	 * set length of CAS
	 * @param //item
	 * @return
	 */
	public static void setCAS(long CAS, long addr){
		UnSafeUtil.putLongVolatile(getHeaderEnd(addr),CAS);
	}
	
	/**
	 * ((item)->slabs_clsid & ~(3<<6))
	 * @param addr
	 * @return
	 */
	public static long ITEM_clsid(long addr){
		return getSlabsClsid(addr) & ~(3<<6) ;
	}
	
	//PigBrother
	/**
	 * length of key
	 * @param //item
	 * @return
	 */
	public static String getKey(long addr){
		byte[] bs = new byte[getNskey(addr)&0xff];
		UnSafeUtil.getBytes(ITEM_key(addr), bs, 0, bs.length);
		return new String(bs);
	}
	//PigBrother
	/**
	 * set length of CAS
	 * @param //item
	 * @return
	 */
	public static void setKey(byte[] key_bytes, long addr){
		if(key_bytes.length!=(getNskey(addr)&0xff)){
			logger.error("Error, NSkey's values != key_bytes.length . key is {},nskey value is {}, key_bytes.legth is {}, addr is {}",getKey(addr),getNskey(addr),key_bytes.length,addr);
			throw new RuntimeException("Error, NSkey's values != key_bytes.length");
		}
		UnSafeUtil.setBytes(ITEM_key(addr), key_bytes, 0, key_bytes.length);
	}
	
	/**
	 * 设置 suffix
	 * @param addr
	 * @param suffix
	 */
	public static void setSuffix(long addr,byte[] suffix){
		UnSafeUtil.setBytes(ITEM_suffix(addr), suffix, 0, suffix.length);
	}
	
	/**
	 * 获取suffix
	 * @param addr
	 * @return
	 */
	public static byte[] getSuffix(long addr){
		int length = getNsuffix(addr);
		byte[] data = new byte[length];
		UnSafeUtil.getBytes(ITEM_suffix(addr), data, 0,length);
		return data;
	}
	
	/**
	 * 获取value
	 * @param addr
	 * @return
	 */
	public static byte[] getValue(long addr){
		int length = getNbytes(addr)-2; //  value 最后两位为 \r\n 获取时 ，不包含这两位
		if(length<0){
			length = 0;
		}
		byte[] data = new byte[length];
		UnSafeUtil.getBytes(ITEM_data(addr), data,0,length); 
		return data;
	}
	
	/**
	 * 设置 value
	 * @param addr
	 * @param value
	 */
	public static void setValue(long addr,byte[] value){
		UnSafeUtil.setBytes(ITEM_data(addr), value, 0, value.length);
	}
	
	public static void setLongValue(long addr,long value){
		UnSafeUtil.putLong(ITEM_data(addr), value);
	}
	
	/**
	 * Generates the variable-sized part of the header for an object.
	 *
	 * key     - The key
	 * nkey    - The length of the key
	 * flags   - key flags
	 * nbytes  - Number of bytes to hold value and addition CRLF terminator
	 * suffix  - Buffer for the "VALUE" line suffix (flags, size).
	 * nsuffix - The length of the suffix is stored here.
	 *
	 * Returns the total size of the header.
	 */	
	public static int item_make_header(int nkey,int flags,int nbytes){
	    /* suffix is defined at 40 chars elsewhere.. */
//	    *nsuffix = (uint8_t) snprintf(suffix, 40, " %u %d\r\n", flags, nbytes - 2);
//	    return sizeof(item) + nkey + *nsuffix + nbytes;
		
		String suffixStr = item_make_header_suffix(nkey,flags,nbytes);
		return Settings.ITEM_HEADER_LENGTH + nkey + suffixStr.length() + nbytes;
	}
	
	public static int item_make_header(int nkey,int flags,int nbytes,String suffixStr){
		return Settings.ITEM_HEADER_LENGTH + nkey + suffixStr.length() + nbytes;
	}
	
	public static String item_make_header_suffix(int nkey,int flags,int nbytes){
		StringBuffer sb = new StringBuffer();
		sb.append(" ").append(flags).append(" ").append((nbytes-2));
		String suffixStr = sb.toString();
		
		if(suffixStr.length()>40){
			suffixStr = suffixStr.substring(0, 40);
		}
		return suffixStr;
	}
	
	/**
	 * 获取 suffix 中 flags
	 * @param addr
	 * @return
	 */
	public static int ITEM_suffix_flags(long addr){
//		int length = getNsuffix(addr);
//		int nbytes = String.valueOf(getNbytes(addr)).length();
//		length -= (nbytes + 2 + 1);  //减去   /r /r  ''  总共三个字符
//		byte[] flagsBytes = new byte[length];
//
//		UnSafeUtil.getBytes(ITEM_suffix(addr), flagsBytes, 0, length);
		return UnSafeUtil.getByte(ITEM_suffix(addr));
	}

	/**
	 * 获取key 开始地址
	 * ITEM_key(item) (((char*)&((item)->data)) + (((item)->it_flags & ITEM_CAS) ? sizeof(uint64_t) : 0))
	 * @param addr
	 * @return
	 */
	public static long ITEM_key(long addr){
		return getHeaderEnd(addr) + (((getItflags(addr)&ItemFlags.ITEM_CAS.getFlags())==0)?0:8);
	}

	/**
	 * 获取 suffix 开始地址
	 * ITEM_suffix(item) ((char*) &((item)->data) + (item)->nkey + 1 + (((item)->it_flags & ITEM_CAS) ? sizeof(uint64_t) : 0))
	 * 获取 suffix 开始地址
	 * @param addr
	 * @return
	 */
	public static long ITEM_suffix(long addr){
		return getHeaderEnd(addr) + getNskey(addr) + 1 + (((getItflags(addr)&ItemFlags.ITEM_CAS.getFlags())==0)?0:8);
	}
	
	/**
	 * 获取data 开始地址
	 * ((char*) &((item)->data) + (item)->nkey + 1 + (item)->nsuffix + (((item)->it_flags & ITEM_CAS) ? sizeof(uint64_t) : 0))
	 * @param addr
	 * @return
	 */
	public static long ITEM_data(long addr){
		return getHeaderEnd(addr) + getNskey(addr) + 1 + getNsuffix(addr) + (((getItflags(addr)&ItemFlags.ITEM_CAS.getFlags())==0)?0:8);
	}
	
	public static void ITEM_set_cas(long addr,long cas){
		byte flags = getItflags(addr);
		if((flags &ItemFlags.ITEM_CAS.getFlags())>0){
			setCAS(cas, addr);
		}
	}

	public static long ITEM_get_cas(long addr){
		byte flags = getItflags(addr);
		return (flags &ItemFlags.ITEM_CAS.getFlags())>0?getCAS(addr):0;
	}

	/**
	 * 获取ntotal
	 * (sizeof(struct _stritem) + (item)->nkey + 1 + (item)->nsuffix + (item)->nbytes + (((item)->it_flags & ITEM_CAS) ? sizeof(uint64_t) : 0))
	 * @param addr
	 * @return
	 */
	public static int ITEM_ntotal(long addr){
		return CAS + getNskey(addr) + 1 + getNsuffix(addr) + getNbytes(addr)+(((getItflags(addr)&ItemFlags.ITEM_CAS.getFlags())==0)?0:8);
	}
	
	public static long get_cas_id(){
		return cas_id.incrementAndGet();
	}
	
	public static long realtime(long exptime){
		/* no. of seconds in 30 days - largest possible delta exptime */
		if(exptime==0) return 0;
		
		if(exptime > (REALTIME_MAXDELTA + System.currentTimeMillis())){
			if(exptime <= Settings.process_started){
				return System.currentTimeMillis();
			}
			return REALTIME_MAXDELTA + System.currentTimeMillis();  // 最大缓存 30 天
		}else{
			return exptime;
		}
	}
}
 public class SlabClassUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(JcacheMain.class);
	
	/**
	 * SlabClass 总长度
	 */
	public static final int ntotal = 44;
	
	/* sizes of items */
	private static final byte size = 0;
	/* how many items per slab */
	private static final byte perslab = 4;
	/* list of item ptrs  当前空闲 slots head  */
	private static final byte slots = 8;
	/* total free items in list */
	private static final byte sl_curr = 16;
	/* how many slabs were allocated for this class */
	private static final byte slabs = 20;
	/* array of slab pointers */
	private static final byte slab_list = 24;
	/* size of prev array */
	private static final byte list_size = 32;
	/* The number of requested bytes */
	private static final byte requested = 36;
	
	/**
	 * 测试使用
	 * 输出当前slabclass 使用状况
	 * @param addr
	 */
	public static String SlabClassToString(long addr){
		return "{size="+getSize(addr)+",perslab = "+getPerslab(addr)+",sl_curr ="+getSlCurr(addr)+","
				+"slabs= "+ getSlabs(addr) 
				+ "slots="+getSlots(addr)
				+ ",list_size = "+getListSize(addr)+"}";
	}
	
	public static int getNtotal() {
		return ntotal;
	}
	
	public static int getSize(long addr){
		return UnSafeUtil.getInt(addr+size);
	}
	
	public static void setSize(long addr,int value){
		UnSafeUtil.putInt(addr+size, value);
	}
	
	public static int getPerslab(long addr) {
		return UnSafeUtil.getInt(addr+perslab);
	}
	
	public static void setPerslab(long addr,int value){
		UnSafeUtil.putInt(addr+perslab, value);
	}
	
	public static long getSlots(long addr) {
		return UnSafeUtil.getLong(addr+slots);
	}
	
	public static void setSlots(long addr,long slotaddr){
		UnSafeUtil.putAddress(addr+slots, slotaddr);
	}
	
	
	public static int getSlCurr(long addr) {
		return UnSafeUtil.getInt(addr+sl_curr);
	}
	
	public static int incrSlCurr(long addr){
		return UnSafeUtil.incrementAndGetInt(addr+sl_curr);
	}
	
	public static int incrSlCurr(long addr,int delta){
		return UnSafeUtil.addAndGetInt(addr+sl_curr, delta);
	}
	
	public static int decrSlCurr(long addr){
		return UnSafeUtil.decrementAndGetInt(addr+sl_curr);
	}
	
	public static int getSlabs(long addr) {
		return UnSafeUtil.getInt(addr+slabs);
	}
	
	public static int incrSlabs(long addr){
		return UnSafeUtil.incrementAndGetInt(addr+slabs);
	}
	
	public static int decrSlabs(long addr){
		return UnSafeUtil.decrementAndGetInt(addr+slabs);
	}
	
	public static long getSlabList(long addr) {
		return UnSafeUtil.getLong(addr+slab_list);
	}
	
	public static void setSlabList(long addr,long value){
		UnSafeUtil.putLongVolatile(addr+slab_list, value);
	}
	
	/**
	 * 将slab 内存首地址，放入到 slablist 指定的位置
	 * @param addr
	 * @param index
	 * @param value
	 */
	public static void setSlablistIndexValue(long addr,int index,long value){
		long slabindex = addr +slab_list+ index *UnSafeUtil.addresssize;
		UnSafeUtil.putLongVolatile(slabindex, value);
	}

	/**
	 * slab 内存首地址，从slablist 指定的位置取出值
	 * @param addr
	 * @param index
     */
	public static Long getSlabListIndexValue(long addr,int index){
		long slabindex = addr +slab_list+ index *UnSafeUtil.addresssize;
		return UnSafeUtil.getLongVolatile(slabindex);
	}
	
	
	public static int getListSize(long addr) {
		return  UnSafeUtil.getInt(addr+list_size);
	}
	
	public static void setListSize(long addr,int value){
		UnSafeUtil.putInt(addr+list_size, value);
	}
	
	public static long getRequested(long addr) {
		return UnSafeUtil.getLong(addr+requested);
	}
	
	public static long incrRequested(long addr,long totalsizes){
		return UnSafeUtil.addAndGetLong(addr+requested, totalsizes);
	}
	
	public static long decrRequested(long addr,long totalsizes){
		return UnSafeUtil.addAndGetLong(addr+requested, -totalsizes);
	}
}
 @SuppressWarnings("restriction")
public class UnSafeUtil {
	
	public static final Unsafe unsafe;
	public static final int BYTE_ARRAY_OFFSET;
	/* see Unsafe  */
	public final static int addresssize = 8;
	
	static{
		try { 
			Field f = Unsafe.class.getDeclaredField("theUnsafe");
			f.setAccessible(true);
			unsafe = (Unsafe) f.get(null);
			BYTE_ARRAY_OFFSET = unsafe.arrayBaseOffset(byte[].class);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * Reads a byte from the specified position.
	 * 
	 * @param pos
	 *            
	 * @return the value read
	 */
	public static byte getByte(long pos) {
		return unsafe.getByte(pos);
	}

	/**
	 * Reads a byte (volatile) from the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @return the value read
	 */
	public static byte getByteVolatile(long pos) {
		return unsafe.getByteVolatile(null, pos );
	}

	/**
	 * Reads a short from the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @return the value read
	 */
	public static short getShort(long pos) {
		return unsafe.getShort(pos);
	}

	/**
	 * Reads a short (volatile) from the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @return the value read
	 */
	public static short getShortVolatile(long pos) {
		return unsafe.getShortVolatile(null, pos);
	}

	/**
	 * Reads an int from the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @return the value read
	 */
	public static int getInt(long pos) {
		return unsafe.getInt(pos);
	}

	/**
	 * Reads an int (volatile) from the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @return the value read
	 */
	public static int getIntVolatile(long pos) {
		return unsafe.getIntVolatile(null, pos);
	}

	/**
	 * Reads a long from the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @return the value read
	 */
	public static long getLong(long pos) {
		return unsafe.getLong(pos);
	}

	/**
	 * Reads a long (volatile) from the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @return the value read
	 */
	public static long getLongVolatile(long pos) {
		return unsafe.getLongVolatile(null, pos);
	}
	
	/**
	 * Writes a byte to the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @param val
	 *            the value to write
	 */
	public static void putByte(long pos, byte val) {
		unsafe.putByte(pos, val);
	}

	/**
	 * Writes a byte (volatile) to the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @param val
	 *            the value to write
	 */
	public static void putByteVolatile(long pos, byte val) {
		unsafe.putByteVolatile(null, pos, val);
	}

	/**
	 * Writes an int to the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @param val
	 *            the value to write
	 */
	public static void putInt(long pos, int val) {
		unsafe.putInt(pos, val);
	}

	/**
	 * Writes an int (volatile) to the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @param val
	 *            the value to write
	 */
	public static void putIntVolatile(long pos, int val) {
		unsafe.putIntVolatile(null, pos, val);
	}

	/**
	 * Writes an short to the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @param val
	 *            the value to write
	 */
	public static void putShort(long pos, short val) {
		unsafe.putShort(null, pos, val);
	}

	/**
	 * Writes an short (volatile) to the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @param val
	 *            the value to write
	 */
	public static void putShortVolatile(long pos, short val) {
		unsafe.putShortVolatile(null, pos, val);
	}

	/**
	 * Writes a long to the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @param val
	 *            the value to write
	 */
	public static void putLong(long pos, long val) {
		unsafe.putLong(pos, val);
	}

	/**
	 * Writes a long (volatile) to the specified position.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @param val
	 *            the value to write
	 */
	public static void putLongVolatile(long pos, long val) {
		unsafe.putLongVolatile(null, pos, val);

	}

	public static void lazySetLong(long pos, long val) {
		unsafe.putOrderedLong(null, pos, val);
	}

	public static void lazySetInt(long pos, int val) {
		unsafe.putOrderedInt(null, pos, val);
	}

	/**
	 * Reads a buffer of data.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @param data
	 *            the input buffer
	 * @param offset
	 *            the offset in the buffer of the first byte to read data into
	 * @param length
	 *            the length of the data
	 */
	public static void getBytes(long pos, byte[] data, int offset, int length) {
		unsafe.copyMemory(null, pos, data, BYTE_ARRAY_OFFSET + offset, length);
	}

	/**
	 * Writes a buffer of data.
	 * 
	 * @param pos
	 *            the position in the memory addrress
	 * @param data
	 *            the output buffer
	 * @param offset
	 *            the offset in the buffer of the first byte to write
	 * @param length
	 *            the length of the data
	 */
	public static void setBytes(long pos, byte[] data, int offset, int length) {
		unsafe.copyMemory(data, BYTE_ARRAY_OFFSET + offset, null, pos, length);
	}

	public static boolean compareAndSwapInt(long pos, int expected, int value) {
		return unsafe.compareAndSwapInt(null, pos, expected, value);
	}

	public static boolean compareAndSwapLong(long pos, long expected, long value) {
		return unsafe.compareAndSwapLong(null, pos, expected, value);
	}

	public static long getAndAddLong(long pos, long delta) {
		return unsafe.getAndAddLong(null, pos, delta);
	}
	
	public static long addAndGetLong(long pos,long delta){
		return unsafe.getAndAddLong(null, pos, delta)+delta;
	}
	
    /**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public static int incrementAndGetInt(long addr) {
        return unsafe.getAndAddInt(null, addr, 1) + 1;
    }

    /**
     * Atomically decrements by one the current value.
     *
     * @return the updated value
     */
    public static int decrementAndGetInt(long addr) {
        return unsafe.getAndAddInt(null, addr, -1) - 1;
    }
    
    /**
     * Atomically adds the given value to the current value.
     *
     * @param delta the value to add
     * @return the updated value
     */
    public static int addAndGetInt(long addr,int delta) {
        return unsafe.getAndAddInt(null, addr, delta) + delta;
    }
    
    /**
     * Atomically adds the given value to the current value.
     *
     * @param delta the value to add
     * @return the previous value
     */
    public static int getAndAddInt(long addr,int delta) {
    	
        return unsafe.getAndAddInt(null, addr, delta);
    }
    
    public static void putAddress(long addr,long value){
    	unsafe.putAddress(addr, value);
    }

	public static void copyMemory(long srcAddr,long dstAddr,long bytes){
		unsafe.copyMemory(srcAddr,dstAddr,bytes);
	}
}

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import io.mycat.jcache.context.JcacheContext;
import io.mycat.jcache.context.Stats;
import io.mycat.jcache.context.StatsState;
import io.mycat.jcache.enums.memory.MOVE_STATUS;
import io.mycat.jcache.items.Items;
import io.mycat.jcache.net.JcacheGlobalConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.mycat.jcache.enums.ItemFlags;
import io.mycat.jcache.enums.memory.REASSIGN_RESULT_TYPE;
import io.mycat.jcache.setting.Settings;
import io.mycat.jcache.util.ItemChunkUtil;
import io.mycat.jcache.util.ItemUtil;
import io.mycat.jcache.util.SlabClassUtil;
import io.mycat.jcache.util.UnSafeUtil;

package io.mycat.jcache.memory;




@SuppressWarnings("restriction")
public class DefaultSlabsImpl implements Slabs,Runnable {
	
	private Logger logger = LoggerFactory.getLogger(DefaultSlabsImpl.class);	
	
	private static long slabclass;     //slabclass 数组内存首地址
	private static long mem_limit;     //总内存大小,收到配置参数 -m 约束.如果没有配置默认 64M
	private static long mem_malloced;   //已分配内存,每分配一个slab ,item 该值均会增加.
	/* If the memory limit has been hit once. Used as a hint to decide when to
	 * early-wake the LRU maintenance thread */
	private static boolean mem_limit_reached = false;

	private static int power_largest;   // 根据当前内存参数配置,分配的最大slabcalss 数量.受到增长因子的影响.
	
	private static long mem_base; // 当前内存池 内存首地址
	private static long mem_current;  // 当前未分配的内存的首地址
	private static long mem_avail;    // 当前可用内存大小.
	
	/**
	 * Access to the slab allocator is protected by this lock
	 */
	private volatile static AtomicBoolean slabs_lock = new AtomicBoolean(false);
	private  static Lock slabs_rebalance_lock = new ReentrantLock();

	private static Condition slab_rebalance_cond = slabs_rebalance_lock.newCondition();
	private volatile  static int do_run_slab_thread=1;
	private volatile  static int do_run_slab_rebalance_thread=1;
	private volatile int slab_rebalance_signal;
	private static final int  DEFAULT_SLAB_BULK_CHECK =1;
	private int slab_bulk_check = DEFAULT_SLAB_BULK_CHECK;
	private static Thread rebalance_tid;
	private SlabRebalance slab_rebal;
	
	/**
	 * 为  slabclass 分配一个新的slab
	 * @param id
	 * @return
	 */
	private boolean do_slabs_newslab(int id){
		long p = getSlabClass(id);
		long g = getSlabClass(Settings.SLAB_GLOBAL_PAGE_POOL);
		/* 获取当前slab 大小   */
		int len = (Settings.slabReassign || Settings.slabChunkSizeMax != Settings.slabPageSize) 
				? Settings.slabPageSize :   /* 默认slab 大小 */
					SlabClassUtil.getSize(p)*SlabClassUtil.getPerslab(p);  /* 当前 slabclass 中,chunk 大小  乘以 chunk 的数量   */
		
		long ptr;   /* 新分配的slab 可以 由 当前slabclass 分配,可能由 全局pool 分配,可能从总内存中分配 */
		
		if(mem_limit>0 && (mem_malloced + len) > mem_limit 
				&& SlabClassUtil.getSlabs(p) > 0
				&& SlabClassUtil.getSlabs(g)==0  /* 这个条件 */
				){
			mem_limit_reached = true;
			return false;
		}
		
		if(!grow_slab_list(id)   // 如果需要扩容slablist 扩容
				||((ptr = get_page_from_global_pool())==0)  //全局pool 中没有可用的slab
				&&(ptr = memory_allocate(len))==0){   //当前可用内存不足
			mem_limit_reached = true;
			return false;
		}
		
		/*初始化内存*/
		UnSafeUtil.unsafe.setMemory(ptr, len, (byte)0);
		split_slab_page_into_freelist(ptr,id);  /*为每个slab  */
		int slabs = SlabClassUtil.getSlabs(p);
		SlabClassUtil.incrSlabs(p);
		SlabClassUtil.setSlablistIndexValue(p, slabs, ptr);
		return true;
	}
	
	//将ptr指向的内存空间按第id个slabclass的size进行切分
	private void split_slab_page_into_freelist(long ptr,int id){
		long p = getSlabClass(id);  /* 当前  slabclass 内存首地址 */
		long perslab = SlabClassUtil.getPerslab(p); /* 每个slab 可以有多少个chunk */
		int x;
		for(x = 0;x<perslab;x++){
			do_slabs_free(ptr, 0, id);
			ptr += SlabClassUtil.getSize(p); /* 当前slab  , chunk 的内存首地址*/
		}
	}
	
	/**
	 * 从当前可用内存中 分配一块内存
	 * @param size
	 * @return
	 */
	public long memory_allocate(long size){
		long ret;
		
		if(mem_base == 0){
			/* We are not using a preallocated large memory chunk */
			ret = UnSafeUtil.unsafe.allocateMemory(size);
		}else{
			ret = mem_current;
			
			if(size > mem_avail){
				return 0;
			}
			
			 /* mem_current pointer _must_ be aligned!!! */
			if(size % Settings.CHUNK_ALIGN_BYTES != 0){
				size += Settings.CHUNK_ALIGN_BYTES - (size % Settings.CHUNK_ALIGN_BYTES);
			}
			
			mem_current  += size;
			
			if(size < mem_avail){
				mem_avail -=size;
			}else{
				mem_avail = 0;
			}
		}
		
		mem_malloced +=size;
		
		return ret;
	}
	
	
	/* Fast FIFO queue */
	/**
	 * 先进先出（FIFO） 将最后一个 slab,即:最先分配的slab 返回
	 * @return
	 */
	private long get_page_from_global_pool(){
		long p = getSlabClass(Settings.SLAB_GLOBAL_PAGE_POOL);
		int slabs = SlabClassUtil.getSlabs(p);
		if(slabs < 1){
			return 0;
		}
		
		long slab_list = SlabClassUtil.getSlabList(p);
		
		long ret = slab_list + (slabs - 1)*UnSafeUtil.addresssize;  //获取 在 global pool 中 分配的最后一个 slab
		SlabClassUtil.decrSlabs(p); //已分配的slabs 数量减一
		return ret;
	}
	
	/**
	 * 判断 slabclass 中 slablist 是否需要扩容 ,
	 * 如果扩容失败 返回 false.
	 * 不需要扩容 或扩容成功,返回成功
	 * @param id
	 * @return
	 */
	private boolean grow_slab_list(int id){
		long p = getSlabClass(id);
		//当前slabclass 中已分配的slab 数，已达到  listsize 上限, 对 slablist 扩容
		if(SlabClassUtil.getSlabs(p)==SlabClassUtil.getListSize(p)){
			int list_size = SlabClassUtil.getListSize(p);
			int new_size = list_size!=0?list_size*2:16;
			long slablist = SlabClassUtil.getSlabList(p);
			if(slablist==0){
				slablist = UnSafeUtil.unsafe.allocateMemory(new_size);
			}else{
				slablist = UnSafeUtil.unsafe.reallocateMemory(slablist, new_size);
			}
			if(slablist==0){  //分配失败 
				return false;
			}
			SlabClassUtil.setListSize(p, new_size);
			SlabClassUtil.setSlabList(p, slablist);
		}
		return true;
	}
	
	/**
	 * 将当前 ptr 对应的item 挂载到 slabclass  空闲链表 slots head 上.
	 * @param ptr
	 * @param size
	 * @param id
	 */
	private void do_slabs_free(long ptr,int size,int id){
		long p = getSlabClass(id);
		long it = ptr;
		
		int it_flags = ItemUtil.getItflags(it);
		if((it_flags & ItemFlags.ITEM_CHUNKED.getFlags()) == 0){
			ItemUtil.setItflags(it, ItemFlags.ITEM_SLABBED.getFlags());
			ItemUtil.setSlabsClsid(it, (byte)0);
			ItemUtil.setPrev(it, 0);
			ItemUtil.setNext(it, SlabClassUtil.getSlots(p));
			long next = ItemUtil.getNext(it);
			if(next!=0){
				ItemUtil.setPrev(next, it);
			}
			SlabClassUtil.setSlots(p, it);
			SlabClassUtil.incrSlCurr(p);
			SlabClassUtil.decrRequested(p, size);
		}else{
			do_slabs_free_chunked(it,size,id,p); 
		}
		return;
	}
	
	/**
	 * @param it
	 * @param size
	 * @param id
	 * @param p
	 */
	private void do_slabs_free_chunked(long it,int size,int id,long p){
		long chunk = ItemUtil.ITEM_data(it);
		int realsize = size;
		while(chunk!=0){

			realsize += ItemChunkUtil.getNtotal();
