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