--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.store.raw.data.RecordId\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.store.raw.data;\r
+\r
+import org.apache.derby.iapi.store.raw.ContainerKey;\r
+import org.apache.derby.iapi.store.raw.PageKey;\r
+import org.apache.derby.iapi.services.locks.Latch;\r
+\r
+import org.apache.derby.iapi.store.raw.RowLock;\r
+import org.apache.derby.iapi.store.raw.RecordHandle;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.services.locks.VirtualLockTable;\r
+\r
+import org.apache.derby.catalog.UUID;\r
+import java.util.Hashtable;\r
+\r
+/**\r
+ Implementation of RecordHandle.\r
+\r
+ <BR>\r
+ MT - Mutable - Immutable identity : Thread Aware -\r
+ <BR>The methods of RecordHandle only access the identity\r
+ of the object and so the object appears immutable to them, as required.\r
+ <BR>The methods of Lockable are single thread required.\r
+\r
+*/\r
+public final class RecordId implements RecordHandle {\r
+\r
+ /**\r
+ Page the record lives in.\r
+ MT - Immutable\r
+ */\r
+ private final PageKey pageId;\r
+\r
+ /**\r
+ The actual record id.\r
+ MT - Immutable\r
+ */\r
+ private final int recordId;\r
+\r
+ /**\r
+ Last slot number this record id was at.\r
+ */\r
+ transient private int slotNumberHint;\r
+\r
+ public RecordId(ContainerKey container, long pageNumber, int recordId) {\r
+ this.pageId = new PageKey(container, pageNumber);\r
+ this.recordId = recordId;\r
+\r
+ // FIRST_SLOT_NUMBER guaranteed to be zero\r
+ // this.slotNumberHint = Page.FIRST_SLOT_NUMBER;\r
+ }\r
+\r
+ public RecordId(PageKey pageId, int recordId) {\r
+ this.pageId = pageId;\r
+ this.recordId = recordId;\r
+\r
+ // FIRST_SLOT_NUMBER guaranteed to be zero\r
+ // this.slotNumberHint = Page.FIRST_SLOT_NUMBER;\r
+ }\r
+\r
+ public RecordId(PageKey pageId, int recordId, int current_slot) {\r
+ this.pageId = pageId;\r
+ this.recordId = recordId;\r
+ this.slotNumberHint = current_slot;\r
+ }\r
+\r
+ /*\r
+ ** Methods of RecordHandle\r
+ */\r
+\r
+ /**\r
+ Get my record id.\r
+\r
+ <BR>\r
+ MT - thread safe\r
+\r
+ @see RecordHandle#getId\r
+ */\r
+ public int getId() {\r
+ return recordId;\r
+ }\r
+\r
+ /**\r
+ Get my page number.\r
+\r
+ <BR>\r
+ MT - thread safe\r
+\r
+ @see RecordHandle#getPageNumber\r
+ */\r
+\r
+ public long getPageNumber() {\r
+ return pageId.getPageNumber();\r
+ }\r
+\r
+ public Object getPageId() {\r
+ return pageId;\r
+ }\r
+\r
+ public ContainerKey getContainerId() {\r
+ return pageId.getContainerId();\r
+ }\r
+\r
+\r
+ /**\r
+ * What slot number might the record be at?\r
+ * <p>\r
+ * The raw store guarantees that the record handle of a record will not\r
+ * change, but its slot number may. When a RecordId is constructed the\r
+ * caller could have provided a slot number, if so return that slot number\r
+ * hint here. If a hint was not provided then the default \r
+ * Page.FIRST_SLOT_NUMBER will be returned.\r
+ *\r
+ * @return The slot number the record handle may be at.\r
+ **/\r
+ public int getSlotNumberHint()\r
+ {\r
+ return(slotNumberHint);\r
+ }\r
+\r
+ /*\r
+ ** Methods of Lockable (from RecordHandle)\r
+ */\r
+\r
+ /**\r
+ Lock me.\r
+\r
+ <BR>\r
+ MT - Single thread required (methods of Lockable)\r
+\r
+ @see org.apache.derby.iapi.services.locks.Lockable#lockEvent\r
+ */\r
+ public void lockEvent(Latch lockInfo) {\r
+ }\r
+\r
+\r
+ /**\r
+ Determine if this request can be granted.\r
+ <p)\r
+ Implements the grant/wait lock logic for row locks. See the\r
+ table in RowLock for more information.\r
+\r
+ <BR>\r
+ MT - Single thread required (methods of Lockable)\r
+\r
+ @see org.apache.derby.iapi.services.locks.Lockable#requestCompatible\r
+ */ \r
+ public boolean requestCompatible(\r
+ Object requestedQualifier, \r
+ Object grantedQualifier)\r
+ {\r
+\r
+ if (SanityManager.DEBUG) {\r
+ SanityManager.ASSERT((requestedQualifier == RowLock.RS2) ||\r
+ (requestedQualifier == RowLock.RS3) ||\r
+ (requestedQualifier == RowLock.RU2) ||\r
+ (requestedQualifier == RowLock.RU3) ||\r
+ (requestedQualifier == RowLock.RIP) ||\r
+ (requestedQualifier == RowLock.RI) ||\r
+ (requestedQualifier == RowLock.RX2) ||\r
+ (requestedQualifier == RowLock.RX3));\r
+ SanityManager.ASSERT((grantedQualifier == RowLock.RS2) ||\r
+ (grantedQualifier == RowLock.RS3) ||\r
+ (grantedQualifier == RowLock.RU2) ||\r
+ (grantedQualifier == RowLock.RU3) ||\r
+ (grantedQualifier == RowLock.RIP) ||\r
+ (grantedQualifier == RowLock.RI) ||\r
+ (grantedQualifier == RowLock.RX2) ||\r
+ (grantedQualifier == RowLock.RX3));\r
+ }\r
+\r
+ RowLock rlRequested = (RowLock) requestedQualifier;\r
+ RowLock rlGranted = (RowLock) grantedQualifier;\r
+\r
+ return(rlRequested.isCompatible(rlGranted));\r
+ }\r
+\r
+ /**\r
+ Is a caller that holds a lock compatible with themselves?\r
+ <p>\r
+ Row locks held in the same transaction are always compatible with\r
+ themselves.\r
+\r
+ <BR>\r
+ MT - Single thread required (methods of Lockable)\r
+\r
+ @see org.apache.derby.iapi.services.locks.Lockable#lockerAlwaysCompatible\r
+ */ \r
+ public boolean lockerAlwaysCompatible() {\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ Unlock me.\r
+\r
+ <BR>\r
+ MT - Single thread required (methods of Lockable)\r
+\r
+ @see org.apache.derby.iapi.services.locks.Lockable#unlockEvent\r
+ */ \r
+ public void unlockEvent(Latch lockInfo) {\r
+ }\r
+\r
+ /*\r
+ ** Methods of Object\r
+ */\r
+\r
+ /**\r
+ Implement value equality.\r
+ <BR>\r
+ MT - Thread safe\r
+ */\r
+ public boolean equals(Object ref) {\r
+\r
+ if (!(ref instanceof RecordId))\r
+ return false;\r
+\r
+ RecordId other = (RecordId) ref;\r
+\r
+ return ((recordId == other.recordId)\r
+ && pageId.equals(other.pageId));\r
+ }\r
+\r
+ /**\r
+ Return a hashcode based on value.\r
+ <BR>\r
+ MT - thread safe\r
+ */\r
+ public int hashCode() {\r
+\r
+ return (int) recordId ^ pageId.hashCode();\r
+ }\r
+\r
+ public String toString()\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ return "Record id=" + recordId + " " + pageId.toString(); \r
+ }\r
+ else\r
+ {\r
+ return(null);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ This lockable wants to participate in the Virtual Lock table.\r
+ */\r
+ public boolean lockAttributes(int flag, Hashtable attributes)\r
+ {\r
+\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(attributes != null, \r
+ "cannot call lockProperties with null attribute list");\r
+ SanityManager.ASSERT(pageId != null,\r
+ "RecordId PageId is null");\r
+ }\r
+\r
+ if ((flag & VirtualLockTable.TABLE_AND_ROWLOCK) == 0)\r
+ return false;\r
+\r
+ attributes.put(VirtualLockTable.CONTAINERID, \r
+ new Long(pageId.getContainerId().getContainerId()));\r
+\r
+ attributes.put(VirtualLockTable.LOCKNAME,\r
+ "(" + pageId.getPageNumber() + "," + recordId + ")");\r
+\r
+ attributes.put(VirtualLockTable.LOCKTYPE, "ROW");\r
+\r
+ // don't new unnecessary things for now\r
+ // attributes.put(VirtualLockTable.SEGMENTID, new Long(pageId.getContainerId().getSegmentId()));\r
+ // attributes.put(VirtualLockTable.PAGENUM, new Long(pageId.getPageNumber()));\r
+ // attributes.put(VirtualLockTable.PAGENUM, new Long(pageId.getPageNumber()));\r
+ // attributes.put(VirtualLockTable.RECID, new Integer(getId()));\r
+\r
+ return true;\r
+ }\r
+\r
+}\r