Util.java
/*
* Copyright (C) 2014 Robert Stupp, Koeln, Germany, robert-stupp.de
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.caffinitas.ohc.linked;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
final class Util
{
// Hash entries
// offset of LRU replacement strategy next pointer (8 bytes, long)
static final long ENTRY_OFF_LRU_NEXT = 0;
// offset of LRU replacement strategy previous pointer (8 bytes, long)
static final long ENTRY_OFF_LRU_PREV = 8;
// offset of next hash entry in a hash bucket (8 bytes, long)
static final long ENTRY_OFF_NEXT = 16;
// offset of entry reference counter (4 bytes, int)
static final long ENTRY_OFF_REFCOUNT = 24;
// offset of entry sentinel (4 bytes, int)
static final long ENTRY_OFF_SENTINEL = 28;
// slot in which the entry resides (8 bytes, long)
static final long ENTRY_OFF_EXPIRE_AT = 32;
// LRU generation (4 bytes, int, only 2 distinct values)
static final long ENTRY_OFF_GENERATION = 40;
// bytes 44..47 unused
// offset of serialized hash value (8 bytes, long)
static final long ENTRY_OFF_HASH = 48;
// offset of serialized value length (4 bytes, int)
static final long ENTRY_OFF_VALUE_LENGTH = 56;
// offset of serialized hash key length (4 bytes, int)
static final long ENTRY_OFF_KEY_LENGTH = 60;
// offset of data in first block
static final long ENTRY_OFF_DATA = 64;
static final int SERIALIZED_ENTRY_SIZE = (int) (ENTRY_OFF_DATA - ENTRY_OFF_HASH);
static final int SERIALIZED_KEY_LEN_SIZE = (int) (ENTRY_OFF_DATA - ENTRY_OFF_KEY_LENGTH);
// Note: keep ENTRY_OFF_HASH, ENTRY_OFF_VALUE_LENGTH, ENTRY_OFF_KEY_LENGTH in exact that order
// and together and at the end of the header because
// org.caffinitas.ohc.linked.OHCacheImpl.(de)serializeEntry relies on it!
// Window Tiny-LFU generations
static final int GEN_EDEN = 0;
static final int GEN_MAIN = 1;
// Hash bucket-table
// total memory required for a hash-partition
static final long BUCKET_ENTRY_LEN = 8;
// Compressed entries header
// 'OHCC'
static final int HEADER_COMPRESSED = 0x4f484343;
// 'OHCC' reversed
static final int HEADER_COMPRESSED_WRONG = 0x4343484f;
// 'OHCE'
static final int HEADER_ENTRIES = 0x4f484345;
// 'OHCE' reversed
static final int HEADER_ENTRIES_WRONG = 0x4543484f;
// 'OHCK'
static final int HEADER_KEYS = 0x4f48434b;
// 'OHCK' reversed
static final int HEADER_KEYS_WRONG = 0x4b43484f;
// sentinel values
static final int SENTINEL_NOT_PRESENT = 0;
static final int SENTINEL_LOADING = 1;
static final int SENTINEL_SUCCESS = 2;
static final int SENTINEL_TEMPORARY_FAILURE = 3;
static final int SENTINEL_PERMANENT_FAILURE = 4;
static long roundUpTo8(long val)
{
long rem = val & 7;
if (rem != 0)
val += 8L - rem;
return val;
}
static long allocLen(long keyLen, long valueLen)
{
return ENTRY_OFF_DATA + roundUpTo8(keyLen) + valueLen;
}
static void writeFully(WritableByteChannel channel, ByteBuffer buffer) throws IOException
{
while (buffer.remaining() > 0)
channel.write(buffer);
}
static boolean readFully(ReadableByteChannel channel, ByteBuffer buffer) throws IOException
{
while (buffer.remaining() > 0)
{
int rd = channel.read(buffer);
if (rd == -1)
return false;
}
return true;
}
static int bitNum(long val)
{
int bit = 0;
for (; val != 0L; bit++)
val >>>= 1;
return bit;
}
static long roundUpToPowerOf2(long number, long max)
{
return number >= max
? max
: (number > 1) ? Long.highestOneBit((number - 1) << 1) : 1;
}
}