package com.jivesoftware.os.amza.api;
import com.google.common.io.BaseEncoding;
import com.jivesoftware.os.amza.api.filer.UIO;
import com.jivesoftware.os.amza.api.partition.PartitionName;
import com.jivesoftware.os.amza.api.partition.VersionedPartitionName;
import com.jivesoftware.os.amza.api.ring.RingMember;
import com.jivesoftware.os.jive.utils.collections.bah.ConcurrentBAHash;
/**
*
*/
public class AmzaInterner {
private final BAInterner baInterner = new BAInterner();
private final ConcurrentBAHash<RingMember> ringMemberInterner = new ConcurrentBAHash<>(3, true, 1024);
public long size() {
return ringMemberInterner.size() + baInterner.size();
}
public RingMember internRingMember(byte[] bytes, int offset, int length) throws InterruptedException {
if (bytes == null || length == -1) {
return null;
}
if (bytes[offset] == 0) {
int o = offset + 1;
int l = length - 1;
RingMember ringMember = ringMemberInterner.get(bytes, o, l);
if (ringMember == null) {
byte[] key = new byte[l];
System.arraycopy(bytes, o, key, 0, l);
ringMember = new RingMember(key);
ringMemberInterner.put(key, ringMember);
}
return ringMember;
}
return null;
}
public RingMember internRingMemberBase64(String base64) throws InterruptedException {
byte[] bytes = BaseEncoding.base64Url().decode(base64);
return internRingMember(bytes, 0, bytes.length);
}
public PartitionName internPartitionName(byte[] bytes, int offset, int length) throws InterruptedException {
if (bytes == null || length == -1) {
return null;
}
int o = offset;
if (bytes[o] == 0) { // version
o++;
boolean systemPartition = (bytes[o] == 1);
o++;
int ringNameLength = UIO.bytesInt(bytes, o);
o += 4;
byte[] ringName = baInterner.intern(bytes, o, ringNameLength);
o += ringNameLength;
int nameLength = UIO.bytesInt(bytes, o);
o += 4;
byte[] name = baInterner.intern(bytes, o, nameLength);
return new PartitionName(systemPartition, ringName, name);
}
throw new RuntimeException("Invalid version:" + bytes[0]);
}
public PartitionName internPartitionNameBase64(String base64) throws InterruptedException {
byte[] bytes = BaseEncoding.base64Url().decode(base64);
return internPartitionName(bytes, 0, bytes.length);
}
public VersionedPartitionName internVersionedPartitionName(byte[] bytes, int offset, int length) throws InterruptedException {
if (bytes == null || length == -1) {
return null;
}
int o = offset;
if (bytes[o] == 0) { // version
o++;
int partitionNameBytesLength = UIO.bytesInt(bytes, o);
o += 4;
PartitionName partitionName = internPartitionName(bytes, o, partitionNameBytesLength);
o += partitionNameBytesLength;
long version = UIO.bytesLong(bytes, o);
return new VersionedPartitionName(partitionName, version);
}
throw new RuntimeException("Invalid version:" + bytes[0]);
}
public VersionedPartitionName internVersionedPartitionNameBase64(String base64) throws InterruptedException {
byte[] bytes = BaseEncoding.base64Url().decode(base64);
return internVersionedPartitionName(bytes, 0, bytes.length);
}
public byte[] internRingName(byte[] key, int offset, int length) throws InterruptedException {
return baInterner.intern(key, offset, length);
}
}