@Test public void testBulkFileCheck() { MetadataConstraints mc = new TestMetadataConstraints(); Mutation m; List<Short> violations; m = new Mutation(new Text("0;foo")); m.put(BulkFileColumnFamily.NAME, new Text("/someFile"), new Value("12345")); m.put(DataFileColumnFamily.NAME, new Text("/someFile"), new DataFileValue(1, 1).encodeAsValue()); violations = mc.check(createEnv(), m); assertNotNull(violations); assertEquals(1, violations.size()); assertEquals(Short.valueOf((short) 8), violations.get(0)); m = new Mutation(new Text("0;foo")); m.put(BulkFileColumnFamily.NAME, new Text("/someFile"), new Value("9")); m.put(DataFileColumnFamily.NAME, new Text("/someFile"), new DataFileValue(1, 1).encodeAsValue()); violations = mc.check(createEnv(), m); assertNotNull(violations); assertEquals(1, violations.size()); assertEquals(Short.valueOf((short) 8), violations.get(0)); m = new Mutation(new Text("0;foo")); m.put(BulkFileColumnFamily.NAME, new Text("/someFile"), new Value("5")); m.put(DataFileColumnFamily.NAME, new Text("/someFile"), new DataFileValue(1, 1).encodeAsValue()); violations = mc.check(createEnv(), m); assertNull(violations); m = new Mutation(new Text("0;foo")); m.put(BulkFileColumnFamily.NAME, new Text("/someFile"), new Value("5")); violations = mc.check(createEnv(), m); assertNotNull(violations); assertEquals(1, violations.size()); assertEquals(Short.valueOf((short) 8), violations.get(0)); m = new Mutation(new Text("0;foo")); m.put(BulkFileColumnFamily.NAME, new Text("/someFile"), new Value("5")); m.put(DataFileColumnFamily.NAME, new Text("/someFile"), new DataFileValue(1, 1).encodeAsValue()); m.put(BulkFileColumnFamily.NAME, new Text("/someFile2"), new Value("7")); m.put(DataFileColumnFamily.NAME, new Text("/someFile2"), new DataFileValue(1, 1).encodeAsValue()); violations = mc.check(createEnv(), m); assertNotNull(violations); assertEquals(1, violations.size()); assertEquals(Short.valueOf((short) 8), violations.get(0)); m = new Mutation(new Text("0;foo")); m.put(BulkFileColumnFamily.NAME, new Text("/someFile"), new Value("5")); m.put(DataFileColumnFamily.NAME, new Text("/someFile"), new DataFileValue(1, 1).encodeAsValue()); m.put(BulkFileColumnFamily.NAME, new Text("/someFile2"), new Value("5")); m.put(DataFileColumnFamily.NAME, new Text("/someFile2"), new DataFileValue(1, 1).encodeAsValue()); violations = mc.check(createEnv(), m); assertNull(violations); m = new Mutation(new Text("0;foo")); m.put(BulkFileColumnFamily.NAME, new Text("/someFile"), new Value("5")); m.put(DataFileColumnFamily.NAME, new Text("/someFile"), new DataFileValue(1, 1).encodeAsValue()); m.put(BulkFileColumnFamily.NAME, new Text("/someFile2"), new Value("5")); violations = mc.check(createEnv(), m); assertNotNull(violations); assertEquals(1, violations.size()); assertEquals(Short.valueOf((short) 8), violations.get(0)); m = new Mutation(new Text("0;foo")); m.put(BulkFileColumnFamily.NAME, new Text("/someFile"), new Value("5")); ServerColumnFamily.DIRECTORY_COLUMN.put(m, new Value("/t1")); violations = mc.check(createEnv(), m); assertNull(violations); m = new Mutation(new Text("0;foo")); m.put(BulkFileColumnFamily.NAME, new Text("/someFile"), new Value("12345")); ServerColumnFamily.DIRECTORY_COLUMN.put(m, new Value("/t1")); violations = mc.check(createEnv(), m); assertNull(violations); m = new Mutation(new Text("0;foo")); m.put(BulkFileColumnFamily.NAME, new Text("/someFile"), new Value("5")); m.put(CurrentLocationColumnFamily.NAME, new Text("789"), new Value("127.0.0.1:9997")); violations = mc.check(createEnv(), m); assertNull(violations); m = new Mutation(new Text("0;foo")); m.put(BulkFileColumnFamily.NAME, new Text("/someFile"), new Value("12345")); m.put(CurrentLocationColumnFamily.NAME, new Text("789"), new Value("127.0.0.1:9997")); violations = mc.check(createEnv(), m); assertNull(violations); m = new Mutation(new Text("0;foo")); m.putDelete(BulkFileColumnFamily.NAME, new Text("/someFile")); violations = mc.check(createEnv(), m); assertNull(violations); }
@Override public List<Short> check(Environment env, Mutation mutation) { final ServerContext context = ((SystemEnvironment) env).getServerContext(); ArrayList<Short> violations = null; Collection<ColumnUpdate> colUpdates = mutation.getUpdates(); boolean containsSemiC = false; byte[] row = mutation.getRow(); if (row.length > 0 && row[0] == '~') return null; if (row.length > 2 && row[0] == '!' && row[1] == '!' && row[2] == '~') return null; for (byte b : row) { if (b == ';') { containsSemiC = true; } if (b == ';' || b == '<') break; if (!validTableNameChars[0xff & b]) { violations = addIfNotPresent(violations, 4); } } if (containsSemiC) { if (row.length == 0) { violations = addIfNotPresent(violations, 4); } } else { if (row.length == 0 || row[row.length - 1] != '<') { violations = addIfNotPresent(violations, 4); } } if (row.length > 0 && row[0] == '!') { if (row.length < 3 || row[1] != '0' || (row[2] != '<' && row[2] != ';')) { violations = addIfNotPresent(violations, 4); } } if (new Text(row).compareTo(new Text(MetadataTable.ID.canonical())) < 0) { violations = addViolation(violations, 5); } boolean checkedBulk = false; for (ColumnUpdate columnUpdate : colUpdates) { Text columnFamily = new Text(columnUpdate.getColumnFamily()); if (columnUpdate.isDeleted()) { if (!isValidColumn(columnUpdate)) { violations = addViolation(violations, 2); } continue; } if (columnUpdate.getValue().length == 0 && !columnFamily.equals(ScanFileColumnFamily.NAME)) { violations = addViolation(violations, 6); } if (columnFamily.equals(DataFileColumnFamily.NAME)) { try { DataFileValue dfv = new DataFileValue(columnUpdate.getValue()); if (dfv.getSize() < 0 || dfv.getNumEntries() < 0) { violations = addViolation(violations, 1); } } catch (NumberFormatException | ArrayIndexOutOfBoundsException nfe) { violations = addViolation(violations, 1); } } else if (columnFamily.equals(ScanFileColumnFamily.NAME)) { } else if (columnFamily.equals(BulkFileColumnFamily.NAME)) { if (!columnUpdate.isDeleted() && !checkedBulk) { boolean isSplitMutation = false; boolean isLocationMutation = false; HashSet<Text> dataFiles = new HashSet<>(); HashSet<Text> loadedFiles = new HashSet<>(); String tidString = new String(columnUpdate.getValue(), UTF_8); int otherTidCount = 0; for (ColumnUpdate update : mutation.getUpdates()) { if (new ColumnFQ(update).equals(ServerColumnFamily.DIRECTORY_COLUMN)) { isSplitMutation = true; } else if (new Text(update.getColumnFamily()) .equals(CurrentLocationColumnFamily.NAME)) { isLocationMutation = true; } else if (new Text(update.getColumnFamily()).equals(DataFileColumnFamily.NAME)) { dataFiles.add(new Text(update.getColumnQualifier())); } else if (new Text(update.getColumnFamily()).equals(BulkFileColumnFamily.NAME)) { loadedFiles.add(new Text(update.getColumnQualifier())); if (!new String(update.getValue(), UTF_8).equals(tidString)) { otherTidCount++; } } } if (!isSplitMutation && !isLocationMutation) { long tid = BulkFileColumnFamily.getBulkLoadTid(new Value(tidString)); try { if (otherTidCount > 0 || !dataFiles.equals(loadedFiles) || !getArbitrator(context) .transactionAlive(Constants.BULK_ARBITRATOR_TYPE, tid)) { violations = addViolation(violations, 8); } } catch (Exception ex) { violations = addViolation(violations, 8); } } checkedBulk = true; } } else { if (!isValidColumn(columnUpdate)) { violations = addViolation(violations, 2); } else if (new ColumnFQ(columnUpdate).equals(TabletColumnFamily.PREV_ROW_COLUMN) && columnUpdate.getValue().length > 0 && (violations == null || !violations.contains((short) 4))) { KeyExtent ke = KeyExtent.fromMetaRow(new Text(mutation.getRow())); Text per = TabletColumnFamily.decodePrevEndRow(new Value(columnUpdate.getValue())); boolean prevEndRowLessThanEndRow = per == null || ke.endRow() == null || per.compareTo(ke.endRow()) < 0; if (!prevEndRowLessThanEndRow) { violations = addViolation(violations, 3); } } else if (new ColumnFQ(columnUpdate).equals(ServerColumnFamily.LOCK_COLUMN)) { if (zooCache == null) { zooCache = new ZooCache(context.getZooReaderWriter(), null); CleanerUtil.zooCacheClearer(this, zooCache); } if (zooRoot == null) { zooRoot = context.getZooKeeperRoot(); } boolean lockHeld = false; String lockId = new String(columnUpdate.getValue(), UTF_8); try { lockHeld = ZooLock.isLockHeld(zooCache, new ZooUtil.LockID(zooRoot, lockId)); } catch (Exception e) { log.debug("Failed to verify lock was held {} {}", lockId, e.getMessage()); } if (!lockHeld) { violations = addViolation(violations, 7); } } } } if (violations != null) { log.debug("violating metadata mutation : {}", new String(mutation.getRow(), UTF_8)); for (ColumnUpdate update : mutation.getUpdates()) { log.debug(" update: {}:{} value {}", new String(update.getColumnFamily(), UTF_8), new String(update.getColumnQualifier(), UTF_8), (update.isDeleted() ? "[delete]" : new String(update.getValue(), UTF_8))); } } return violations; }
MetadataConstraints implements Constraint { @Override public List<Short> check(Environment env, Mutation mutation) { final ServerContext context = ((SystemEnvironment) env).getServerContext(); ArrayList<Short> violations = null; Collection<ColumnUpdate> colUpdates = mutation.getUpdates(); boolean containsSemiC = false; byte[] row = mutation.getRow(); if (row.length > 0 && row[0] == '~') return null; if (row.length > 2 && row[0] == '!' && row[1] == '!' && row[2] == '~') return null; for (byte b : row) { if (b == ';') { containsSemiC = true; } if (b == ';' || b == '<') break; if (!validTableNameChars[0xff & b]) { violations = addIfNotPresent(violations, 4); } } if (containsSemiC) { if (row.length == 0) { violations = addIfNotPresent(violations, 4); } } else { if (row.length == 0 || row[row.length - 1] != '<') { violations = addIfNotPresent(violations, 4); } } if (row.length > 0 && row[0] == '!') { if (row.length < 3 || row[1] != '0' || (row[2] != '<' && row[2] != ';')) { violations = addIfNotPresent(violations, 4); } } if (new Text(row).compareTo(new Text(MetadataTable.ID.canonical())) < 0) { violations = addViolation(violations, 5); } boolean checkedBulk = false; for (ColumnUpdate columnUpdate : colUpdates) { Text columnFamily = new Text(columnUpdate.getColumnFamily()); if (columnUpdate.isDeleted()) { if (!isValidColumn(columnUpdate)) { violations = addViolation(violations, 2); } continue; } if (columnUpdate.getValue().length == 0 && !columnFamily.equals(ScanFileColumnFamily.NAME)) { violations = addViolation(violations, 6); } if (columnFamily.equals(DataFileColumnFamily.NAME)) { try { DataFileValue dfv = new DataFileValue(columnUpdate.getValue()); if (dfv.getSize() < 0 || dfv.getNumEntries() < 0) { violations = addViolation(violations, 1); } } catch (NumberFormatException | ArrayIndexOutOfBoundsException nfe) { violations = addViolation(violations, 1); } } else if (columnFamily.equals(ScanFileColumnFamily.NAME)) { } else if (columnFamily.equals(BulkFileColumnFamily.NAME)) { if (!columnUpdate.isDeleted() && !checkedBulk) { boolean isSplitMutation = false; boolean isLocationMutation = false; HashSet<Text> dataFiles = new HashSet<>(); HashSet<Text> loadedFiles = new HashSet<>(); String tidString = new String(columnUpdate.getValue(), UTF_8); int otherTidCount = 0; for (ColumnUpdate update : mutation.getUpdates()) { if (new ColumnFQ(update).equals(ServerColumnFamily.DIRECTORY_COLUMN)) { isSplitMutation = true; } else if (new Text(update.getColumnFamily()) .equals(CurrentLocationColumnFamily.NAME)) { isLocationMutation = true; } else if (new Text(update.getColumnFamily()).equals(DataFileColumnFamily.NAME)) { dataFiles.add(new Text(update.getColumnQualifier())); } else if (new Text(update.getColumnFamily()).equals(BulkFileColumnFamily.NAME)) { loadedFiles.add(new Text(update.getColumnQualifier())); if (!new String(update.getValue(), UTF_8).equals(tidString)) { otherTidCount++; } } } if (!isSplitMutation && !isLocationMutation) { long tid = BulkFileColumnFamily.getBulkLoadTid(new Value(tidString)); try { if (otherTidCount > 0 || !dataFiles.equals(loadedFiles) || !getArbitrator(context) .transactionAlive(Constants.BULK_ARBITRATOR_TYPE, tid)) { violations = addViolation(violations, 8); } } catch (Exception ex) { violations = addViolation(violations, 8); } } checkedBulk = true; } } else { if (!isValidColumn(columnUpdate)) { violations = addViolation(violations, 2); } else if (new ColumnFQ(columnUpdate).equals(TabletColumnFamily.PREV_ROW_COLUMN) && columnUpdate.getValue().length > 0 && (violations == null || !violations.contains((short) 4))) { KeyExtent ke = KeyExtent.fromMetaRow(new Text(mutation.getRow())); Text per = TabletColumnFamily.decodePrevEndRow(new Value(columnUpdate.getValue())); boolean prevEndRowLessThanEndRow = per == null || ke.endRow() == null || per.compareTo(ke.endRow()) < 0; if (!prevEndRowLessThanEndRow) { violations = addViolation(violations, 3); } } else if (new ColumnFQ(columnUpdate).equals(ServerColumnFamily.LOCK_COLUMN)) { if (zooCache == null) { zooCache = new ZooCache(context.getZooReaderWriter(), null); CleanerUtil.zooCacheClearer(this, zooCache); } if (zooRoot == null) { zooRoot = context.getZooKeeperRoot(); } boolean lockHeld = false; String lockId = new String(columnUpdate.getValue(), UTF_8); try { lockHeld = ZooLock.isLockHeld(zooCache, new ZooUtil.LockID(zooRoot, lockId)); } catch (Exception e) { log.debug("Failed to verify lock was held {} {}", lockId, e.getMessage()); } if (!lockHeld) { violations = addViolation(violations, 7); } } } } if (violations != null) { log.debug("violating metadata mutation : {}", new String(mutation.getRow(), UTF_8)); for (ColumnUpdate update : mutation.getUpdates()) { log.debug(" update: {}:{} value {}", new String(update.getColumnFamily(), UTF_8), new String(update.getColumnQualifier(), UTF_8), (update.isDeleted() ? "[delete]" : new String(update.getValue(), UTF_8))); } } return violations; } }
MetadataConstraints implements Constraint { @Override public List<Short> check(Environment env, Mutation mutation) { final ServerContext context = ((SystemEnvironment) env).getServerContext(); ArrayList<Short> violations = null; Collection<ColumnUpdate> colUpdates = mutation.getUpdates(); boolean containsSemiC = false; byte[] row = mutation.getRow(); if (row.length > 0 && row[0] == '~') return null; if (row.length > 2 && row[0] == '!' && row[1] == '!' && row[2] == '~') return null; for (byte b : row) { if (b == ';') { containsSemiC = true; } if (b == ';' || b == '<') break; if (!validTableNameChars[0xff & b]) { violations = addIfNotPresent(violations, 4); } } if (containsSemiC) { if (row.length == 0) { violations = addIfNotPresent(violations, 4); } } else { if (row.length == 0 || row[row.length - 1] != '<') { violations = addIfNotPresent(violations, 4); } } if (row.length > 0 && row[0] == '!') { if (row.length < 3 || row[1] != '0' || (row[2] != '<' && row[2] != ';')) { violations = addIfNotPresent(violations, 4); } } if (new Text(row).compareTo(new Text(MetadataTable.ID.canonical())) < 0) { violations = addViolation(violations, 5); } boolean checkedBulk = false; for (ColumnUpdate columnUpdate : colUpdates) { Text columnFamily = new Text(columnUpdate.getColumnFamily()); if (columnUpdate.isDeleted()) { if (!isValidColumn(columnUpdate)) { violations = addViolation(violations, 2); } continue; } if (columnUpdate.getValue().length == 0 && !columnFamily.equals(ScanFileColumnFamily.NAME)) { violations = addViolation(violations, 6); } if (columnFamily.equals(DataFileColumnFamily.NAME)) { try { DataFileValue dfv = new DataFileValue(columnUpdate.getValue()); if (dfv.getSize() < 0 || dfv.getNumEntries() < 0) { violations = addViolation(violations, 1); } } catch (NumberFormatException | ArrayIndexOutOfBoundsException nfe) { violations = addViolation(violations, 1); } } else if (columnFamily.equals(ScanFileColumnFamily.NAME)) { } else if (columnFamily.equals(BulkFileColumnFamily.NAME)) { if (!columnUpdate.isDeleted() && !checkedBulk) { boolean isSplitMutation = false; boolean isLocationMutation = false; HashSet<Text> dataFiles = new HashSet<>(); HashSet<Text> loadedFiles = new HashSet<>(); String tidString = new String(columnUpdate.getValue(), UTF_8); int otherTidCount = 0; for (ColumnUpdate update : mutation.getUpdates()) { if (new ColumnFQ(update).equals(ServerColumnFamily.DIRECTORY_COLUMN)) { isSplitMutation = true; } else if (new Text(update.getColumnFamily()) .equals(CurrentLocationColumnFamily.NAME)) { isLocationMutation = true; } else if (new Text(update.getColumnFamily()).equals(DataFileColumnFamily.NAME)) { dataFiles.add(new Text(update.getColumnQualifier())); } else if (new Text(update.getColumnFamily()).equals(BulkFileColumnFamily.NAME)) { loadedFiles.add(new Text(update.getColumnQualifier())); if (!new String(update.getValue(), UTF_8).equals(tidString)) { otherTidCount++; } } } if (!isSplitMutation && !isLocationMutation) { long tid = BulkFileColumnFamily.getBulkLoadTid(new Value(tidString)); try { if (otherTidCount > 0 || !dataFiles.equals(loadedFiles) || !getArbitrator(context) .transactionAlive(Constants.BULK_ARBITRATOR_TYPE, tid)) { violations = addViolation(violations, 8); } } catch (Exception ex) { violations = addViolation(violations, 8); } } checkedBulk = true; } } else { if (!isValidColumn(columnUpdate)) { violations = addViolation(violations, 2); } else if (new ColumnFQ(columnUpdate).equals(TabletColumnFamily.PREV_ROW_COLUMN) && columnUpdate.getValue().length > 0 && (violations == null || !violations.contains((short) 4))) { KeyExtent ke = KeyExtent.fromMetaRow(new Text(mutation.getRow())); Text per = TabletColumnFamily.decodePrevEndRow(new Value(columnUpdate.getValue())); boolean prevEndRowLessThanEndRow = per == null || ke.endRow() == null || per.compareTo(ke.endRow()) < 0; if (!prevEndRowLessThanEndRow) { violations = addViolation(violations, 3); } } else if (new ColumnFQ(columnUpdate).equals(ServerColumnFamily.LOCK_COLUMN)) { if (zooCache == null) { zooCache = new ZooCache(context.getZooReaderWriter(), null); CleanerUtil.zooCacheClearer(this, zooCache); } if (zooRoot == null) { zooRoot = context.getZooKeeperRoot(); } boolean lockHeld = false; String lockId = new String(columnUpdate.getValue(), UTF_8); try { lockHeld = ZooLock.isLockHeld(zooCache, new ZooUtil.LockID(zooRoot, lockId)); } catch (Exception e) { log.debug("Failed to verify lock was held {} {}", lockId, e.getMessage()); } if (!lockHeld) { violations = addViolation(violations, 7); } } } } if (violations != null) { log.debug("violating metadata mutation : {}", new String(mutation.getRow(), UTF_8)); for (ColumnUpdate update : mutation.getUpdates()) { log.debug(" update: {}:{} value {}", new String(update.getColumnFamily(), UTF_8), new String(update.getColumnQualifier(), UTF_8), (update.isDeleted() ? "[delete]" : new String(update.getValue(), UTF_8))); } } return violations; }  }
MetadataConstraints implements Constraint { @Override public List<Short> check(Environment env, Mutation mutation) { final ServerContext context = ((SystemEnvironment) env).getServerContext(); ArrayList<Short> violations = null; Collection<ColumnUpdate> colUpdates = mutation.getUpdates(); boolean containsSemiC = false; byte[] row = mutation.getRow(); if (row.length > 0 && row[0] == '~') return null; if (row.length > 2 && row[0] == '!' && row[1] == '!' && row[2] == '~') return null; for (byte b : row) { if (b == ';') { containsSemiC = true; } if (b == ';' || b == '<') break; if (!validTableNameChars[0xff & b]) { violations = addIfNotPresent(violations, 4); } } if (containsSemiC) { if (row.length == 0) { violations = addIfNotPresent(violations, 4); } } else { if (row.length == 0 || row[row.length - 1] != '<') { violations = addIfNotPresent(violations, 4); } } if (row.length > 0 && row[0] == '!') { if (row.length < 3 || row[1] != '0' || (row[2] != '<' && row[2] != ';')) { violations = addIfNotPresent(violations, 4); } } if (new Text(row).compareTo(new Text(MetadataTable.ID.canonical())) < 0) { violations = addViolation(violations, 5); } boolean checkedBulk = false; for (ColumnUpdate columnUpdate : colUpdates) { Text columnFamily = new Text(columnUpdate.getColumnFamily()); if (columnUpdate.isDeleted()) { if (!isValidColumn(columnUpdate)) { violations = addViolation(violations, 2); } continue; } if (columnUpdate.getValue().length == 0 && !columnFamily.equals(ScanFileColumnFamily.NAME)) { violations = addViolation(violations, 6); } if (columnFamily.equals(DataFileColumnFamily.NAME)) { try { DataFileValue dfv = new DataFileValue(columnUpdate.getValue()); if (dfv.getSize() < 0 || dfv.getNumEntries() < 0) { violations = addViolation(violations, 1); } } catch (NumberFormatException | ArrayIndexOutOfBoundsException nfe) { violations = addViolation(violations, 1); } } else if (columnFamily.equals(ScanFileColumnFamily.NAME)) { } else if (columnFamily.equals(BulkFileColumnFamily.NAME)) { if (!columnUpdate.isDeleted() && !checkedBulk) { boolean isSplitMutation = false; boolean isLocationMutation = false; HashSet<Text> dataFiles = new HashSet<>(); HashSet<Text> loadedFiles = new HashSet<>(); String tidString = new String(columnUpdate.getValue(), UTF_8); int otherTidCount = 0; for (ColumnUpdate update : mutation.getUpdates()) { if (new ColumnFQ(update).equals(ServerColumnFamily.DIRECTORY_COLUMN)) { isSplitMutation = true; } else if (new Text(update.getColumnFamily()) .equals(CurrentLocationColumnFamily.NAME)) { isLocationMutation = true; } else if (new Text(update.getColumnFamily()).equals(DataFileColumnFamily.NAME)) { dataFiles.add(new Text(update.getColumnQualifier())); } else if (new Text(update.getColumnFamily()).equals(BulkFileColumnFamily.NAME)) { loadedFiles.add(new Text(update.getColumnQualifier())); if (!new String(update.getValue(), UTF_8).equals(tidString)) { otherTidCount++; } } } if (!isSplitMutation && !isLocationMutation) { long tid = BulkFileColumnFamily.getBulkLoadTid(new Value(tidString)); try { if (otherTidCount > 0 || !dataFiles.equals(loadedFiles) || !getArbitrator(context) .transactionAlive(Constants.BULK_ARBITRATOR_TYPE, tid)) { violations = addViolation(violations, 8); } } catch (Exception ex) { violations = addViolation(violations, 8); } } checkedBulk = true; } } else { if (!isValidColumn(columnUpdate)) { violations = addViolation(violations, 2); } else if (new ColumnFQ(columnUpdate).equals(TabletColumnFamily.PREV_ROW_COLUMN) && columnUpdate.getValue().length > 0 && (violations == null || !violations.contains((short) 4))) { KeyExtent ke = KeyExtent.fromMetaRow(new Text(mutation.getRow())); Text per = TabletColumnFamily.decodePrevEndRow(new Value(columnUpdate.getValue())); boolean prevEndRowLessThanEndRow = per == null || ke.endRow() == null || per.compareTo(ke.endRow()) < 0; if (!prevEndRowLessThanEndRow) { violations = addViolation(violations, 3); } } else if (new ColumnFQ(columnUpdate).equals(ServerColumnFamily.LOCK_COLUMN)) { if (zooCache == null) { zooCache = new ZooCache(context.getZooReaderWriter(), null); CleanerUtil.zooCacheClearer(this, zooCache); } if (zooRoot == null) { zooRoot = context.getZooKeeperRoot(); } boolean lockHeld = false; String lockId = new String(columnUpdate.getValue(), UTF_8); try { lockHeld = ZooLock.isLockHeld(zooCache, new ZooUtil.LockID(zooRoot, lockId)); } catch (Exception e) { log.debug("Failed to verify lock was held {} {}", lockId, e.getMessage()); } if (!lockHeld) { violations = addViolation(violations, 7); } } } } if (violations != null) { log.debug("violating metadata mutation : {}", new String(mutation.getRow(), UTF_8)); for (ColumnUpdate update : mutation.getUpdates()) { log.debug(" update: {}:{} value {}", new String(update.getColumnFamily(), UTF_8), new String(update.getColumnQualifier(), UTF_8), (update.isDeleted() ? "[delete]" : new String(update.getValue(), UTF_8))); } } return violations; }  @Override List<Short> check(Environment env, Mutation mutation); @Override String getViolationDescription(short violationCode); }
MetadataConstraints implements Constraint { @Override public List<Short> check(Environment env, Mutation mutation) { final ServerContext context = ((SystemEnvironment) env).getServerContext(); ArrayList<Short> violations = null; Collection<ColumnUpdate> colUpdates = mutation.getUpdates(); boolean containsSemiC = false; byte[] row = mutation.getRow(); if (row.length > 0 && row[0] == '~') return null; if (row.length > 2 && row[0] == '!' && row[1] == '!' && row[2] == '~') return null; for (byte b : row) { if (b == ';') { containsSemiC = true; } if (b == ';' || b == '<') break; if (!validTableNameChars[0xff & b]) { violations = addIfNotPresent(violations, 4); } } if (containsSemiC) { if (row.length == 0) { violations = addIfNotPresent(violations, 4); } } else { if (row.length == 0 || row[row.length - 1] != '<') { violations = addIfNotPresent(violations, 4); } } if (row.length > 0 && row[0] == '!') { if (row.length < 3 || row[1] != '0' || (row[2] != '<' && row[2] != ';')) { violations = addIfNotPresent(violations, 4); } } if (new Text(row).compareTo(new Text(MetadataTable.ID.canonical())) < 0) { violations = addViolation(violations, 5); } boolean checkedBulk = false; for (ColumnUpdate columnUpdate : colUpdates) { Text columnFamily = new Text(columnUpdate.getColumnFamily()); if (columnUpdate.isDeleted()) { if (!isValidColumn(columnUpdate)) { violations = addViolation(violations, 2); } continue; } if (columnUpdate.getValue().length == 0 && !columnFamily.equals(ScanFileColumnFamily.NAME)) { violations = addViolation(violations, 6); } if (columnFamily.equals(DataFileColumnFamily.NAME)) { try { DataFileValue dfv = new DataFileValue(columnUpdate.getValue()); if (dfv.getSize() < 0 || dfv.getNumEntries() < 0) { violations = addViolation(violations, 1); } } catch (NumberFormatException | ArrayIndexOutOfBoundsException nfe) { violations = addViolation(violations, 1); } } else if (columnFamily.equals(ScanFileColumnFamily.NAME)) { } else if (columnFamily.equals(BulkFileColumnFamily.NAME)) { if (!columnUpdate.isDeleted() && !checkedBulk) { boolean isSplitMutation = false; boolean isLocationMutation = false; HashSet<Text> dataFiles = new HashSet<>(); HashSet<Text> loadedFiles = new HashSet<>(); String tidString = new String(columnUpdate.getValue(), UTF_8); int otherTidCount = 0; for (ColumnUpdate update : mutation.getUpdates()) { if (new ColumnFQ(update).equals(ServerColumnFamily.DIRECTORY_COLUMN)) { isSplitMutation = true; } else if (new Text(update.getColumnFamily()) .equals(CurrentLocationColumnFamily.NAME)) { isLocationMutation = true; } else if (new Text(update.getColumnFamily()).equals(DataFileColumnFamily.NAME)) { dataFiles.add(new Text(update.getColumnQualifier())); } else if (new Text(update.getColumnFamily()).equals(BulkFileColumnFamily.NAME)) { loadedFiles.add(new Text(update.getColumnQualifier())); if (!new String(update.getValue(), UTF_8).equals(tidString)) { otherTidCount++; } } } if (!isSplitMutation && !isLocationMutation) { long tid = BulkFileColumnFamily.getBulkLoadTid(new Value(tidString)); try { if (otherTidCount > 0 || !dataFiles.equals(loadedFiles) || !getArbitrator(context) .transactionAlive(Constants.BULK_ARBITRATOR_TYPE, tid)) { violations = addViolation(violations, 8); } } catch (Exception ex) { violations = addViolation(violations, 8); } } checkedBulk = true; } } else { if (!isValidColumn(columnUpdate)) { violations = addViolation(violations, 2); } else if (new ColumnFQ(columnUpdate).equals(TabletColumnFamily.PREV_ROW_COLUMN) && columnUpdate.getValue().length > 0 && (violations == null || !violations.contains((short) 4))) { KeyExtent ke = KeyExtent.fromMetaRow(new Text(mutation.getRow())); Text per = TabletColumnFamily.decodePrevEndRow(new Value(columnUpdate.getValue())); boolean prevEndRowLessThanEndRow = per == null || ke.endRow() == null || per.compareTo(ke.endRow()) < 0; if (!prevEndRowLessThanEndRow) { violations = addViolation(violations, 3); } } else if (new ColumnFQ(columnUpdate).equals(ServerColumnFamily.LOCK_COLUMN)) { if (zooCache == null) { zooCache = new ZooCache(context.getZooReaderWriter(), null); CleanerUtil.zooCacheClearer(this, zooCache); } if (zooRoot == null) { zooRoot = context.getZooKeeperRoot(); } boolean lockHeld = false; String lockId = new String(columnUpdate.getValue(), UTF_8); try { lockHeld = ZooLock.isLockHeld(zooCache, new ZooUtil.LockID(zooRoot, lockId)); } catch (Exception e) { log.debug("Failed to verify lock was held {} {}", lockId, e.getMessage()); } if (!lockHeld) { violations = addViolation(violations, 7); } } } } if (violations != null) { log.debug("violating metadata mutation : {}", new String(mutation.getRow(), UTF_8)); for (ColumnUpdate update : mutation.getUpdates()) { log.debug(" update: {}:{} value {}", new String(update.getColumnFamily(), UTF_8), new String(update.getColumnQualifier(), UTF_8), (update.isDeleted() ? "[delete]" : new String(update.getValue(), UTF_8))); } } return violations; }  @Override List<Short> check(Environment env, Mutation mutation); @Override String getViolationDescription(short violationCode);  }