Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentCheckpointMBean.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentCheckpointMBean.java (revision ) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentCheckpointMBean.java (revision ) @@ -0,0 +1,114 @@ +/* + * 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.segment; + +import java.util.Date; + +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.PropertyState; +import org.apache.jackrabbit.oak.api.Type; +import org.apache.jackrabbit.oak.api.jmx.CheckpointMBean; +import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry; +import org.apache.jackrabbit.oak.spi.state.NodeState; + +/** + * {@code CheckpointMBean} implementation for the {@code SegmentNodeStore}. + */ +public class SegmentCheckpointMBean 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(SegmentCheckpointMBean.class.getName(), + "Checkpoints", FIELD_NAMES, FIELD_DESCRIPTIONS, FIELD_TYPES); + } catch (OpenDataException e) { + throw new IllegalStateException(e); + } + } + + private final SegmentNodeStore store; + + public SegmentCheckpointMBean(SegmentNodeStore store) { + this.store = store; + } + + @Override + public TabularData listCheckpoints() { + NodeState checkpoints = store.getCheckpoints(); + + try { + TabularDataSupport tab = new TabularDataSupport( + new TabularType(SegmentCheckpointMBean.class.getName(), + "Checkpoints", TYPE, new String[] { "id" })); + + for (ChildNodeEntry cne : checkpoints.getChildNodeEntries()) { + String id = cne.getName(); + NodeState checkpoint = cne.getNodeState(); + String created = getDate(checkpoint, "created"); + String expires = getDate(checkpoint, "timestamp"); + tab.put(id, toCompositeData(id, created, expires)); + } + + 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 }); + } + + private static String getDate(NodeState checkpoint, String name) { + PropertyState p = checkpoint.getProperty(name); + if (p == null) { + return "NA"; + } + + return new Date(p.getValue(Type.LONG)).toString(); + } + + @Override + public String createCheckpoint(long lifetime) { + return store.checkpoint(lifetime); + } + + @Override + public boolean releaseCheckpoint(String checkpoint) { + return store.release(checkpoint); + } + +} Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java (revision 0ba98a1c19a9934c1b14d02d5b633a422cd89e4d) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java (revision ) @@ -35,6 +35,7 @@ import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.ReferencePolicy; +import org.apache.jackrabbit.oak.api.jmx.CheckpointMBean; import org.apache.jackrabbit.oak.osgi.ObserverTracker; import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard; import org.apache.jackrabbit.oak.plugins.blob.BlobGC; @@ -108,6 +109,7 @@ private ServiceRegistration storeRegistration; private ServiceRegistration providerRegistration; + private Registration checkpointRegistration; private Registration revisionGCRegistration; private Registration blobGCRegistration; private WhiteboardExecutor executor; @@ -188,6 +190,9 @@ executor = new WhiteboardExecutor(); executor.start(whiteboard); + checkpointRegistration = registerMBean(whiteboard, CheckpointMBean.class, new SegmentCheckpointMBean(delegate), + CheckpointMBean.TYPE, "Segment node store checkpoint management"); + RevisionGC revisionGC = new RevisionGC(new Runnable() { @Override public void run() { @@ -255,6 +260,10 @@ if(storeRegistration != null){ storeRegistration.unregister(); storeRegistration = null; + } + if (checkpointRegistration != null) { + checkpointRegistration.unregister(); + checkpointRegistration = null; } if (revisionGCRegistration != null) { revisionGCRegistration.unregister(); Index: oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/CheckpointMBean.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/CheckpointMBean.java (revision ) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/CheckpointMBean.java (revision ) @@ -0,0 +1,52 @@ +/* + * 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.api.jmx; + +import javax.management.openmbean.TabularData; + +/** + * MBean for managing {@link org.apache.jackrabbit.oak.spi.state.NodeStore#checkpoint checkpoints}. + */ +public interface CheckpointMBean { + String TYPE = "CheckpointManger"; + + /** + * List the checkpoints that are currently present along with + * its id, creation time and expiry time. + * @return + */ + TabularData listCheckpoints(); + + /** + * Create a new checkpoint with the given {@code lifetime}. + * @param lifetime + * @return the id of the newly created checkpoint + * @see org.apache.jackrabbit.oak.spi.state.NodeStore#checkpoint + */ + String createCheckpoint(long lifetime); + + /** + * Release the checkpoint with the given {@code id}. + * @param id + * @return {@code true} on success, {@code false} otherwise. + * @see org.apache.jackrabbit.oak.spi.state.NodeStore#checkpoint + */ + boolean releaseCheckpoint(String id); +} Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java (revision 0ba98a1c19a9934c1b14d02d5b633a422cd89e4d) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java (revision ) @@ -302,6 +302,10 @@ return false; } + NodeState getCheckpoints() { + return head.get().getChildNode(CHECKPOINTS); + } + private class Commit { private final Random random = new Random();