mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

abobrov
26.44.2009 8a13236c15cb27e62c4654fc0120aa8896633dd8
- [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.
2 files modified
56 ■■■■ changed files
opendj-sdk/opends/src/server/org/opends/server/backends/ndb/EntryContainer.java 31 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/ndb/OperationContainer.java 25 ●●●● patch | view | raw | blame | history
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
    {
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) {