You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by pl...@apache.org on 2015/11/04 09:25:42 UTC
[16/48] directory-kerby git commit: DIRKRB-422. Enhance json backend
to support transaction for reasonable efficiency,
allowing flush only when commit
DIRKRB-422. Enhance json backend to support transaction for reasonable efficiency, allowing flush only when commit
Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/3dd63f3b
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/3dd63f3b
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/3dd63f3b
Branch: refs/heads/pkinit-support
Commit: 3dd63f3b8a931e6a9ca44c6e70ff95ff48202c8b
Parents: cd135c0
Author: Kai Zheng <ka...@intel.com>
Authored: Mon Sep 28 22:27:09 2015 +0800
Committer: Kai Zheng <ka...@intel.com>
Committed: Mon Sep 28 22:27:09 2015 +0800
----------------------------------------------------------------------
.../identitybackend/JsonIdentityBackend.java | 202 ++++++++++++++-----
1 file changed, 150 insertions(+), 52 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/3dd63f3b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java
----------------------------------------------------------------------
diff --git a/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java
index 37e210d..7aadf43 100644
--- a/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java
+++ b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java
@@ -27,6 +27,7 @@ import org.apache.kerby.kerberos.kdc.identitybackend.typeAdapter.EncryptionKeyAd
import org.apache.kerby.kerberos.kdc.identitybackend.typeAdapter.KerberosTimeAdapter;
import org.apache.kerby.kerberos.kdc.identitybackend.typeAdapter.PrincipalNameAdapter;
import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.identity.BatchTrans;
import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
import org.apache.kerby.kerberos.kerb.identity.backend.AbstractIdentityBackend;
import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
@@ -45,13 +46,16 @@ import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
/**
* A Json file based backend implementation.
- *
*/
public class JsonIdentityBackend extends AbstractIdentityBackend {
- private static final Logger LOG = LoggerFactory.getLogger(JsonIdentityBackend.class);
+ private static final Logger LOG =
+ LoggerFactory.getLogger(JsonIdentityBackend.class);
+
public static final String JSON_IDENTITY_BACKEND_DIR = "backend.json.dir";
private File jsonKdbFile;
private Gson gson;
@@ -61,6 +65,8 @@ public class JsonIdentityBackend extends AbstractIdentityBackend {
new ConcurrentHashMap<>(new TreeMap<String, KrbIdentity>());
private long kdbFileUpdateTime = -1;
+ private Lock lock = new ReentrantLock();
+
public JsonIdentityBackend() {
}
@@ -78,69 +84,90 @@ public class JsonIdentityBackend extends AbstractIdentityBackend {
* {@inheritDoc}
*/
@Override
- protected void doInitialize() throws KrbException {
- LOG.info("Initializing the Json identity backend.");
- createGson();
- load();
+ public boolean supportBatchTrans() {
+ return true;
}
/**
- * Load identities from file
+ * {@inheritDoc}
*/
- private void load() throws KrbException {
- LOG.info("Loading the identities from json file.");
- String jsonFile = getConfig().getString(JSON_IDENTITY_BACKEND_DIR);
+ @Override
+ public BatchTrans startBatchTrans() throws KrbException {
+ if (lock.tryLock()) {
+ checkAndReload();
+ return new JsonBatchTrans();
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doInitialize() throws KrbException {
+ LOG.info("Initializing the Json identity backend.");
+
+ initGsonBuilder();
+
+ String dirPath = getConfig().getString(JSON_IDENTITY_BACKEND_DIR);
File jsonFileDir;
- if (jsonFile == null || jsonFile.isEmpty()) {
+ if (dirPath == null || dirPath.isEmpty()) {
jsonFileDir = getBackendConfig().getConfDir();
} else {
- jsonFileDir = new File(jsonFile);
+ jsonFileDir = new File(dirPath);
if (!jsonFileDir.exists() && !jsonFileDir.mkdirs()) {
- throw new KrbException("could not create json file dir " + jsonFileDir);
+ throw new KrbException("Failed to create json file dir " + jsonFileDir);
}
}
jsonKdbFile = new File(jsonFileDir, "json-backend.json");
-
if (!jsonKdbFile.exists()) {
try {
jsonKdbFile.createNewFile();
} catch (IOException e) {
- e.printStackTrace();
+ throw new KrbException("Failed to create " + jsonKdbFile.getAbsolutePath());
}
}
-
- checkAndReload();
}
- /**
- * Check kdb file timestamp to see if it's changed or not. If
- * necessary load the kdb again.
- */
- private synchronized void checkAndReload() throws KrbException {
- long nowTimeStamp = jsonKdbFile.lastModified();
+ private void load() throws KrbException {
+ LOG.info("Loading the identities from json file.");
- if (kdbFileUpdateTime < 0 ||
- nowTimeStamp != kdbFileUpdateTime) {
- //load identities
- String reloadedJsonContent;
+ long nowTimeStamp = jsonKdbFile.lastModified();
+ String reloadedJsonContent;
+ if (lock.tryLock()) {
try {
- reloadedJsonContent = IOUtil.readFile(jsonKdbFile);
- } catch (IOException e) {
- throw new KrbException("Failed to read file", e);
- }
+ try {
+ reloadedJsonContent = IOUtil.readFile(jsonKdbFile);
+ } catch (IOException e) {
+ throw new KrbException("Failed to read file", e);
+ }
- Map<String, KrbIdentity> reloadedEntries =
- gson.fromJson(reloadedJsonContent,
- new TypeToken<HashMap<String, KrbIdentity>>() {
- }.getType());
+ Map<String, KrbIdentity> reloadedEntries =
+ gson.fromJson(reloadedJsonContent,
+ new TypeToken<HashMap<String, KrbIdentity>>() {
+ }.getType());
- if (reloadedEntries != null) {
- identities.clear();
- identities.putAll(reloadedEntries);
+ if (reloadedEntries != null) {
+ identities.clear();
+ identities.putAll(reloadedEntries);
+ }
+
+ kdbFileUpdateTime = nowTimeStamp;
+ } finally {
+ lock.unlock();
}
+ }
+ }
- kdbFileUpdateTime = nowTimeStamp;
+ /**
+ * Check kdb file timestamp to see if it's changed or not. If
+ * necessary load the kdb again.
+ */
+ private void checkAndReload() throws KrbException {
+ long nowTimeStamp = jsonKdbFile.lastModified();
+ if (nowTimeStamp != kdbFileUpdateTime) {
+ load();
}
}
@@ -160,8 +187,14 @@ public class JsonIdentityBackend extends AbstractIdentityBackend {
protected KrbIdentity doAddIdentity(KrbIdentity identity) throws KrbException {
checkAndReload();
- identities.put(identity.getPrincipalName(), identity);
- persistToFile();
+ if (lock.tryLock()) {
+ try {
+ identities.put(identity.getPrincipalName(), identity);
+ persistToFile();
+ } finally {
+ lock.unlock();
+ }
+ }
return doGetIdentity(identity.getPrincipalName());
}
@@ -172,8 +205,15 @@ public class JsonIdentityBackend extends AbstractIdentityBackend {
@Override
protected KrbIdentity doUpdateIdentity(KrbIdentity identity) throws KrbException {
checkAndReload();
- identities.put(identity.getPrincipalName(), identity);
- persistToFile();
+
+ if (lock.tryLock()) {
+ try {
+ identities.put(identity.getPrincipalName(), identity);
+ persistToFile();
+ } finally {
+ lock.unlock();
+ }
+ }
return doGetIdentity(identity.getPrincipalName());
}
@@ -184,10 +224,19 @@ public class JsonIdentityBackend extends AbstractIdentityBackend {
@Override
protected void doDeleteIdentity(String principalName) throws KrbException {
checkAndReload();
- if (identities.containsKey(principalName)) {
- identities.remove(principalName);
+
+ if (!identities.containsKey(principalName)) {
+ return;
+ }
+
+ if (lock.tryLock()) {
+ try {
+ identities.remove(principalName);
+ persistToFile();
+ } finally {
+ lock.unlock();
+ }
}
- persistToFile();
}
/**
@@ -201,10 +250,7 @@ public class JsonIdentityBackend extends AbstractIdentityBackend {
return principals;
}
- /**
- *Create a gson
- */
- private void createGson() {
+ private void initGsonBuilder() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(EncryptionKey.class, new EncryptionKeyAdapter());
gsonBuilder.registerTypeAdapter(PrincipalName.class, new PrincipalNameAdapter());
@@ -214,14 +260,66 @@ public class JsonIdentityBackend extends AbstractIdentityBackend {
gson = gsonBuilder.create();
}
- private synchronized void persistToFile() throws KrbException {
+ private void persistToFile() throws KrbException {
String newJsonContent = gson.toJson(identities);
try {
- IOUtil.writeFile(newJsonContent, jsonKdbFile);
+ File newJsonKdbFile = File.createTempFile("kerby-kdb",
+ ".json", jsonKdbFile.getParentFile());
+ IOUtil.writeFile(newJsonContent, newJsonKdbFile);
+ newJsonKdbFile.renameTo(jsonKdbFile);
kdbFileUpdateTime = jsonKdbFile.lastModified();
} catch (IOException e) {
LOG.error("Error occurred while writing identities to file: " + jsonKdbFile);
throw new KrbException("Failed to write file", e);
}
}
+
+ class JsonBatchTrans implements BatchTrans {
+
+ @Override
+ public void commit() throws KrbException {
+ try {
+ // Force to persist memory states to disk file.
+ persistToFile();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ public void rollback() throws KrbException {
+ // Force to reload from disk file and disgard the memory states.
+ try {
+ load();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ public BatchTrans addIdentity(KrbIdentity identity) throws KrbException {
+ if (identity != null &&
+ identities.containsKey(identity.getPrincipalName())) {
+ identities.put(identity.getPrincipalName(), identity);
+ }
+ return this;
+ }
+
+ @Override
+ public BatchTrans updateIdentity(KrbIdentity identity) throws KrbException {
+ if (identity != null &&
+ identities.containsKey(identity.getPrincipalName())) {
+ identities.put(identity.getPrincipalName(), identity);
+ }
+ return this;
+ }
+
+ @Override
+ public BatchTrans deleteIdentity(String principalName) throws KrbException {
+ if (principalName != null && identities.containsKey(principalName)) {
+ identities.remove(principalName);
+ }
+ return this;
+ }
+ }
}