From c252260311a6899184fa9477f220510e36e74031 Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Wed, 12 Aug 2015 00:57:46 -0400
Subject: [PATCH] Separate range and cert status threads

We currently disable the cert status maintenance thread on
clone CAs because CRL processing should only be done on the
master CA.  Currently, the maintenance thread also performs
other checks on serial number ranges and settings.  By disabling
the maintenance thread, we disable these checks too.

To fix this, we have separated the serial number checks into a
different maintenance thread, so that these tasks will occur
even if the cert status thread is disabled.

Bugzilla # 1251606
---
 .../src/com/netscape/ca/CertificateAuthority.java  |  5 ++
 .../cmscore/dbs/CertificateRepository.java         | 80 ++++++++++++++++++++--
 2 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java
index 65296113e1df07f82070d639ee68588f8e0dbaf7..158ecff1f72ec2d3cfa3c73b7599bf2c3b59bc6e 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java
@@ -371,6 +371,11 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
             mCertRepot.setSkipIfInConsistent(
                     mConfig.getBoolean("SkipIfInConsistent", false));
 
+            // set serial number update task to run every 10 minutes
+            mCertRepot.setSerialNumberUpdateInterval(
+                    mRequestQueue.getRequestRepository(),
+                    mConfig.getInteger("serialNumberUpdateInterval", 10 * 60));
+
             mService.init(config.getSubStore("connector"));
 
             initMiscellaneousListeners();
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java
index 8d96265213ad5826a43dfd8ccd8bbf979fd0da4f..1631c79b333aec562a7107cdbc151b6bff07e64d 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java
@@ -110,6 +110,7 @@ public class CertificateRepository extends Repository
 
     public CertStatusUpdateTask certStatusUpdateTask;
     public RetrieveModificationsTask retrieveModificationsTask;
+    public SerialNumberUpdateTask serialNumberUpdateTask;
 
     /**
      * Constructs a certificate repository.
@@ -298,7 +299,7 @@ public class CertificateRepository extends Repository
         return nextSerialNumber;
     }
 
-    private void updateCounter() {
+    public void updateCounter() {
         CMS.debug("CertificateRepository: updateCounter  mEnableRandomSerialNumbers="+
                   mEnableRandomSerialNumbers+"  mCounter="+mCounter);
         try {
@@ -616,6 +617,29 @@ public class CertificateRepository extends Repository
         certStatusUpdateTask.start();
     }
 
+    /**
+     * interval value: (in seconds)
+     * 0 - disable
+     * >0 - enable
+     */
+    public void setSerialNumberUpdateInterval(IRepository requestRepository, int interval) {
+        CMS.debug("In setCertStatusUpdateInterval " + interval);
+
+        // stop running tasks
+        if (serialNumberUpdateTask != null) {
+            serialNumberUpdateTask.stop();
+        }
+
+        if (interval == 0) {
+            CMS.debug("In setSerialNumberUpdateInterval interval = 0");
+            return;
+        }
+
+        CMS.debug("In setSerialNumberUpdateInterval scheduling serial number update every " + interval + " seconds.");
+        serialNumberUpdateTask = new SerialNumberUpdateTask(this, requestRepository, interval);
+        serialNumberUpdateTask.start();
+    }
+
     public void updateCertStatus() throws EBaseException {
 
         CMS.debug("In updateCertStatus()");
@@ -637,7 +661,6 @@ public class CertificateRepository extends Repository
         transitRevokedExpiredCertificates();
         CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
                 CMS.getLogMessage("CMSCORE_DBS_FINISH_REVOKED_EXPIRED_SEARCH"));
-        updateCounter();
     }
 
     /**
@@ -2265,6 +2288,10 @@ public class CertificateRepository extends Repository
         if (retrieveModificationsTask != null) {
             retrieveModificationsTask.stop();
         }
+
+        if (serialNumberUpdateTask != null) {
+            serialNumberUpdateTask.stop();
+        }
     }
 }
 
@@ -2307,14 +2334,59 @@ class CertStatusUpdateTask implements Runnable {
         CMS.debug("Starting updateCertStatus (entered lock)");
         repository.updateCertStatus();
         CMS.debug("updateCertStatus done");
+    }
+
+    public void stop() {
+        // shutdown executorService without interrupting running task
+        if (executorService != null) executorService.shutdown();
+    }
+}
+
+class SerialNumberUpdateTask implements Runnable {
+
+    CertificateRepository repository;
+    IRepository requestRepository;
+
+    int interval;
+
+    ScheduledExecutorService executorService;
+
+    public SerialNumberUpdateTask(CertificateRepository repository, IRepository requestRepository, int interval) {
+        this.repository = repository;
+        this.requestRepository = requestRepository;
+        this.interval = interval;
+    }
+
+    public void start() {
+        // schedule task to run immediately and repeat after specified interval
+        executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
+            public Thread newThread(Runnable r) {
+                return new Thread(r, "SerialNumberUpdateTask");
+            }
+        });
+        executorService.scheduleWithFixedDelay(this, 0, interval, TimeUnit.SECONDS);
+    }
+
+    public void run() {
+        try {
+            CMS.debug("About to start updateSerialNumbers");
+            updateSerialNumbers();
+
+        } catch (EBaseException e) {
+            CMS.debug("updateSerialNumbers done: " + e.toString());
+        }
+    }
+
+    public synchronized void updateSerialNumbers() throws EBaseException {
+        CMS.debug("Starting updateSerialNumbers (entered lock)");
+        repository.updateCounter();
 
         CMS.debug("Starting cert checkRanges");
         repository.checkRanges();
-        CMS.debug("cert checkRanges done");
 
         CMS.debug("Starting request checkRanges");
         requestRepository.checkRanges();
-        CMS.debug("request checkRanges done");
+        CMS.debug("updateSerialNumbers done");
     }
 
     public void stop() {
-- 
2.4.3

