Index: src/main/java/org/apache/jackrabbit/oak/plugins/document/Checkpoints.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- src/main/java/org/apache/jackrabbit/oak/plugins/document/Checkpoints.java (revision 1640726) +++ src/main/java/org/apache/jackrabbit/oak/plugins/document/Checkpoints.java (revision ) @@ -124,7 +124,7 @@ @SuppressWarnings("unchecked") @CheckForNull - private SortedMap getCheckpoints() { + SortedMap getCheckpoints() { Document cdoc = store.find(Collection.SETTINGS, ID, 0); return (SortedMap) cdoc.get(PROP_CHECKPOINT); } Index: src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java (revision 1640726) +++ src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java (revision ) @@ -18,6 +18,12 @@ */ package org.apache.jackrabbit.oak.plugins.document; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toBoolean; +import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toInteger; +import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toLong; +import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean; + import java.io.IOException; import java.util.ArrayList; import java.util.Dictionary; @@ -42,6 +48,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.ReferencePolicy; import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean; +import org.apache.jackrabbit.oak.api.jmx.CheckpointMBean; import org.apache.jackrabbit.oak.commons.PropertiesUtil; import org.apache.jackrabbit.oak.kernel.KernelNodeStore; import org.apache.jackrabbit.oak.osgi.ObserverTracker; @@ -66,12 +73,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toBoolean; -import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toInteger; -import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toLong; -import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean; - /** * The OSGi service to start/stop a DocumentNodeStore instance. */ @@ -413,6 +414,13 @@ store.getDocChildrenCacheStats(), CacheStatsMBean.TYPE, store.getDocChildrenCacheStats().getName()) + ); + registrations.add( + registerMBean(whiteboard, + CheckpointMBean.class, + new DocumentCheckpointMBean(store), + CheckpointMBean.TYPE, + "Document node store checkpoint management") ); DiffCache cl = store.getDiffCache(); if (cl instanceof MemoryDiffCache) { Index: src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointMBean.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointMBean.java (revision ) +++ src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointMBean.java (revision ) @@ -0,0 +1,106 @@ +/* + * 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.jackrabbit.oak.plugins.document; + +import java.util.Collections; +import java.util.Date; +import java.util.Map; +import java.util.Map.Entry; + +import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.OpenDataException; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; +import javax.management.openmbean.TabularData; +import javax.management.openmbean.TabularDataSupport; +import javax.management.openmbean.TabularType; + +import org.apache.jackrabbit.oak.api.jmx.CheckpointMBean; + +/** + * {@code CheckpointMBean} implementation for the {@code DocumentNodeStore}. + */ +public class DocumentCheckpointMBean implements CheckpointMBean { + private static final String[] FIELD_NAMES = new String[] { "id", "created", "expires"}; + private static final String[] FIELD_DESCRIPTIONS = FIELD_NAMES; + + @SuppressWarnings("rawtypes") + private static final OpenType[] FIELD_TYPES = new OpenType[] { + SimpleType.STRING, SimpleType.STRING, SimpleType.STRING }; + + private static final CompositeType TYPE = createCompositeType(); + + private static CompositeType createCompositeType() { + try { + return new CompositeType(DocumentCheckpointMBean.class.getName(), + "Checkpoints", FIELD_NAMES, FIELD_DESCRIPTIONS, FIELD_TYPES); + } catch (OpenDataException e) { + throw new IllegalStateException(e); + } + } + + private final DocumentNodeStore store; + + public DocumentCheckpointMBean(DocumentNodeStore store) { + this.store = store; + } + + @Override + public TabularData listCheckpoints() { + Map checkpoints = store.getCheckpoints().getCheckpoints(); + if (checkpoints == null) { + checkpoints = Collections.emptyMap(); + } + + try { + TabularDataSupport tab = new TabularDataSupport( + new TabularType(DocumentCheckpointMBean.class.getName(), + "Checkpoints", TYPE, new String[] { "id" })); + + for (Entry checkpoint : checkpoints.entrySet()) { + String id = checkpoint.getKey().toString(); + Date created = new Date(checkpoint.getKey().getTimestamp()); + Date expires = new Date(Long.parseLong(checkpoint.getValue())); + tab.put(id, toCompositeData(id, created.toString(), expires.toString())); + } + + return tab; + } catch (OpenDataException e) { + throw new IllegalStateException(e); + } + } + + private static CompositeDataSupport toCompositeData(String id, String created, String expires) + throws OpenDataException { + return new CompositeDataSupport(TYPE, FIELD_NAMES, new String[] { id, created, expires }); + } + + @Override + public String createCheckpoint(long lifetime) { + return store.checkpoint(lifetime); + } + + @Override + public boolean releaseCheckpoint(String checkpoint) { + return store.release(checkpoint); + } + +}