From 47437ad525caabd5ad6331598f4945a4d240b6ca Mon Sep 17 00:00:00 2001
From: Chris Ridd <chris.ridd@forgerock.com>
Date: Wed, 10 Dec 2014 11:19:15 +0000
Subject: [PATCH] Fix OPENDJ-1665 (CR-5619) Cache backup.info files

---
 opendj3-server-dev/src/server/org/opends/server/backends/BackupBackend.java |  105 ++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 80 insertions(+), 25 deletions(-)

diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/BackupBackend.java b/opendj3-server-dev/src/server/org/opends/server/backends/BackupBackend.java
index 6e4e99f..e75810c 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/BackupBackend.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/BackupBackend.java
@@ -27,6 +27,7 @@
 package org.opends.server.backends;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.*;
 
 import org.forgerock.i18n.LocalizableMessage;
@@ -82,9 +83,61 @@
   /** The backup base entry. */
   private Entry backupBaseEntry;
 
-  /** The set of predefined backup directories that we will use. */
-  private LinkedHashSet<File> backupDirectories;
+  /** A cache of BackupDirectories. */
+  private HashMap<File,CachedBackupDirectory> backupDirectories;
 
+  /**
+   * To avoid parsing and reparsing the contents of backup.info files, we
+   * cache the BackupDirectory for each directory using this class.
+   */
+  private class CachedBackupDirectory
+  {
+    /** The path to the 'bak' directory. */
+    private final String directoryPath;
+
+    /** The 'backup.info' file. */
+    private final File backupInfo;
+
+    /** The last modify time of the backupInfo file */
+    private long lastModified;
+
+    /** The BackupDirectory parsed at lastModified time. */
+    private BackupDirectory backupDirectory;
+
+    /**
+     * A BackupDirectory that is cached based on the backup descriptor file.
+     *
+     * @param directory Path to the backup directory itself.
+     */
+    public CachedBackupDirectory(File directory)
+    {
+      directoryPath = directory.getPath();
+      backupInfo = new File(directoryPath + File.separator + BACKUP_DIRECTORY_DESCRIPTOR_FILE);
+      lastModified = -1;
+      backupDirectory = null;
+    }
+
+    /**
+     * Return a BackupDirectory. This will be recomputed every time the underlying descriptor (backup.info) file
+     * changes.
+     *
+     * @return An up-to-date BackupDirectory
+     * @throws IOException If a problem occurs while trying to read the contents of the descriptor file.
+     * @throws ConfigException If the contents of the descriptor file cannot be parsed to create a backup directory
+     *                         structure.
+     */
+    public synchronized BackupDirectory getBackupDirectory()
+            throws IOException, ConfigException
+    {
+      long currentModified = backupInfo.lastModified();
+      if (backupDirectory == null || currentModified != lastModified)
+      {
+        backupDirectory = BackupDirectory.readBackupDirectoryDescriptor(directoryPath);
+        lastModified = currentModified;
+      }
+      return backupDirectory;
+    }
+  }
 
 
   /**
@@ -142,10 +195,11 @@
 
     // Determine the set of backup directories that we will use by default.
     Set<String> values = currentConfig.getBackupDirectory();
-    backupDirectories = new LinkedHashSet<File>(values.size());
+    backupDirectories = new LinkedHashMap<File,CachedBackupDirectory>(values.size());
     for (String s : values)
     {
-      backupDirectories.add(getFileForPath(s));
+      File dir = getFileForPath(s);
+      backupDirectories.put(dir, new CachedBackupDirectory(dir));
     }
 
 
@@ -234,23 +288,24 @@
     AttributeType backupPathType =
          DirectoryServer.getAttributeType(ATTR_BACKUP_DIRECTORY_PATH, true);
 
-    for (File f : backupDirectories)
+    for (File dir : backupDirectories.keySet())
     {
       try
       {
         // Check to see if the descriptor file exists.  If not, then skip this
         // backup directory.
-        File descriptorFile = new File(f, BACKUP_DIRECTORY_DESCRIPTOR_FILE);
+        File descriptorFile = new File(dir, BACKUP_DIRECTORY_DESCRIPTOR_FILE);
         if (! descriptorFile.exists())
         {
           continue;
         }
 
         DN backupDirDN = makeChildDN(backupBaseDN, backupPathType,
-                                     f.getAbsolutePath());
+                                     dir.getAbsolutePath());
         getBackupDirectoryEntry(backupDirDN);
         numEntries++;
-      } catch (Exception e) {}
+      }
+      catch (Exception e) {}
     }
 
     return numEntries;
@@ -308,11 +363,11 @@
     if (backupBaseDN.equals(entryDN))
     {
       long count = 0;
-      for (File f : backupDirectories)
+      for (File dir : backupDirectories.keySet())
       {
         // Check to see if the descriptor file exists.  If not, then skip this
         // backup directory.
-        File descriptorFile = new File(f, BACKUP_DIRECTORY_DESCRIPTOR_FILE);
+        File descriptorFile = new File(dir, BACKUP_DIRECTORY_DESCRIPTOR_FILE);
         if (! descriptorFile.exists())
         {
           continue;
@@ -324,8 +379,7 @@
         {
           try
           {
-            BackupDirectory backupDirectory =
-                BackupDirectory.readBackupDirectoryDescriptor(f.getPath());
+            BackupDirectory backupDirectory = backupDirectories.get(dir).getBackupDirectory();
             count += backupDirectory.getBackups().keySet().size();
           }
           catch (Exception e)
@@ -362,8 +416,8 @@
         {
           try
           {
-            BackupDirectory backupDirectory =
-                BackupDirectory.readBackupDirectoryDescriptor(v.toString());
+            File dir = new File(v.toString());
+            BackupDirectory backupDirectory = backupDirectories.get(dir).getBackupDirectory();
             count += backupDirectory.getBackups().keySet().size();
           }
           catch (Exception e)
@@ -468,7 +522,8 @@
     BackupDirectory backupDirectory;
     try
     {
-      backupDirectory = BackupDirectory.readBackupDirectoryDescriptor(v.toString());
+      File dir = new File(v.toString());
+      backupDirectory = backupDirectories.get(dir).getBackupDirectory();
     }
     catch (ConfigException ce)
     {
@@ -752,11 +807,11 @@
       {
         AttributeType backupPathType =
              DirectoryServer.getAttributeType(ATTR_BACKUP_DIRECTORY_PATH, true);
-        for (File f : backupDirectories)
+        for (File dir : backupDirectories.keySet())
         {
           // Check to see if the descriptor file exists.  If not, then skip this
           // backup directory.
-          File descriptorFile = new File(f, BACKUP_DIRECTORY_DESCRIPTOR_FILE);
+          File descriptorFile = new File(dir, BACKUP_DIRECTORY_DESCRIPTOR_FILE);
           if (! descriptorFile.exists())
           {
             continue;
@@ -764,7 +819,7 @@
 
 
           DN backupDirDN = makeChildDN(backupBaseDN, backupPathType,
-                                       f.getAbsolutePath());
+                                       dir.getAbsolutePath());
 
           Entry backupDirEntry;
           try
@@ -793,8 +848,8 @@
               {
                 try
                 {
-                  BackupDirectory backupDirectory =
-                       BackupDirectory.readBackupDirectoryDescriptor(v.toString());
+                  File subtreeDir = new File(v.toString());
+                  BackupDirectory backupDirectory = backupDirectories.get(subtreeDir).getBackupDirectory();
                   AttributeType idType =
                        DirectoryServer.getAttributeType(ATTR_BACKUP_ID,
                                                         true);
@@ -843,8 +898,8 @@
           {
             try
             {
-              BackupDirectory backupDirectory =
-                   BackupDirectory.readBackupDirectoryDescriptor(v.toString());
+              File dir = new File(v.toString());
+              BackupDirectory backupDirectory = backupDirectories.get(dir).getBackupDirectory();
               AttributeType idType =
                    DirectoryServer.getAttributeType(ATTR_BACKUP_ID,
                                                     true);
@@ -1038,10 +1093,11 @@
 
 
     Set<String> values = cfg.getBackupDirectory();
-    backupDirectories = new LinkedHashSet<File>(values.size());
+    backupDirectories = new LinkedHashMap<File,CachedBackupDirectory>(values.size());
     for (String s : values)
     {
-      backupDirectories.add(getFileForPath(s));
+      File dir = getFileForPath(s);
+      backupDirectories.put(dir, new CachedBackupDirectory(dir));
     }
 
     currentConfig = cfg;
@@ -1068,7 +1124,6 @@
 
 
   /** {@inheritDoc} */
-  @Override
   public void preloadEntryCache() throws UnsupportedOperationException {
     throw new UnsupportedOperationException("Operation not supported.");
   }

--
Gitblit v1.10.0