protected long freePhysTake(int size, boolean ensureAvail, boolean recursive) {
        assert(structuralLock.isHeldByCurrentThread());
        assert(size>0);
        //check free space
        if(spaceReclaimReuse){
            long ret =  longStackTake(size2ListIoRecid(size),recursive);
            if(ret!=0){
                freeSize-=roundTo16(size);
                return ret;
            }
        }
        //try to take large record and split it into two
        if(!recursive && spaceReclaimSplit ){
            for(long s=  roundTo16(size)+16;s<MAX_REC_SIZE;s+=16){
                final long ioList = size2ListIoRecid(s);
                if(ioList>maxUsedIoList) break;
                long ret = longStackTake(ioList,recursive);
                if(ret!=0){
                    //found larger record, split in two chunks, take first, mark second free
                    final long offset = ret & MASK_OFFSET;

                    long remaining = s - roundTo16(size);
                    long markFree = (remaining<<48) | (offset+s-remaining);
                    freePhysPut(markFree,recursive);

                    freeSize-=roundTo16(s);
                    return (((long)size)<<48) |offset;
                }
            }
        }

        //not available, increase file size
        if((physSize&CHUNK_SIZE_MOD_MASK)+size>CHUNK_SIZE)
            physSize += CHUNK_SIZE - (physSize&CHUNK_SIZE_MOD_MASK);
        long physSize2 = physSize;
        physSize = roundTo16(physSize+size);
        if(ensureAvail)
            phys.ensureAvailable(physSize);
        return physSize2;
    }