Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id D73D9200D0B for ; Tue, 12 Sep 2017 17:14:19 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id D58651609C7; Tue, 12 Sep 2017 15:14:19 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 58E401609C8 for ; Tue, 12 Sep 2017 17:14:17 +0200 (CEST) Received: (qmail 66575 invoked by uid 500); 12 Sep 2017 15:14:16 -0000 Mailing-List: contact commits-help@hbase.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@hbase.apache.org Delivered-To: mailing list commits@hbase.apache.org Received: (qmail 65982 invoked by uid 99); 12 Sep 2017 15:14:14 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 12 Sep 2017 15:14:14 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 74335F5766; Tue, 12 Sep 2017 15:14:14 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: git-site-role@apache.org To: commits@hbase.apache.org Date: Tue, 12 Sep 2017 15:14:18 -0000 Message-Id: <0eec646079fd4eba8c4f3f2dd2127c6e@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [05/51] [partial] hbase-site git commit: Published site at . archived-at: Tue, 12 Sep 2017 15:14:20 -0000 http://git-wip-us.apache.org/repos/asf/hbase-site/blob/b63bb380/devapidocs/src-html/org/apache/hadoop/hbase/KeyValue.KVComparator.html ---------------------------------------------------------------------- diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/KeyValue.KVComparator.html b/devapidocs/src-html/org/apache/hadoop/hbase/KeyValue.KVComparator.html index cced781..d27f757 100644 --- a/devapidocs/src-html/org/apache/hadoop/hbase/KeyValue.KVComparator.html +++ b/devapidocs/src-html/org/apache/hadoop/hbase/KeyValue.KVComparator.html @@ -1245,1583 +1245,1584 @@ 1237 //--------------------------------------------------------------------------- 1238 1239 /** -1240 * @return The byte array backing this KeyValue. -1241 * @deprecated Since 0.98.0. Use Cell Interface instead. Do not presume single backing buffer. -1242 */ -1243 @Deprecated -1244 public byte [] getBuffer() { -1245 return this.bytes; -1246 } -1247 -1248 /** -1249 * @return Offset into {@link #getBuffer()} at which this KeyValue starts. -1250 */ -1251 public int getOffset() { -1252 return this.offset; -1253 } -1254 -1255 /** -1256 * @return Length of bytes this KeyValue occupies in {@link #getBuffer()}. -1257 */ -1258 public int getLength() { -1259 return length; -1260 } -1261 -1262 //--------------------------------------------------------------------------- -1263 // -1264 // Length and Offset Calculators -1265 // -1266 //--------------------------------------------------------------------------- -1267 -1268 /** -1269 * Determines the total length of the KeyValue stored in the specified -1270 * byte array and offset. Includes all headers. -1271 * @param bytes byte array -1272 * @param offset offset to start of the KeyValue -1273 * @return length of entire KeyValue, in bytes -1274 */ -1275 private static int getLength(byte [] bytes, int offset) { -1276 int klength = ROW_OFFSET + Bytes.toInt(bytes, offset); -1277 int vlength = Bytes.toInt(bytes, offset + Bytes.SIZEOF_INT); -1278 return klength + vlength; -1279 } -1280 -1281 /** -1282 * @return Key offset in backing buffer.. -1283 */ -1284 public int getKeyOffset() { -1285 return this.offset + ROW_OFFSET; -1286 } -1287 -1288 public String getKeyString() { -1289 return Bytes.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength()); -1290 } -1291 -1292 /** -1293 * @return Length of key portion. -1294 */ -1295 public int getKeyLength() { -1296 return Bytes.toInt(this.bytes, this.offset); -1297 } -1298 -1299 /** -1300 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) -1301 */ -1302 @Override -1303 public byte[] getValueArray() { -1304 return bytes; -1305 } -1306 -1307 /** -1308 * @return the value offset -1309 */ -1310 @Override -1311 public int getValueOffset() { -1312 int voffset = getKeyOffset() + getKeyLength(); -1313 return voffset; -1314 } -1315 -1316 /** -1317 * @return Value length -1318 */ -1319 @Override -1320 public int getValueLength() { -1321 int vlength = Bytes.toInt(this.bytes, this.offset + Bytes.SIZEOF_INT); -1322 return vlength; -1323 } -1324 -1325 /** -1326 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) -1327 */ -1328 @Override -1329 public byte[] getRowArray() { -1330 return bytes; -1331 } -1332 -1333 /** -1334 * @return Row offset -1335 */ -1336 @Override -1337 public int getRowOffset() { -1338 return this.offset + ROW_KEY_OFFSET; -1339 } -1340 -1341 /** -1342 * @return Row length -1343 */ -1344 @Override -1345 public short getRowLength() { -1346 return Bytes.toShort(this.bytes, getKeyOffset()); -1347 } -1348 -1349 /** -1350 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) -1351 */ -1352 @Override -1353 public byte[] getFamilyArray() { -1354 return bytes; -1355 } -1356 -1357 /** -1358 * @return Family offset -1359 */ -1360 @Override -1361 public int getFamilyOffset() { -1362 return getFamilyOffset(getRowLength()); -1363 } -1364 -1365 /** -1366 * @return Family offset -1367 */ -1368 private int getFamilyOffset(int rlength) { -1369 return this.offset + ROW_KEY_OFFSET + rlength + Bytes.SIZEOF_BYTE; -1370 } -1371 -1372 /** -1373 * @return Family length -1374 */ -1375 @Override -1376 public byte getFamilyLength() { -1377 return getFamilyLength(getFamilyOffset()); -1378 } -1379 -1380 /** -1381 * @return Family length -1382 */ -1383 public byte getFamilyLength(int foffset) { -1384 return this.bytes[foffset-1]; -1385 } -1386 -1387 /** -1388 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) -1389 */ -1390 @Override -1391 public byte[] getQualifierArray() { -1392 return bytes; -1393 } -1394 -1395 /** -1396 * @return Qualifier offset -1397 */ -1398 @Override -1399 public int getQualifierOffset() { -1400 return getQualifierOffset(getFamilyOffset()); -1401 } -1402 -1403 /** -1404 * @return Qualifier offset -1405 */ -1406 private int getQualifierOffset(int foffset) { -1407 return foffset + getFamilyLength(foffset); -1408 } -1409 -1410 /** -1411 * @return Qualifier length -1412 */ -1413 @Override -1414 public int getQualifierLength() { -1415 return getQualifierLength(getRowLength(),getFamilyLength()); -1416 } -1417 -1418 /** -1419 * @return Qualifier length -1420 */ -1421 private int getQualifierLength(int rlength, int flength) { -1422 return getKeyLength() - (int) getKeyDataStructureSize(rlength, flength, 0); -1423 } -1424 -1425 /** -1426 * @return Timestamp offset -1427 */ -1428 public int getTimestampOffset() { -1429 return getTimestampOffset(getKeyLength()); -1430 } -1431 -1432 /** -1433 * @param keylength Pass if you have it to save on a int creation. -1434 * @return Timestamp offset -1435 */ -1436 private int getTimestampOffset(final int keylength) { -1437 return getKeyOffset() + keylength - TIMESTAMP_TYPE_SIZE; -1438 } -1439 -1440 /** -1441 * @return True if this KeyValue has a LATEST_TIMESTAMP timestamp. -1442 */ -1443 public boolean isLatestTimestamp() { -1444 return Bytes.equals(getBuffer(), getTimestampOffset(), Bytes.SIZEOF_LONG, -1445 HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG); -1446 } -1447 -1448 /** -1449 * @param now Time to set into <code>this</code> IFF timestamp == -1450 * {@link HConstants#LATEST_TIMESTAMP} (else, its a noop). -1451 * @return True is we modified this. -1452 */ -1453 public boolean updateLatestStamp(final byte [] now) { -1454 if (this.isLatestTimestamp()) { -1455 int tsOffset = getTimestampOffset(); -1456 System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG); -1457 // clear cache or else getTimestamp() possibly returns an old value -1458 return true; -1459 } -1460 return false; -1461 } -1462 -1463 @Override -1464 public void setTimestamp(long ts) { -1465 Bytes.putBytes(this.bytes, this.getTimestampOffset(), Bytes.toBytes(ts), 0, Bytes.SIZEOF_LONG); -1466 } -1467 -1468 @Override -1469 public void setTimestamp(byte[] ts, int tsOffset) { -1470 Bytes.putBytes(this.bytes, this.getTimestampOffset(), ts, tsOffset, Bytes.SIZEOF_LONG); -1471 } -1472 -1473 //--------------------------------------------------------------------------- -1474 // -1475 // Methods that return copies of fields -1476 // -1477 //--------------------------------------------------------------------------- -1478 -1479 /** -1480 * Do not use unless you have to. Used internally for compacting and testing. Use -1481 * {@link #getRowArray()}, {@link #getFamilyArray()}, {@link #getQualifierArray()}, and -1482 * {@link #getValueArray()} if accessing a KeyValue client-side. -1483 * @return Copy of the key portion only. -1484 */ -1485 public byte [] getKey() { -1486 int keylength = getKeyLength(); -1487 byte [] key = new byte[keylength]; -1488 System.arraycopy(getBuffer(), getKeyOffset(), key, 0, keylength); -1489 return key; -1490 } -1491 -1492 /** -1493 * -1494 * @return Timestamp -1495 */ -1496 @Override -1497 public long getTimestamp() { -1498 return getTimestamp(getKeyLength()); -1499 } -1500 -1501 /** -1502 * @param keylength Pass if you have it to save on a int creation. -1503 * @return Timestamp -1504 */ -1505 long getTimestamp(final int keylength) { -1506 int tsOffset = getTimestampOffset(keylength); -1507 return Bytes.toLong(this.bytes, tsOffset); -1508 } -1509 -1510 /** -1511 * @return Type of this KeyValue. -1512 */ -1513 @Deprecated -1514 public byte getType() { -1515 return getTypeByte(); -1516 } -1517 -1518 /** -1519 * @return KeyValue.TYPE byte representation -1520 */ -1521 @Override -1522 public byte getTypeByte() { -1523 return this.bytes[this.offset + getKeyLength() - 1 + ROW_OFFSET]; -1524 } -1525 -1526 /** -1527 * @return True if a delete type, a {@link KeyValue.Type#Delete} or -1528 * a {KeyValue.Type#DeleteFamily} or a {@link KeyValue.Type#DeleteColumn} -1529 * KeyValue type. -1530 */ -1531 @Deprecated // use CellUtil#isDelete -1532 public boolean isDelete() { -1533 return KeyValue.isDelete(getType()); -1534 } -1535 -1536 /** -1537 * This returns the offset where the tag actually starts. -1538 */ -1539 @Override -1540 public int getTagsOffset() { -1541 int tagsLen = getTagsLength(); -1542 if (tagsLen == 0) { -1543 return this.offset + this.length; -1544 } -1545 return this.offset + this.length - tagsLen; -1546 } -1547 -1548 /** -1549 * This returns the total length of the tag bytes -1550 */ -1551 @Override -1552 public int getTagsLength() { -1553 int tagsLen = this.length - (getKeyLength() + getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE); -1554 if (tagsLen > 0) { -1555 // There are some Tag bytes in the byte[]. So reduce 2 bytes which is added to denote the tags -1556 // length -1557 tagsLen -= TAGS_LENGTH_SIZE; -1558 } -1559 return tagsLen; -1560 } -1561 -1562 /** -1563 * Returns any tags embedded in the KeyValue. Used in testcases. -1564 * @return The tags -1565 */ -1566 public List<Tag> getTags() { -1567 int tagsLength = getTagsLength(); -1568 if (tagsLength == 0) { -1569 return EMPTY_ARRAY_LIST; -1570 } -1571 return TagUtil.asList(getTagsArray(), getTagsOffset(), tagsLength); -1572 } -1573 -1574 /** -1575 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) -1576 */ -1577 @Override -1578 public byte[] getTagsArray() { -1579 return bytes; -1580 } -1581 -1582 /** -1583 * Creates a new KeyValue that only contains the key portion (the value is -1584 * set to be null). -1585 * -1586 * TODO only used by KeyOnlyFilter -- move there. -1587 * @param lenAsVal replace value with the actual value length (false=empty) -1588 */ -1589 public KeyValue createKeyOnly(boolean lenAsVal) { -1590 // KV format: <keylen:4><valuelen:4><key:keylen><value:valuelen> -1591 // Rebuild as: <keylen:4><0:4><key:keylen> -1592 int dataLen = lenAsVal? Bytes.SIZEOF_INT : 0; -1593 byte [] newBuffer = new byte[getKeyLength() + ROW_OFFSET + dataLen]; -1594 System.arraycopy(this.bytes, this.offset, newBuffer, 0, -1595 Math.min(newBuffer.length,this.length)); -1596 Bytes.putInt(newBuffer, Bytes.SIZEOF_INT, dataLen); -1597 if (lenAsVal) { -1598 Bytes.putInt(newBuffer, newBuffer.length - dataLen, this.getValueLength()); -1599 } -1600 return new KeyValue(newBuffer); -1601 } -1602 -1603 /** -1604 * Splits a column in {@code family:qualifier} form into separate byte arrays. An empty qualifier -1605 * (ie, {@code fam:}) is parsed as <code>{ fam, EMPTY_BYTE_ARRAY }</code> while no delimiter (ie, -1606 * {@code fam}) is parsed as an array of one element, <code>{ fam }</code>. -1607 * <p> -1608 * Don't forget, HBase DOES support empty qualifiers. (see HBASE-9549) -1609 * </p> -1610 * <p> -1611 * Not recommend to be used as this is old-style API. -1612 * </p> -1613 * @param c The column. -1614 * @return The parsed column. -1615 */ -1616 public static byte [][] parseColumn(byte [] c) { -1617 final int index = getDelimiter(c, 0, c.length, COLUMN_FAMILY_DELIMITER); -1618 if (index == -1) { -1619 // If no delimiter, return array of size 1 -1620 return new byte [][] { c }; -1621 } else if(index == c.length - 1) { -1622 // family with empty qualifier, return array size 2 -1623 byte [] family = new byte[c.length-1]; -1624 System.arraycopy(c, 0, family, 0, family.length); -1625 return new byte [][] { family, HConstants.EMPTY_BYTE_ARRAY}; -1626 } -1627 // Family and column, return array size 2 -1628 final byte [][] result = new byte [2][]; -1629 result[0] = new byte [index]; -1630 System.arraycopy(c, 0, result[0], 0, index); -1631 final int len = c.length - (index + 1); -1632 result[1] = new byte[len]; -1633 System.arraycopy(c, index + 1 /* Skip delimiter */, result[1], 0, len); -1634 return result; -1635 } -1636 -1637 /** -1638 * Makes a column in family:qualifier form from separate byte arrays. -1639 * <p> -1640 * Not recommended for usage as this is old-style API. -1641 * @param family -1642 * @param qualifier -1643 * @return family:qualifier -1644 */ -1645 public static byte [] makeColumn(byte [] family, byte [] qualifier) { -1646 return Bytes.add(family, COLUMN_FAMILY_DELIM_ARRAY, qualifier); -1647 } -1648 -1649 /** -1650 * @param b -1651 * @param delimiter -1652 * @return Index of delimiter having started from start of <code>b</code> -1653 * moving rightward. -1654 */ -1655 public static int getDelimiter(final byte [] b, int offset, final int length, -1656 final int delimiter) { -1657 if (b == null) { -1658 throw new IllegalArgumentException("Passed buffer is null"); -1659 } -1660 int result = -1; -1661 for (int i = offset; i < length + offset; i++) { -1662 if (b[i] == delimiter) { -1663 result = i; -1664 break; -1665 } -1666 } -1667 return result; -1668 } -1669 -1670 /** -1671 * Find index of passed delimiter walking from end of buffer backwards. -1672 * @param b -1673 * @param delimiter -1674 * @return Index of delimiter -1675 */ -1676 public static int getDelimiterInReverse(final byte [] b, final int offset, -1677 final int length, final int delimiter) { -1678 if (b == null) { -1679 throw new IllegalArgumentException("Passed buffer is null"); -1680 } -1681 int result = -1; -1682 for (int i = (offset + length) - 1; i >= offset; i--) { -1683 if (b[i] == delimiter) { -1684 result = i; -1685 break; -1686 } -1687 } -1688 return result; -1689 } -1690 -1691 /** -1692 * A {@link KVComparator} for <code>hbase:meta</code> catalog table -1693 * {@link KeyValue}s. -1694 * @deprecated : {@link CellComparator#META_COMPARATOR} to be used -1695 */ -1696 @Deprecated -1697 public static class MetaComparator extends KVComparator { -1698 /** -1699 * Compare key portion of a {@link KeyValue} for keys in <code>hbase:meta</code> -1700 * table. -1701 */ -1702 @Override -1703 public int compare(final Cell left, final Cell right) { -1704 return CellComparator.META_COMPARATOR.compareKeyIgnoresMvcc(left, right); -1705 } -1706 -1707 @Override -1708 public int compareOnlyKeyPortion(Cell left, Cell right) { -1709 return compare(left, right); -1710 } -1711 -1712 @Override -1713 public int compareRows(byte [] left, int loffset, int llength, -1714 byte [] right, int roffset, int rlength) { -1715 int leftDelimiter = getDelimiter(left, loffset, llength, -1716 HConstants.DELIMITER); -1717 int rightDelimiter = getDelimiter(right, roffset, rlength, -1718 HConstants.DELIMITER); -1719 // Compare up to the delimiter -1720 int lpart = (leftDelimiter < 0 ? llength :leftDelimiter - loffset); -1721 int rpart = (rightDelimiter < 0 ? rlength :rightDelimiter - roffset); -1722 int result = Bytes.compareTo(left, loffset, lpart, right, roffset, rpart); -1723 if (result != 0) { -1724 return result; -1725 } else { -1726 if (leftDelimiter < 0 && rightDelimiter >= 0) { -1727 return -1; -1728 } else if (rightDelimiter < 0 && leftDelimiter >= 0) { -1729 return 1; -1730 } else if (leftDelimiter < 0 && rightDelimiter < 0) { -1731 return 0; -1732 } -1733 } -1734 // Compare middle bit of the row. -1735 // Move past delimiter -1736 leftDelimiter++; -1737 rightDelimiter++; -1738 int leftFarDelimiter = getDelimiterInReverse(left, leftDelimiter, -1739 llength - (leftDelimiter - loffset), HConstants.DELIMITER); -1740 int rightFarDelimiter = getDelimiterInReverse(right, -1741 rightDelimiter, rlength - (rightDelimiter - roffset), -1742 HConstants.DELIMITER); -1743 // Now compare middlesection of row. -1744 lpart = (leftFarDelimiter < 0 ? llength + loffset: leftFarDelimiter) - leftDelimiter; -1745 rpart = (rightFarDelimiter < 0 ? rlength + roffset: rightFarDelimiter)- rightDelimiter; -1746 result = super.compareRows(left, leftDelimiter, lpart, right, rightDelimiter, rpart); -1747 if (result != 0) { -1748 return result; -1749 } else { -1750 if (leftDelimiter < 0 && rightDelimiter >= 0) { -1751 return -1; -1752 } else if (rightDelimiter < 0 && leftDelimiter >= 0) { -1753 return 1; -1754 } else if (leftDelimiter < 0 && rightDelimiter < 0) { -1755 return 0; -1756 } -1757 } -1758 // Compare last part of row, the rowid. -1759 leftFarDelimiter++; -1760 rightFarDelimiter++; -1761 result = Bytes.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset), -1762 right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset)); -1763 return result; -1764 } -1765 -1766 /** -1767 * Don't do any fancy Block Index splitting tricks. -1768 */ -1769 @Override -1770 public byte[] getShortMidpointKey(final byte[] leftKey, final byte[] rightKey) { -1771 return Arrays.copyOf(rightKey, rightKey.length); -1772 } -1773 -1774 /** -1775 * The HFileV2 file format's trailer contains this class name. We reinterpret this and -1776 * instantiate the appropriate comparator. -1777 * TODO: With V3 consider removing this. -1778 * @return legacy class name for FileFileTrailer#comparatorClassName -1779 */ -1780 @Override -1781 public String getLegacyKeyComparatorName() { -1782 return "org.apache.hadoop.hbase.KeyValue$MetaKeyComparator"; -1783 } -1784 -1785 @Override -1786 protected Object clone() throws CloneNotSupportedException { -1787 return new MetaComparator(); -1788 } -1789 -1790 /** -1791 * Override the row key comparison to parse and compare the meta row key parts. -1792 */ -1793 @Override -1794 protected int compareRowKey(final Cell l, final Cell r) { -1795 byte[] left = l.getRowArray(); -1796 int loffset = l.getRowOffset(); -1797 int llength = l.getRowLength(); -1798 byte[] right = r.getRowArray(); -1799 int roffset = r.getRowOffset(); -1800 int rlength = r.getRowLength(); -1801 return compareRows(left, loffset, llength, right, roffset, rlength); -1802 } -1803 } -1804 -1805 /** -1806 * Compare KeyValues. When we compare KeyValues, we only compare the Key -1807 * portion. This means two KeyValues with same Key but different Values are -1808 * considered the same as far as this Comparator is concerned. -1809 * @deprecated : Use {@link CellComparator}. -1810 */ -1811 @Deprecated -1812 public static class KVComparator implements RawComparator<Cell>, SamePrefixComparator<byte[]> { -1813 -1814 /** -1815 * The HFileV2 file format's trailer contains this class name. We reinterpret this and -1816 * instantiate the appropriate comparator. -1817 * TODO: With V3 consider removing this. -1818 * @return legacy class name for FileFileTrailer#comparatorClassName -1819 */ -1820 public String getLegacyKeyComparatorName() { -1821 return "org.apache.hadoop.hbase.KeyValue$KeyComparator"; -1822 } -1823 -1824 @Override // RawComparator -1825 public int compare(byte[] l, int loff, int llen, byte[] r, int roff, int rlen) { -1826 return compareFlatKey(l,loff,llen, r,roff,rlen); -1827 } -1828 +1240 * To be used only in tests where the Cells are clearly assumed to be of type KeyValue +1241 * and that we need access to the backing array to do some test case related assertions. +1242 * @return The byte array backing this KeyValue. +1243 */ +1244 @VisibleForTesting +1245 public byte [] getBuffer() { +1246 return this.bytes; +1247 } +1248 +1249 /** +1250 * @return Offset into {@link #getBuffer()} at which this KeyValue starts. +1251 */ +1252 public int getOffset() { +1253 return this.offset; +1254 } +1255 +1256 /** +1257 * @return Length of bytes this KeyValue occupies in {@link #getBuffer()}. +1258 */ +1259 public int getLength() { +1260 return length; +1261 } +1262 +1263 //--------------------------------------------------------------------------- +1264 // +1265 // Length and Offset Calculators +1266 // +1267 //--------------------------------------------------------------------------- +1268 +1269 /** +1270 * Determines the total length of the KeyValue stored in the specified +1271 * byte array and offset. Includes all headers. +1272 * @param bytes byte array +1273 * @param offset offset to start of the KeyValue +1274 * @return length of entire KeyValue, in bytes +1275 */ +1276 private static int getLength(byte [] bytes, int offset) { +1277 int klength = ROW_OFFSET + Bytes.toInt(bytes, offset); +1278 int vlength = Bytes.toInt(bytes, offset + Bytes.SIZEOF_INT); +1279 return klength + vlength; +1280 } +1281 +1282 /** +1283 * @return Key offset in backing buffer.. +1284 */ +1285 public int getKeyOffset() { +1286 return this.offset + ROW_OFFSET; +1287 } +1288 +1289 public String getKeyString() { +1290 return Bytes.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength()); +1291 } +1292 +1293 /** +1294 * @return Length of key portion. +1295 */ +1296 public int getKeyLength() { +1297 return Bytes.toInt(this.bytes, this.offset); +1298 } +1299 +1300 /** +1301 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) +1302 */ +1303 @Override +1304 public byte[] getValueArray() { +1305 return bytes; +1306 } +1307 +1308 /** +1309 * @return the value offset +1310 */ +1311 @Override +1312 public int getValueOffset() { +1313 int voffset = getKeyOffset() + getKeyLength(); +1314 return voffset; +1315 } +1316 +1317 /** +1318 * @return Value length +1319 */ +1320 @Override +1321 public int getValueLength() { +1322 int vlength = Bytes.toInt(this.bytes, this.offset + Bytes.SIZEOF_INT); +1323 return vlength; +1324 } +1325 +1326 /** +1327 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) +1328 */ +1329 @Override +1330 public byte[] getRowArray() { +1331 return bytes; +1332 } +1333 +1334 /** +1335 * @return Row offset +1336 */ +1337 @Override +1338 public int getRowOffset() { +1339 return this.offset + ROW_KEY_OFFSET; +1340 } +1341 +1342 /** +1343 * @return Row length +1344 */ +1345 @Override +1346 public short getRowLength() { +1347 return Bytes.toShort(this.bytes, getKeyOffset()); +1348 } +1349 +1350 /** +1351 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) +1352 */ +1353 @Override +1354 public byte[] getFamilyArray() { +1355 return bytes; +1356 } +1357 +1358 /** +1359 * @return Family offset +1360 */ +1361 @Override +1362 public int getFamilyOffset() { +1363 return getFamilyOffset(getRowLength()); +1364 } +1365 +1366 /** +1367 * @return Family offset +1368 */ +1369 private int getFamilyOffset(int rlength) { +1370 return this.offset + ROW_KEY_OFFSET + rlength + Bytes.SIZEOF_BYTE; +1371 } +1372 +1373 /** +1374 * @return Family length +1375 */ +1376 @Override +1377 public byte getFamilyLength() { +1378 return getFamilyLength(getFamilyOffset()); +1379 } +1380 +1381 /** +1382 * @return Family length +1383 */ +1384 public byte getFamilyLength(int foffset) { +1385 return this.bytes[foffset-1]; +1386 } +1387 +1388 /** +1389 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) +1390 */ +1391 @Override +1392 public byte[] getQualifierArray() { +1393 return bytes; +1394 } +1395 +1396 /** +1397 * @return Qualifier offset +1398 */ +1399 @Override +1400 public int getQualifierOffset() { +1401 return getQualifierOffset(getFamilyOffset()); +1402 } +1403 +1404 /** +1405 * @return Qualifier offset +1406 */ +1407 private int getQualifierOffset(int foffset) { +1408 return foffset + getFamilyLength(foffset); +1409 } +1410 +1411 /** +1412 * @return Qualifier length +1413 */ +1414 @Override +1415 public int getQualifierLength() { +1416 return getQualifierLength(getRowLength(),getFamilyLength()); +1417 } +1418 +1419 /** +1420 * @return Qualifier length +1421 */ +1422 private int getQualifierLength(int rlength, int flength) { +1423 return getKeyLength() - (int) getKeyDataStructureSize(rlength, flength, 0); +1424 } +1425 +1426 /** +1427 * @return Timestamp offset +1428 */ +1429 public int getTimestampOffset() { +1430 return getTimestampOffset(getKeyLength()); +1431 } +1432 +1433 /** +1434 * @param keylength Pass if you have it to save on a int creation. +1435 * @return Timestamp offset +1436 */ +1437 private int getTimestampOffset(final int keylength) { +1438 return getKeyOffset() + keylength - TIMESTAMP_TYPE_SIZE; +1439 } +1440 +1441 /** +1442 * @return True if this KeyValue has a LATEST_TIMESTAMP timestamp. +1443 */ +1444 public boolean isLatestTimestamp() { +1445 return Bytes.equals(getBuffer(), getTimestampOffset(), Bytes.SIZEOF_LONG, +1446 HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG); +1447 } +1448 +1449 /** +1450 * @param now Time to set into <code>this</code> IFF timestamp == +1451 * {@link HConstants#LATEST_TIMESTAMP} (else, its a noop). +1452 * @return True is we modified this. +1453 */ +1454 public boolean updateLatestStamp(final byte [] now) { +1455 if (this.isLatestTimestamp()) { +1456 int tsOffset = getTimestampOffset(); +1457 System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG); +1458 // clear cache or else getTimestamp() possibly returns an old value +1459 return true; +1460 } +1461 return false; +1462 } +1463 +1464 @Override +1465 public void setTimestamp(long ts) { +1466 Bytes.putBytes(this.bytes, this.getTimestampOffset(), Bytes.toBytes(ts), 0, Bytes.SIZEOF_LONG); +1467 } +1468 +1469 @Override +1470 public void setTimestamp(byte[] ts, int tsOffset) { +1471 Bytes.putBytes(this.bytes, this.getTimestampOffset(), ts, tsOffset, Bytes.SIZEOF_LONG); +1472 } +1473 +1474 //--------------------------------------------------------------------------- +1475 // +1476 // Methods that return copies of fields +1477 // +1478 //--------------------------------------------------------------------------- +1479 +1480 /** +1481 * Do not use unless you have to. Used internally for compacting and testing. Use +1482 * {@link #getRowArray()}, {@link #getFamilyArray()}, {@link #getQualifierArray()}, and +1483 * {@link #getValueArray()} if accessing a KeyValue client-side. +1484 * @return Copy of the key portion only. +1485 */ +1486 public byte [] getKey() { +1487 int keylength = getKeyLength(); +1488 byte [] key = new byte[keylength]; +1489 System.arraycopy(getBuffer(), getKeyOffset(), key, 0, keylength); +1490 return key; +1491 } +1492 +1493 /** +1494 * +1495 * @return Timestamp +1496 */ +1497 @Override +1498 public long getTimestamp() { +1499 return getTimestamp(getKeyLength()); +1500 } +1501 +1502 /** +1503 * @param keylength Pass if you have it to save on a int creation. +1504 * @return Timestamp +1505 */ +1506 long getTimestamp(final int keylength) { +1507 int tsOffset = getTimestampOffset(keylength); +1508 return Bytes.toLong(this.bytes, tsOffset); +1509 } +1510 +1511 /** +1512 * @return Type of this KeyValue. +1513 */ +1514 @Deprecated +1515 public byte getType() { +1516 return getTypeByte(); +1517 } +1518 +1519 /** +1520 * @return KeyValue.TYPE byte representation +1521 */ +1522 @Override +1523 public byte getTypeByte() { +1524 return this.bytes[this.offset + getKeyLength() - 1 + ROW_OFFSET]; +1525 } +1526 +1527 /** +1528 * @return True if a delete type, a {@link KeyValue.Type#Delete} or +1529 * a {KeyValue.Type#DeleteFamily} or a {@link KeyValue.Type#DeleteColumn} +1530 * KeyValue type. +1531 */ +1532 @Deprecated // use CellUtil#isDelete +1533 public boolean isDelete() { +1534 return KeyValue.isDelete(getType()); +1535 } +1536 +1537 /** +1538 * This returns the offset where the tag actually starts. +1539 */ +1540 @Override +1541 public int getTagsOffset() { +1542 int tagsLen = getTagsLength(); +1543 if (tagsLen == 0) { +1544 return this.offset + this.length; +1545 } +1546 return this.offset + this.length - tagsLen; +1547 } +1548 +1549 /** +1550 * This returns the total length of the tag bytes +1551 */ +1552 @Override +1553 public int getTagsLength() { +1554 int tagsLen = this.length - (getKeyLength() + getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE); +1555 if (tagsLen > 0) { +1556 // There are some Tag bytes in the byte[]. So reduce 2 bytes which is added to denote the tags +1557 // length +1558 tagsLen -= TAGS_LENGTH_SIZE; +1559 } +1560 return tagsLen; +1561 } +1562 +1563 /** +1564 * Returns any tags embedded in the KeyValue. Used in testcases. +1565 * @return The tags +1566 */ +1567 public List<Tag> getTags() { +1568 int tagsLength = getTagsLength(); +1569 if (tagsLength == 0) { +1570 return EMPTY_ARRAY_LIST; +1571 } +1572 return TagUtil.asList(getTagsArray(), getTagsOffset(), tagsLength); +1573 } +1574 +1575 /** +1576 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) +1577 */ +1578 @Override +1579 public byte[] getTagsArray() { +1580 return bytes; +1581 } +1582 +1583 /** +1584 * Creates a new KeyValue that only contains the key portion (the value is +1585 * set to be null). +1586 * +1587 * TODO only used by KeyOnlyFilter -- move there. +1588 * @param lenAsVal replace value with the actual value length (false=empty) +1589 */ +1590 public KeyValue createKeyOnly(boolean lenAsVal) { +1591 // KV format: <keylen:4><valuelen:4><key:keylen><value:valuelen> +1592 // Rebuild as: <keylen:4><0:4><key:keylen> +1593 int dataLen = lenAsVal? Bytes.SIZEOF_INT : 0; +1594 byte [] newBuffer = new byte[getKeyLength() + ROW_OFFSET + dataLen]; +1595 System.arraycopy(this.bytes, this.offset, newBuffer, 0, +1596 Math.min(newBuffer.length,this.length)); +1597 Bytes.putInt(newBuffer, Bytes.SIZEOF_INT, dataLen); +1598 if (lenAsVal) { +1599 Bytes.putInt(newBuffer, newBuffer.length - dataLen, this.getValueLength()); +1600 } +1601 return new KeyValue(newBuffer); +1602 } +1603 +1604 /** +1605 * Splits a column in {@code family:qualifier} form into separate byte arrays. An empty qualifier +1606 * (ie, {@code fam:}) is parsed as <code>{ fam, EMPTY_BYTE_ARRAY }</code> while no delimiter (ie, +1607 * {@code fam}) is parsed as an array of one element, <code>{ fam }</code>. +1608 * <p> +1609 * Don't forget, HBase DOES support empty qualifiers. (see HBASE-9549) +1610 * </p> +1611 * <p> +1612 * Not recommend to be used as this is old-style API. +1613 * </p> +1614 * @param c The column. +1615 * @return The parsed column. +1616 */ +1617 public static byte [][] parseColumn(byte [] c) { +1618 final int index = getDelimiter(c, 0, c.length, COLUMN_FAMILY_DELIMITER); +1619 if (index == -1) { +<