This is an automated email from the ASF dual-hosted git repository. sijie pushed a commit to branch branch-4.8 in repository https://gitbox.apache.org/repos/asf/bookkeeper.git
The following commit(s) were added to refs/heads/branch-4.8 by this push: new 0c98b40 Add rest endpoint trigger_gc to trigger GC on Bookie 0c98b40 is described below commit 0c98b400221b5e508807dd96f71c5bec5da89c65 Author: Jia Zhai <jiaz...@users.noreply.github.com> AuthorDate: Tue Nov 27 18:16:19 2018 +0800 Add rest endpoint trigger_gc to trigger GC on Bookie 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 <eolive...@gmail.com>, Sijie Guo <si...@apache.org> This closes #1838 from jiazhai/rest_force_gc (cherry picked from commit 641db3b4ff29d8e04216fee84625546707631e8e) Signed-off-by: Sijie Guo <si...@apache.org> --- .../org/apache/bookkeeper/http/HttpRouter.java | 2 + .../org/apache/bookkeeper/http/HttpServer.java | 1 + .../bookkeeper/bookie/GarbageCollectorThread.java | 7 +++ .../bookie/InterleavedLedgerStorage.java | 5 ++ .../apache/bookkeeper/bookie/LedgerStorage.java | 6 ++ .../bookkeeper/bookie/SortedLedgerStorage.java | 5 ++ .../bookie/storage/ldb/DbLedgerStorage.java | 4 ++ .../ldb/SingleDirectoryDbLedgerStorage.java | 5 ++ .../server/http/BKHttpServiceProvider.java | 3 + .../server/http/service/TriggerGCService.java | 71 ++++++++++++++++++++++ .../bookkeeper/server/http/TestHttpService.java | 38 ++++++++++++ site/docs/latest/admin/http.md | 11 ++++ 12 files changed, 158 insertions(+) diff --git a/bookkeeper-http/http-server/src/main/java/org/apache/bookkeeper/http/HttpRouter.java b/bookkeeper-http/http-server/src/main/java/org/apache/bookkeeper/http/HttpRouter.java index a856c72..5384df6 100644 --- a/bookkeeper-http/http-server/src/main/java/org/apache/bookkeeper/http/HttpRouter.java +++ b/bookkeeper-http/http-server/src/main/java/org/apache/bookkeeper/http/HttpRouter.java @@ -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"; @@ -73,6 +74,7 @@ public abstract class HttpRouter<Handler> { 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)); diff --git a/bookkeeper-http/http-server/src/main/java/org/apache/bookkeeper/http/HttpServer.java b/bookkeeper-http/http-server/src/main/java/org/apache/bookkeeper/http/HttpServer.java index 30e4d05..5e9f509 100644 --- a/bookkeeper-http/http-server/src/main/java/org/apache/bookkeeper/http/HttpServer.java +++ b/bookkeeper-http/http-server/src/main/java/org/apache/bookkeeper/http/HttpServer.java @@ -77,6 +77,7 @@ public interface HttpServer { LAST_LOG_MARK, LIST_DISK_FILE, EXPAND_STORAGE, + GC, // autorecovery RECOVERY_BOOKIE, LIST_UNDER_REPLICATED_LEDGER, diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java index ad752de..c4d9414 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java @@ -382,6 +382,13 @@ public class GarbageCollectorThread extends SafeRunnable { 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); } diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/InterleavedLedgerStorage.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/InterleavedLedgerStorage.java index 8ab6517..d7d4977 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/InterleavedLedgerStorage.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/InterleavedLedgerStorage.java @@ -192,6 +192,11 @@ public class InterleavedLedgerStorage implements CompactableLedgerStorage, Entry } @Override + public void forceGC() { + gcThread.enableForceGC(); + } + + @Override public void start() { gcThread.start(); } diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerStorage.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerStorage.java index 34e32b9..ef64ff9 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerStorage.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerStorage.java @@ -175,4 +175,10 @@ public interface LedgerStorage { return this; } + /** + * Force trigger Garbage Collection. + */ + default void forceGC() { + return; + } } diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/SortedLedgerStorage.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/SortedLedgerStorage.java index e4b137f..dd7b373 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/SortedLedgerStorage.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/SortedLedgerStorage.java @@ -327,4 +327,9 @@ public class SortedLedgerStorage public LedgerStorage getUnderlyingLedgerStorage() { return interleavedLedgerStorage; } + + @Override + public void forceGC() { + interleavedLedgerStorage.forceGC(); + } } diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/DbLedgerStorage.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/DbLedgerStorage.java index 8753363..831de53 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/DbLedgerStorage.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/DbLedgerStorage.java @@ -348,4 +348,8 @@ public class DbLedgerStorage implements LedgerStorage { } } + @Override + public void forceGC() { + ledgerStorageList.stream().forEach(SingleDirectoryDbLedgerStorage::forceGC); + } } diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/SingleDirectoryDbLedgerStorage.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/SingleDirectoryDbLedgerStorage.java index e31b44e..27b4214 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/SingleDirectoryDbLedgerStorage.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/SingleDirectoryDbLedgerStorage.java @@ -264,6 +264,11 @@ public class SingleDirectoryDbLedgerStorage implements CompactableLedgerStorage } @Override + public void forceGC() { + gcThread.enableForceGC(); + } + + @Override public void shutdown() throws InterruptedException { try { flush(); diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/BKHttpServiceProvider.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/BKHttpServiceProvider.java index 052b50e..102b0eb 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/BKHttpServiceProvider.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/BKHttpServiceProvider.java @@ -53,6 +53,7 @@ import org.apache.bookkeeper.server.http.service.MetricsService; 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; @@ -208,6 +209,8 @@ public class BKHttpServiceProvider implements HttpServiceProvider { return new ListDiskFilesService(configuration); case EXPAND_STORAGE: return new ExpandStorageService(configuration); + case GC: + return new TriggerGCService(configuration, bookieServer); // autorecovery case RECOVERY_BOOKIE: diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/service/TriggerGCService.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/service/TriggerGCService.java new file mode 100644 index 0000000..185965a --- /dev/null +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/service/TriggerGCService.java @@ -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; + } + } +} diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/server/http/TestHttpService.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/server/http/TestHttpService.java index 5d87ca9..c3859d6 100644 --- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/server/http/TestHttpService.java +++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/server/http/TestHttpService.java @@ -749,4 +749,42 @@ public class TestHttpService extends BookKeeperClusterTestCase { 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()); + } } diff --git a/site/docs/latest/admin/http.md b/site/docs/latest/admin/http.md index dc64744..7c1abea 100644 --- a/site/docs/latest/admin/http.md +++ b/site/docs/latest/admin/http.md @@ -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/