You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bookkeeper.apache.org by si...@apache.org on 2018/12/13 14:45:15 UTC
[bookkeeper] branch master updated: Add get method for rest
endpoint gc
This is an automated email from the ASF dual-hosted git repository.
sijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git
The following commit(s) were added to refs/heads/master by this push:
new e05850a Add get method for rest endpoint gc
e05850a is described below
commit e05850aad6d0cff0dcb143e90bbbedcc88b2caef
Author: Jia Zhai <ji...@users.noreply.github.com>
AuthorDate: Thu Dec 13 22:45:09 2018 +0800
Add get method for rest endpoint gc
Descriptions of the changes in this PR:
Add get method for rest endpoint gc to get force triggered GC running status on Bookie.
true -- force triggered GC is running on Bookie. false -- not running.
### Motivation
This is base on PR #1838, and in the review comments sijie is suggested to add get methods.
### Changes
Add get method for rest endpoint gc and unit test.
Reviewers: Sijie Guo <si...@apache.org>
This closes #1840 from jiazhai/rest_gc_get
---
.../org/apache/bookkeeper/http/HttpRouter.java | 2 +
.../org/apache/bookkeeper/http/HttpServer.java | 2 +
.../bookkeeper/bookie/GarbageCollectionStatus.java | 47 +++++++++++++++++++
.../bookkeeper/bookie/GarbageCollectorThread.java | 24 ++++++++++
.../bookie/InterleavedLedgerStorage.java | 31 ++++++++-----
.../apache/bookkeeper/bookie/LedgerStorage.java | 21 +++++++++
.../bookkeeper/bookie/SortedLedgerStorage.java | 10 +++++
.../bookie/storage/ldb/DbLedgerStorage.java | 13 ++++++
.../ldb/SingleDirectoryDbLedgerStorage.java | 13 ++++++
.../server/http/BKHttpServiceProvider.java | 3 ++
...TriggerGCService.java => GCDetailsService.java} | 38 +++++++++++-----
.../server/http/service/TriggerGCService.java | 25 +++++++++--
.../bookkeeper/server/http/TestHttpService.java | 52 +++++++++++++++++++---
site/docs/latest/admin/http.md | 39 ++++++++++++++++
14 files changed, 290 insertions(+), 30 deletions(-)
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 5384df6..b4251d7 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
@@ -46,6 +46,7 @@ public abstract class HttpRouter<Handler> {
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";
+ public static final String GC_DETAILS = "/api/v1/bookie/gc_details";
// 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";
@@ -75,6 +76,7 @@ public abstract class HttpRouter<Handler> {
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));
+ this.endpointHandlers.put(GC_DETAILS, handlerFactory.newHandler(HttpServer.ApiType.GC_DETAILS));
// 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 5e9f509..0922b56 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
@@ -78,6 +78,8 @@ public interface HttpServer {
LIST_DISK_FILE,
EXPAND_STORAGE,
GC,
+ GC_DETAILS,
+
// autorecovery
RECOVERY_BOOKIE,
LIST_UNDER_REPLICATED_LEDGER,
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectionStatus.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectionStatus.java
new file mode 100644
index 0000000..e1728dd
--- /dev/null
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectionStatus.java
@@ -0,0 +1,47 @@
+/**
+ *
+ * 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.bookie;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * This is the garbage collection thread status.
+ * It includes what phase GarbageCollection (major/minor), gc counters, last gc time, etc.
+ */
+@Setter
+@Getter
+@Builder
+public class GarbageCollectionStatus {
+ // whether the GC thread is in force GC.
+ private boolean forceCompacting;
+ // whether the GC thread is in major compacting.
+ private boolean majorCompacting;
+ // whether the GC thread is in minor compacting.
+ private boolean minorCompacting;
+
+ private long lastMajorCompactionTime;
+ private long lastMinorCompactionTime;
+ private long majorCompactionCounter;
+ private long minorCompactionCounter;
+}
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 369883c..ca02651 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
@@ -108,6 +108,10 @@ public class GarbageCollectorThread extends SafeRunnable {
// to reduce the risk getting entry log corrupted
final AtomicBoolean compacting = new AtomicBoolean(false);
+ // use to get the compacting status
+ final AtomicBoolean minorCompacting = new AtomicBoolean(false);
+ final AtomicBoolean majorCompacting = new AtomicBoolean(false);
+
volatile boolean running = true;
// track the last scanned successfully log id
@@ -298,6 +302,10 @@ public class GarbageCollectorThread extends SafeRunnable {
});
}
+ public boolean isInForceGC() {
+ return forceGarbageCollection.get();
+ }
+
public void suspendMajorGC() {
if (suspendMajorCompaction.compareAndSet(false, true)) {
LOG.info("Suspend Major Compaction triggered by thread: {}", Thread.currentThread().getName());
@@ -376,18 +384,22 @@ public class GarbageCollectorThread extends SafeRunnable {
&& (force || curTime - lastMajorCompactionTime > majorCompactionInterval)) {
// enter major compaction
LOG.info("Enter major compaction, suspendMajor {}", suspendMajor);
+ majorCompacting.set(true);
doCompactEntryLogs(majorCompactionThreshold);
lastMajorCompactionTime = System.currentTimeMillis();
// and also move minor compaction time
lastMinorCompactionTime = lastMajorCompactionTime;
majorCompactionCounter.inc();
+ majorCompacting.set(false);
} else if (enableMinorCompaction && (!suspendMinor)
&& (force || curTime - lastMinorCompactionTime > minorCompactionInterval)) {
// enter minor compaction
LOG.info("Enter minor compaction, suspendMinor {}", suspendMinor);
+ minorCompacting.set(true);
doCompactEntryLogs(minorCompactionThreshold);
lastMinorCompactionTime = System.currentTimeMillis();
minorCompactionCounter.inc();
+ minorCompacting.set(false);
}
if (force) {
@@ -601,4 +613,16 @@ public class GarbageCollectorThread extends SafeRunnable {
CompactableLedgerStorage getLedgerStorage() {
return ledgerStorage;
}
+
+ public GarbageCollectionStatus getGarbageCollectionStatus() {
+ return GarbageCollectionStatus.builder()
+ .forceCompacting(forceGarbageCollection.get())
+ .majorCompacting(majorCompacting.get())
+ .minorCompacting(minorCompacting.get())
+ .lastMajorCompactionTime(lastMajorCompactionTime)
+ .lastMinorCompactionTime(lastMinorCompactionTime)
+ .majorCompactionCounter(majorCompactionCounter.get())
+ .minorCompactionCounter(minorCompactionCounter.get())
+ .build();
+ }
}
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 0a0e60d..6078d69 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
@@ -37,6 +37,7 @@ import io.netty.buffer.ByteBuf;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
@@ -227,6 +228,11 @@ public class InterleavedLedgerStorage implements CompactableLedgerStorage, Entry
}
@Override
+ public boolean isInForceGC() {
+ return gcThread.isInForceGC();
+ }
+
+ @Override
public void start() {
gcThread.start();
}
@@ -563,10 +569,10 @@ public class InterleavedLedgerStorage implements CompactableLedgerStorage, Entry
if (success.booleanValue()) {
pageScanStats.registerSuccessfulEvent(
- MathUtils.elapsedNanos(start), TimeUnit.NANOSECONDS);
+ MathUtils.elapsedNanos(start), TimeUnit.NANOSECONDS);
} else {
pageScanStats.registerFailedEvent(
- MathUtils.elapsedNanos(start), TimeUnit.NANOSECONDS);
+ MathUtils.elapsedNanos(start), TimeUnit.NANOSECONDS);
}
} while (retry.booleanValue());
checkedPages++;
@@ -584,15 +590,20 @@ public class InterleavedLedgerStorage implements CompactableLedgerStorage, Entry
checkedLedgers++;
}
LOG.info(
- "Finished localConsistencyCheck, took {}s to scan {} ledgers, {} pages, "
- + "{} entries with {} retries, {} errors",
- TimeUnit.NANOSECONDS.toSeconds(MathUtils.elapsedNanos(checkStart)),
- checkedLedgers,
- checkedPages,
- checkedEntries.longValue(),
- pageRetries.longValue(),
- errors.size());
+ "Finished localConsistencyCheck, took {}s to scan {} ledgers, {} pages, "
+ + "{} entries with {} retries, {} errors",
+ TimeUnit.NANOSECONDS.toSeconds(MathUtils.elapsedNanos(checkStart)),
+ checkedLedgers,
+ checkedPages,
+ checkedEntries.longValue(),
+ pageRetries.longValue(),
+ errors.size());
return errors;
}
+
+ @Override
+ public List<GarbageCollectionStatus> getGarbageCollectionStatus() {
+ return Collections.singletonList(gcThread.getGarbageCollectionStatus());
+ }
}
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 7a98fc7..111b8c2 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
@@ -25,6 +25,7 @@ import com.google.common.util.concurrent.RateLimiter;
import io.netty.buffer.ByteBuf;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.apache.bookkeeper.bookie.CheckpointSource.Checkpoint;
@@ -224,4 +225,24 @@ public interface LedgerStorage {
default List<DetectedInconsistency> localConsistencyCheck(Optional<RateLimiter> rateLimiter) throws IOException {
return new ArrayList<>();
}
+
+ /**
+ * Whether force triggered Garbage Collection is running or not.
+ *
+ * @return
+ * true -- force triggered Garbage Collection is running,
+ * false -- force triggered Garbage Collection is not running
+ */
+ default boolean isInForceGC() {
+ return false;
+ }
+
+
+ /**
+ * Get Garbage Collection status.
+ * Since DbLedgerStorage is a list of storage instances, we should return a list.
+ */
+ default List<GarbageCollectionStatus> getGarbageCollectionStatus() {
+ return Collections.emptyList();
+ }
}
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 dd07d75..5e4dbad 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
@@ -340,4 +340,14 @@ public class SortedLedgerStorage
public List<DetectedInconsistency> localConsistencyCheck(Optional<RateLimiter> rateLimiter) throws IOException {
return interleavedLedgerStorage.localConsistencyCheck(rateLimiter);
}
+
+ @Override
+ public boolean isInForceGC() {
+ return interleavedLedgerStorage.isInForceGC();
+ }
+
+ @Override
+ public List<GarbageCollectionStatus> getGarbageCollectionStatus() {
+ return interleavedLedgerStorage.getGarbageCollectionStatus();
+ }
}
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 4c5fd33..0706565 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
@@ -39,12 +39,14 @@ import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.bookkeeper.bookie.BookieException;
import org.apache.bookkeeper.bookie.CheckpointSource;
import org.apache.bookkeeper.bookie.CheckpointSource.Checkpoint;
import org.apache.bookkeeper.bookie.Checkpointer;
+import org.apache.bookkeeper.bookie.GarbageCollectionStatus;
import org.apache.bookkeeper.bookie.LastAddConfirmedUpdateNotification;
import org.apache.bookkeeper.bookie.LedgerCache;
import org.apache.bookkeeper.bookie.LedgerDirsManager;
@@ -359,4 +361,15 @@ public class DbLedgerStorage implements LedgerStorage {
public void forceGC() {
ledgerStorageList.stream().forEach(SingleDirectoryDbLedgerStorage::forceGC);
}
+
+ @Override
+ public boolean isInForceGC() {
+ return ledgerStorageList.stream().anyMatch(SingleDirectoryDbLedgerStorage::isInForceGC);
+ }
+
+ @Override
+ public List<GarbageCollectionStatus> getGarbageCollectionStatus() {
+ return ledgerStorageList.stream()
+ .map(single -> single.getGarbageCollectionStatus().get(0)).collect(Collectors.toList());
+ }
}
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 2e3c556..58504ab 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
@@ -30,6 +30,8 @@ import io.netty.buffer.ByteBuf;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -49,6 +51,7 @@ import org.apache.bookkeeper.bookie.Checkpointer;
import org.apache.bookkeeper.bookie.CompactableLedgerStorage;
import org.apache.bookkeeper.bookie.EntryLocation;
import org.apache.bookkeeper.bookie.EntryLogger;
+import org.apache.bookkeeper.bookie.GarbageCollectionStatus;
import org.apache.bookkeeper.bookie.GarbageCollectorThread;
import org.apache.bookkeeper.bookie.LastAddConfirmedUpdateNotification;
import org.apache.bookkeeper.bookie.LedgerCache;
@@ -270,6 +273,11 @@ public class SingleDirectoryDbLedgerStorage implements CompactableLedgerStorage
}
@Override
+ public boolean isInForceGC() {
+ return gcThread.isInForceGC();
+ }
+
+ @Override
public void shutdown() throws InterruptedException {
try {
flush();
@@ -922,6 +930,11 @@ public class SingleDirectoryDbLedgerStorage implements CompactableLedgerStorage
return readCache.count();
}
+ @Override
+ public List<GarbageCollectionStatus> getGarbageCollectionStatus() {
+ return Collections.singletonList(gcThread.getGarbageCollectionStatus());
+ }
+
/**
* Interface which process ledger logger.
*/
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 102b0eb..662777c 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
@@ -41,6 +41,7 @@ import org.apache.bookkeeper.server.http.service.ConfigurationService;
import org.apache.bookkeeper.server.http.service.DecommissionService;
import org.apache.bookkeeper.server.http.service.DeleteLedgerService;
import org.apache.bookkeeper.server.http.service.ExpandStorageService;
+import org.apache.bookkeeper.server.http.service.GCDetailsService;
import org.apache.bookkeeper.server.http.service.GetLastLogMarkService;
import org.apache.bookkeeper.server.http.service.GetLedgerMetaService;
import org.apache.bookkeeper.server.http.service.ListBookieInfoService;
@@ -211,6 +212,8 @@ public class BKHttpServiceProvider implements HttpServiceProvider {
return new ExpandStorageService(configuration);
case GC:
return new TriggerGCService(configuration, bookieServer);
+ case GC_DETAILS:
+ return new GCDetailsService(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/GCDetailsService.java
similarity index 61%
copy from bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/service/TriggerGCService.java
copy to bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/service/GCDetailsService.java
index 185965a..29b59e2 100644
--- 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/GCDetailsService.java
@@ -20,6 +20,8 @@ package org.apache.bookkeeper.server.http.service;
import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.List;
+import org.apache.bookkeeper.bookie.GarbageCollectionStatus;
import org.apache.bookkeeper.common.util.JsonUtil;
import org.apache.bookkeeper.conf.ServerConfiguration;
import org.apache.bookkeeper.http.HttpServer;
@@ -31,18 +33,27 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * HttpEndpointService that handle force trigger GC requests.
+ * HttpEndpointService that handle get garbage collection details service.
*
- * <p>The PUT method will force trigger GC on current bookie, and make GC run at backend.
+ * <p>Get Garbage Collection status, the output would be like:
+ * [ {
+ * "forceCompacting" : false,
+ * "majorCompacting" : false,
+ * "minorCompacting" : false,
+ * "lastMajorCompactionTime" : 1544578144944,
+ * "lastMinorCompactionTime" : 1544578144944,
+ * "majorCompactionCounter" : 1,
+ * "minorCompactionCounter" : 0
+ * } ]
*/
-public class TriggerGCService implements HttpEndpointService {
+public class GCDetailsService implements HttpEndpointService {
- static final Logger LOG = LoggerFactory.getLogger(TriggerGCService.class);
+ static final Logger LOG = LoggerFactory.getLogger(GCDetailsService.class);
protected ServerConfiguration conf;
protected BookieServer bookieServer;
- public TriggerGCService(ServerConfiguration conf, BookieServer bookieServer) {
+ public GCDetailsService(ServerConfiguration conf, BookieServer bookieServer) {
checkNotNull(conf);
checkNotNull(bookieServer);
this.conf = conf;
@@ -52,19 +63,22 @@ public class TriggerGCService implements HttpEndpointService {
@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);
+ if (HttpServer.Method.GET == request.getMethod()) {
+ List<GarbageCollectionStatus> details = bookieServer.getBookie()
+ .getLedgerStorage().getGarbageCollectionStatus();
+
+ String jsonResponse = JsonUtil.toJson(details);
+ if (LOG.isDebugEnabled()) {
+ 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.");
+ response.setBody("Only support GET method to retrieve GC details."
+ + " If you want to trigger gc, send a POST to gc endpoint.");
return response;
}
}
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
index 185965a..ebf9ea9 100644
--- 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
@@ -27,6 +27,7 @@ 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.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,6 +35,12 @@ 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.
+ *
+ * <p>The GET method will get the force triggered GC running or not.
+ * Output would be like:
+ * {
+ * "is_in_force_gc" : "false"
+ * }
*/
public class TriggerGCService implements HttpEndpointService {
@@ -52,19 +59,31 @@ public class TriggerGCService implements HttpEndpointService {
@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);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("output body:" + jsonResponse);
+ }
+ response.setBody(jsonResponse);
+ response.setCode(HttpServer.StatusCode.OK);
+ return response;
+ } else if (HttpServer.Method.GET == request.getMethod()) {
+ Boolean isInForceGC = bookieServer.getBookie().getLedgerStorage().isInForceGC();
+ Pair<String, String> output = Pair.of("is_in_force_gc", isInForceGC.toString());
+ String jsonResponse = JsonUtil.toJson(output);
+ if (LOG.isDebugEnabled()) {
+ 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.");
+ response.setBody("Not found method. Should be PUT to trigger GC, Or GET to get Force GC state.");
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 e88d29d..da25d14 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
@@ -743,9 +743,6 @@ public class TestHttpService extends BookKeeperClusterTestCase {
stopAuditorElector();
}
- /**
- * Create ledgers, then test Delete Ledger service.
- */
@Test
public void testTriggerGCService() throws Exception {
baseConf.setMetadataServiceUri(zkUtil.getMetadataServiceUri());
@@ -771,14 +768,59 @@ public class TestHttpService extends BookKeeperClusterTestCase {
HttpEndpointService triggerGCService = bkHttpServiceProvider
.provideHttpEndpointService(HttpServer.ApiType.GC);
- //1, GET, should return NOT_FOUND
+ //1, GET, should return OK
HttpServiceRequest request1 = new HttpServiceRequest(null, HttpServer.Method.GET, null);
HttpServiceResponse response1 = triggerGCService.handle(request1);
- assertEquals(HttpServer.StatusCode.NOT_FOUND.getValue(), response1.getStatusCode());
+ assertEquals(HttpServer.StatusCode.OK.getValue(), response1.getStatusCode());
+ assertTrue(response1.getBody().contains("\"is_in_force_gc\" : \"false\""));
//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());
}
+
+ @Test
+ public void testGCDetailsService() 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 = "This is test for GC details service!";
+ // 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 gcDetailsService = bkHttpServiceProvider
+ .provideHttpEndpointService(HttpServer.ApiType.GC_DETAILS);
+
+ // force trigger a GC
+ HttpEndpointService triggerGCService = bkHttpServiceProvider
+ .provideHttpEndpointService(HttpServer.ApiType.GC);
+ HttpServiceRequest request0 = new HttpServiceRequest(null, HttpServer.Method.PUT, null);
+ HttpServiceResponse response0 = triggerGCService.handle(request0);
+ assertEquals(HttpServer.StatusCode.OK.getValue(), response0.getStatusCode());
+
+ //1, GET, should return OK
+ HttpServiceRequest request1 = new HttpServiceRequest(null, HttpServer.Method.GET, null);
+ HttpServiceResponse response1 = gcDetailsService.handle(request1);
+ assertEquals(HttpServer.StatusCode.OK.getValue(), response1.getStatusCode());
+ LOG.info("Get response: {}", response1.getBody());
+
+ //2, PUT, should return NOT_FOUND
+ HttpServiceRequest request3 = new HttpServiceRequest(null, HttpServer.Method.PUT, null);
+ HttpServiceResponse response3 = gcDetailsService.handle(request3);
+ assertEquals(HttpServer.StatusCode.NOT_FOUND.getValue(), response3.getStatusCode());
+ }
}
diff --git a/site/docs/latest/admin/http.md b/site/docs/latest/admin/http.md
index 7c1abea..270dcb3 100644
--- a/site/docs/latest/admin/http.md
+++ b/site/docs/latest/admin/http.md
@@ -282,6 +282,45 @@ Currently all the HTTP endpoints could be divided into these 4 components:
|403 | Permission denied |
|404 | Not found |
+1. Method: GET
+ * Description: whether force triggered Garbage Collection is running or not for this bookie. true for is running.
+ * Response:
+
+ | Code | Description |
+ |:-------|:------------|
+ |200 | Successful operation |
+ |403 | Permission denied |
+ |404 | Not found |
+ * Body:
+ ```json
+ {
+ "is_in_force_gc" : "false"
+ }
+ ```
+
+### Endpoint: /api/v1/bookie/gc_details
+1. Method: GET
+ * Description: get details of Garbage Collection Thread, like whether it is in compacting, last compaction time, compaction counter, etc.
+ * Response:
+
+ | Code | Description |
+ |:-------|:------------|
+ |200 | Successful operation |
+ |403 | Permission denied |
+ |404 | Not found |
+ * Body:
+ ```json
+ [ {
+ "forceCompacting" : false,
+ "majorCompacting" : false,
+ "minorCompacting" : false,
+ "lastMajorCompactionTime" : 1544578144944,
+ "lastMinorCompactionTime" : 1544578144944,
+ "majorCompactionCounter" : 1,
+ "minorCompactionCounter" : 0
+ } ]
+ ```
+
## Auto recovery
### Endpoint: /api/v1/autorecovery/bookie/