From 6d1adc785e87fcf45219afc07cc435c6e9570b95 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Fri, 08 Dec 2006 23:54:57 +0000
Subject: [PATCH] Update the backend API to provide a method for getting the number of entries contained in that backend. Also, create a new monitor entry for each registered backend that will report the backend ID, base DNs, writability mode, and entry count for that backend.
---
opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java | 14 +
opendj-sdk/opends/src/server/org/opends/server/api/Backend.java | 47 +++++
opendj-sdk/opends/src/server/org/opends/server/backends/task/TaskBackend.java | 17 ++
opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java | 13 +
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java | 24 +++
opendj-sdk/opends/src/server/org/opends/server/backends/BackupBackend.java | 28 +++
opendj-sdk/opends/src/server/org/opends/server/backends/MonitorBackend.java | 12 +
opendj-sdk/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java | 12 +
opendj-sdk/opends/src/server/org/opends/server/backends/RootDSEBackend.java | 13 +
opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java | 33 ++++
opendj-sdk/opends/src/server/org/opends/server/backends/MemoryBackend.java | 17 ++
opendj-sdk/opends/src/server/org/opends/server/backends/task/TaskScheduler.java | 23 ++
opendj-sdk/opends/src/server/org/opends/server/monitors/BackendMonitor.java | 207 +++++++++++++++++++++++++
opendj-sdk/opends/resource/schema/02-config.ldif | 11 +
14 files changed, 471 insertions(+), 0 deletions(-)
diff --git a/opendj-sdk/opends/resource/schema/02-config.ldif b/opendj-sdk/opends/resource/schema/02-config.ldif
index 4688e6e..a6be239 100644
--- a/opendj-sdk/opends/resource/schema/02-config.ldif
+++ b/opendj-sdk/opends/resource/schema/02-config.ldif
@@ -998,6 +998,17 @@
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.291 NAME 'ds-private-naming-contexts'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE directoryOperation
X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.292 NAME 'ds-backend-id'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
+ X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.293 NAME 'ds-backend-base-dn'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.294 NAME 'ds-backend-entry-count'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE
+ X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.295 NAME 'ds-backend-writability-mode'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
+ X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/Backend.java b/opendj-sdk/opends/src/server/org/opends/server/api/Backend.java
index eba5623..033fd81 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/Backend.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/Backend.java
@@ -42,6 +42,7 @@
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.SearchOperation;
+import org.opends.server.monitors.BackendMonitor;
import org.opends.server.types.BackupConfig;
import org.opends.server.types.BackupDirectory;
import org.opends.server.types.CancelledOperationException;
@@ -83,6 +84,9 @@
// hierarchically below the information in this backend.
private Backend[] subordinateBackends;
+ // The backend monitor associated with this backend.
+ private BackendMonitor backendMonitor;
+
// Indicates whether this is a private backend or one that holds
// user data.
private boolean isPrivateBackend;
@@ -109,6 +113,7 @@
subordinateBackends = new Backend[0];
isPrivateBackend = false;
writabilityMode = WritabilityMode.ENABLED;
+ backendMonitor = null;
}
@@ -716,6 +721,48 @@
/**
+ * Retrieves the backend monitor that is associated with this
+ * backend.
+ *
+ * @return The backend monitor that is associated with this
+ * backend, or {@code null} if none has been assigned.
+ */
+ public BackendMonitor getBackendMonitor()
+ {
+ assert debugEnter(CLASS_NAME, "getBackendMonitor");
+
+ return backendMonitor;
+ }
+
+
+
+ /**
+ * Sets the backend monitor for this backend.
+ *
+ * @param backendMonitor The backend monitor for this backend.
+ */
+ public void setBackendMonitor(BackendMonitor backendMonitor)
+ {
+ assert debugEnter(CLASS_NAME, "setBackendMonitor",
+ String.valueOf(backendMonitor));
+
+ this.backendMonitor = backendMonitor;
+ }
+
+
+
+ /**
+ * Retrieves the total number of entries contained in this backend,
+ * if that information is available.
+ *
+ * @return The total number of entries contained in this backend,
+ * or -1 if that information is not available.
+ */
+ public abstract long getEntryCount();
+
+
+
+ /**
* Retrieves the parent backend for this backend.
*
* @return The parent backend for this backend, or
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/BackupBackend.java b/opendj-sdk/opends/src/server/org/opends/server/backends/BackupBackend.java
index 0576804..6d92aad 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/BackupBackend.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/BackupBackend.java
@@ -336,6 +336,34 @@
/**
+ * {@inheritDoc}
+ */
+ public long getEntryCount()
+ {
+ assert debugEnter(CLASS_NAME, "getEntryCount");
+
+ int numEntries = 1;
+
+ AttributeType backupPathType =
+ DirectoryServer.getAttributeType(ATTR_BACKUP_DIRECTORY_PATH, true);
+
+ for (File f : backupDirectories)
+ {
+ try
+ {
+ DN backupDirDN = makeChildDN(backupBaseDN, backupPathType,
+ f.getAbsolutePath());
+ getBackupDirectoryEntry(backupDirDN);
+ numEntries++;
+ } catch (Exception e) {}
+ }
+
+ return numEntries;
+ }
+
+
+
+ /**
* Indicates whether the data associated with this backend may be considered
* local (i.e., in a repository managed by the Directory Server) rather than
* remote (i.e., in an external repository accessed by the Directory Server
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/MemoryBackend.java b/opendj-sdk/opends/src/server/org/opends/server/backends/MemoryBackend.java
index 10bd317..67f6399 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/MemoryBackend.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/MemoryBackend.java
@@ -254,6 +254,23 @@
/**
* {@inheritDoc}
*/
+ public synchronized long getEntryCount()
+ {
+ assert debugEnter(CLASS_NAME, "getEntryCount");
+
+ if (entryMap != null)
+ {
+ return entryMap.size();
+ }
+
+ return -1;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
public boolean isLocal()
{
assert debugEnter(CLASS_NAME, "isLocal");
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/MonitorBackend.java b/opendj-sdk/opends/src/server/org/opends/server/backends/MonitorBackend.java
index 9e4850e..5803d79 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/MonitorBackend.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/MonitorBackend.java
@@ -336,6 +336,18 @@
/**
+ * {@inheritDoc}
+ */
+ public long getEntryCount()
+ {
+ assert debugEnter(CLASS_NAME, "getEntryCount");
+
+ return DirectoryServer.getMonitorProviders().size() + 1;
+ }
+
+
+
+ /**
* Indicates whether the data associated with this backend may be considered
* local (i.e., in a repository managed by the Directory Server) rather than
* remote (i.e., in an external repository accessed by the Directory Server
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/RootDSEBackend.java b/opendj-sdk/opends/src/server/org/opends/server/backends/RootDSEBackend.java
index 17aac64..1a4a76e 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/RootDSEBackend.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/RootDSEBackend.java
@@ -413,6 +413,19 @@
/**
+ * {@inheritDoc}
+ */
+ public synchronized long getEntryCount()
+ {
+ assert debugEnter(CLASS_NAME, "getEntryCount");
+
+ // There is always just a single entry in this backend.
+ return 1;
+ }
+
+
+
+ /**
* Indicates whether the data associated with this backend may be considered
* local (i.e., in a repository managed by the Directory Server) rather than
* remote (i.e., in an external repository accessed by the Directory Server
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java b/opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java
index 1bf567d..c919b90 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java
@@ -380,6 +380,19 @@
/**
+ * {@inheritDoc}
+ */
+ public long getEntryCount()
+ {
+ assert debugEnter(CLASS_NAME, "getEntryCount");
+
+ // There is always only a single entry in this backend.
+ return 1;
+ }
+
+
+
+ /**
* Indicates whether the data associated with this backend may be considered
* local (i.e., in a repository managed by the Directory Server) rather than
* remote (i.e., in an external repository accessed by the Directory Server
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
index 98742e2..a125e9d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
@@ -611,6 +611,30 @@
/**
+ * {@inheritDoc}
+ */
+ public long getEntryCount()
+ {
+ assert debugEnter(CLASS_NAME, "getEntryCount");
+
+ if (rootContainer != null)
+ {
+ try
+ {
+ return rootContainer.getEntryCount();
+ }
+ catch (Exception e)
+ {
+ assert debugException(CLASS_NAME, "getEntryCount", e);
+ }
+ }
+
+ return -1;
+ }
+
+
+
+ /**
* Retrieves the requested entry from this backend. Note that the caller must
* hold a read or write lock on the specified DN.
*
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/task/TaskBackend.java b/opendj-sdk/opends/src/server/org/opends/server/backends/task/TaskBackend.java
index 5fcbf15..beed09f6 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/task/TaskBackend.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/task/TaskBackend.java
@@ -421,6 +421,23 @@
/**
+ * {@inheritDoc}
+ */
+ public long getEntryCount()
+ {
+ assert debugEnter(CLASS_NAME, "getEntryCount");
+
+ if (taskScheduler != null)
+ {
+ return taskScheduler.getEntryCount();
+ }
+
+ return -1;
+ }
+
+
+
+ /**
* Indicates whether the data associated with this backend may be considered
* local (i.e., in a repository managed by the Directory Server) rather than
* remote (i.e., in an external repository accessed by the Directory Server
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/task/TaskScheduler.java b/opendj-sdk/opends/src/server/org/opends/server/backends/task/TaskScheduler.java
index 13a0de4..9472b79 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/task/TaskScheduler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/task/TaskScheduler.java
@@ -1315,6 +1315,29 @@
/**
+ * Retrieves the total number of entries in the task backend.
+ *
+ * @return The total number of entries in the task backend.
+ */
+ public long getEntryCount()
+ {
+ assert debugEnter(CLASS_NAME, "getEntryCount");
+
+ schedulerLock.lock();
+
+ try
+ {
+ return tasks.size() + recurringTasks.size() + 3;
+ }
+ finally
+ {
+ schedulerLock.unlock();
+ }
+ }
+
+
+
+ /**
* Retrieves the root entry that is the common ancestor for all entries in the
* task backend.
*
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java b/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
index e113da4..e4f69a6 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -90,6 +90,7 @@
import org.opends.server.extensions.JMXAlertHandler;
import org.opends.server.loggers.StartupDebugLogger;
import org.opends.server.loggers.StartupErrorLogger;
+import org.opends.server.monitors.BackendMonitor;
import org.opends.server.schema.AttributeTypeSyntax;
import org.opends.server.schema.BinarySyntax;
import org.opends.server.schema.BooleanEqualityMatchingRule;
@@ -5300,6 +5301,11 @@
{
newBackends.put(backendID, backend);
directoryServer.backends = newBackends;
+
+ BackendMonitor monitor = new BackendMonitor(backend);
+ monitor.initializeMonitorProvider(null);
+ backend.setBackendMonitor(monitor);
+ registerMonitorProvider(monitor);
}
}
}
@@ -5327,6 +5333,14 @@
newBackends.remove(backend.getBackendID());
directoryServer.backends = newBackends;
+
+ BackendMonitor monitor = backend.getBackendMonitor();
+ if (monitor != null)
+ {
+ String instanceName = toLowerCase(monitor.getMonitorInstanceName());
+ deregisterMonitorProvider(instanceName);
+ monitor.finalizeMonitorProvider();
+ }
}
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
index f377127..7aad4f2 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
@@ -856,6 +856,18 @@
/**
+ * {@inheritDoc}
+ */
+ public long getEntryCount()
+ {
+ assert debugEnter(CLASS_NAME, "getEntryCount");
+
+ return configEntries.size();
+ }
+
+
+
+ /**
* Indicates whether the data associated with this backend may be considered
* local (i.e., in a repository managed by the Directory Server) rather than
* remote (i.e., in an external repository accessed by the Directory Server
diff --git a/opendj-sdk/opends/src/server/org/opends/server/monitors/BackendMonitor.java b/opendj-sdk/opends/src/server/org/opends/server/monitors/BackendMonitor.java
new file mode 100644
index 0000000..42029df
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/monitors/BackendMonitor.java
@@ -0,0 +1,207 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.server.monitors;
+
+
+
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.opends.server.api.Backend;
+import org.opends.server.api.MonitorProvider;
+import org.opends.server.config.ConfigEntry;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.ByteStringFactory;
+import org.opends.server.types.DirectoryConfig;
+import org.opends.server.types.DN;
+
+import static org.opends.server.loggers.Debug.*;
+import static org.opends.server.util.ServerConstants.*;
+
+
+
+/**
+ * This class implements a monitor provider that will report generic information
+ * for an enabled Directory Server backend, including its backend ID, base DNs,
+ * writability mode, and the number of entries it contains.
+ */
+public class BackendMonitor
+ extends MonitorProvider
+{
+ /**
+ * The fully-qualified name of this class for debugging purposes.
+ */
+ private static final String CLASS_NAME =
+ "org.opends.server.monitors.BackendMonitor";
+
+
+
+ // The attribute type that will be used to report the backend ID.
+ private AttributeType backendIDType;
+
+ // The attribute type that will be used to report the set of base DNs.
+ private AttributeType baseDNType;
+
+ // The attribute type that will be used to report the number of entries.
+ private AttributeType entryCountType;
+
+ // The attribute type that will be used to report the writability mode.
+ private AttributeType writabilityModeType;
+
+ // The backend with which this monitor is associated.
+ private Backend backend;
+
+ // The name for this monitor.
+ private String monitorName;
+
+
+
+ /**
+ * Creates a new instance of this backend monitor provider that will work with
+ * the provided backend. Most of the initialization should be handled in the
+ * {@code initializeMonitorProvider} method.
+ *
+ * @param backend The backend with which this monitor is associated.
+ */
+ public BackendMonitor(Backend backend)
+ {
+ super(backend.getBackendID() + " Backend");
+
+ assert debugConstructor(CLASS_NAME, String.valueOf(backend));
+
+ this.backend = backend;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void initializeMonitorProvider(ConfigEntry configEntry)
+ {
+ assert debugEnter(CLASS_NAME, "initializeMonitorProvider",
+ String.valueOf(configEntry));
+
+ monitorName = backend.getBackendID() + " Backend";
+
+ backendIDType = DirectoryConfig.getAttributeType(ATTR_MONITOR_BACKEND_ID,
+ true);
+
+ baseDNType = DirectoryConfig.getAttributeType(ATTR_MONITOR_BACKEND_BASE_DN,
+ true);
+
+ entryCountType =
+ DirectoryConfig.getAttributeType(ATTR_MONITOR_BACKEND_ENTRY_COUNT,
+ true);
+
+ writabilityModeType =
+ DirectoryConfig.getAttributeType(ATTR_MONITOR_BACKEND_WRITABILITY_MODE,
+ true);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getMonitorInstanceName()
+ {
+ assert debugEnter(CLASS_NAME, "getMonitorInstanceName");
+
+ return monitorName;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getUpdateInterval()
+ {
+ assert debugEnter(CLASS_NAME, "getUpdateInterval");
+
+ // We don't need do anything on a periodic basis.
+ return 0;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void updateMonitorData()
+ {
+ assert debugEnter(CLASS_NAME, "updateMonitorData");
+
+ // No implementaiton is required.
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Attribute> getMonitorData()
+ {
+ assert debugEnter(CLASS_NAME, "getMonitorData");
+
+ LinkedList<Attribute> attrs = new LinkedList<Attribute>();
+
+ LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>();
+ values.add(new AttributeValue(backendIDType,
+ ByteStringFactory.create(backend.getBackendID())));
+ attrs.add(new Attribute(backendIDType, ATTR_MONITOR_BACKEND_ID, values));
+
+ values = new LinkedHashSet<AttributeValue>();
+ DN[] baseDNs = backend.getBaseDNs();
+ for (DN dn : baseDNs)
+ {
+ values.add(new AttributeValue(baseDNType,
+ ByteStringFactory.create(dn.toString())));
+ }
+ attrs.add(new Attribute(baseDNType, ATTR_MONITOR_BACKEND_BASE_DN, values));
+
+ values = new LinkedHashSet<AttributeValue>();
+ values.add(new AttributeValue(entryCountType,
+ ByteStringFactory.create(String.valueOf(backend.getEntryCount()))));
+ attrs.add(new Attribute(entryCountType, ATTR_MONITOR_BACKEND_ENTRY_COUNT,
+ values));
+
+ values = new LinkedHashSet<AttributeValue>();
+ values.add(new AttributeValue(writabilityModeType,
+ ByteStringFactory.create(
+ String.valueOf(backend.getWritabilityMode()))));
+ attrs.add(new Attribute(writabilityModeType,
+ ATTR_MONITOR_BACKEND_WRITABILITY_MODE, values));
+
+ return attrs;
+ }
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java b/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
index 3cb85e8..c103f85 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -185,6 +185,39 @@
/**
+ * The name of the monitor attribute that is used to hold a backend ID.
+ */
+ public static final String ATTR_MONITOR_BACKEND_ID = "ds-backend-id";
+
+
+
+ /**
+ * The name of the monitor attribute that is used to hold the set of base DNs.
+ */
+ public static final String ATTR_MONITOR_BACKEND_BASE_DN =
+ "ds-backend-base-dn";
+
+
+
+ /**
+ * The name of the monitor attribute that is used to hold the backend entry
+ * count.
+ */
+ public static final String ATTR_MONITOR_BACKEND_ENTRY_COUNT =
+ "ds-backend-entry-count";
+
+
+
+ /**
+ * The name of the monitor attribute that is used to hold the backend
+ * writability mode.
+ */
+ public static final String ATTR_MONITOR_BACKEND_WRITABILITY_MODE =
+ "ds-backend-writability-mode";
+
+
+
+ /**
* The name of the standard attribute that is used to specify the set of
* public naming contexts (suffixes) for the Directory Server, formatted in
* camel case.
--
Gitblit v1.10.0