blob: 46b215386691cffdf2d4b5ff5f7b354f777e1080 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.jena.tdb2.store;
import static org.apache.jena.tdb2.store.NodeIdType.PTR;
import static org.apache.jena.tdb2.store.NodeIdType.isSpecial;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.jena.atlas.lib.BitsInt;
import org.apache.jena.atlas.lib.BitsLong;
import org.apache.jena.atlas.lib.Bytes;
import org.apache.jena.tdb2.TDBException;
import org.apache.jena.tdb2.store.value.DoubleNode62;
/** Factory for NodeIds, including to/from disk forms via ByteBuffers and byte[].*/
final
public class NodeIdFactory
{
// On-disk: may be shorter (controlled by get/set ByteBuffer and byte[]).
// In-memory - always int-long
// XXX Chance for a cache?
// See also TupleIndexRecord.
private static NodeId create(NodeIdType type, int v1, long v2) {
if ( isSpecial(type) ) {
if ( NodeId.equals(NodeId.NodeDoesNotExist, v1, v2) )
return NodeId.NodeDoesNotExist;
if ( NodeId.equals(NodeId.NodeIdAny, v1, v2) )
return NodeId.NodeIdAny;
if ( NodeId.equals(NodeId.NodeIdDefined, v1, v2) )
return NodeId.NodeIdDefined;
if ( NodeId.equals(NodeId.NodeIdDefined, v1, v2) )
return NodeId.NodeIdDefined;
if ( NodeId.equals(NodeId.NodeIdUndefined, v1, v2) )
return NodeId.NodeIdUndefined;
//throw new IllegalArgumentException("Special not recognized");
}
return createNew(type, v1, v2);
}
/** Make a NodeId of type and value - the value is assumed to be the right format for the type. */
public static NodeId createValue(NodeIdType type, long value) {
return createNew(type, 0, value);
}
private static NodeId createNew(NodeIdType type, int v1, long v2) {
// Create general NodeId form.
return NodeId.createRaw(type, v1, v2);
}
public static NodeId createPtr(long lo) {
return createNew(PTR, 0, lo);
}
/*package*/ /*long*/ static NodeId createPtrLong(int hi, long lo) {
return create(PTR, hi, lo);
}
// ---- Create from binary.
// 64 bit create
private static NodeId create64(long value2) {
if ( !BitsLong.isSet(value2, 63) )
return createPtr(value2);
// Inline.
long v2 = value2;
if ( BitsLong.isSet(v2, 62) ) {
// XSD_DOUBLE
v2 = DoubleNode62.removeType(v2);
return NodeId.createRaw(NodeIdType.XSD_DOUBLE, v2);
}
int t = (int)BitsLong.unpack(v2, 56, 63); // 7 bits
v2 = BitsLong.clear(v2, 56, 64);
NodeIdType type = NodeIdType.intToEnum(t);
if ( type == NodeIdType.SPECIAL )
throw new TDBException(String.format("Attempt to create a special from a long: 0x%016", v2));
return NodeId.createRaw(type, v2);
}
private static NodeId create(int v1, long v2) {
if ( !BitsInt.isSet(v1, 32) )
return createPtrLong(v1, v2);
int t = v1 >> 24;
NodeIdType type = NodeIdType.intToEnum(t);
if ( type == NodeIdType.SPECIAL )
throw new TDBException(String.format("Attempt to create a special from a long: 0x%016", v2));
return createNew(type, 0, v2);
}
// ------- On-disk forms.
//
/** Not relative - get from position zero */
public static NodeId get(byte[] b) { return get(b,0); }
// **** 64 bit NodeId ****
/** Relative {@code ByteBuffer} {@code get} */
public static NodeId get(ByteBuffer b) {
long value2 = b.getLong();
return decode(value2);
}
public static NodeId get(byte[] b, int idx) {
long value2 = Bytes.getLong(b, idx);
return decode(value2);
}
public static NodeId get(ByteBuffer b, int idx) {
long value2 = b.getLong(idx);
return decode(value2);
}
// 64 bit version
private static NodeId decode(long value2) {
return NodeIdFactory.create64(value2);
}
/** Not relative - set at position zero */
public static void set(NodeId nodeId, byte[] b) {
long v2 = encode(nodeId);
Bytes.setLong(v2, b, 0);
}
private static long encode(NodeId nodeId) {
long x = nodeId.value2;
switch(nodeId.type()) {
case PTR:
return x;
case XSD_DOUBLE:
// XSD_DOUBLE is special.
// Set value bit (63) and bit 62
x = DoubleNode62.insertType(x);
return x;
default:
// Bit 62 is zero - tagt is for doubles.
x = BitsLong.pack(x, nodeId.getTypeValue(), 56, 62);
// Set the high, value bit.
x = BitsLong.set(x, 63);
return x;
}
}
/** Relative {@code set} */
public static void set(NodeId nodeId, ByteBuffer b) {
long v2 = encode(nodeId);
b.putLong(v2);
}
public static void set(NodeId nodeId, byte[] b, int idx) {
long v2 = encode(nodeId);
Bytes.setLong(v2, b, idx);
}
public static void set(NodeId nodeId, ByteBuffer b, int idx) {
long v2 = encode(nodeId);
b.putLong(idx, v2);
}
public static void setNext(NodeId nodeId, byte[] b, int idx) {
long v2 = encode(nodeId);
Bytes.setLong(v2+1, b, idx);
}
// (int,long) versions : check before use
// /** Relative {@code ByteBuffer} {@code get} */
// public static NodeId get(ByteBuffer b) {
// int value1 = b.getInt();
// long value2 = b.getLong();
// return decode(value1,value2);
// }
//
// public static NodeId get(byte[] b, int idx) {
// int value1 = Bytes.getInt(b, idx);
// long value2 = Bytes.getLong(b, idx+SystemTDB.SizeOfInt);
// return decode(value1, value2);
// }
//
// public static NodeId get(ByteBuffer b, int idx) {
// int value1 = b.getInt(idx);
// long value2 = b.getLong(idx+SystemTDB.SizeOfInt);
// return decode(value1,value2);
// }
//
// private static NodeId decode(int value1, long value2) {
// return NodeIdFactory.create(value1, value2);
// }
//
// /** Not relative - set at position zero */
// public static void set(NodeId nodeId, byte[] b) {
// int v1 = encode(nodeId.value1);
// Bytes.setInt(v1, b, 0);
// Bytes.setLong(nodeId.value2, b, SystemTDB.SizeOfInt);
// }
//
// /** Relative {@code set} */
// public static void set(NodeId nodeId, ByteBuffer b) {
// int v1 = encode(nodeId.value1);
// b.putInt(v1);
// b.putLong(nodeId.value2);
// }
//
// public static void set(NodeId nodeId, byte[] b, int idx) {
// int v1 = encode(nodeId.value1);
// Bytes.setInt(v1, b, idx);
// Bytes.setLong(nodeId.value2, b, idx+SystemTDB.SizeOfInt);
// }
//
// public static void set(NodeId nodeId, ByteBuffer b, int idx) {
// int v1 = encode(nodeId.value1);
// b.putInt(idx, v1);
// b.putLong(idx+SystemTDB.SizeOfInt, nodeId.value2);
// }
//
// public static void setNext(NodeId nodeId, byte[] b, int idx) {
// int v1 = encode(nodeId.value1);
// long v2 = nodeId.value2;
// // Unsigned 96 bit add!
// if ( v2 < 0 ) {
// if ( v2 == Long.MIN_VALUE )
// v1++;
// else
// v2--;
// } else
// v2++;
// Bytes.setInt(v1, b, idx);
// Bytes.setLong(v2, b, idx+Integer.SIZE);
// }
// private int encode(NodeId nodeId) {
// long x = nodeId.value1;
// if ( nodeId.isPtr() )
// return x;
// x = BitsInt.pack(x, nodeId.getTypeValue(), 24, 32);
// return x;
// }
private static AtomicInteger counter = new AtomicInteger(0xB0);
public static NodeId genUnique() {
return NodeIdFactory.create(NodeIdType.SPECIAL, counter.incrementAndGet(), 0);
}
}