private MapEntry findFreeEntryByLength(int index, int realLength) throws IOException {
		FreeEntry freeEntry = freeEntries[index];
		if (freeEntry.count > 0) { // possible candidate
			synchronized(freeEntry) {
				
				if (freeEntry.count > 0) {
					
					FreeNode p = freeEntry.first;
					FreeNode q = p;
					
					// find a node with right size
					while(p != null && p.size < realLength) {
						q = p;
						p = p.next;
					}
					
					if (p == null) return null; // no luck
					
					// Get first free slot
					if (p == freeEntry.first) {
						freeEntry.first = p.next;
					} else {
						q.next = p.next;
						p.next = null; // ready for GC
					}
					
					// metrics
					this.freeEntryCount.decrementAndGet();
					freeEntry.count --;
					freeEntry.totalSlotSize -= p.size;
					totalFreeSlotSize.addAndGet(p.size * -1);
					
					// reuse the free entry
					// remove the free slot from the free list
					long indexPageIndex = Calculator.div(p.index, INDEX_ITEMS_PER_PAGE_BITS);
					IMappedPage indexPage = indexPageFactory.acquirePage(indexPageIndex);
					int indexItemOffset = (int)(Calculator.mul(Calculator.mod(p.index, INDEX_ITEMS_PER_PAGE_BITS), INDEX_ITEM_LENGTH_BITS));
					
					MapEntry mapEntry = new MapEntry(p.index, realLength, indexItemOffset, indexPage, this.dataPageFactory);
					
					// update freeEntryIndexSet if there is no free slot with specific size
					if (freeEntry.count == 0) {
						this.freeEntryIndexSet.remove(index);
					}
					
					return mapEntry;
				} 
				
			}
		}
		return null; // no luck
	}