Skip to content

Commit

Permalink
Speed up data_dir load by making ConfigurationPasswordEncryptionHelpe…
Browse files Browse the repository at this point in the history
…r faster

ConfigurationPasswordEncryptionHelper.decode(String)
is called by XstreamPersister -> StoreInfoConverter
for each DataStoreInfo read from the data directory at
start up time.

This patch makes it use a ConcurrentMap internally
instead of a HashMap, and removes the sychronization
on its CACHE member variable. Additionally, and most
importantly, caches the encryptable store parameter
names by StoreInfo.getType() too, avoiding the fallback
to full DataAccessFactory parameter lookup, which
implies a rather expensive call to getCatalog() \
.getResourcePool().getDataStoreFactory((DataStoreInfo) info)

As a result, loading time when there are lots of
DataStoreInfos is reduced to about 1/3 of the time
it takes without this patch.
  • Loading branch information
groldan committed May 31, 2019
1 parent 35927a4 commit acfdccc
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 19 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/ */
package org.geoserver.config; package org.geoserver.config;


import com.google.common.base.Stopwatch;
import java.io.*; import java.io.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
Expand Down Expand Up @@ -391,7 +392,10 @@ protected void readCatalog(Catalog catalog, XStreamPersister xp) throws Exceptio
Resource f = resourceLoader.get("catalog.xml"); Resource f = resourceLoader.get("catalog.xml");
if (!Resources.exists(f)) { if (!Resources.exists(f)) {
// assume 2.x style data directory // assume 2.x style data directory
Stopwatch sw = Stopwatch.createStarted();
LOGGER.info("Loading catalog...");
CatalogImpl catalog2 = (CatalogImpl) readCatalog(xp); CatalogImpl catalog2 = (CatalogImpl) readCatalog(xp);
LOGGER.info("Read catalog in " + sw.stop());
// make to remove the old resource pool catalog listener // make to remove the old resource pool catalog listener
((CatalogImpl) catalog).sync(catalog2); ((CatalogImpl) catalog).sync(catalog2);
} else { } else {
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@


import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.geoserver.catalog.Catalog; import org.geoserver.catalog.Catalog;
Expand All @@ -36,8 +36,14 @@ public class ConfigurationPasswordEncryptionHelper {
protected static Logger LOGGER = Logging.getLogger("org.geoserver.security"); protected static Logger LOGGER = Logging.getLogger("org.geoserver.security");


/** cache of datastore factory class to fields to encrypt */ /** cache of datastore factory class to fields to encrypt */
protected static Map<Class<? extends DataAccessFactory>, Set<String>> CACHE = protected static ConcurrentMap<Class<? extends DataAccessFactory>, Set<String>> CACHE =
new HashMap<Class<? extends DataAccessFactory>, Set<String>>(); new ConcurrentHashMap<>();
/**
* cache of {@link StoreInfo#getType()} to fields to encrypt, if key not found defer to full
* DataAccessFactory lookup
*/
protected static ConcurrentMap<String, Set<String>> STORE_INFO_TYPE_CACHE =
new ConcurrentHashMap<>();


GeoServerSecurityManager securityManager; GeoServerSecurityManager securityManager;


Expand Down Expand Up @@ -65,7 +71,18 @@ public Set<String> getEncryptedFields(StoreInfo info) {
return Collections.emptySet(); return Collections.emptySet();
} }


// find this store object data access factory Set<String> toEncrypt;

// fast lookup by store type
final String storeType = info.getType();
if (storeType != null) {
toEncrypt = STORE_INFO_TYPE_CACHE.get(storeType);
if (toEncrypt != null) {
return toEncrypt;
}
}

// store type not cached, find this store object data access factory
DataAccessFactory factory; DataAccessFactory factory;
try { try {
factory = getCatalog().getResourcePool().getDataStoreFactory((DataStoreInfo) info); factory = getCatalog().getResourcePool().getDataStoreFactory((DataStoreInfo) info);
Expand Down Expand Up @@ -94,27 +111,28 @@ public Set<String> getEncryptedFields(StoreInfo info) {
return Collections.emptySet(); return Collections.emptySet();
} }


Set<String> toEncrypt = CACHE.get(factory.getClass()); toEncrypt = CACHE.get(factory.getClass());
if (toEncrypt != null) { if (toEncrypt != null) {
return toEncrypt; return toEncrypt;
} }


synchronized (CACHE) { toEncrypt = CACHE.get(info.getClass());
toEncrypt = CACHE.get(info.getClass()); if (toEncrypt != null) {
if (toEncrypt != null) { return toEncrypt;
return toEncrypt; }
}


toEncrypt = Collections.emptySet(); toEncrypt = Collections.emptySet();
if (info != null && info.getConnectionParameters() != null) { if (info != null && info.getConnectionParameters() != null) {
toEncrypt = new HashSet<String>(3); toEncrypt = new HashSet<String>(3);
for (Param p : factory.getParametersInfo()) { for (Param p : factory.getParametersInfo()) {
if (p.isPassword()) { if (p.isPassword()) {
toEncrypt.add(p.getName()); toEncrypt.add(p.getName());
}
} }
} }
CACHE.put(factory.getClass(), toEncrypt); }
CACHE.put(factory.getClass(), toEncrypt);
if (storeType != null) {
STORE_INFO_TYPE_CACHE.put(storeType, toEncrypt);
} }
return toEncrypt; return toEncrypt;
} }
Expand Down

0 comments on commit acfdccc

Please sign in to comment.