use of org.apache.accumulo.server.manager.state.Assignment in project accumulo by apache.
the class AssignmentHandler method run.
@Override
public void run() {
synchronized (server.unopenedTablets) {
synchronized (server.openingTablets) {
synchronized (server.onlineTablets) {
// nothing should be moving between sets, do a sanity
// check
Set<KeyExtent> unopenedOverlapping = KeyExtent.findOverlapping(extent, server.unopenedTablets);
Set<KeyExtent> openingOverlapping = KeyExtent.findOverlapping(extent, server.openingTablets);
Set<KeyExtent> onlineOverlapping = KeyExtent.findOverlapping(extent, server.onlineTablets.snapshot());
if (openingOverlapping.contains(extent) || onlineOverlapping.contains(extent)) {
return;
}
if (!unopenedOverlapping.contains(extent)) {
log.info("assignment {} no longer in the unopened set", extent);
return;
}
if (unopenedOverlapping.size() != 1 || !openingOverlapping.isEmpty() || !onlineOverlapping.isEmpty()) {
throw new IllegalStateException("overlaps assigned " + extent + " " + !server.unopenedTablets.contains(extent) + " " + unopenedOverlapping + " " + openingOverlapping + " " + onlineOverlapping);
}
}
server.unopenedTablets.remove(extent);
server.openingTablets.add(extent);
}
}
// check Metadata table before accepting assignment
Text locationToOpen = null;
TabletMetadata tabletMetadata = null;
boolean canLoad = false;
try {
tabletMetadata = server.getContext().getAmple().readTablet(extent);
canLoad = checkTabletMetadata(extent, server.getTabletSession(), tabletMetadata);
if (canLoad && tabletMetadata.sawOldPrevEndRow()) {
KeyExtent fixedExtent = ManagerMetadataUtil.fixSplit(server.getContext(), tabletMetadata, server.getLock());
synchronized (server.openingTablets) {
server.openingTablets.remove(extent);
server.openingTablets.notifyAll();
// should not be added to unopenedTablets
if (!KeyExtent.findOverlapping(extent, new TreeSet<>(Arrays.asList(fixedExtent))).contains(fixedExtent)) {
throw new IllegalStateException("Fixed split does not overlap " + extent + " " + fixedExtent);
}
server.unopenedTablets.add(fixedExtent);
}
// split was rolled back... try again
new AssignmentHandler(server, fixedExtent).run();
return;
}
} catch (Exception e) {
synchronized (server.openingTablets) {
server.openingTablets.remove(extent);
server.openingTablets.notifyAll();
}
log.warn("Failed to verify tablet " + extent, e);
server.enqueueManagerMessage(new TabletStatusMessage(TabletLoadState.LOAD_FAILURE, extent));
throw new RuntimeException(e);
}
if (!canLoad) {
log.debug("Reporting tablet {} assignment failure: unable to verify Tablet Information", extent);
synchronized (server.openingTablets) {
server.openingTablets.remove(extent);
server.openingTablets.notifyAll();
}
server.enqueueManagerMessage(new TabletStatusMessage(TabletLoadState.LOAD_FAILURE, extent));
return;
}
Tablet tablet = null;
boolean successful = false;
try {
server.acquireRecoveryMemory(extent);
TabletResourceManager trm = server.resourceManager.createTabletResourceManager(extent, server.getTableConfiguration(extent));
TabletData data = new TabletData(tabletMetadata);
tablet = new Tablet(server, extent, trm, data);
// this could cause duplicate data to replay.
if (tablet.getNumEntriesInMemory() > 0 && !tablet.minorCompactNow(MinorCompactionReason.RECOVERY)) {
throw new RuntimeException("Minor compaction after recovery fails for " + extent);
}
Assignment assignment = new Assignment(extent, server.getTabletSession());
TabletStateStore.setLocation(server.getContext(), assignment);
synchronized (server.openingTablets) {
synchronized (server.onlineTablets) {
server.openingTablets.remove(extent);
server.onlineTablets.put(extent, tablet);
server.openingTablets.notifyAll();
server.recentlyUnloadedCache.remove(tablet.getExtent());
}
}
// release this reference
tablet = null;
successful = true;
} catch (Exception e) {
log.warn("exception trying to assign tablet {} {}", extent, locationToOpen, e);
if (e.getMessage() != null) {
log.warn("{}", e.getMessage());
}
TableId tableId = extent.tableId();
ProblemReports.getInstance(server.getContext()).report(new ProblemReport(tableId, TABLET_LOAD, extent.getUUID().toString(), server.getClientAddressString(), e));
} finally {
server.releaseRecoveryMemory(extent);
}
if (successful) {
server.enqueueManagerMessage(new TabletStatusMessage(TabletLoadState.LOADED, extent));
} else {
synchronized (server.unopenedTablets) {
synchronized (server.openingTablets) {
server.openingTablets.remove(extent);
server.unopenedTablets.add(extent);
server.openingTablets.notifyAll();
}
}
log.warn("failed to open tablet {} reporting failure to manager", extent);
server.enqueueManagerMessage(new TabletStatusMessage(TabletLoadState.LOAD_FAILURE, extent));
long reschedule = Math.min((1L << Math.min(32, retryAttempt)) * 1000, MINUTES.toMillis(10));
log.warn(String.format("rescheduling tablet load in %.2f seconds", reschedule / 1000.));
this.server.getContext().getScheduledExecutor().schedule(new Runnable() {
@Override
public void run() {
log.info("adding tablet {} back to the assignment pool (retry {})", extent, retryAttempt);
AssignmentHandler handler = new AssignmentHandler(server, extent, retryAttempt + 1);
if (extent.isMeta()) {
if (extent.isRootTablet()) {
Threads.createThread("Root tablet assignment retry", handler).start();
} else {
server.resourceManager.addMetaDataAssignment(extent, log, handler);
}
} else {
server.resourceManager.addAssignment(extent, log, handler);
}
}
}, reschedule, TimeUnit.MILLISECONDS);
}
}
use of org.apache.accumulo.server.manager.state.Assignment in project accumulo by apache.
the class NullTserver method main.
public static void main(String[] args) throws Exception {
Opts opts = new Opts();
opts.parseArgs(NullTserver.class.getName(), args);
// modify metadata
int zkTimeOut = (int) DefaultConfiguration.getInstance().getTimeInMillis(Property.INSTANCE_ZK_TIMEOUT);
var siteConfig = SiteConfiguration.auto();
ServerContext context = ServerContext.override(siteConfig, opts.iname, opts.keepers, zkTimeOut);
TransactionWatcher watcher = new TransactionWatcher(context);
ThriftClientHandler tch = new ThriftClientHandler(context, watcher);
Processor<Iface> processor = new Processor<>(tch);
TServerUtils.startTServer(context.getConfiguration(), ThriftServerType.CUSTOM_HS_HA, processor, "NullTServer", "null tserver", 2, ThreadPools.DEFAULT_TIMEOUT_MILLISECS, 1000, 10 * 1024 * 1024, null, null, -1, HostAndPort.fromParts("0.0.0.0", opts.port));
HostAndPort addr = HostAndPort.fromParts(InetAddress.getLocalHost().getHostName(), opts.port);
TableId tableId = context.getTableId(opts.tableName);
// read the locations for the table
Range tableRange = new KeyExtent(tableId, null, null).toMetaRange();
List<Assignment> assignments = new ArrayList<>();
try (var s = new MetaDataTableScanner(context, tableRange, MetadataTable.NAME)) {
long randomSessionID = opts.port;
TServerInstance instance = new TServerInstance(addr, randomSessionID);
while (s.hasNext()) {
TabletLocationState next = s.next();
assignments.add(new Assignment(next.extent, instance));
}
}
// point them to this server
TabletStateStore store = TabletStateStore.getStoreForLevel(DataLevel.USER, context);
store.setLocations(assignments);
while (true) {
sleepUninterruptibly(10, TimeUnit.SECONDS);
}
}
use of org.apache.accumulo.server.manager.state.Assignment in project accumulo by apache.
the class SplitRecoveryIT method splitPartiallyAndRecover.
private void splitPartiallyAndRecover(ServerContext context, KeyExtent extent, KeyExtent high, KeyExtent low, double splitRatio, SortedMap<StoredTabletFile, DataFileValue> mapFiles, Text midRow, String location, int steps, ServiceLock zl) throws Exception {
SortedMap<StoredTabletFile, DataFileValue> lowDatafileSizes = new TreeMap<>();
SortedMap<StoredTabletFile, DataFileValue> highDatafileSizes = new TreeMap<>();
List<StoredTabletFile> highDatafilesToRemove = new ArrayList<>();
MetadataTableUtil.splitDatafiles(midRow, splitRatio, new HashMap<>(), mapFiles, lowDatafileSizes, highDatafileSizes, highDatafilesToRemove);
MetadataTableUtil.splitTablet(high, extent.prevEndRow(), splitRatio, context, zl, Set.of());
TServerInstance instance = new TServerInstance(location, zl.getSessionId());
Assignment assignment = new Assignment(high, instance);
TabletMutator tabletMutator = context.getAmple().mutateTablet(extent);
tabletMutator.putLocation(assignment.server, LocationType.FUTURE);
tabletMutator.mutate();
if (steps >= 1) {
Map<Long, List<TabletFile>> bulkFiles = getBulkFilesLoaded(context, high);
ManagerMetadataUtil.addNewTablet(context, low, "lowDir", instance, lowDatafileSizes, bulkFiles, new MetadataTime(0, TimeType.LOGICAL), -1L, -1L, zl);
}
if (steps >= 2) {
MetadataTableUtil.finishSplit(high, highDatafileSizes, highDatafilesToRemove, context, zl);
}
TabletMetadata meta = context.getAmple().readTablet(high);
KeyExtent fixedExtent = ManagerMetadataUtil.fixSplit(context, meta, zl);
if (steps < 2)
assertEquals(splitRatio, meta.getSplitRatio(), 0.0);
if (steps >= 1) {
assertEquals(high, fixedExtent);
ensureTabletHasNoUnexpectedMetadataEntries(context, low, lowDatafileSizes);
ensureTabletHasNoUnexpectedMetadataEntries(context, high, highDatafileSizes);
Map<Long, ? extends Collection<TabletFile>> lowBulkFiles = getBulkFilesLoaded(context, low);
Map<Long, ? extends Collection<TabletFile>> highBulkFiles = getBulkFilesLoaded(context, high);
if (!lowBulkFiles.equals(highBulkFiles)) {
throw new Exception(" " + lowBulkFiles + " != " + highBulkFiles + " " + low + " " + high);
}
if (lowBulkFiles.isEmpty()) {
throw new Exception(" no bulk files " + low);
}
} else {
assertEquals(extent, fixedExtent);
ensureTabletHasNoUnexpectedMetadataEntries(context, extent, mapFiles);
}
}
use of org.apache.accumulo.server.manager.state.Assignment in project accumulo by apache.
the class MergeStateIT method test.
@Test
public void test() throws Exception {
ServerContext context = getServerContext();
try (AccumuloClient accumuloClient = Accumulo.newClient().from(getClientProperties()).build()) {
accumuloClient.securityOperations().grantTablePermission(accumuloClient.whoami(), MetadataTable.NAME, TablePermission.WRITE);
BatchWriter bw = accumuloClient.createBatchWriter(MetadataTable.NAME);
// Create a fake METADATA table with these splits
String[] splits = { "a", "e", "j", "o", "t", "z" };
// create metadata for a table "t" with the splits above
TableId tableId = TableId.of("t");
Text pr = null;
for (String s : splits) {
Text split = new Text(s);
Mutation prevRow = TabletColumnFamily.createPrevRowMutation(new KeyExtent(tableId, split, pr));
prevRow.put(CurrentLocationColumnFamily.NAME, new Text("123456"), new Value("127.0.0.1:1234"));
ChoppedColumnFamily.CHOPPED_COLUMN.put(prevRow, new Value("junk"));
bw.addMutation(prevRow);
pr = split;
}
// Add the default tablet
Mutation defaultTablet = TabletColumnFamily.createPrevRowMutation(new KeyExtent(tableId, null, pr));
defaultTablet.put(CurrentLocationColumnFamily.NAME, new Text("123456"), new Value("127.0.0.1:1234"));
bw.addMutation(defaultTablet);
bw.close();
// Read out the TabletLocationStates
MockCurrentState state = new MockCurrentState(new MergeInfo(new KeyExtent(tableId, new Text("p"), new Text("e")), MergeInfo.Operation.MERGE));
// Verify the tablet state: hosted, and count
TabletStateStore metaDataStateStore = TabletStateStore.getStoreForLevel(DataLevel.USER, context, state);
int count = 0;
for (TabletLocationState tss : metaDataStateStore) {
if (tss != null)
count++;
}
// the normal case is to skip tablets in a good state
assertEquals(0, count);
// Create the hole
// Split the tablet at one end of the range
Mutation m = TabletColumnFamily.createPrevRowMutation(new KeyExtent(tableId, new Text("t"), new Text("p")));
TabletColumnFamily.SPLIT_RATIO_COLUMN.put(m, new Value("0.5"));
TabletColumnFamily.OLD_PREV_ROW_COLUMN.put(m, TabletColumnFamily.encodePrevEndRow(new Text("o")));
update(accumuloClient, m);
// do the state check
MergeStats stats = scan(state, metaDataStateStore);
MergeState newState = stats.nextMergeState(accumuloClient, state);
assertEquals(MergeState.WAITING_FOR_OFFLINE, newState);
// unassign the tablets
try (BatchDeleter deleter = accumuloClient.createBatchDeleter(MetadataTable.NAME, Authorizations.EMPTY, 1000)) {
deleter.fetchColumnFamily(CurrentLocationColumnFamily.NAME);
deleter.setRanges(Collections.singletonList(new Range()));
deleter.delete();
}
// now we should be ready to merge but, we have inconsistent metadata
stats = scan(state, metaDataStateStore);
assertEquals(MergeState.WAITING_FOR_OFFLINE, stats.nextMergeState(accumuloClient, state));
// finish the split
KeyExtent tablet = new KeyExtent(tableId, new Text("p"), new Text("o"));
m = TabletColumnFamily.createPrevRowMutation(tablet);
TabletColumnFamily.SPLIT_RATIO_COLUMN.put(m, new Value("0.5"));
update(accumuloClient, m);
metaDataStateStore.setLocations(Collections.singletonList(new Assignment(tablet, state.someTServer)));
// onos... there's a new tablet online
stats = scan(state, metaDataStateStore);
assertEquals(MergeState.WAITING_FOR_CHOPPED, stats.nextMergeState(accumuloClient, state));
// chop it
m = TabletColumnFamily.createPrevRowMutation(tablet);
ChoppedColumnFamily.CHOPPED_COLUMN.put(m, new Value("junk"));
update(accumuloClient, m);
stats = scan(state, metaDataStateStore);
assertEquals(MergeState.WAITING_FOR_OFFLINE, stats.nextMergeState(accumuloClient, state));
// take it offline
m = TabletColumnFamily.createPrevRowMutation(tablet);
Collection<Collection<String>> walogs = Collections.emptyList();
metaDataStateStore.unassign(Collections.singletonList(new TabletLocationState(tablet, null, state.someTServer, null, null, walogs, false)), null);
// now we can split
stats = scan(state, metaDataStateStore);
assertEquals(MergeState.MERGING, stats.nextMergeState(accumuloClient, state));
}
}
Aggregations