public void waitForFlush(TInfo tinfo, TCredentials c, String tableId, ByteBuffer startRow, ByteBuffer endRow, long flushID, long maxLoops)
throws ThriftSecurityException, ThriftTableOperationException, TException {
security.canFlush(c, tableId);
if (endRow != null && startRow != null && ByteBufferUtil.toText(startRow).compareTo(ByteBufferUtil.toText(endRow)) >= 0)
throw new ThriftTableOperationException(tableId, null, TableOperation.FLUSH, TableOperationExceptionType.BAD_RANGE,
"start row must be less than end row");
Set<TServerInstance> serversToFlush = new HashSet<TServerInstance>(tserverSet.getCurrentServers());
for (long l = 0; l < maxLoops; l++) {
for (TServerInstance instance : serversToFlush) {
try {
final TServerConnection server = tserverSet.getConnection(instance);
if (server != null)
server.flush(masterLock, tableId, ByteBufferUtil.toBytes(startRow), ByteBufferUtil.toBytes(endRow));
} catch (TException ex) {
log.error(ex.toString());
}
}
if (l == maxLoops - 1)
break;
UtilWaitThread.sleep(50);
serversToFlush.clear();
try {
Connector conn = getConnector();
Scanner scanner = new IsolatedScanner(conn.createScanner(Constants.METADATA_TABLE_NAME, Constants.NO_AUTHS));
Constants.METADATA_FLUSH_COLUMN.fetch(scanner);
Constants.METADATA_DIRECTORY_COLUMN.fetch(scanner);
scanner.fetchColumnFamily(Constants.METADATA_CURRENT_LOCATION_COLUMN_FAMILY);
scanner.fetchColumnFamily(Constants.METADATA_LOG_COLUMN_FAMILY);
scanner.setRange(new KeyExtent(new Text(tableId), null, ByteBufferUtil.toText(startRow)).toMetadataRange());
RowIterator ri = new RowIterator(scanner);
int tabletsToWaitFor = 0;
int tabletCount = 0;
Text ert = ByteBufferUtil.toText(endRow);
while (ri.hasNext()) {
Iterator<Entry<Key,Value>> row = ri.next();
long tabletFlushID = -1;
int logs = 0;
boolean online = false;
TServerInstance server = null;
Entry<Key,Value> entry = null;
while (row.hasNext()) {
entry = row.next();
Key key = entry.getKey();
if (Constants.METADATA_FLUSH_COLUMN.equals(key.getColumnFamily(), key.getColumnQualifier())) {
tabletFlushID = Long.parseLong(entry.getValue().toString());
}
if (Constants.METADATA_LOG_COLUMN_FAMILY.equals(key.getColumnFamily()))
logs++;
if (Constants.METADATA_CURRENT_LOCATION_COLUMN_FAMILY.equals(key.getColumnFamily())) {
online = true;
server = new TServerInstance(entry.getValue(), key.getColumnQualifier());
}
}
// when tablet is not online and has no logs, there is no reason to wait for it
if ((online || logs > 0) && tabletFlushID < flushID) {
tabletsToWaitFor++;
if (server != null)
serversToFlush.add(server);
}
tabletCount++;
Text tabletEndRow = new KeyExtent(entry.getKey().getRow(), (Text) null).getEndRow();
if (tabletEndRow == null || (ert != null && tabletEndRow.compareTo(ert) >= 0))
break;
}
if (tabletsToWaitFor == 0)
break;
// TODO detect case of table offline AND tablets w/ logs? - ACCUMULO-1296
if (tabletCount == 0 && !Tables.exists(instance, tableId))
throw new ThriftTableOperationException(tableId, null, TableOperation.FLUSH, TableOperationExceptionType.NOTFOUND, null);
} catch (AccumuloException e) {
log.debug("Failed to scan !METADATA table to wait for flush " + tableId, e);
} catch (TabletDeletedException tde) {
log.debug("Failed to scan !METADATA table to wait for flush " + tableId, tde);
} catch (AccumuloSecurityException e) {
log.warn(e.getMessage(), e);
throw new ThriftSecurityException();
} catch (TableNotFoundException e) {
log.error(e.getMessage(), e);
throw new ThriftTableOperationException();
}
}
}