blob: be45084c957e157122bc2cc3188aad65226068d9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.accumulo.gc;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import org.apache.accumulo.core.client.AccumuloClient;
import org.apache.accumulo.core.client.Scanner;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.data.impl.KeyExtent;
import org.apache.accumulo.core.gc.thrift.GCStatus;
import org.apache.accumulo.core.gc.thrift.GcCycleStats;
import org.apache.accumulo.core.metadata.MetadataTable;
import org.apache.accumulo.core.metadata.schema.MetadataSchema;
import org.apache.accumulo.core.replication.ReplicationSchema;
import org.apache.accumulo.core.replication.ReplicationTable;
import org.apache.accumulo.core.security.Authorizations;
import org.apache.accumulo.core.util.Pair;
import org.apache.accumulo.server.ServerContext;
import org.apache.accumulo.server.fs.VolumeManager;
import org.apache.accumulo.server.log.WalStateManager;
import org.apache.accumulo.server.log.WalStateManager.WalState;
import org.apache.accumulo.server.master.LiveTServerSet;
import org.apache.accumulo.server.master.state.TServerInstance;
import org.apache.accumulo.server.master.state.TabletLocationState;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.zookeeper.KeeperException;
import org.easymock.EasyMock;
import org.junit.Test;
public class GarbageCollectWriteAheadLogsTest {
private final TServerInstance server1 = new TServerInstance("localhost:1234[SESSION]");
private final TServerInstance server2 = new TServerInstance("localhost:1234[OTHERSESS]");
private final UUID id = UUID.randomUUID();
private final Map<TServerInstance,List<UUID>> markers = Collections.singletonMap(server1,
Collections.singletonList(id));
private final Map<TServerInstance,List<UUID>> markers2 = Collections.singletonMap(server2,
Collections.singletonList(id));
private final Path path = new Path("hdfs://localhost:9000/accumulo/wal/localhost+1234/" + id);
private final KeyExtent extent = new KeyExtent(new Text("1<"), new Text(new byte[] {0}));
private final Collection<Collection<String>> walogs = Collections.emptyList();
private final TabletLocationState tabletAssignedToServer1;
private final TabletLocationState tabletAssignedToServer2;
{
try {
tabletAssignedToServer1 = new TabletLocationState(extent, null, server1, null, null, walogs,
false);
tabletAssignedToServer2 = new TabletLocationState(extent, null, server2, null, null, walogs,
false);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private final Iterable<TabletLocationState> tabletOnServer1List = Collections
.singletonList(tabletAssignedToServer1);
private final Iterable<TabletLocationState> tabletOnServer2List = Collections
.singletonList(tabletAssignedToServer2);
private final List<Entry<Key,Value>> emptyList = Collections.emptyList();
private final Iterator<Entry<Key,Value>> emptyKV = emptyList.iterator();
@Test
public void testRemoveUnusedLog() throws Exception {
ServerContext context = EasyMock.createMock(ServerContext.class);
VolumeManager fs = EasyMock.createMock(VolumeManager.class);
WalStateManager marker = EasyMock.createMock(WalStateManager.class);
LiveTServerSet tserverSet = EasyMock.createMock(LiveTServerSet.class);
GCStatus status = new GCStatus(null, null, null, new GcCycleStats());
EasyMock.expect(tserverSet.getCurrentServers()).andReturn(Collections.singleton(server1));
EasyMock.expect(marker.getAllMarkers()).andReturn(markers).once();
EasyMock.expect(marker.state(server1, id)).andReturn(new Pair<>(WalState.UNREFERENCED, path));
EasyMock.expect(fs.deleteRecursively(path)).andReturn(true).once();
marker.removeWalMarker(server1, id);
EasyMock.expectLastCall().once();
EasyMock.replay(context, fs, marker, tserverSet);
GarbageCollectWriteAheadLogs gc = new GarbageCollectWriteAheadLogs(context, fs, false,
tserverSet, marker, tabletOnServer1List) {
@Override
protected int removeReplicationEntries(Map<UUID,TServerInstance> candidates)
throws IOException, KeeperException, InterruptedException {
return 0;
}
@Override
protected Map<UUID,Path> getSortedWALogs() throws IOException {
return Collections.emptyMap();
}
};
gc.collect(status);
EasyMock.verify(context, fs, marker, tserverSet);
}
@Test
public void testKeepClosedLog() throws Exception {
ServerContext context = EasyMock.createMock(ServerContext.class);
VolumeManager fs = EasyMock.createMock(VolumeManager.class);
WalStateManager marker = EasyMock.createMock(WalStateManager.class);
LiveTServerSet tserverSet = EasyMock.createMock(LiveTServerSet.class);
GCStatus status = new GCStatus(null, null, null, new GcCycleStats());
EasyMock.expect(tserverSet.getCurrentServers()).andReturn(Collections.singleton(server1));
EasyMock.expect(marker.getAllMarkers()).andReturn(markers).once();
EasyMock.expect(marker.state(server1, id)).andReturn(new Pair<>(WalState.CLOSED, path));
EasyMock.replay(context, marker, tserverSet, fs);
GarbageCollectWriteAheadLogs gc = new GarbageCollectWriteAheadLogs(context, fs, false,
tserverSet, marker, tabletOnServer1List) {
@Override
protected int removeReplicationEntries(Map<UUID,TServerInstance> candidates)
throws IOException, KeeperException, InterruptedException {
return 0;
}
@Override
protected Map<UUID,Path> getSortedWALogs() throws IOException {
return Collections.emptyMap();
}
};
gc.collect(status);
EasyMock.verify(context, marker, tserverSet, fs);
}
@Test
public void deleteUnreferenceLogOnDeadServer() throws Exception {
ServerContext context = EasyMock.createMock(ServerContext.class);
VolumeManager fs = EasyMock.createMock(VolumeManager.class);
WalStateManager marker = EasyMock.createMock(WalStateManager.class);
LiveTServerSet tserverSet = EasyMock.createMock(LiveTServerSet.class);
AccumuloClient client = EasyMock.createMock(AccumuloClient.class);
Scanner mscanner = EasyMock.createMock(Scanner.class);
Scanner rscanner = EasyMock.createMock(Scanner.class);
GCStatus status = new GCStatus(null, null, null, new GcCycleStats());
EasyMock.expect(tserverSet.getCurrentServers()).andReturn(Collections.singleton(server1));
EasyMock.expect(marker.getAllMarkers()).andReturn(markers2).once();
EasyMock.expect(marker.state(server2, id)).andReturn(new Pair<>(WalState.OPEN, path));
EasyMock.expect(context.getClient()).andReturn(client);
EasyMock.expect(client.createScanner(ReplicationTable.NAME, Authorizations.EMPTY))
.andReturn(rscanner);
rscanner.fetchColumnFamily(ReplicationSchema.StatusSection.NAME);
EasyMock.expectLastCall().once();
EasyMock.expect(rscanner.iterator()).andReturn(emptyKV);
EasyMock.expect(client.createScanner(MetadataTable.NAME, Authorizations.EMPTY))
.andReturn(mscanner);
mscanner.fetchColumnFamily(MetadataSchema.ReplicationSection.COLF);
EasyMock.expectLastCall().once();
mscanner.setRange(MetadataSchema.ReplicationSection.getRange());
EasyMock.expectLastCall().once();
EasyMock.expect(mscanner.iterator()).andReturn(emptyKV);
EasyMock.expect(fs.deleteRecursively(path)).andReturn(true).once();
marker.removeWalMarker(server2, id);
EasyMock.expectLastCall().once();
marker.forget(server2);
EasyMock.expectLastCall().once();
EasyMock.replay(context, fs, marker, tserverSet, client, rscanner, mscanner);
GarbageCollectWriteAheadLogs gc = new GarbageCollectWriteAheadLogs(context, fs, false,
tserverSet, marker, tabletOnServer1List) {
@Override
protected Map<UUID,Path> getSortedWALogs() throws IOException {
return Collections.emptyMap();
}
};
gc.collect(status);
EasyMock.verify(context, fs, marker, tserverSet, client, rscanner, mscanner);
}
@Test
public void ignoreReferenceLogOnDeadServer() throws Exception {
ServerContext context = EasyMock.createMock(ServerContext.class);
VolumeManager fs = EasyMock.createMock(VolumeManager.class);
WalStateManager marker = EasyMock.createMock(WalStateManager.class);
LiveTServerSet tserverSet = EasyMock.createMock(LiveTServerSet.class);
AccumuloClient client = EasyMock.createMock(AccumuloClient.class);
Scanner mscanner = EasyMock.createMock(Scanner.class);
Scanner rscanner = EasyMock.createMock(Scanner.class);
GCStatus status = new GCStatus(null, null, null, new GcCycleStats());
EasyMock.expect(tserverSet.getCurrentServers()).andReturn(Collections.singleton(server1));
EasyMock.expect(marker.getAllMarkers()).andReturn(markers2).once();
EasyMock.expect(marker.state(server2, id)).andReturn(new Pair<>(WalState.OPEN, path));
EasyMock.expect(context.getClient()).andReturn(client);
EasyMock.expect(client.createScanner(ReplicationTable.NAME, Authorizations.EMPTY))
.andReturn(rscanner);
rscanner.fetchColumnFamily(ReplicationSchema.StatusSection.NAME);
EasyMock.expectLastCall().once();
EasyMock.expect(rscanner.iterator()).andReturn(emptyKV);
EasyMock.expect(client.createScanner(MetadataTable.NAME, Authorizations.EMPTY))
.andReturn(mscanner);
mscanner.fetchColumnFamily(MetadataSchema.ReplicationSection.COLF);
EasyMock.expectLastCall().once();
mscanner.setRange(MetadataSchema.ReplicationSection.getRange());
EasyMock.expectLastCall().once();
EasyMock.expect(mscanner.iterator()).andReturn(emptyKV);
EasyMock.replay(context, fs, marker, tserverSet, client, rscanner, mscanner);
GarbageCollectWriteAheadLogs gc = new GarbageCollectWriteAheadLogs(context, fs, false,
tserverSet, marker, tabletOnServer2List) {
@Override
protected Map<UUID,Path> getSortedWALogs() throws IOException {
return Collections.emptyMap();
}
};
gc.collect(status);
EasyMock.verify(context, fs, marker, tserverSet, client, rscanner, mscanner);
}
@Test
public void replicationDelaysFileCollection() throws Exception {
ServerContext context = EasyMock.createMock(ServerContext.class);
VolumeManager fs = EasyMock.createMock(VolumeManager.class);
WalStateManager marker = EasyMock.createMock(WalStateManager.class);
LiveTServerSet tserverSet = EasyMock.createMock(LiveTServerSet.class);
AccumuloClient client = EasyMock.createMock(AccumuloClient.class);
Scanner mscanner = EasyMock.createMock(Scanner.class);
Scanner rscanner = EasyMock.createMock(Scanner.class);
String row = MetadataSchema.ReplicationSection.getRowPrefix() + path;
String colf = MetadataSchema.ReplicationSection.COLF.toString();
String colq = "1";
Map<Key,Value> replicationWork = Collections.singletonMap(new Key(row, colf, colq),
new Value(new byte[0]));
GCStatus status = new GCStatus(null, null, null, new GcCycleStats());
EasyMock.expect(tserverSet.getCurrentServers()).andReturn(Collections.singleton(server1));
EasyMock.expect(marker.getAllMarkers()).andReturn(markers).once();
EasyMock.expect(marker.state(server1, id)).andReturn(new Pair<>(WalState.UNREFERENCED, path));
EasyMock.expect(context.getClient()).andReturn(client);
EasyMock.expect(client.createScanner(ReplicationTable.NAME, Authorizations.EMPTY))
.andReturn(rscanner);
rscanner.fetchColumnFamily(ReplicationSchema.StatusSection.NAME);
EasyMock.expectLastCall().once();
EasyMock.expect(rscanner.iterator()).andReturn(emptyKV);
EasyMock.expect(client.createScanner(MetadataTable.NAME, Authorizations.EMPTY))
.andReturn(mscanner);
mscanner.fetchColumnFamily(MetadataSchema.ReplicationSection.COLF);
EasyMock.expectLastCall().once();
mscanner.setRange(MetadataSchema.ReplicationSection.getRange());
EasyMock.expectLastCall().once();
EasyMock.expect(mscanner.iterator()).andReturn(replicationWork.entrySet().iterator());
EasyMock.replay(context, fs, marker, tserverSet, client, rscanner, mscanner);
GarbageCollectWriteAheadLogs gc = new GarbageCollectWriteAheadLogs(context, fs, false,
tserverSet, marker, tabletOnServer1List) {
@Override
protected Map<UUID,Path> getSortedWALogs() throws IOException {
return Collections.emptyMap();
}
};
gc.collect(status);
EasyMock.verify(context, fs, marker, tserverSet, client, rscanner, mscanner);
}
}