com.orientechnologies.orient.core.id.ORecordId Maven / Gradle / Ivy
/*
*
* * Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
* *
* * 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.
* *
* * For more information: http://www.orientechnologies.com
*
*/
package com.orientechnologies.orient.core.id;
import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.exception.ODatabaseException;
import com.orientechnologies.orient.core.record.ORecord;
import com.orientechnologies.orient.core.serialization.OBinaryProtocol;
import com.orientechnologies.orient.core.serialization.OMemoryStream;
import com.orientechnologies.orient.core.serialization.serializer.OStringSerializerHelper;
import com.orientechnologies.orient.core.storage.OStorage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
public class ORecordId implements ORID {
public static final ORecordId EMPTY_RECORD_ID = new ORecordId();
public static final byte[] EMPTY_RECORD_ID_STREAM = EMPTY_RECORD_ID.toStream();
public static final int PERSISTENT_SIZE = OBinaryProtocol.SIZE_SHORT + OBinaryProtocol.SIZE_LONG;
private static final long serialVersionUID = 247070594054408657L;
// INT TO AVOID JVM PENALTY, BUT IT'S STORED AS SHORT
public int clusterId = CLUSTER_ID_INVALID;
public long clusterPosition = CLUSTER_POS_INVALID;
public ORecordId() {
}
public ORecordId(final int iClusterId, final long iPosition) {
clusterId = iClusterId;
checkClusterLimits();
clusterPosition = iPosition;
}
public ORecordId(final int iClusterIdId) {
clusterId = iClusterIdId;
checkClusterLimits();
}
public ORecordId(final String iRecordId) {
fromString(iRecordId);
}
/**
* Copy constructor.
*
* @param parentRid
* Source object
*/
public ORecordId(final ORID parentRid) {
clusterId = parentRid.getClusterId();
clusterPosition = parentRid.getClusterPosition();
}
public static String generateString(final int iClusterId, final long iPosition) {
final StringBuilder buffer = new StringBuilder(12);
buffer.append(PREFIX);
buffer.append(iClusterId);
buffer.append(SEPARATOR);
buffer.append(iPosition);
return buffer.toString();
}
public static boolean isValid(final long pos) {
return pos != CLUSTER_POS_INVALID;
}
public static boolean isPersistent(final long pos) {
return pos > CLUSTER_POS_INVALID;
}
public static boolean isNew(final long pos) {
return pos < 0;
}
public static boolean isTemporary(final long clusterPosition) {
return clusterPosition < CLUSTER_POS_INVALID;
}
public static boolean isA(final String iString) {
return iString.matches("#(-?[0-9]+):(-?[0-9]+)");
}
public void reset() {
clusterId = CLUSTER_ID_INVALID;
clusterPosition = CLUSTER_POS_INVALID;
}
public boolean isValid() {
return clusterPosition != CLUSTER_POS_INVALID;
}
public boolean isPersistent() {
return clusterId > -1 && clusterPosition > CLUSTER_POS_INVALID;
}
public boolean isNew() {
return clusterPosition < 0;
}
public boolean isTemporary() {
return clusterId != -1 && clusterPosition < CLUSTER_POS_INVALID;
}
@Override
public String toString() {
return generateString(clusterId, clusterPosition);
}
public StringBuilder toString(StringBuilder iBuffer) {
if (iBuffer == null)
iBuffer = new StringBuilder();
iBuffer.append(PREFIX);
iBuffer.append(clusterId);
iBuffer.append(SEPARATOR);
iBuffer.append(clusterPosition);
return iBuffer;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof OIdentifiable))
return false;
final ORecordId other = (ORecordId) ((OIdentifiable) obj).getIdentity();
if (clusterId != other.clusterId)
return false;
if (clusterPosition != other.clusterPosition)
return false;
return true;
}
@Override
public int hashCode() {
int result = clusterId;
result = 31 * result + (int) (clusterPosition ^ (clusterPosition >>> 32));
return result;
}
public int compareTo(final OIdentifiable iOther) {
if (iOther == this)
return 0;
if (iOther == null)
return 1;
final int otherClusterId = iOther.getIdentity().getClusterId();
if (clusterId == otherClusterId) {
final long otherClusterPos = iOther.getIdentity().getClusterPosition();
return (clusterPosition < otherClusterPos) ? -1 : ((clusterPosition == otherClusterPos) ? 0 : 1);
} else if (clusterId > otherClusterId)
return 1;
return -1;
}
public int compare(final OIdentifiable iObj1, final OIdentifiable iObj2) {
if (iObj1 == iObj2)
return 0;
if (iObj1 != null)
return iObj1.compareTo(iObj2);
return -1;
}
public ORecordId copy() {
return new ORecordId(clusterId, clusterPosition);
}
public ORecordId fromStream(final InputStream iStream) throws IOException {
clusterId = OBinaryProtocol.bytes2short(iStream);
clusterPosition = OBinaryProtocol.bytes2long(iStream);
return this;
}
public ORecordId fromStream(final OMemoryStream iStream) {
clusterId = iStream.getAsShort();
clusterPosition = iStream.getAsLong();
return this;
}
public ORecordId fromStream(final byte[] iBuffer) {
if (iBuffer != null) {
clusterId = OBinaryProtocol.bytes2short(iBuffer, 0);
clusterPosition = OBinaryProtocol.bytes2long(iBuffer, OBinaryProtocol.SIZE_SHORT);
}
return this;
}
public int toStream(final OutputStream iStream) throws IOException {
final int beginOffset = OBinaryProtocol.short2bytes((short) clusterId, iStream);
OBinaryProtocol.long2bytes(clusterPosition, iStream);
return beginOffset;
}
public int toStream(final OMemoryStream iStream) throws IOException {
final int beginOffset = OBinaryProtocol.short2bytes((short) clusterId, iStream);
OBinaryProtocol.long2bytes(clusterPosition, iStream);
return beginOffset;
}
public byte[] toStream() {
final byte[] buffer = new byte[OBinaryProtocol.SIZE_SHORT + OBinaryProtocol.SIZE_LONG];
OBinaryProtocol.short2bytes((short) clusterId, buffer, 0);
OBinaryProtocol.long2bytes(clusterPosition, buffer, OBinaryProtocol.SIZE_SHORT);
return buffer;
}
public int getClusterId() {
return clusterId;
}
public long getClusterPosition() {
return clusterPosition;
}
public void fromString(String iRecordId) {
if (iRecordId != null)
iRecordId = iRecordId.trim();
if (iRecordId == null || iRecordId.isEmpty()) {
clusterId = CLUSTER_ID_INVALID;
clusterPosition = CLUSTER_POS_INVALID;
return;
}
if (!OStringSerializerHelper.contains(iRecordId, SEPARATOR))
throw new IllegalArgumentException("Argument '" + iRecordId
+ "' is not a RecordId in form of string. Format must be: :");
final List parts = OStringSerializerHelper.split(iRecordId, SEPARATOR, PREFIX);
if (parts.size() != 2)
throw new IllegalArgumentException("Argument received '" + iRecordId
+ "' is not a RecordId in form of string. Format must be: #:. Example: #3:12");
clusterId = Integer.parseInt(parts.get(0));
checkClusterLimits();
clusterPosition = Long.parseLong(parts.get(1));
}
public void copyFrom(final ORID iSource) {
if (iSource == null)
throw new IllegalArgumentException("Source is null");
clusterId = iSource.getClusterId();
clusterPosition = iSource.getClusterPosition();
}
@Override
public void lock(final boolean iExclusive) {
ODatabaseRecordThreadLocal.INSTANCE.get().getTransaction()
.lockRecord(this, iExclusive ? OStorage.LOCKING_STRATEGY.EXCLUSIVE_LOCK : OStorage.LOCKING_STRATEGY.SHARED_LOCK);
}
@Override
public boolean isLocked() {
return ODatabaseRecordThreadLocal.INSTANCE.get().getTransaction().isLockedRecord(this);
}
@Override
public void unlock() {
ODatabaseRecordThreadLocal.INSTANCE.get().getTransaction().unlockRecord(this);
}
public String next() {
return generateString(clusterId, clusterPosition + 1);
}
@Override
public ORID nextRid() {
return new ORecordId(clusterId, clusterPosition + 1);
}
public ORID getIdentity() {
return this;
}
@SuppressWarnings("unchecked")
public T getRecord() {
if (!isValid())
return null;
final ODatabaseDocument db = ODatabaseRecordThreadLocal.INSTANCE.get();
if (db == null)
throw new ODatabaseException(
"No database found in current thread local space. If you manually control databases over threads assure to set the current database before to use it by calling: ODatabaseRecordThreadLocal.INSTANCE.set(db);");
return (T) db.load(this);
}
private void checkClusterLimits() {
if (clusterId < -2)
throw new ODatabaseException("RecordId cannot support negative cluster id. You've used: " + clusterId);
if (clusterId > CLUSTER_MAX)
throw new ODatabaseException("RecordId cannot support cluster id major than 32767. You've used: " + clusterId);
}
}