Changed ID2Entry#getRecordCount to use the Database#count method in JE 3.1.0. The JE backend no longer keeps a count of entries in entry ID 0. Modified TestVerifyJob unit test to no longer simulate a incorrect entry count.
Fix for issue 740
| | |
| | | } |
| | | } |
| | | |
| | | // Increment the entry count. |
| | | id2entry.adjustRecordCount(txn, 1); |
| | | } |
| | | |
| | | /** |
| | |
| | | id2cBuffered.flush(); |
| | | id2sBuffered.flush(); |
| | | |
| | | // Decrement the entry count. |
| | | id2entry.adjustRecordCount(txn, -getDeletedEntryCount()); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public long getEntryCount() throws DatabaseException |
| | | { |
| | | return id2entry.getRecordCount(null); |
| | | return id2entry.getRecordCount(); |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | /** |
| | | * Get the count of key/data pairs in the database in a JE database. |
| | | * This is a simple wrapper around the JE Database.count method. |
| | | * @param database the JE database handle. |
| | | * @return The count of key/data pairs in the database. |
| | | * @throws DatabaseException If an error occurs in the JE operation. |
| | | */ |
| | | public static long count(Database database) throws DatabaseException |
| | | { |
| | | long count = database.count(); |
| | | assert debugAccess("count", DATABASE_READ, null, database, |
| | | null, null, null); |
| | | return count; |
| | | } |
| | | |
| | | /** |
| | | * Remove a database from disk. |
| | | * |
| | | * @param name The short database name, to which the entryContainer name will |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006 Sun Microsystems, Inc. |
| | | * Portions Copyright 2006 - 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | |
| | | /** |
| | | * Get the count of the number of entries stored. |
| | | * |
| | | * @param txn A JE database transaction to be used for database access, or |
| | | * null if none is required. |
| | | * @return The number of entries stored. |
| | | * |
| | | * @throws DatabaseException If an error occurs in the JE database. |
| | | */ |
| | | public long getRecordCount(Transaction txn) throws DatabaseException |
| | | public long getRecordCount() throws DatabaseException |
| | | { |
| | | DatabaseEntry key; |
| | | DatabaseEntry data = new DatabaseEntry(); |
| | | |
| | | // The count is stored in a special record whose key is entry ID zero. |
| | | EntryID id = new EntryID(0); |
| | | key = id.getDatabaseEntry(); |
| | | |
| | | // Read the current count, if any. |
| | | OperationStatus status = EntryContainer.read(getDatabase(), txn, |
| | | key, data, LockMode.DEFAULT); |
| | | |
| | | // Parse the current count. |
| | | long count = 0; |
| | | if (status == OperationStatus.SUCCESS) |
| | | { |
| | | count = JebFormat.entryIDFromDatabase(data.getData()); |
| | | } |
| | | |
| | | return count; |
| | | return EntryContainer.count(getDatabase()); |
| | | } |
| | | |
| | | /** |
| | | * Adjust the count of the number of entries stored. |
| | | * |
| | | * @param txn A database transaction, required to be non-null if multiple |
| | | * threads are calling this method concurrently. |
| | | * @param deltaCount Amount to increment (or decrement if negative). |
| | | * @throws DatabaseException If an error occurs in the JE database. |
| | | */ |
| | | public void adjustRecordCount(Transaction txn, long deltaCount) |
| | | throws DatabaseException |
| | | { |
| | | DatabaseEntry key; |
| | | DatabaseEntry data = new DatabaseEntry(); |
| | | |
| | | // The count is stored in a special record whose key is entry ID zero. |
| | | EntryID id = new EntryID(0); |
| | | key = id.getDatabaseEntry(); |
| | | |
| | | // Read the current count, if any. |
| | | OperationStatus status = EntryContainer.read(getDatabase(), txn, |
| | | key, data, LockMode.RMW); |
| | | |
| | | // Parse the current count. |
| | | long count = 0; |
| | | if (status == OperationStatus.SUCCESS) |
| | | { |
| | | count = JebFormat.entryIDFromDatabase(data.getData()); |
| | | } |
| | | |
| | | // Adjust the count. |
| | | count += deltaCount; |
| | | |
| | | // Write it. |
| | | byte[] bytes = JebFormat.entryIDToDatabase(count); |
| | | data.setData(bytes); |
| | | EntryContainer.put(getDatabase(), txn, key, data); |
| | | } |
| | | } |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006 Sun Microsystems, Inc. |
| | | * Portions Copyright 2006 - 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | // Record the entry count for each base DN. |
| | | for (ImportContext ic : importMap.values()) |
| | | { |
| | | ID2Entry id2e = ic.getEntryContainer().getID2Entry(); |
| | | id2e.adjustRecordCount(null, ic.getEntryInsertCount()); |
| | | } |
| | | |
| | | return moreData; |
| | | } |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006 Sun Microsystems, Inc. |
| | | * Portions Copyright 2006 - 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | |
| | | DatabaseEntry key = new DatabaseEntry(); |
| | | DatabaseEntry data = new DatabaseEntry(); |
| | | |
| | | Long storedEntryCount = null; |
| | | Long storedEntryCount = id2entry.getRecordCount(); |
| | | |
| | | OperationStatus status; |
| | | for (status = cursor.getFirst(key, data, LockMode.DEFAULT); |
| | |
| | | continue; |
| | | } |
| | | |
| | | if (entryID.longValue() == 0) |
| | | { |
| | | // This is the stored entry count. |
| | | storedEntryCount = JebFormat.entryIDFromDatabase(data.getData()); |
| | | } |
| | | else |
| | | { |
| | | keyCount++; |
| | | keyCount++; |
| | | |
| | | Entry entry; |
| | | try |
| | | { |
| | | entry = JebFormat.entryFromDatabase(data.getData()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "iterateID2Entry", e); |
| | | errorCount++; |
| | | System.err.printf("Malformed id2entry record for ID %d:%n%s%n", |
| | | entryID.longValue(), |
| | | StaticUtils.bytesToHex(data.getData())); |
| | | continue; |
| | | } |
| | | |
| | | verifyEntry(entryID, entry); |
| | | } |
| | | } |
| | | if (storedEntryCount != null) |
| | | { |
| | | if (keyCount != storedEntryCount) |
| | | Entry entry; |
| | | try |
| | | { |
| | | entry = JebFormat.entryFromDatabase(data.getData()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "iterateID2Entry", e); |
| | | errorCount++; |
| | | System.err.printf("The stored entry count in id2entry (%d) does " + |
| | | "not agree with the actual number of entry " + |
| | | "records found (%d).%n", |
| | | storedEntryCount, keyCount); |
| | | System.err.printf("Malformed id2entry record for ID %d:%n%s%n", |
| | | entryID.longValue(), |
| | | StaticUtils.bytesToHex(data.getData())); |
| | | continue; |
| | | } |
| | | |
| | | verifyEntry(entryID, entry); |
| | | } |
| | | else |
| | | if (keyCount != storedEntryCount) |
| | | { |
| | | errorCount++; |
| | | System.err.printf("Missing record count in id2entry.%n"); |
| | | System.err.printf("The stored entry count in id2entry (%d) does " + |
| | | "not agree with the actual number of entry " + |
| | | "records found (%d).%n", |
| | | storedEntryCount, keyCount); |
| | | } |
| | | } |
| | | finally |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006 Sun Microsystems, Inc. |
| | | * Portions Copyright 2006 - 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | |
| | | assertTrue(id2entry.putRaw(txn, key1, data1)); |
| | | performBECompleteVerify("telephoneNumber", 3); |
| | | } |
| | | |
| | | /** |
| | | * Change the stored count to invalid value in the telephoneNumber |
| | | * index. |
| | | * @throws Exception if the error count is not equal 1. |
| | | */ |
| | | @Test() public void testBadStoredCount() throws Exception { |
| | | preTest(2); |
| | | //whack the count |
| | | setStoredCount(100); |
| | | performBECompleteVerify("telephoneNumber", 1); |
| | | } |
| | | |
| | | /** |
| | | * |
| | |
| | | testDN=DN.decode(noParentDN); |
| | | id=new EntryID(12); |
| | | assertTrue(dn2id.insert(txn, testDN, id)); |
| | | setStoredCount(12); |
| | | performBECompleteVerify("dn2id", 3); |
| | | } |
| | | |
| | |
| | | byte[] idBytesp=new byte[16]; |
| | | idBytesp[7]=(byte) 0xFF; |
| | | EntryIDSet idSetp=new EntryIDSet(null, idBytesp); |
| | | id2child.writeKey(txn, keyp, idSetp); |
| | | setStoredCount(12); |
| | | id2child.writeKey(txn, keyp, idSetp); |
| | | performBECompleteVerify("id2children", 3); |
| | | } |
| | | |
| | |
| | | EntryIDSet idSetp=new EntryIDSet(); |
| | | DatabaseEntry key= new EntryID(2).getDatabaseEntry(); |
| | | id2child.writeKey(txn, key, idSetp); |
| | | setStoredCount(3); |
| | | performBECompleteVerify("id2children", 0); |
| | | } |
| | | |
| | |
| | | public void testVerifyID2Subtree() throws Exception { |
| | | preTest(2); |
| | | //Add entry with no parent |
| | | addID2EntryReturnKey(noParentDN, 3, false); |
| | | setStoredCount(3); |
| | | addID2EntryReturnKey(noParentDN, 3, false); |
| | | performBECompleteVerify("id2subtree", 3); |
| | | } |
| | | |
| | |
| | | EntryIDSet idSet=new EntryIDSet(); |
| | | DatabaseEntry key= new EntryID(2).getDatabaseEntry(); |
| | | id2subtree.writeKey(txn, key, idSet); |
| | | setStoredCount(3); |
| | | performBECompleteVerify("id2subtree", 1); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Adjust stored entry count in the id2entry file. |
| | | * @param c new count. |
| | | * @throws Exception if the putRaw method fails. |
| | | */ |
| | | private void setStoredCount(long c) throws Exception { |
| | | DatabaseEntry keyS= new EntryID(0).getDatabaseEntry(); |
| | | DatabaseEntry dataS= new EntryID(c).getDatabaseEntry(); |
| | | assertTrue(id2entry.putRaw(txn, keyS, dataS)); |
| | | } |
| | | |
| | | /** |
| | | * Does a pretest setup. Creates some number of entries, gets |