001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import java.io.IOException; 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.HashSet; 024import java.util.Map; 025import java.util.Set; 026import java.util.function.Function; 027import org.apache.hadoop.hbase.HConstants; 028import org.apache.hadoop.hbase.KeepDeletedCells; 029import org.apache.hadoop.hbase.MemoryCompactionPolicy; 030import org.apache.hadoop.hbase.exceptions.DeserializationException; 031import org.apache.hadoop.hbase.exceptions.HBaseException; 032import org.apache.hadoop.hbase.io.compress.Compression; 033import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding; 034import org.apache.hadoop.hbase.io.encoding.IndexBlockEncoding; 035import org.apache.hadoop.hbase.regionserver.BloomType; 036import org.apache.hadoop.hbase.util.Bytes; 037import org.apache.hadoop.hbase.util.PrettyPrinter; 038import org.apache.hadoop.hbase.util.PrettyPrinter.Unit; 039import org.apache.yetus.audience.InterfaceAudience; 040 041import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; 042 043import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 044import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ColumnFamilySchema; 045 046@InterfaceAudience.Public 047public class ColumnFamilyDescriptorBuilder { 048 // For future backward compatibility 049 050 // Version 3 was when column names become byte arrays and when we picked up 051 // Time-to-live feature. Version 4 was when we moved to byte arrays, HBASE-82. 052 // Version 5 was when bloom filter descriptors were removed. 053 // Version 6 adds metadata as a map where keys and values are byte[]. 054 // Version 7 -- add new compression and hfile blocksize to HColumnDescriptor (HBASE-1217) 055 // Version 8 -- reintroduction of bloom filters, changed from boolean to enum 056 // Version 9 -- add data block encoding 057 // Version 10 -- change metadata to standard type. 058 // Version 11 -- add column family level configuration. 059 private static final byte COLUMN_DESCRIPTOR_VERSION = (byte) 11; 060 061 @InterfaceAudience.Private 062 public static final String IN_MEMORY_COMPACTION = "IN_MEMORY_COMPACTION"; 063 private static final Bytes IN_MEMORY_COMPACTION_BYTES = 064 new Bytes(Bytes.toBytes(IN_MEMORY_COMPACTION)); 065 066 @InterfaceAudience.Private 067 public static final String IN_MEMORY = HConstants.IN_MEMORY; 068 private static final Bytes IN_MEMORY_BYTES = new Bytes(Bytes.toBytes(IN_MEMORY)); 069 070 // These constants are used as FileInfo keys 071 @InterfaceAudience.Private 072 public static final String COMPRESSION = "COMPRESSION"; 073 private static final Bytes COMPRESSION_BYTES = new Bytes(Bytes.toBytes(COMPRESSION)); 074 @InterfaceAudience.Private 075 public static final String COMPRESSION_COMPACT = "COMPRESSION_COMPACT"; 076 private static final Bytes COMPRESSION_COMPACT_BYTES = 077 new Bytes(Bytes.toBytes(COMPRESSION_COMPACT)); 078 public static final String COMPRESSION_COMPACT_MAJOR = "COMPRESSION_COMPACT_MAJOR"; 079 private static final Bytes COMPRESSION_COMPACT_MAJOR_BYTES = 080 new Bytes(Bytes.toBytes(COMPRESSION_COMPACT_MAJOR)); 081 public static final String COMPRESSION_COMPACT_MINOR = "COMPRESSION_COMPACT_MINOR"; 082 private static final Bytes COMPRESSION_COMPACT_MINOR_BYTES = 083 new Bytes(Bytes.toBytes(COMPRESSION_COMPACT_MINOR)); 084 @InterfaceAudience.Private 085 public static final String DATA_BLOCK_ENCODING = "DATA_BLOCK_ENCODING"; 086 private static final Bytes DATA_BLOCK_ENCODING_BYTES = 087 new Bytes(Bytes.toBytes(DATA_BLOCK_ENCODING)); 088 @InterfaceAudience.Private 089 public static final String INDEX_BLOCK_ENCODING = "INDEX_BLOCK_ENCODING"; 090 private static final Bytes INDEX_BLOCK_ENCODING_BYTES = 091 new Bytes(Bytes.toBytes(INDEX_BLOCK_ENCODING)); 092 /** 093 * Key for the BLOCKCACHE attribute. A more exact name would be CACHE_DATA_ON_READ because this 094 * flag sets whether or not we cache DATA blocks. We always cache INDEX and BLOOM blocks; caching 095 * these blocks cannot be disabled. 096 */ 097 @InterfaceAudience.Private 098 public static final String BLOCKCACHE = "BLOCKCACHE"; 099 private static final Bytes BLOCKCACHE_BYTES = new Bytes(Bytes.toBytes(BLOCKCACHE)); 100 @InterfaceAudience.Private 101 public static final String CACHE_DATA_ON_WRITE = "CACHE_DATA_ON_WRITE"; 102 private static final Bytes CACHE_DATA_ON_WRITE_BYTES = 103 new Bytes(Bytes.toBytes(CACHE_DATA_ON_WRITE)); 104 @InterfaceAudience.Private 105 public static final String CACHE_INDEX_ON_WRITE = "CACHE_INDEX_ON_WRITE"; 106 private static final Bytes CACHE_INDEX_ON_WRITE_BYTES = 107 new Bytes(Bytes.toBytes(CACHE_INDEX_ON_WRITE)); 108 @InterfaceAudience.Private 109 public static final String CACHE_BLOOMS_ON_WRITE = "CACHE_BLOOMS_ON_WRITE"; 110 private static final Bytes CACHE_BLOOMS_ON_WRITE_BYTES = 111 new Bytes(Bytes.toBytes(CACHE_BLOOMS_ON_WRITE)); 112 @InterfaceAudience.Private 113 public static final String EVICT_BLOCKS_ON_CLOSE = "EVICT_BLOCKS_ON_CLOSE"; 114 private static final Bytes EVICT_BLOCKS_ON_CLOSE_BYTES = 115 new Bytes(Bytes.toBytes(EVICT_BLOCKS_ON_CLOSE)); 116 117 /** 118 * Key for the PREFETCH_BLOCKS_ON_OPEN attribute. If set, all INDEX, BLOOM, and DATA blocks of 119 * HFiles belonging to this family will be loaded into the cache as soon as the file is opened. 120 * These loads will not count as cache misses. 121 */ 122 @InterfaceAudience.Private 123 public static final String PREFETCH_BLOCKS_ON_OPEN = "PREFETCH_BLOCKS_ON_OPEN"; 124 private static final Bytes PREFETCH_BLOCKS_ON_OPEN_BYTES = 125 new Bytes(Bytes.toBytes(PREFETCH_BLOCKS_ON_OPEN)); 126 127 /** 128 * Size of storefile/hfile 'blocks'. Default is {@link #DEFAULT_BLOCKSIZE}. Use smaller block 129 * sizes for faster random-access at expense of larger indices (more memory consumption). Note 130 * that this is a soft limit and that blocks have overhead (metadata, CRCs) so blocks will tend to 131 * be the size specified here and then some; i.e. don't expect that setting BLOCKSIZE=4k means 132 * hbase data will align with an SSDs 4k page accesses (TODO). 133 */ 134 @InterfaceAudience.Private 135 public static final String BLOCKSIZE = "BLOCKSIZE"; 136 private static final Bytes BLOCKSIZE_BYTES = new Bytes(Bytes.toBytes(BLOCKSIZE)); 137 138 @InterfaceAudience.Private 139 public static final String TTL = "TTL"; 140 private static final Bytes TTL_BYTES = new Bytes(Bytes.toBytes(TTL)); 141 @InterfaceAudience.Private 142 public static final String BLOOMFILTER = "BLOOMFILTER"; 143 private static final Bytes BLOOMFILTER_BYTES = new Bytes(Bytes.toBytes(BLOOMFILTER)); 144 @InterfaceAudience.Private 145 public static final String REPLICATION_SCOPE = "REPLICATION_SCOPE"; 146 @InterfaceAudience.Private 147 public static final String MAX_VERSIONS = HConstants.VERSIONS; 148 private static final Bytes MAX_VERSIONS_BYTES = new Bytes(Bytes.toBytes(MAX_VERSIONS)); 149 @InterfaceAudience.Private 150 public static final String MIN_VERSIONS = "MIN_VERSIONS"; 151 private static final Bytes MIN_VERSIONS_BYTES = new Bytes(Bytes.toBytes(MIN_VERSIONS)); 152 /** 153 * Retain all cells across flushes and compactions even if they fall behind a delete tombstone. To 154 * see all retained cells, do a 'raw' scan; see Scan#setRaw or pass RAW => true attribute in 155 * the shell. 156 */ 157 @InterfaceAudience.Private 158 public static final String KEEP_DELETED_CELLS = "KEEP_DELETED_CELLS"; 159 private static final Bytes KEEP_DELETED_CELLS_BYTES = 160 new Bytes(Bytes.toBytes(KEEP_DELETED_CELLS)); 161 @InterfaceAudience.Private 162 public static final String COMPRESS_TAGS = "COMPRESS_TAGS"; 163 private static final Bytes COMPRESS_TAGS_BYTES = new Bytes(Bytes.toBytes(COMPRESS_TAGS)); 164 @InterfaceAudience.Private 165 public static final String ENCRYPTION = "ENCRYPTION"; 166 private static final Bytes ENCRYPTION_BYTES = new Bytes(Bytes.toBytes(ENCRYPTION)); 167 @InterfaceAudience.Private 168 public static final String ENCRYPTION_KEY = "ENCRYPTION_KEY"; 169 private static final Bytes ENCRYPTION_KEY_BYTES = new Bytes(Bytes.toBytes(ENCRYPTION_KEY)); 170 171 private static final boolean DEFAULT_MOB = false; 172 @InterfaceAudience.Private 173 public static final String IS_MOB = "IS_MOB"; 174 private static final Bytes IS_MOB_BYTES = new Bytes(Bytes.toBytes(IS_MOB)); 175 @InterfaceAudience.Private 176 public static final String MOB_THRESHOLD = "MOB_THRESHOLD"; 177 private static final Bytes MOB_THRESHOLD_BYTES = new Bytes(Bytes.toBytes(MOB_THRESHOLD)); 178 public static final long DEFAULT_MOB_THRESHOLD = 100 * 1024; // 100k 179 @InterfaceAudience.Private 180 public static final String MOB_COMPACT_PARTITION_POLICY = "MOB_COMPACT_PARTITION_POLICY"; 181 private static final Bytes MOB_COMPACT_PARTITION_POLICY_BYTES = 182 new Bytes(Bytes.toBytes(MOB_COMPACT_PARTITION_POLICY)); 183 public static final MobCompactPartitionPolicy DEFAULT_MOB_COMPACT_PARTITION_POLICY = 184 MobCompactPartitionPolicy.DAILY; 185 @InterfaceAudience.Private 186 public static final String DFS_REPLICATION = "DFS_REPLICATION"; 187 private static final Bytes DFS_REPLICATION_BYTES = new Bytes(Bytes.toBytes(DFS_REPLICATION)); 188 public static final short DEFAULT_DFS_REPLICATION = 0; 189 @InterfaceAudience.Private 190 public static final String STORAGE_POLICY = "STORAGE_POLICY"; 191 private static final Bytes STORAGE_POLICY_BYTES = new Bytes(Bytes.toBytes(STORAGE_POLICY)); 192 193 public static final String NEW_VERSION_BEHAVIOR = "NEW_VERSION_BEHAVIOR"; 194 private static final Bytes NEW_VERSION_BEHAVIOR_BYTES = 195 new Bytes(Bytes.toBytes(NEW_VERSION_BEHAVIOR)); 196 public static final boolean DEFAULT_NEW_VERSION_BEHAVIOR = false; 197 /** 198 * Default compression type. 199 */ 200 public static final Compression.Algorithm DEFAULT_COMPRESSION = Compression.Algorithm.NONE; 201 202 /** 203 * Default data block encoding algorithm. 204 */ 205 public static final DataBlockEncoding DEFAULT_DATA_BLOCK_ENCODING = DataBlockEncoding.NONE; 206 207 /** 208 * Default index block encoding algorithm. 209 */ 210 public static final IndexBlockEncoding DEFAULT_INDEX_BLOCK_ENCODING = IndexBlockEncoding.NONE; 211 212 /** 213 * Default number of versions of a record to keep. 214 */ 215 public static final int DEFAULT_MAX_VERSIONS = 1; 216 217 /** 218 * Default is not to keep a minimum of versions. 219 */ 220 public static final int DEFAULT_MIN_VERSIONS = 0; 221 222 /** 223 * Default setting for whether to try and serve this column family from memory or not. 224 */ 225 public static final boolean DEFAULT_IN_MEMORY = false; 226 227 /** 228 * Default setting for preventing deleted from being collected immediately. 229 */ 230 public static final KeepDeletedCells DEFAULT_KEEP_DELETED = KeepDeletedCells.FALSE; 231 232 /** 233 * Default setting for whether to use a block cache or not. 234 */ 235 public static final boolean DEFAULT_BLOCKCACHE = true; 236 237 /** 238 * Default setting for whether to cache data blocks on write if block caching is enabled. 239 */ 240 public static final boolean DEFAULT_CACHE_DATA_ON_WRITE = false; 241 242 /** 243 * Default setting for whether to cache index blocks on write if block caching is enabled. 244 */ 245 public static final boolean DEFAULT_CACHE_INDEX_ON_WRITE = false; 246 247 /** 248 * Default size of blocks in files stored to the filesytem (hfiles). 249 */ 250 public static final int DEFAULT_BLOCKSIZE = HConstants.DEFAULT_BLOCKSIZE; 251 252 /** 253 * Default setting for whether or not to use bloomfilters. 254 */ 255 public static final BloomType DEFAULT_BLOOMFILTER = BloomType.ROW; 256 257 /** 258 * Default setting for whether to cache bloom filter blocks on write if block caching is enabled. 259 */ 260 public static final boolean DEFAULT_CACHE_BLOOMS_ON_WRITE = false; 261 262 /** 263 * Default time to live of cell contents. 264 */ 265 public static final int DEFAULT_TTL = HConstants.FOREVER; 266 267 /** 268 * Default scope. 269 */ 270 public static final int DEFAULT_REPLICATION_SCOPE = HConstants.REPLICATION_SCOPE_LOCAL; 271 272 /** 273 * Default setting for whether to evict cached blocks from the blockcache on close. 274 */ 275 public static final boolean DEFAULT_EVICT_BLOCKS_ON_CLOSE = false; 276 277 /** 278 * Default compress tags along with any type of DataBlockEncoding. 279 */ 280 public static final boolean DEFAULT_COMPRESS_TAGS = true; 281 282 /* 283 * Default setting for whether to prefetch blocks into the blockcache on open. 284 */ 285 public static final boolean DEFAULT_PREFETCH_BLOCKS_ON_OPEN = false; 286 287 private final static Map<String, String> DEFAULT_VALUES = new HashMap<>(); 288 289 private static Map<Bytes, Bytes> getDefaultValuesBytes() { 290 Map<Bytes, Bytes> values = new HashMap<>(); 291 DEFAULT_VALUES 292 .forEach((k, v) -> values.put(new Bytes(Bytes.toBytes(k)), new Bytes(Bytes.toBytes(v)))); 293 return values; 294 } 295 296 public static Map<String, String> getDefaultValues() { 297 return Collections.unmodifiableMap(DEFAULT_VALUES); 298 } 299 300 private final static Set<Bytes> RESERVED_KEYWORDS = new HashSet<>(); 301 302 static { 303 DEFAULT_VALUES.put(BLOOMFILTER, DEFAULT_BLOOMFILTER.name()); 304 DEFAULT_VALUES.put(REPLICATION_SCOPE, String.valueOf(DEFAULT_REPLICATION_SCOPE)); 305 DEFAULT_VALUES.put(MAX_VERSIONS, String.valueOf(DEFAULT_MAX_VERSIONS)); 306 DEFAULT_VALUES.put(MIN_VERSIONS, String.valueOf(DEFAULT_MIN_VERSIONS)); 307 DEFAULT_VALUES.put(COMPRESSION, DEFAULT_COMPRESSION.name()); 308 DEFAULT_VALUES.put(TTL, String.valueOf(DEFAULT_TTL)); 309 DEFAULT_VALUES.put(BLOCKSIZE, String.valueOf(DEFAULT_BLOCKSIZE)); 310 DEFAULT_VALUES.put(IN_MEMORY, String.valueOf(DEFAULT_IN_MEMORY)); 311 DEFAULT_VALUES.put(BLOCKCACHE, String.valueOf(DEFAULT_BLOCKCACHE)); 312 DEFAULT_VALUES.put(KEEP_DELETED_CELLS, String.valueOf(DEFAULT_KEEP_DELETED)); 313 DEFAULT_VALUES.put(DATA_BLOCK_ENCODING, String.valueOf(DEFAULT_DATA_BLOCK_ENCODING)); 314 DEFAULT_VALUES.put(INDEX_BLOCK_ENCODING, String.valueOf(DEFAULT_INDEX_BLOCK_ENCODING)); 315 // Do NOT add this key/value by default. NEW_VERSION_BEHAVIOR is NOT defined in hbase1 so 316 // it is not possible to make an hbase1 HCD the same as an hbase2 HCD and so the replication 317 // compare of schemas will fail. It is OK not adding the below to the initial map because of 318 // fetch of this value, we will check for null and if null will return the default. 319 // DEFAULT_VALUES.put(NEW_VERSION_BEHAVIOR, String.valueOf(DEFAULT_NEW_VERSION_BEHAVIOR)); 320 DEFAULT_VALUES.keySet().forEach(s -> RESERVED_KEYWORDS.add(new Bytes(Bytes.toBytes(s)))); 321 RESERVED_KEYWORDS.add(new Bytes(Bytes.toBytes(ENCRYPTION))); 322 RESERVED_KEYWORDS.add(new Bytes(Bytes.toBytes(ENCRYPTION_KEY))); 323 RESERVED_KEYWORDS.add(new Bytes(Bytes.toBytes(IS_MOB))); 324 RESERVED_KEYWORDS.add(new Bytes(Bytes.toBytes(MOB_THRESHOLD))); 325 RESERVED_KEYWORDS.add(new Bytes(Bytes.toBytes(MOB_COMPACT_PARTITION_POLICY))); 326 } 327 328 public static Unit getUnit(String key) { 329 /* TTL for now, we can add more as we need */ 330 switch (key) { 331 case TTL: 332 return Unit.TIME_INTERVAL; 333 case BLOCKSIZE: 334 return Unit.BYTE; 335 default: 336 return Unit.NONE; 337 } 338 } 339 340 /** 341 * Check if the column family name is legal. 342 * @param b Family name. 343 * @return <code>b</code> 344 * @throws IllegalArgumentException If not null and not a legitimate family name: i.e. 'printable' 345 * and ends in a ':' (Null passes are allowed because 346 * <code>b</code> can be null when deserializing). Cannot start 347 * with a '.' either. Also Family can not be an empty value or 348 * equal "recovered.edits". 349 */ 350 public static byte[] isLegalColumnFamilyName(final byte[] b) { 351 if (b == null) { 352 return null; 353 } 354 Preconditions.checkArgument(b.length != 0, "Column Family name can not be empty"); 355 if (b[0] == '.') { 356 throw new IllegalArgumentException( 357 "Column Family names cannot start with a " + "period: " + Bytes.toString(b)); 358 } 359 for (int i = 0; i < b.length; i++) { 360 if (Character.isISOControl(b[i]) || b[i] == ':' || b[i] == '\\' || b[i] == '/') { 361 throw new IllegalArgumentException("Illegal character <" + b[i] 362 + ">. Column Family names cannot contain control characters or colons: " 363 + Bytes.toString(b)); 364 } 365 } 366 byte[] recoveredEdit = Bytes.toBytes(HConstants.RECOVERED_EDITS_DIR); 367 if (Bytes.equals(recoveredEdit, b)) { 368 throw new IllegalArgumentException( 369 "Column Family name cannot be: " + HConstants.RECOVERED_EDITS_DIR); 370 } 371 return b; 372 } 373 374 private final ModifyableColumnFamilyDescriptor desc; 375 376 public static ColumnFamilyDescriptor parseFrom(final byte[] pbBytes) 377 throws DeserializationException { 378 return ModifyableColumnFamilyDescriptor.parseFrom(pbBytes); 379 } 380 381 public static ColumnFamilyDescriptorBuilder newBuilder(final byte[] name) { 382 return new ColumnFamilyDescriptorBuilder(name); 383 } 384 385 public static ColumnFamilyDescriptorBuilder newBuilder(final ColumnFamilyDescriptor desc) { 386 return new ColumnFamilyDescriptorBuilder(desc); 387 } 388 389 public static ColumnFamilyDescriptor copy(ColumnFamilyDescriptor desc) { 390 return new ModifyableColumnFamilyDescriptor(desc); 391 } 392 393 public static ColumnFamilyDescriptor of(String name) { 394 return of(Bytes.toBytes(name)); 395 } 396 397 public static ColumnFamilyDescriptor of(byte[] name) { 398 return newBuilder(name).build(); 399 } 400 401 private ColumnFamilyDescriptorBuilder(final byte[] name) { 402 this.desc = new ModifyableColumnFamilyDescriptor(name); 403 } 404 405 private ColumnFamilyDescriptorBuilder(final ColumnFamilyDescriptor desc) { 406 this.desc = new ModifyableColumnFamilyDescriptor(desc); 407 } 408 409 /** 410 * Serialize the table descriptor to a byte array. 411 * @param desc The table descriptor to serialize 412 * @return This instance serialized with pb with pb magic prefix 413 */ 414 public static byte[] toByteArray(ColumnFamilyDescriptor desc) { 415 if (desc instanceof ModifyableColumnFamilyDescriptor) { 416 return ((ModifyableColumnFamilyDescriptor) desc).toByteArray(); 417 } 418 return new ModifyableColumnFamilyDescriptor(desc).toByteArray(); 419 } 420 421 public ColumnFamilyDescriptor build() { 422 return new ModifyableColumnFamilyDescriptor(desc); 423 } 424 425 public ColumnFamilyDescriptorBuilder removeConfiguration(String key) { 426 desc.removeConfiguration(key); 427 return this; 428 } 429 430 public String getNameAsString() { 431 return desc.getNameAsString(); 432 } 433 434 public ColumnFamilyDescriptorBuilder setBlockCacheEnabled(boolean value) { 435 desc.setBlockCacheEnabled(value); 436 return this; 437 } 438 439 public ColumnFamilyDescriptorBuilder setBlocksize(int value) { 440 desc.setBlocksize(value); 441 return this; 442 } 443 444 public ColumnFamilyDescriptorBuilder setBlocksize(String value) throws HBaseException { 445 desc.setBlocksize(value); 446 return this; 447 } 448 449 public ColumnFamilyDescriptorBuilder setBloomFilterType(final BloomType value) { 450 desc.setBloomFilterType(value); 451 return this; 452 } 453 454 public ColumnFamilyDescriptorBuilder setCacheBloomsOnWrite(boolean value) { 455 desc.setCacheBloomsOnWrite(value); 456 return this; 457 } 458 459 public ColumnFamilyDescriptorBuilder setCacheDataOnWrite(boolean value) { 460 desc.setCacheDataOnWrite(value); 461 return this; 462 } 463 464 public ColumnFamilyDescriptorBuilder setCacheIndexesOnWrite(final boolean value) { 465 desc.setCacheIndexesOnWrite(value); 466 return this; 467 } 468 469 public ColumnFamilyDescriptorBuilder setCompactionCompressionType(Compression.Algorithm value) { 470 desc.setCompactionCompressionType(value); 471 return this; 472 } 473 474 public ColumnFamilyDescriptorBuilder 475 setMajorCompactionCompressionType(Compression.Algorithm value) { 476 desc.setMajorCompactionCompressionType(value); 477 return this; 478 } 479 480 public ColumnFamilyDescriptorBuilder 481 setMinorCompactionCompressionType(Compression.Algorithm value) { 482 desc.setMinorCompactionCompressionType(value); 483 return this; 484 } 485 486 public ColumnFamilyDescriptorBuilder setCompressTags(boolean value) { 487 desc.setCompressTags(value); 488 return this; 489 } 490 491 public ColumnFamilyDescriptorBuilder setCompressionType(Compression.Algorithm value) { 492 desc.setCompressionType(value); 493 return this; 494 } 495 496 public Compression.Algorithm getCompressionType() { 497 return desc.getCompressionType(); 498 } 499 500 public ColumnFamilyDescriptorBuilder setConfiguration(final String key, final String value) { 501 desc.setConfiguration(key, value); 502 return this; 503 } 504 505 public ColumnFamilyDescriptorBuilder setDFSReplication(short value) { 506 desc.setDFSReplication(value); 507 return this; 508 } 509 510 public ColumnFamilyDescriptorBuilder setDataBlockEncoding(DataBlockEncoding value) { 511 desc.setDataBlockEncoding(value); 512 return this; 513 } 514 515 public ColumnFamilyDescriptorBuilder setIndexBlockEncoding(IndexBlockEncoding value) { 516 desc.setIndexBlockEncoding(value); 517 return this; 518 } 519 520 public ColumnFamilyDescriptorBuilder setEncryptionKey(final byte[] value) { 521 desc.setEncryptionKey(value); 522 return this; 523 } 524 525 public ColumnFamilyDescriptorBuilder setEncryptionType(String value) { 526 desc.setEncryptionType(value); 527 return this; 528 } 529 530 public ColumnFamilyDescriptorBuilder setEvictBlocksOnClose(boolean value) { 531 desc.setEvictBlocksOnClose(value); 532 return this; 533 } 534 535 public ColumnFamilyDescriptorBuilder setInMemory(final boolean value) { 536 desc.setInMemory(value); 537 return this; 538 } 539 540 public ColumnFamilyDescriptorBuilder setInMemoryCompaction(final MemoryCompactionPolicy value) { 541 desc.setInMemoryCompaction(value); 542 return this; 543 } 544 545 public ColumnFamilyDescriptorBuilder setKeepDeletedCells(KeepDeletedCells value) { 546 desc.setKeepDeletedCells(value); 547 return this; 548 } 549 550 public ColumnFamilyDescriptorBuilder setMaxVersions(final int value) { 551 desc.setMaxVersions(value); 552 return this; 553 } 554 555 public ColumnFamilyDescriptorBuilder setMinVersions(final int value) { 556 desc.setMinVersions(value); 557 return this; 558 } 559 560 public ColumnFamilyDescriptorBuilder 561 setMobCompactPartitionPolicy(final MobCompactPartitionPolicy value) { 562 desc.setMobCompactPartitionPolicy(value); 563 return this; 564 } 565 566 public ColumnFamilyDescriptorBuilder setMobEnabled(final boolean value) { 567 desc.setMobEnabled(value); 568 return this; 569 } 570 571 public ColumnFamilyDescriptorBuilder setMobThreshold(final long value) { 572 desc.setMobThreshold(value); 573 return this; 574 } 575 576 public ColumnFamilyDescriptorBuilder setPrefetchBlocksOnOpen(final boolean value) { 577 desc.setPrefetchBlocksOnOpen(value); 578 return this; 579 } 580 581 public ColumnFamilyDescriptorBuilder setScope(final int value) { 582 desc.setScope(value); 583 return this; 584 } 585 586 public ColumnFamilyDescriptorBuilder setStoragePolicy(final String value) { 587 desc.setStoragePolicy(value); 588 return this; 589 } 590 591 public ColumnFamilyDescriptorBuilder setTimeToLive(final int value) { 592 desc.setTimeToLive(value); 593 return this; 594 } 595 596 public ColumnFamilyDescriptorBuilder setTimeToLive(final String value) throws HBaseException { 597 desc.setTimeToLive(value); 598 return this; 599 } 600 601 public ColumnFamilyDescriptorBuilder setNewVersionBehavior(final boolean value) { 602 desc.setNewVersionBehavior(value); 603 return this; 604 } 605 606 public ColumnFamilyDescriptorBuilder setValue(final Bytes key, final Bytes value) { 607 desc.setValue(key, value); 608 return this; 609 } 610 611 public ColumnFamilyDescriptorBuilder setValue(final byte[] key, final byte[] value) { 612 desc.setValue(key, value); 613 return this; 614 } 615 616 public ColumnFamilyDescriptorBuilder setValue(final String key, final String value) { 617 desc.setValue(key, value); 618 return this; 619 } 620 621 public ColumnFamilyDescriptorBuilder setVersionsWithTimeToLive(final int retentionInterval, 622 final int versionAfterInterval) { 623 desc.setVersionsWithTimeToLive(retentionInterval, versionAfterInterval); 624 return this; 625 } 626 627 /** 628 * An ModifyableFamilyDescriptor contains information about a column family such as the number of 629 * versions, compression settings, etc. It is used as input when creating a table or adding a 630 * column. 631 */ 632 private static final class ModifyableColumnFamilyDescriptor 633 implements ColumnFamilyDescriptor, Comparable<ModifyableColumnFamilyDescriptor> { 634 635 // Column family name 636 private final byte[] name; 637 638 // Column metadata 639 private final Map<Bytes, Bytes> values = new HashMap<>(); 640 641 /** 642 * A map which holds the configuration specific to the column family. The keys of the map have 643 * the same names as config keys and override the defaults with cf-specific settings. Example 644 * usage may be for compactions, etc. 645 */ 646 private final Map<String, String> configuration = new HashMap<>(); 647 648 /** 649 * Construct a column descriptor specifying only the family name The other attributes are 650 * defaulted. 651 * @param name Column family name. Must be 'printable' -- digit or letter -- and may not contain 652 * a <code>:</code> TODO: make this private after the HCD is removed. 653 */ 654 @InterfaceAudience.Private 655 public ModifyableColumnFamilyDescriptor(final byte[] name) { 656 this(isLegalColumnFamilyName(name), getDefaultValuesBytes(), Collections.emptyMap()); 657 } 658 659 /** 660 * Constructor. Makes a deep copy of the supplied descriptor. TODO: make this private after the 661 * HCD is removed. 662 * @param desc The descriptor. 663 */ 664 @InterfaceAudience.Private 665 public ModifyableColumnFamilyDescriptor(ColumnFamilyDescriptor desc) { 666 this(desc.getName(), desc.getValues(), desc.getConfiguration()); 667 } 668 669 private ModifyableColumnFamilyDescriptor(byte[] name, Map<Bytes, Bytes> values, 670 Map<String, String> config) { 671 this.name = name; 672 this.values.putAll(values); 673 this.configuration.putAll(config); 674 } 675 676 @Override 677 public byte[] getName() { 678 return Bytes.copy(name); 679 } 680 681 @Override 682 public String getNameAsString() { 683 return Bytes.toString(name); 684 } 685 686 @Override 687 public Bytes getValue(Bytes key) { 688 return values.get(key); 689 } 690 691 @Override 692 public byte[] getValue(byte[] key) { 693 Bytes value = values.get(new Bytes(key)); 694 return value == null ? null : value.get(); 695 } 696 697 @Override 698 public String getValue(String key) { 699 Bytes rval = values.get(new Bytes(Bytes.toBytes(key))); 700 return rval == null ? null : Bytes.toString(rval.get(), rval.getOffset(), rval.getLength()); 701 } 702 703 @Override 704 public Map<Bytes, Bytes> getValues() { 705 return Collections.unmodifiableMap(values); 706 } 707 708 public ModifyableColumnFamilyDescriptor setValue(byte[] key, byte[] value) { 709 return setValue(toBytesOrNull(key, Function.identity()), 710 toBytesOrNull(value, Function.identity())); 711 } 712 713 public ModifyableColumnFamilyDescriptor setValue(String key, String value) { 714 return setValue(toBytesOrNull(key, Bytes::toBytes), toBytesOrNull(value, Bytes::toBytes)); 715 } 716 717 private ModifyableColumnFamilyDescriptor setValue(Bytes key, String value) { 718 return setValue(key, toBytesOrNull(value, Bytes::toBytes)); 719 } 720 721 private ModifyableColumnFamilyDescriptor setValue(Bytes key, Bytes value) { 722 if (value == null || value.getLength() == 0) { 723 values.remove(key); 724 } else { 725 values.put(key, value); 726 } 727 return this; 728 } 729 730 private static <T> Bytes toBytesOrNull(T t, Function<T, byte[]> f) { 731 if (t == null) { 732 return null; 733 } else { 734 return new Bytes(f.apply(t)); 735 } 736 } 737 738 private <T> T getStringOrDefault(Bytes key, Function<String, T> function, T defaultValue) { 739 return getOrDefault(key, b -> function.apply(Bytes.toString(b)), defaultValue); 740 } 741 742 private <T> T getOrDefault(Bytes key, Function<byte[], T> function, T defaultValue) { 743 Bytes value = values.get(key); 744 if (value == null) { 745 return defaultValue; 746 } else { 747 return function.apply(value.get()); 748 } 749 } 750 751 @Override 752 public int getMaxVersions() { 753 return getStringOrDefault(MAX_VERSIONS_BYTES, Integer::parseInt, DEFAULT_MAX_VERSIONS); 754 } 755 756 /** 757 * Set the maximum number of versions to retain. 758 * @param maxVersions maximum number of versions 759 * @return this (for chained invocation) 760 */ 761 public ModifyableColumnFamilyDescriptor setMaxVersions(int maxVersions) { 762 if (maxVersions <= 0) { 763 // TODO: Allow maxVersion of 0 to be the way you say "Keep all versions". 764 // Until there is support, consider 0 or < 0 -- a configuration error. 765 throw new IllegalArgumentException("Maximum versions must be positive"); 766 } 767 if (maxVersions < this.getMinVersions()) { 768 throw new IllegalArgumentException( 769 "Set MaxVersion to " + maxVersions + " while minVersion is " + this.getMinVersions() 770 + ". Maximum versions must be >= minimum versions "); 771 } 772 setValue(MAX_VERSIONS_BYTES, Integer.toString(maxVersions)); 773 return this; 774 } 775 776 /** 777 * Set minimum and maximum versions to keep. 778 * @param minVersions minimal number of versions 779 * @param maxVersions maximum number of versions 780 * @return this (for chained invocation) 781 */ 782 public ModifyableColumnFamilyDescriptor setVersions(int minVersions, int maxVersions) { 783 if (minVersions <= 0) { 784 // TODO: Allow minVersion and maxVersion of 0 to be the way you say "Keep all versions". 785 // Until there is support, consider 0 or < 0 -- a configuration error. 786 throw new IllegalArgumentException("Minimum versions must be positive"); 787 } 788 789 if (maxVersions < minVersions) { 790 throw new IllegalArgumentException( 791 "Unable to set MaxVersion to " + maxVersions + " and set MinVersion to " + minVersions 792 + ", as maximum versions must be >= minimum versions."); 793 } 794 setMinVersions(minVersions); 795 setMaxVersions(maxVersions); 796 return this; 797 } 798 799 @Override 800 public int getBlocksize() { 801 return getStringOrDefault(BLOCKSIZE_BYTES, Integer::valueOf, DEFAULT_BLOCKSIZE); 802 } 803 804 public ModifyableColumnFamilyDescriptor setBlocksize(int s) { 805 return setValue(BLOCKSIZE_BYTES, Integer.toString(s)); 806 } 807 808 public ModifyableColumnFamilyDescriptor setBlocksize(String blocksize) throws HBaseException { 809 return setBlocksize( 810 Integer.parseInt(PrettyPrinter.valueOf(blocksize, PrettyPrinter.Unit.BYTE))); 811 } 812 813 @Override 814 public Compression.Algorithm getCompressionType() { 815 return getStringOrDefault(COMPRESSION_BYTES, 816 n -> Compression.Algorithm.valueOf(n.toUpperCase()), DEFAULT_COMPRESSION); 817 } 818 819 /** 820 * Compression types supported in hbase. LZO is not bundled as part of the hbase distribution. 821 * See See <a href="http://hbase.apache.org/book.html#lzo.compression">LZO Compression</a> for 822 * how to enable it. 823 * @param type Compression type setting. 824 * @return this (for chained invocation) 825 */ 826 public ModifyableColumnFamilyDescriptor setCompressionType(Compression.Algorithm type) { 827 return setValue(COMPRESSION_BYTES, type.name()); 828 } 829 830 @Override 831 public DataBlockEncoding getDataBlockEncoding() { 832 return getStringOrDefault(DATA_BLOCK_ENCODING_BYTES, 833 n -> DataBlockEncoding.valueOf(n.toUpperCase()), DataBlockEncoding.NONE); 834 } 835 836 /** 837 * Set data block encoding algorithm used in block cache. 838 * @param type What kind of data block encoding will be used. 839 * @return this (for chained invocation) 840 */ 841 public ModifyableColumnFamilyDescriptor setDataBlockEncoding(DataBlockEncoding type) { 842 return setValue(DATA_BLOCK_ENCODING_BYTES, 843 type == null ? DataBlockEncoding.NONE.name() : type.name()); 844 } 845 846 @Override 847 public IndexBlockEncoding getIndexBlockEncoding() { 848 return getStringOrDefault(INDEX_BLOCK_ENCODING_BYTES, 849 n -> IndexBlockEncoding.valueOf(n.toUpperCase()), IndexBlockEncoding.NONE); 850 } 851 852 /** 853 * Set index block encoding algorithm used in block cache. 854 * @param type What kind of index block encoding will be used. 855 * @return this (for chained invocation) 856 */ 857 public ModifyableColumnFamilyDescriptor setIndexBlockEncoding(IndexBlockEncoding type) { 858 return setValue(INDEX_BLOCK_ENCODING_BYTES, 859 type == null ? IndexBlockEncoding.NONE.name() : type.name()); 860 } 861 862 /** 863 * Set whether the tags should be compressed along with DataBlockEncoding. When no 864 * DataBlockEncoding is been used, this is having no effect. 865 * @return this (for chained invocation) 866 */ 867 public ModifyableColumnFamilyDescriptor setCompressTags(boolean compressTags) { 868 return setValue(COMPRESS_TAGS_BYTES, String.valueOf(compressTags)); 869 } 870 871 @Override 872 public boolean isCompressTags() { 873 return getStringOrDefault(COMPRESS_TAGS_BYTES, Boolean::valueOf, DEFAULT_COMPRESS_TAGS); 874 } 875 876 @Override 877 public Compression.Algorithm getCompactionCompressionType() { 878 return getStringOrDefault(COMPRESSION_COMPACT_BYTES, 879 n -> Compression.Algorithm.valueOf(n.toUpperCase()), getCompressionType()); 880 } 881 882 @Override 883 public Compression.Algorithm getMajorCompactionCompressionType() { 884 return getStringOrDefault(COMPRESSION_COMPACT_MAJOR_BYTES, 885 n -> Compression.Algorithm.valueOf(n.toUpperCase()), getCompactionCompressionType()); 886 } 887 888 @Override 889 public Compression.Algorithm getMinorCompactionCompressionType() { 890 return getStringOrDefault(COMPRESSION_COMPACT_MINOR_BYTES, 891 n -> Compression.Algorithm.valueOf(n.toUpperCase()), getCompactionCompressionType()); 892 } 893 894 /** 895 * Compression types supported in hbase. LZO is not bundled as part of the hbase distribution. 896 * See See <a href="http://hbase.apache.org/book.html#lzo.compression">LZO Compression</a> for 897 * how to enable it. 898 * @param type Compression type setting. 899 * @return this (for chained invocation) 900 */ 901 public ModifyableColumnFamilyDescriptor 902 setCompactionCompressionType(Compression.Algorithm type) { 903 return setValue(COMPRESSION_COMPACT_BYTES, type.name()); 904 } 905 906 public ModifyableColumnFamilyDescriptor 907 setMajorCompactionCompressionType(Compression.Algorithm type) { 908 return setValue(COMPRESSION_COMPACT_MAJOR_BYTES, type.name()); 909 } 910 911 public ModifyableColumnFamilyDescriptor 912 setMinorCompactionCompressionType(Compression.Algorithm type) { 913 return setValue(COMPRESSION_COMPACT_MINOR_BYTES, type.name()); 914 } 915 916 @Override 917 public boolean isInMemory() { 918 return getStringOrDefault(IN_MEMORY_BYTES, Boolean::valueOf, DEFAULT_IN_MEMORY); 919 } 920 921 /** 922 * Set the inMemory flag 923 * @param inMemory True if we are to favor keeping all values for this column family in the 924 * HRegionServer cache 925 * @return this (for chained invocation) 926 */ 927 public ModifyableColumnFamilyDescriptor setInMemory(boolean inMemory) { 928 return setValue(IN_MEMORY_BYTES, Boolean.toString(inMemory)); 929 } 930 931 @Override 932 public MemoryCompactionPolicy getInMemoryCompaction() { 933 return getStringOrDefault(IN_MEMORY_COMPACTION_BYTES, 934 n -> MemoryCompactionPolicy.valueOf(n.toUpperCase()), null); 935 } 936 937 public ModifyableColumnFamilyDescriptor 938 setInMemoryCompaction(MemoryCompactionPolicy inMemoryCompaction) { 939 return setValue(IN_MEMORY_COMPACTION_BYTES, inMemoryCompaction.name()); 940 } 941 942 @Override 943 public KeepDeletedCells getKeepDeletedCells() { 944 return getStringOrDefault(KEEP_DELETED_CELLS_BYTES, KeepDeletedCells::getValue, 945 DEFAULT_KEEP_DELETED); 946 } 947 948 public ModifyableColumnFamilyDescriptor setKeepDeletedCells(KeepDeletedCells keepDeletedCells) { 949 return setValue(KEEP_DELETED_CELLS_BYTES, keepDeletedCells.name()); 950 } 951 952 /** 953 * By default, HBase only consider timestamp in versions. So a previous Delete with higher ts 954 * will mask a later Put with lower ts. Set this to true to enable new semantics of versions. We 955 * will also consider mvcc in versions. See HBASE-15968 for details. 956 */ 957 @Override 958 public boolean isNewVersionBehavior() { 959 return getStringOrDefault(NEW_VERSION_BEHAVIOR_BYTES, Boolean::parseBoolean, 960 DEFAULT_NEW_VERSION_BEHAVIOR); 961 } 962 963 public ModifyableColumnFamilyDescriptor setNewVersionBehavior(boolean newVersionBehavior) { 964 return setValue(NEW_VERSION_BEHAVIOR_BYTES, Boolean.toString(newVersionBehavior)); 965 } 966 967 @Override 968 public int getTimeToLive() { 969 return getStringOrDefault(TTL_BYTES, Integer::parseInt, DEFAULT_TTL); 970 } 971 972 /** 973 * Set the time to live 974 * @param timeToLive Time-to-live of cell contents, in seconds. 975 * @return this (for chained invocation) 976 */ 977 public ModifyableColumnFamilyDescriptor setTimeToLive(int timeToLive) { 978 return setValue(TTL_BYTES, Integer.toString(timeToLive)); 979 } 980 981 /** 982 * Set the time to live 983 * @param timeToLive Time-to-live of cell contents, in seconds. 984 * @return this (for chained invocation) 985 * @throws org.apache.hadoop.hbase.exceptions.HBaseException exception 986 */ 987 public ModifyableColumnFamilyDescriptor setTimeToLive(String timeToLive) throws HBaseException { 988 return setTimeToLive(Integer.parseInt(PrettyPrinter.valueOf(timeToLive, Unit.TIME_INTERVAL))); 989 } 990 991 @Override 992 public int getMinVersions() { 993 return getStringOrDefault(MIN_VERSIONS_BYTES, Integer::valueOf, DEFAULT_MIN_VERSIONS); 994 } 995 996 /** 997 * Set minimum versions to retain. 998 * @param minVersions The minimum number of versions to keep. (used when timeToLive is set) 999 * @return this (for chained invocation) 1000 */ 1001 public ModifyableColumnFamilyDescriptor setMinVersions(int minVersions) { 1002 return setValue(MIN_VERSIONS_BYTES, Integer.toString(minVersions)); 1003 } 1004 1005 /** 1006 * Retain all versions for a given TTL(retentionInterval), and then only a specific number of 1007 * versions(versionAfterInterval) after that interval elapses. 1008 * @param retentionInterval Retain all versions for this interval 1009 * @param versionAfterInterval Retain no of versions to retain after retentionInterval 1010 * @return this (for chained invocation) 1011 */ 1012 public ModifyableColumnFamilyDescriptor setVersionsWithTimeToLive(final int retentionInterval, 1013 final int versionAfterInterval) { 1014 ModifyableColumnFamilyDescriptor modifyableColumnFamilyDescriptor = 1015 setVersions(versionAfterInterval, Integer.MAX_VALUE); 1016 modifyableColumnFamilyDescriptor.setTimeToLive(retentionInterval); 1017 modifyableColumnFamilyDescriptor.setKeepDeletedCells(KeepDeletedCells.TTL); 1018 return modifyableColumnFamilyDescriptor; 1019 } 1020 1021 @Override 1022 public boolean isBlockCacheEnabled() { 1023 return getStringOrDefault(BLOCKCACHE_BYTES, Boolean::valueOf, DEFAULT_BLOCKCACHE); 1024 } 1025 1026 /** 1027 * Set the blockCacheEnabled flag 1028 * @param blockCacheEnabled True if hfile DATA type blocks should be cached (We always cache 1029 * INDEX and BLOOM blocks; you cannot turn this off). 1030 * @return this (for chained invocation) 1031 */ 1032 public ModifyableColumnFamilyDescriptor setBlockCacheEnabled(boolean blockCacheEnabled) { 1033 return setValue(BLOCKCACHE_BYTES, Boolean.toString(blockCacheEnabled)); 1034 } 1035 1036 @Override 1037 public BloomType getBloomFilterType() { 1038 return getStringOrDefault(BLOOMFILTER_BYTES, n -> BloomType.valueOf(n.toUpperCase()), 1039 DEFAULT_BLOOMFILTER); 1040 } 1041 1042 public ModifyableColumnFamilyDescriptor setBloomFilterType(final BloomType bt) { 1043 return setValue(BLOOMFILTER_BYTES, bt.name()); 1044 } 1045 1046 @Override 1047 public int getScope() { 1048 return getStringOrDefault(REPLICATION_SCOPE_BYTES, Integer::valueOf, 1049 DEFAULT_REPLICATION_SCOPE); 1050 } 1051 1052 public ModifyableColumnFamilyDescriptor setScope(int scope) { 1053 return setValue(REPLICATION_SCOPE_BYTES, Integer.toString(scope)); 1054 } 1055 1056 @Override 1057 public boolean isCacheDataOnWrite() { 1058 return getStringOrDefault(CACHE_DATA_ON_WRITE_BYTES, Boolean::valueOf, 1059 DEFAULT_CACHE_DATA_ON_WRITE); 1060 } 1061 1062 /** 1063 * Set the setCacheDataOnWrite flag 1064 * @param value true if we should cache data blocks on write 1065 * @return this (for chained invocation) 1066 */ 1067 public ModifyableColumnFamilyDescriptor setCacheDataOnWrite(boolean value) { 1068 return setValue(CACHE_DATA_ON_WRITE_BYTES, Boolean.toString(value)); 1069 } 1070 1071 @Override 1072 public boolean isCacheIndexesOnWrite() { 1073 return getStringOrDefault(CACHE_INDEX_ON_WRITE_BYTES, Boolean::valueOf, 1074 DEFAULT_CACHE_INDEX_ON_WRITE); 1075 } 1076 1077 /** 1078 * Set the setCacheIndexesOnWrite flag 1079 * @param value true if we should cache index blocks on write 1080 * @return this (for chained invocation) 1081 */ 1082 public ModifyableColumnFamilyDescriptor setCacheIndexesOnWrite(boolean value) { 1083 return setValue(CACHE_INDEX_ON_WRITE_BYTES, Boolean.toString(value)); 1084 } 1085 1086 @Override 1087 public boolean isCacheBloomsOnWrite() { 1088 return getStringOrDefault(CACHE_BLOOMS_ON_WRITE_BYTES, Boolean::valueOf, 1089 DEFAULT_CACHE_BLOOMS_ON_WRITE); 1090 } 1091 1092 /** 1093 * Set the setCacheBloomsOnWrite flag. 1094 * @param value true if we should cache bloomfilter blocks on write 1095 * @return this (for chained invocation) 1096 */ 1097 public ModifyableColumnFamilyDescriptor setCacheBloomsOnWrite(boolean value) { 1098 return setValue(CACHE_BLOOMS_ON_WRITE_BYTES, Boolean.toString(value)); 1099 } 1100 1101 @Override 1102 public boolean isEvictBlocksOnClose() { 1103 return getStringOrDefault(EVICT_BLOCKS_ON_CLOSE_BYTES, Boolean::valueOf, 1104 DEFAULT_EVICT_BLOCKS_ON_CLOSE); 1105 } 1106 1107 /** 1108 * Set the setEvictBlocksOnClose flag. 1109 * @param value true if we should evict cached blocks from the blockcache on close 1110 * @return this (for chained invocation) 1111 */ 1112 public ModifyableColumnFamilyDescriptor setEvictBlocksOnClose(boolean value) { 1113 return setValue(EVICT_BLOCKS_ON_CLOSE_BYTES, Boolean.toString(value)); 1114 } 1115 1116 @Override 1117 public boolean isPrefetchBlocksOnOpen() { 1118 return getStringOrDefault(PREFETCH_BLOCKS_ON_OPEN_BYTES, Boolean::valueOf, 1119 DEFAULT_PREFETCH_BLOCKS_ON_OPEN); 1120 } 1121 1122 /** 1123 * Set the setPrefetchBlocksOnOpen flag 1124 * @param value true if we should prefetch blocks into the blockcache on open 1125 * @return this (for chained invocation) 1126 */ 1127 public ModifyableColumnFamilyDescriptor setPrefetchBlocksOnOpen(boolean value) { 1128 return setValue(PREFETCH_BLOCKS_ON_OPEN_BYTES, Boolean.toString(value)); 1129 } 1130 1131 @Override 1132 public String toString() { 1133 StringBuilder s = new StringBuilder(); 1134 s.append('{'); 1135 s.append(HConstants.NAME); 1136 s.append(" => '"); 1137 s.append(getNameAsString()); 1138 s.append("'"); 1139 s.append(getValues(true)); 1140 s.append('}'); 1141 return s.toString(); 1142 } 1143 1144 @Override 1145 public String toStringCustomizedValues() { 1146 StringBuilder s = new StringBuilder(); 1147 s.append('{'); 1148 s.append(HConstants.NAME); 1149 s.append(" => '"); 1150 s.append(getNameAsString()); 1151 s.append("'"); 1152 s.append(getValues(false)); 1153 s.append('}'); 1154 return s.toString(); 1155 } 1156 1157 private StringBuilder getValues(boolean printDefaults) { 1158 StringBuilder s = new StringBuilder(); 1159 1160 boolean hasConfigKeys = false; 1161 1162 // print all reserved keys first 1163 for (Map.Entry<Bytes, Bytes> entry : values.entrySet()) { 1164 if (!RESERVED_KEYWORDS.contains(entry.getKey())) { 1165 hasConfigKeys = true; 1166 continue; 1167 } 1168 String key = Bytes.toString(entry.getKey().get()); 1169 String value = Bytes.toStringBinary(entry.getValue().get()); 1170 if ( 1171 printDefaults || !DEFAULT_VALUES.containsKey(key) 1172 || !DEFAULT_VALUES.get(key).equalsIgnoreCase(value) 1173 ) { 1174 s.append(", "); 1175 s.append(key); 1176 s.append(" => "); 1177 s.append('\'').append(PrettyPrinter.format(value, getUnit(key))).append('\''); 1178 } 1179 } 1180 1181 // print all non-reserved, advanced config keys as a separate subset 1182 if (hasConfigKeys) { 1183 s.append(", "); 1184 s.append(HConstants.METADATA).append(" => "); 1185 s.append('{'); 1186 boolean printComma = false; 1187 for (Map.Entry<Bytes, Bytes> entry : values.entrySet()) { 1188 Bytes k = entry.getKey(); 1189 if (RESERVED_KEYWORDS.contains(k)) { 1190 continue; 1191 } 1192 String key = Bytes.toString(k.get()); 1193 String value = Bytes.toStringBinary(entry.getValue().get()); 1194 if (printComma) { 1195 s.append(", "); 1196 } 1197 printComma = true; 1198 s.append('\'').append(key).append('\''); 1199 s.append(" => "); 1200 s.append('\'').append(PrettyPrinter.format(value, getUnit(key))).append('\''); 1201 } 1202 s.append('}'); 1203 } 1204 1205 if (!configuration.isEmpty()) { 1206 s.append(", "); 1207 s.append(HConstants.CONFIGURATION).append(" => "); 1208 s.append('{'); 1209 boolean printCommaForConfiguration = false; 1210 for (Map.Entry<String, String> e : configuration.entrySet()) { 1211 if (printCommaForConfiguration) { 1212 s.append(", "); 1213 } 1214 printCommaForConfiguration = true; 1215 s.append('\'').append(e.getKey()).append('\''); 1216 s.append(" => "); 1217 s.append('\'').append(PrettyPrinter.format(e.getValue(), getUnit(e.getKey()))) 1218 .append('\''); 1219 } 1220 s.append("}"); 1221 } 1222 return s; 1223 } 1224 1225 @Override 1226 public boolean equals(Object obj) { 1227 if (this == obj) { 1228 return true; 1229 } 1230 if (obj instanceof ModifyableColumnFamilyDescriptor) { 1231 return ColumnFamilyDescriptor.COMPARATOR.compare(this, 1232 (ModifyableColumnFamilyDescriptor) obj) == 0; 1233 } 1234 return false; 1235 } 1236 1237 @Override 1238 public int hashCode() { 1239 int result = Bytes.hashCode(name); 1240 result ^= (int) COLUMN_DESCRIPTOR_VERSION; 1241 result ^= values.hashCode(); 1242 result ^= configuration.hashCode(); 1243 return result; 1244 } 1245 1246 @Override 1247 public int compareTo(ModifyableColumnFamilyDescriptor other) { 1248 return COMPARATOR.compare(this, other); 1249 } 1250 1251 /** Returns This instance serialized with pb with pb magic prefix */ 1252 private byte[] toByteArray() { 1253 return ProtobufUtil.prependPBMagic(ProtobufUtil.toColumnFamilySchema(this).toByteArray()); 1254 } 1255 1256 /** 1257 * Parse the serialized representation of a {@link ModifyableColumnFamilyDescriptor} 1258 * @param bytes A pb serialized {@link ModifyableColumnFamilyDescriptor} instance with pb magic 1259 * prefix 1260 * @return An instance of {@link ModifyableColumnFamilyDescriptor} made from <code>bytes</code> 1261 * @see #toByteArray() 1262 */ 1263 private static ColumnFamilyDescriptor parseFrom(final byte[] bytes) 1264 throws DeserializationException { 1265 if (!ProtobufUtil.isPBMagicPrefix(bytes)) { 1266 throw new DeserializationException("No magic"); 1267 } 1268 int pblen = ProtobufUtil.lengthOfPBMagic(); 1269 ColumnFamilySchema.Builder builder = ColumnFamilySchema.newBuilder(); 1270 ColumnFamilySchema cfs = null; 1271 try { 1272 ProtobufUtil.mergeFrom(builder, bytes, pblen, bytes.length - pblen); 1273 cfs = builder.build(); 1274 } catch (IOException e) { 1275 throw new DeserializationException(e); 1276 } 1277 return ProtobufUtil.toColumnFamilyDescriptor(cfs); 1278 } 1279 1280 @Override 1281 public String getConfigurationValue(String key) { 1282 return configuration.get(key); 1283 } 1284 1285 @Override 1286 public Map<String, String> getConfiguration() { 1287 // shallow pointer copy 1288 return Collections.unmodifiableMap(configuration); 1289 } 1290 1291 /** 1292 * Setter for storing a configuration setting in {@link #configuration} map. 1293 * @param key Config key. Same as XML config key e.g. hbase.something.or.other. 1294 * @param value String value. If null, removes the configuration. 1295 * @return this (for chained invocation) 1296 */ 1297 public ModifyableColumnFamilyDescriptor setConfiguration(String key, String value) { 1298 if (value == null || value.length() == 0) { 1299 configuration.remove(key); 1300 } else { 1301 configuration.put(key, value); 1302 } 1303 return this; 1304 } 1305 1306 /** 1307 * Remove a configuration setting represented by the key from the {@link #configuration} map. 1308 * @return this (for chained invocation) 1309 */ 1310 public ModifyableColumnFamilyDescriptor removeConfiguration(final String key) { 1311 return setConfiguration(key, null); 1312 } 1313 1314 @Override 1315 public String getEncryptionType() { 1316 return getStringOrDefault(ENCRYPTION_BYTES, Function.identity(), null); 1317 } 1318 1319 /** 1320 * Set the encryption algorithm for use with this family 1321 * @return this (for chained invocation) 1322 */ 1323 public ModifyableColumnFamilyDescriptor setEncryptionType(String algorithm) { 1324 return setValue(ENCRYPTION_BYTES, algorithm); 1325 } 1326 1327 @Override 1328 public byte[] getEncryptionKey() { 1329 return getOrDefault(ENCRYPTION_KEY_BYTES, Bytes::copy, null); 1330 } 1331 1332 /** 1333 * Set the raw crypto key attribute for the family 1334 * @return this (for chained invocation) 1335 */ 1336 public ModifyableColumnFamilyDescriptor setEncryptionKey(byte[] keyBytes) { 1337 return setValue(ENCRYPTION_KEY_BYTES, new Bytes(keyBytes)); 1338 } 1339 1340 @Override 1341 public long getMobThreshold() { 1342 return getStringOrDefault(MOB_THRESHOLD_BYTES, Long::valueOf, DEFAULT_MOB_THRESHOLD); 1343 } 1344 1345 /** 1346 * Sets the mob threshold of the family. 1347 * @param threshold The mob threshold. 1348 * @return this (for chained invocation) 1349 */ 1350 public ModifyableColumnFamilyDescriptor setMobThreshold(long threshold) { 1351 return setValue(MOB_THRESHOLD_BYTES, String.valueOf(threshold)); 1352 } 1353 1354 @Override 1355 public boolean isMobEnabled() { 1356 return getStringOrDefault(IS_MOB_BYTES, Boolean::valueOf, DEFAULT_MOB); 1357 } 1358 1359 /** 1360 * Enables the mob for the family. 1361 * @param isMobEnabled Whether to enable the mob for the family. 1362 * @return this (for chained invocation) 1363 */ 1364 public ModifyableColumnFamilyDescriptor setMobEnabled(boolean isMobEnabled) { 1365 return setValue(IS_MOB_BYTES, String.valueOf(isMobEnabled)); 1366 } 1367 1368 @Override 1369 public MobCompactPartitionPolicy getMobCompactPartitionPolicy() { 1370 return getStringOrDefault(MOB_COMPACT_PARTITION_POLICY_BYTES, 1371 n -> MobCompactPartitionPolicy.valueOf(n.toUpperCase()), 1372 DEFAULT_MOB_COMPACT_PARTITION_POLICY); 1373 } 1374 1375 /** 1376 * Set the mob compact partition policy for the family. 1377 * @param policy policy type 1378 * @return this (for chained invocation) 1379 */ 1380 public ModifyableColumnFamilyDescriptor 1381 setMobCompactPartitionPolicy(MobCompactPartitionPolicy policy) { 1382 return setValue(MOB_COMPACT_PARTITION_POLICY_BYTES, policy.name()); 1383 } 1384 1385 @Override 1386 public short getDFSReplication() { 1387 return getStringOrDefault(DFS_REPLICATION_BYTES, Short::valueOf, DEFAULT_DFS_REPLICATION); 1388 } 1389 1390 /** 1391 * Set the replication factor to hfile(s) belonging to this family 1392 * @param replication number of replicas the blocks(s) belonging to this CF should have, or 1393 * {@link #DEFAULT_DFS_REPLICATION} for the default replication factor set in 1394 * the filesystem 1395 * @return this (for chained invocation) 1396 */ 1397 public ModifyableColumnFamilyDescriptor setDFSReplication(short replication) { 1398 if (replication < 1 && replication != DEFAULT_DFS_REPLICATION) { 1399 throw new IllegalArgumentException( 1400 "DFS replication factor cannot be less than 1 if explicitly set."); 1401 } 1402 return setValue(DFS_REPLICATION_BYTES, Short.toString(replication)); 1403 } 1404 1405 @Override 1406 public String getStoragePolicy() { 1407 return getStringOrDefault(STORAGE_POLICY_BYTES, Function.identity(), null); 1408 } 1409 1410 /** 1411 * Set the storage policy for use with this family 1412 * @param policy the policy to set, valid setting includes: <i>"LAZY_PERSIST"</i>, 1413 * <i>"ALL_SSD"</i>, <i>"ONE_SSD"</i>, <i>"HOT"</i>, <i>"WARM"</i>, <i>"COLD"</i> 1414 * @return this (for chained invocation) 1415 */ 1416 public ModifyableColumnFamilyDescriptor setStoragePolicy(String policy) { 1417 return setValue(STORAGE_POLICY_BYTES, policy); 1418 } 1419 1420 } 1421}