@Override protected void updateMeta(final byte[] oldRegion1, final byte[] oldRegion2, HRegion newRegion) throws IOException { byte[][] regionsToDelete = {oldRegion1, oldRegion2}; for (int r = 0; r < regionsToDelete.length; r++) { Delete delete = new Delete(regionsToDelete[r]); delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER); delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER); delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER); delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.SPLITA_QUALIFIER); delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.SPLITB_QUALIFIER); root.delete(delete, null, true); if (LOG.isDebugEnabled()) { LOG.debug("updated columns in row: " + Bytes.toStringBinary(regionsToDelete[r])); } } HRegionInfo newInfo = newRegion.getRegionInfo(); newInfo.setOffline(true); Put put = new Put(newRegion.getRegionName()); put.add( HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, Writables.getBytes(newInfo)); root.put(put); if (LOG.isDebugEnabled()) { LOG.debug("updated columns in row: " + Bytes.toStringBinary(newRegion.getRegionName())); } }
@Override protected void updateMeta(final byte[] oldRegion1, final byte[] oldRegion2, HRegion newRegion) throws IOException { byte[][] regionsToDelete = {oldRegion1, oldRegion2}; for (int r = 0; r < regionsToDelete.length; r++) { if (Bytes.equals(regionsToDelete[r], latestRegion.getRegionName())) { latestRegion = null; } Delete delete = new Delete(regionsToDelete[r]); table.delete(delete); if (LOG.isDebugEnabled()) { LOG.debug("updated columns in row: " + Bytes.toStringBinary(regionsToDelete[r])); } } newRegion.getRegionInfo().setOffline(true); Put put = new Put(newRegion.getRegionName()); put.add( HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, Writables.getBytes(newRegion.getRegionInfo())); table.put(put); if (LOG.isDebugEnabled()) { LOG.debug("updated columns in row: " + Bytes.toStringBinary(newRegion.getRegionName())); } }
protected boolean merge(final HRegionInfo[] info) throws IOException { if (info.length < 2) { LOG.info("only one region - nothing to merge"); return false; } HRegion currentRegion = null; long currentSize = 0; HRegion nextRegion = null; long nextSize = 0; for (int i = 0; i < info.length - 1; i++) { if (currentRegion == null) { currentRegion = HRegion.newHRegion(tabledir, hlog, fs, conf, info[i], this.htd, null); currentRegion.initialize(); currentSize = currentRegion.getLargestHStoreSize(); } nextRegion = HRegion.newHRegion(tabledir, hlog, fs, conf, info[i + 1], this.htd, null); nextRegion.initialize(); nextSize = nextRegion.getLargestHStoreSize(); if ((currentSize + nextSize) <= (maxFilesize / 2)) { // We merge two adjacent regions if their total size is less than // one half of the desired maximum size LOG.info( "Merging regions " + currentRegion.getRegionNameAsString() + " and " + nextRegion.getRegionNameAsString()); HRegion mergedRegion = HRegion.mergeAdjacent(currentRegion, nextRegion); updateMeta(currentRegion.getRegionName(), nextRegion.getRegionName(), mergedRegion); break; } LOG.info( "not merging regions " + Bytes.toStringBinary(currentRegion.getRegionName()) + " and " + Bytes.toStringBinary(nextRegion.getRegionName())); currentRegion.close(); currentRegion = nextRegion; currentSize = nextSize; } if (currentRegion != null) { currentRegion.close(); } return true; }
/** * Unfortunately, the easiest way to test this is to spin up a mini-cluster since we want to do * the usual compaction mechanism on the region, rather than going through the backdoor to the * region */ @Test public void testRegionObserverCompactionTimeStacking() throws Exception { // setup a mini cluster so we can do a real compaction on a region Configuration conf = UTIL.getConfiguration(); conf.setClass(HConstants.REGION_IMPL, CompactionCompletionNotifyingRegion.class, HRegion.class); conf.setInt("hbase.hstore.compaction.min", 2); UTIL.startMiniCluster(); String tableName = "testRegionObserverCompactionTimeStacking"; byte[] ROW = Bytes.toBytes("testRow"); byte[] A = Bytes.toBytes("A"); HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName)); desc.addFamily(new HColumnDescriptor(A)); desc.addCoprocessor(EmptyRegionObsever.class.getName(), null, Coprocessor.PRIORITY_USER, null); desc.addCoprocessor( NoDataFromCompaction.class.getName(), null, Coprocessor.PRIORITY_HIGHEST, null); Admin admin = UTIL.getHBaseAdmin(); admin.createTable(desc); Table table = UTIL.getConnection().getTable(desc.getTableName()); // put a row and flush it to disk Put put = new Put(ROW); put.add(A, A, A); table.put(put); HRegionServer rs = UTIL.getRSForFirstRegionInTable(desc.getTableName()); List<HRegion> regions = rs.getOnlineRegions(desc.getTableName()); assertEquals("More than 1 region serving test table with 1 row", 1, regions.size()); HRegion region = regions.get(0); admin.flushRegion(region.getRegionName()); CountDownLatch latch = ((CompactionCompletionNotifyingRegion) region).getCompactionStateChangeLatch(); // put another row and flush that too put = new Put(Bytes.toBytes("anotherrow")); put.add(A, A, A); table.put(put); admin.flushRegion(region.getRegionName()); // run a compaction, which normally would should get rid of the data // wait for the compaction checker to complete latch.await(); // check both rows to ensure that they aren't there Get get = new Get(ROW); Result r = table.get(get); assertNull( "Got an unexpected number of rows - no data should be returned with the NoDataFromScan coprocessor. Found: " + r, r.listCells()); get = new Get(Bytes.toBytes("anotherrow")); r = table.get(get); assertNull( "Got an unexpected number of rows - no data should be returned with the NoDataFromScan coprocessor Found: " + r, r.listCells()); table.close(); UTIL.shutdownMiniCluster(); }