001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.client; 020 021import java.util.Collections; 022import java.util.Map; 023import java.util.Set; 024import java.util.TreeMap; 025import java.util.TreeSet; 026 027import org.apache.hadoop.hbase.util.Bytes; 028import org.apache.yetus.audience.InterfaceAudience; 029 030import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; 031 032@InterfaceAudience.Public 033public final class TableDescriptorUtils { 034 public final static class TableDescriptorDelta { 035 private final Set<byte[]> columnsAdded; 036 private final Set<byte[]> columnsDeleted; 037 private final Set<byte[]> columnsModified; 038 039 private TableDescriptorDelta(TableDescriptor oldTD, TableDescriptor newTD) { 040 Preconditions.checkNotNull(oldTD); 041 Preconditions.checkNotNull(newTD); 042 043 Map<byte[], ColumnFamilyDescriptor> oldCFs = new TreeMap<>(Bytes.BYTES_COMPARATOR); 044 Set<byte[]> newCFs = new TreeSet<>(Bytes.BYTES_COMPARATOR); 045 046 // CFD -> (name, CFD) 047 for (ColumnFamilyDescriptor cfd : oldTD.getColumnFamilies()) { 048 oldCFs.put(cfd.getName(), cfd); 049 } 050 051 Set<byte[]> added = new TreeSet<>(Bytes.BYTES_COMPARATOR); 052 Set<byte[]> modified = new TreeSet<>(Bytes.BYTES_COMPARATOR); 053 054 for (ColumnFamilyDescriptor cfd : newTD.getColumnFamilies()) { 055 byte[] cfName = cfd.getName(); 056 newCFs.add(cfName); 057 058 if (!oldCFs.containsKey(cfName)) { 059 // If column family is in newTD but not oldTD, then it was added 060 added.add(cfName); 061 } else if (!cfd.equals(oldCFs.get(cfName))) { 062 // If column family is in both, but not equal, then it was modified 063 modified.add(cfName); 064 } 065 } 066 067 // If column family is in oldTD, but not in newTD, then it got deleted. 068 Set<byte[]> deleted = oldCFs.keySet(); 069 deleted.removeAll(newCFs); 070 071 columnsAdded = Collections.unmodifiableSet(added); 072 columnsDeleted = Collections.unmodifiableSet(deleted); 073 columnsModified = Collections.unmodifiableSet(modified); 074 } 075 076 public Set<byte[]> getColumnsAdded() { 077 return columnsAdded; 078 } 079 080 public Set<byte[]> getColumnsDeleted() { 081 return columnsDeleted; 082 } 083 084 public Set<byte[]> getColumnsModified() { 085 return columnsModified; 086 } 087 } 088 089 private TableDescriptorUtils() { } 090 091 /** 092 * Compares two {@link TableDescriptor} and indicate which columns were added, deleted, 093 * or modified from oldTD to newTD 094 * @return a TableDescriptorDelta that contains the added/deleted/modified column names 095 */ 096 public static TableDescriptorDelta computeDelta(TableDescriptor oldTD, TableDescriptor newTD) { 097 return new TableDescriptorDelta(oldTD, newTD); 098 } 099}