From 8a13236c15cb27e62c4654fc0120aa8896633dd8 Mon Sep 17 00:00:00 2001
From: abobrov <abobrov@localhost>
Date: Thu, 26 Mar 2009 16:44:59 +0000
Subject: [PATCH] - [Issue 3894] possible data corruption issues when writing binary attributes/blobs : move blobs to active state before writing the actual data, use new writeData API, optimize add operation to invoke execute/NoCommit past insert only when necessary ie when batching.
---
opendj-sdk/opends/src/server/org/opends/server/backends/ndb/EntryContainer.java | 31 +++++++++++++++++++------------
opendj-sdk/opends/src/server/org/opends/server/backends/ndb/OperationContainer.java | 25 ++++++++++++++++++++++---
2 files changed, 41 insertions(+), 15 deletions(-)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/ndb/EntryContainer.java b/opendj-sdk/opends/src/server/org/opends/server/backends/ndb/EntryContainer.java
index 0379c05..196afa7 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/ndb/EntryContainer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/ndb/EntryContainer.java
@@ -661,7 +661,7 @@
try
{
// Invoke the operation.
- operation.invokeOperation(txn);
+ operation.invokeOperation(txn, commit);
// One last check before committing.
if (ldapOperation != null) {
@@ -734,12 +734,13 @@
* Invoke the operation under the given transaction.
*
* @param txn The transaction to be used to perform the operation.
+ * @param willCommit Indicates whether or not the caller will commit.
* @throws NdbApiException If an error occurs in the NDB database.
* @throws DirectoryException If a Directory Server error occurs.
* @throws NDBException If an error occurs in the NDB backend.
*/
- public abstract void invokeOperation(AbstractTransaction txn)
- throws NdbApiException, DirectoryException,
+ public abstract void invokeOperation(AbstractTransaction txn,
+ boolean willCommit) throws NdbApiException, DirectoryException,
CanceledOperationException, NDBException;
/**
@@ -785,11 +786,12 @@
* Invoke the operation under the given transaction.
*
* @param txn The transaction to be used to perform the operation.
+ * @param willCommit Indicates whether or not the caller will commit.
* @throws NdbApiException If an error occurs in the NDB database.
* @throws DirectoryException If a Directory Server error occurs.
* @throws NDBException If an error occurs in the NDB backend.
*/
- public void invokeOperation(AbstractTransaction txn)
+ public void invokeOperation(AbstractTransaction txn, boolean willCommit)
throws NdbApiException, DirectoryException, NDBException
{
// Check that the parent entry exists.
@@ -816,7 +818,9 @@
// Insert.
try {
dn2id.insert(txn, entry.getDN(), entryID, entry);
- txn.execute();
+ if (!willCommit) {
+ txn.execute();
+ }
} catch (NdbApiException ne) {
if (ne.getErrorObj().getClassification() ==
NdbError.Classification.ConstraintViolation)
@@ -1129,11 +1133,12 @@
* Invoke the operation under the given transaction.
*
* @param txn The transaction to be used to perform the operation.
+ * @param willCommit Indicates whether or not the caller will commit.
* @throws NdbApiException If an error occurs in the NDB database.
* @throws DirectoryException If a Directory Server error occurs.
* @throws NDBException If an error occurs in the NDB backend.
*/
- public void invokeOperation(AbstractTransaction txn)
+ public void invokeOperation(AbstractTransaction txn, boolean willCommit)
throws CanceledOperationException, NdbApiException,
DirectoryException, NDBException
{
@@ -1412,12 +1417,13 @@
/**
* Invoke the operation under the given transaction.
*
- * @param txn The transaction to be used to perform the operation
+ * @param txn The transaction to be used to perform the operation.
+ * @param willCommit Indicates whether or not the caller will commit.
* @throws NdbApiException If an error occurs in the NDB database.
* @throws DirectoryException If a Directory Server error occurs.
* @throws NDBException If an error occurs in the NDB backend.
*/
- public void invokeOperation(AbstractTransaction txn)
+ public void invokeOperation(AbstractTransaction txn, boolean willCommit)
throws NdbApiException, DirectoryException, NDBException
{
entry = dn2id.get(txn, entryDN, lockMode);
@@ -1510,13 +1516,13 @@
* Invoke the operation under the given transaction.
*
* @param txn The transaction to be used to perform the operation.
+ * @param willCommit Indicates whether or not the caller will commit.
* @throws NdbApiException If an error occurs in the NDB database.
* @throws DirectoryException If a Directory Server error occurs.
* @throws NDBException If an error occurs in the NDB backend.
*/
- public void invokeOperation(AbstractTransaction txn) throws NdbApiException,
- DirectoryException,
- NDBException
+ public void invokeOperation(AbstractTransaction txn, boolean willCommit)
+ throws NdbApiException, DirectoryException, NDBException
{
DN entryDN = newEntry.getDN();
entryID = (Long) oldEntry.getAttachment();
@@ -1645,11 +1651,12 @@
* Invoke the operation under the given transaction.
*
* @param txn The transaction to be used to perform the operation.
+ * @param willCommit Indicates whether or not the caller will commit.
* @throws NdbApiException If an error occurs in the NDB database.
* @throws DirectoryException If a Directory Server error occurs.
* @throws NDBException If an error occurs in the NDB backend.
*/
- public void invokeOperation(AbstractTransaction txn)
+ public void invokeOperation(AbstractTransaction txn, boolean willCommit)
throws NdbApiException, DirectoryException,
CanceledOperationException, NDBException
{
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/ndb/OperationContainer.java b/opendj-sdk/opends/src/server/org/opends/server/backends/ndb/OperationContainer.java
index 3154152..18bc508 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/ndb/OperationContainer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/ndb/OperationContainer.java
@@ -161,6 +161,8 @@
Map<ObjectClass, String> ocMap = entry.getObjectClasses();
Map<AttributeType, List<Attribute>> userAttrMap =
entry.getUserAttributes();
+ Map<NdbBlob, byte[]> blobMap =
+ new HashMap<NdbBlob, byte[]>(BackendImpl.blobAttributes.size());
ArrayList<AttributeType> userAttributes =
new ArrayList<AttributeType>();
@@ -252,7 +254,9 @@
}
if (BackendImpl.blobAttributes.contains(attrName)) {
NdbBlob blob = attrOp.getBlobHandle(attrName);
- blob.setValue(attrVal.getValue().toByteArray());
+ blob.setValue(new byte[0]);
+ byte[] blobBytes = attrVal.getValue().toByteArray();
+ blobMap.put(blob, blobBytes);
} else {
attrOp.setString(attrName, attrStringVal);
}
@@ -328,7 +332,9 @@
}
if (BackendImpl.blobAttributes.contains(attrName)) {
NdbBlob blob = attrOp.getBlobHandle(attrName);
- blob.setValue(attrVal.getValue().toByteArray());
+ blob.setValue(new byte[0]);
+ byte[] blobBytes = attrVal.getValue().toByteArray();
+ blobMap.put(blob, blobBytes);
} else {
attrOp.setString(attrName, attrStringVal);
}
@@ -421,7 +427,9 @@
}
if (BackendImpl.blobAttributes.contains(attrName)) {
NdbBlob blob = attrOp.getBlobHandle(attrName);
- blob.setValue(attrVal.getValue().toByteArray());
+ blob.setValue(new byte[0]);
+ byte[] blobBytes = attrVal.getValue().toByteArray();
+ blobMap.put(blob, blobBytes);
} else {
attrOp.setString(attrName, attrStringVal);
}
@@ -477,6 +485,17 @@
}
}
+ // Move this txn into the active state and write blob data if any.
+ if (!blobMap.isEmpty()) {
+ ndbDATxn.execute(ExecType.NoCommit, AbortOption.AbortOnError, true);
+ Set<Map.Entry<NdbBlob, byte[]>> blobEntrySet = blobMap.entrySet();
+ for (Map.Entry blobEntry : blobEntrySet) {
+ NdbBlob blob = (NdbBlob) blobEntry.getKey();
+ byte[] blobBytes = (byte[]) blobEntry.getValue();
+ blob.writeData(blobBytes);
+ }
+ }
+
// Update dn2id table.
NdbTransaction ndbTxn = txn.getNdbTransaction();
if (overwrite) {
--
Gitblit v1.10.0