Skip to content

Commit

Permalink
Add rest endpoint trigger_gc to trigger GC on Bookie
Browse files Browse the repository at this point in the history
Descriptions of the changes in this PR:

Add rest endpoint trigger_gc to trigger GC on Bookie

### Motivation

Some times user would like to trigger GC manually instead of waiting to the timeout or disk full. 




Reviewers: Enrico Olivelli <[email protected]>, Sijie Guo <[email protected]>

This closes apache#1838 from jiazhai/rest_force_gc
  • Loading branch information
jiazhai authored and sijie committed Nov 27, 2018
1 parent 1a44de7 commit 641db3b
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public abstract class HttpRouter<Handler> {
public static final String LAST_LOG_MARK = "/api/v1/bookie/last_log_mark";
public static final String LIST_DISK_FILE = "/api/v1/bookie/list_disk_file";
public static final String EXPAND_STORAGE = "/api/v1/bookie/expand_storage";
public static final String GC = "/api/v1/bookie/gc";
// autorecovery
public static final String RECOVERY_BOOKIE = "/api/v1/autorecovery/bookie";
public static final String LIST_UNDER_REPLICATED_LEDGER = "/api/v1/autorecovery/list_under_replicated_ledger";
Expand Down Expand Up @@ -73,6 +74,7 @@ public HttpRouter(AbstractHttpHandlerFactory<Handler> handlerFactory) {
this.endpointHandlers.put(LAST_LOG_MARK, handlerFactory.newHandler(HttpServer.ApiType.LAST_LOG_MARK));
this.endpointHandlers.put(LIST_DISK_FILE, handlerFactory.newHandler(HttpServer.ApiType.LIST_DISK_FILE));
this.endpointHandlers.put(EXPAND_STORAGE, handlerFactory.newHandler(HttpServer.ApiType.EXPAND_STORAGE));
this.endpointHandlers.put(GC, handlerFactory.newHandler(HttpServer.ApiType.GC));

// autorecovery
this.endpointHandlers.put(RECOVERY_BOOKIE, handlerFactory.newHandler(HttpServer.ApiType.RECOVERY_BOOKIE));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ enum ApiType {
LAST_LOG_MARK,
LIST_DISK_FILE,
EXPAND_STORAGE,
GC,
// autorecovery
RECOVERY_BOOKIE,
LIST_UNDER_REPLICATED_LEDGER,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,13 @@ public void runWithFlags(boolean force, boolean suspendMajor, boolean suspendMin
lastMinorCompactionTime = System.currentTimeMillis();
minorCompactionCounter.inc();
}

if (force) {
if (forceGarbageCollection.compareAndSet(true, false)) {
LOG.info("{} Set forceGarbageCollection to false after force GC to make it forceGC-able again.", Thread
.currentThread().getName());
}
}
this.gcThreadRuntime.registerSuccessfulEvent(
MathUtils.nowInNano() - threadStart, TimeUnit.NANOSECONDS);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ public void diskJustWritable(File disk) {
};
}

@Override
public void forceGC() {
gcThread.enableForceGC();
}

@Override
public void start() {
gcThread.start();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,10 @@ default LedgerStorage getUnderlyingLedgerStorage() {
return this;
}

/**
* Force trigger Garbage Collection.
*/
default void forceGC() {
return;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,9 @@ public void flushEntriesLocationsIndex() throws IOException {
public LedgerStorage getUnderlyingLedgerStorage() {
return interleavedLedgerStorage;
}

@Override
public void forceGC() {
interleavedLedgerStorage.forceGC();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -348,4 +348,8 @@ public static void readLedgerIndexEntries(long ledgerId, ServerConfiguration ser
}
}

@Override
public void forceGC() {
ledgerStorageList.stream().forEach(SingleDirectoryDbLedgerStorage::forceGC);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ public void start() {
gcThread.start();
}

@Override
public void forceGC() {
gcThread.enableForceGC();
}

@Override
public void shutdown() throws InterruptedException {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.apache.bookkeeper.server.http.service.ReadLedgerEntryService;
import org.apache.bookkeeper.server.http.service.RecoveryBookieService;
import org.apache.bookkeeper.server.http.service.TriggerAuditService;
import org.apache.bookkeeper.server.http.service.TriggerGCService;
import org.apache.bookkeeper.server.http.service.WhoIsAuditorService;
import org.apache.bookkeeper.stats.StatsProvider;
import org.apache.bookkeeper.zookeeper.ZooKeeperClient;
Expand Down Expand Up @@ -208,6 +209,8 @@ public HttpEndpointService provideHttpEndpointService(ApiType type) {
return new ListDiskFilesService(configuration);
case EXPAND_STORAGE:
return new ExpandStorageService(configuration);
case GC:
return new TriggerGCService(configuration, bookieServer);

// autorecovery
case RECOVERY_BOOKIE:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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.bookkeeper.server.http.service;

import static com.google.common.base.Preconditions.checkNotNull;

import org.apache.bookkeeper.common.util.JsonUtil;
import org.apache.bookkeeper.conf.ServerConfiguration;
import org.apache.bookkeeper.http.HttpServer;
import org.apache.bookkeeper.http.service.HttpEndpointService;
import org.apache.bookkeeper.http.service.HttpServiceRequest;
import org.apache.bookkeeper.http.service.HttpServiceResponse;
import org.apache.bookkeeper.proto.BookieServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* HttpEndpointService that handle force trigger GC requests.
*
* <p>The PUT method will force trigger GC on current bookie, and make GC run at backend.
*/
public class TriggerGCService implements HttpEndpointService {

static final Logger LOG = LoggerFactory.getLogger(TriggerGCService.class);

protected ServerConfiguration conf;
protected BookieServer bookieServer;

public TriggerGCService(ServerConfiguration conf, BookieServer bookieServer) {
checkNotNull(conf);
checkNotNull(bookieServer);
this.conf = conf;
this.bookieServer = bookieServer;
}

@Override
public HttpServiceResponse handle(HttpServiceRequest request) throws Exception {
HttpServiceResponse response = new HttpServiceResponse();
// PUT
if (HttpServer.Method.PUT == request.getMethod()) {
bookieServer.getBookie().getLedgerStorage().forceGC();

String output = "Triggered GC on BookieServer: " + bookieServer.toString();
String jsonResponse = JsonUtil.toJson(output);
LOG.debug("output body:" + jsonResponse);
response.setBody(jsonResponse);
response.setCode(HttpServer.StatusCode.OK);
return response;
} else {
response.setCode(HttpServer.StatusCode.NOT_FOUND);
response.setBody("Not found method. Should be PUT method to trigger GC.");
return response;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -741,4 +741,42 @@ public void testDecommissionService() throws Exception {
stopAuditorElector();
}

/**
* Create ledgers, then test Delete Ledger service.
*/
@Test
public void testTriggerGCService() throws Exception {
baseConf.setMetadataServiceUri(zkUtil.getMetadataServiceUri());
BookKeeper.DigestType digestType = BookKeeper.DigestType.CRC32;
int numLedgers = 4;
int numMsgs = 100;
LedgerHandle[] lh = new LedgerHandle[numLedgers];
// create ledgers
for (int i = 0; i < numLedgers; i++) {
lh[i] = bkc.createLedger(digestType, "".getBytes());
}
String content = "Apache BookKeeper is cool!";
// add entries
for (int i = 0; i < numMsgs; i++) {
for (int j = 0; j < numLedgers; j++) {
lh[j].addEntry(content.getBytes());
}
}
// close ledgers
for (int i = 0; i < numLedgers; i++) {
lh[i].close();
}
HttpEndpointService triggerGCService = bkHttpServiceProvider
.provideHttpEndpointService(HttpServer.ApiType.GC);

//1, GET, should return NOT_FOUND
HttpServiceRequest request1 = new HttpServiceRequest(null, HttpServer.Method.GET, null);
HttpServiceResponse response1 = triggerGCService.handle(request1);
assertEquals(HttpServer.StatusCode.NOT_FOUND.getValue(), response1.getStatusCode());

//2, PUT, should return OK
HttpServiceRequest request2 = new HttpServiceRequest(null, HttpServer.Method.PUT, null);
HttpServiceResponse response2 = triggerGCService.handle(request2);
assertEquals(HttpServer.StatusCode.OK.getValue(), response2.getStatusCode());
}
}
11 changes: 11 additions & 0 deletions site/docs/latest/admin/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,17 @@ Currently all the HTTP endpoints could be divided into these 4 components:
|403 | Permission denied |
|404 | Not found |

### Endpoint: /api/v1/bookie/gc
1. Method: PUT
* Description: trigger gc for this bookie.
* Response:

| Code | Description |
|:-------|:------------|
|200 | Successful operation |
|403 | Permission denied |
|404 | Not found |

## Auto recovery

### Endpoint: /api/v1/autorecovery/bookie/
Expand Down

0 comments on commit 641db3b

Please sign in to comment.