| | |
| | | { |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | |
| | | /** |
| | | * The verify configuration. |
| | | */ |
| | | private VerifyConfig verifyConfig; |
| | | |
| | | /** |
| | | * The root container used for the verify job. |
| | | */ |
| | | /** The verify configuration. */ |
| | | private final VerifyConfig verifyConfig; |
| | | /** The root container used for the verify job. */ |
| | | private RootContainer rootContainer; |
| | | |
| | | /** |
| | | * The number of milliseconds between job progress reports. |
| | | */ |
| | | private long progressInterval = 10000; |
| | | |
| | | /** |
| | | * The number of index keys processed. |
| | | */ |
| | | private long keyCount = 0; |
| | | |
| | | /** |
| | | * The number of errors found. |
| | | */ |
| | | private long errorCount = 0; |
| | | |
| | | /** |
| | | * The number of records that have exceeded the entry limit. |
| | | */ |
| | | private long entryLimitExceededCount = 0; |
| | | |
| | | /** |
| | | * The number of records that reference more than one entry. |
| | | */ |
| | | private long multiReferenceCount = 0; |
| | | |
| | | /** |
| | | * The total number of entry references. |
| | | */ |
| | | private long entryReferencesCount = 0; |
| | | |
| | | /** |
| | | * The maximum number of references per record. |
| | | */ |
| | | private long maxEntryPerValue = 0; |
| | | /** The number of milliseconds between job progress reports. */ |
| | | private final long progressInterval = 10000; |
| | | /** The number of index keys processed. */ |
| | | private long keyCount; |
| | | /** The number of errors found. */ |
| | | private long errorCount; |
| | | /** The number of records that have exceeded the entry limit. */ |
| | | private long entryLimitExceededCount; |
| | | /** The number of records that reference more than one entry. */ |
| | | private long multiReferenceCount; |
| | | /** The total number of entry references. */ |
| | | private long entryReferencesCount; |
| | | /** The maximum number of references per record. */ |
| | | private long maxEntryPerValue; |
| | | |
| | | /** |
| | | * This map is used to gather some statistics about values that have |
| | |
| | | private IdentityHashMap<Index, HashMap<ByteString, Long>> entryLimitMap = |
| | | new IdentityHashMap<Index, HashMap<ByteString, Long>>(); |
| | | |
| | | /** |
| | | * Indicates whether the DN database is to be verified. |
| | | */ |
| | | private boolean verifyDN2ID = false; |
| | | /** Indicates whether the DN database is to be verified. */ |
| | | private boolean verifyDN2ID; |
| | | /** Indicates whether the children database is to be verified. */ |
| | | private boolean verifyID2Children; |
| | | /** Indicates whether the subtree database is to be verified. */ |
| | | private boolean verifyID2Subtree; |
| | | |
| | | /** |
| | | * Indicates whether the children database is to be verified. |
| | | */ |
| | | private boolean verifyID2Children = false; |
| | | |
| | | /** |
| | | * Indicates whether the subtree database is to be verified. |
| | | */ |
| | | private boolean verifyID2Subtree = false; |
| | | |
| | | /** |
| | | * The entry database. |
| | | */ |
| | | /** The entry database. */ |
| | | private ID2Entry id2entry; |
| | | |
| | | /** |
| | | * The DN database. |
| | | */ |
| | | /** The DN database. */ |
| | | private DN2ID dn2id; |
| | | |
| | | /** |
| | | * The children database. |
| | | */ |
| | | /** The children database. */ |
| | | private Index id2c; |
| | | |
| | | /** |
| | | * The subtree database. |
| | | */ |
| | | /** The subtree database. */ |
| | | private Index id2s; |
| | | |
| | | /** |
| | | * A list of the attribute indexes to be verified. |
| | | */ |
| | | private ArrayList<AttributeIndex> attrIndexList = |
| | | new ArrayList<AttributeIndex>(); |
| | | private final ArrayList<AttributeIndex> attrIndexList = new ArrayList<AttributeIndex>(); |
| | | |
| | | /** |
| | | * A list of the VLV indexes to be verified. |
| | | */ |
| | | private ArrayList<VLVIndex> vlvIndexList = new ArrayList<VLVIndex>(); |
| | | private final ArrayList<VLVIndex> vlvIndexList = new ArrayList<VLVIndex>(); |
| | | |
| | | /** |
| | | * Construct a VerifyJob. |
| | |
| | | for (String index : list) |
| | | { |
| | | String lowerName = index.toLowerCase(); |
| | | if (lowerName.equals("dn2id")) |
| | | if ("dn2id".equals(lowerName)) |
| | | { |
| | | verifyDN2ID = true; |
| | | } |
| | | else if (lowerName.equals("id2children")) |
| | | else if ("id2children".equals(lowerName)) |
| | | { |
| | | if (rootContainer.getConfiguration().isSubordinateIndexesEnabled()) |
| | | { |
| | |
| | | throw new JebException(msg); |
| | | } |
| | | } |
| | | else if (lowerName.equals("id2subtree")) |
| | | else if ("id2subtree".equals(lowerName)) |
| | | { |
| | | if (rootContainer.getConfiguration().isSubordinateIndexesEnabled()) |
| | | { |
| | |
| | | } |
| | | |
| | | long finishTime = System.currentTimeMillis(); |
| | | long totalTime = (finishTime - startTime); |
| | | long totalTime = finishTime - startTime; |
| | | |
| | | float rate = 0; |
| | | if (totalTime > 0) |
| | |
| | | float averageEntryReferences = 0; |
| | | if (keyCount > 0) |
| | | { |
| | | averageEntryReferences = (float)entryReferencesCount/keyCount; |
| | | averageEntryReferences = entryReferencesCount/keyCount; |
| | | } |
| | | |
| | | logger.debug(INFO_JEB_VERIFY_MULTIPLE_REFERENCE_COUNT, multiReferenceCount); |
| | |
| | | { |
| | | iterateID2Subtree(); |
| | | } |
| | | else |
| | | { |
| | | if(attrIndexList.size() > 0) |
| | | else if (attrIndexList.size() > 0) |
| | | { |
| | | AttributeIndex attrIndex = attrIndexList.get(0); |
| | | final IndexingOptions options = attrIndex.getIndexingOptions(); |
| | |
| | | iterateAttrIndex(attrIndex.getOrderingIndex(), options); |
| | | iterateAttrIndex(attrIndex.getApproximateIndex(), options); |
| | | // TODO: Need to iterate through ExtendedMatchingRules indexes. |
| | | } else if(vlvIndexList.size() > 0) |
| | | } |
| | | else if (vlvIndexList.size() > 0) |
| | | { |
| | | iterateVLVIndex(vlvIndexList.get(0), true); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Iterate through the entries in DN2ID to perform a check for |
| | |
| | | "ID %d%n", new String(key.getData()), entryID.longValue()); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (!Arrays.equals(JebFormat.dnToDNKey( |
| | | else if (!Arrays.equals(JebFormat.dnToDNKey( |
| | | entry.getName(), verifyConfig.getBaseDN().size()), key.getData())) |
| | | { |
| | | errorCount++; |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.trace("File dn2id has DN <%s> referencing entry " + |
| | | "with wrong DN <%s>%n", new String(key.getData()), |
| | | entry.getName().toString()); |
| | | } |
| | | logger.trace("File dn2id has DN <%s> referencing entry with wrong DN <%s>%n", |
| | | new String(key.getData()), entry.getName()); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | ByteString octetString = ByteString.wrap(key); |
| | | Long counter = hashMap.get(octetString); |
| | | if (counter == null) |
| | | if (counter != null) |
| | | { |
| | | counter = 1L; |
| | | counter++; |
| | | } |
| | | else |
| | | { |
| | | counter++; |
| | | counter = 1L; |
| | | } |
| | | hashMap.put(octetString, counter); |
| | | } |
| | |
| | | |
| | | for (EntryID id : entryIDList) |
| | | { |
| | | if (prevID != null && id.equals(prevID)) |
| | | { |
| | | if (logger.isTraceEnabled()) |
| | | if (prevID != null && id.equals(prevID) && logger.isTraceEnabled()) |
| | | { |
| | | logger.trace("Duplicate reference to ID %d%n%s", |
| | | id.longValue(), keyDump(index, key.getData())); |
| | | } |
| | | } |
| | | prevID = id; |
| | | |
| | | Entry entry; |
| | |
| | | { |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.trace("File dn2id is missing key %s.%n", |
| | | dn.toString()); |
| | | logger.trace("File dn2id is missing key %s.%n", dn); |
| | | } |
| | | errorCount++; |
| | | } |
| | |
| | | { |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.trace("File dn2id has ID %d instead of %d for key %s.%n", |
| | | id.longValue(), |
| | | entryID.longValue(), |
| | | dn.toString()); |
| | | logger.trace("File dn2id has ID %d instead of %d for key %s.%n", id.longValue(), entryID.longValue(), dn); |
| | | } |
| | | errorCount++; |
| | | } |
| | |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | logger.trace("File dn2id has error reading key %s: %s.%n", |
| | | dn.toString(), |
| | | e.getMessage()); |
| | | logger.trace("File dn2id has error reading key %s: %s.%n", dn, e.getMessage()); |
| | | } |
| | | errorCount++; |
| | | } |
| | |
| | | { |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.trace("File dn2id is missing key %s.%n", |
| | | parentDN.toString()); |
| | | logger.trace("File dn2id is missing key %s.%n", parentDN); |
| | | } |
| | | errorCount++; |
| | | } |
| | |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | logger.trace("File dn2id has error reading key %s: %s.%n", |
| | | parentDN.toString(), |
| | | e.getMessage()); |
| | | logger.trace("File dn2id has error reading key %s: %s.%n", parentDN, e.getMessage()); |
| | | } |
| | | errorCount++; |
| | | } |
| | |
| | | { |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.trace("File dn2id is missing key %s.%n", |
| | | parentDN.toString()); |
| | | logger.trace("File dn2id is missing key %s.%n", parentDN); |
| | | } |
| | | errorCount++; |
| | | } |
| | |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | logger.trace("File dn2id has error reading key %s: %s.", |
| | | parentDN.toString(), |
| | | e.getMessage()); |
| | | logger.trace("File dn2id has error reading key %s: %s.", parentDN, e.getMessage()); |
| | | } |
| | | errorCount++; |
| | | } |
| | |
| | | { |
| | | try |
| | | { |
| | | ConditionResult cr; |
| | | cr = id2c.containsID(null, parentID.getDatabaseEntry(), entryID); |
| | | ConditionResult cr = id2c.containsID(null, parentID.getDatabaseEntry(), entryID); |
| | | if (cr == ConditionResult.FALSE) |
| | | { |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.trace("File id2children is missing ID %d " + |
| | | "for key %d.%n", |
| | | logger.trace("File id2children is missing ID %d for key %d.%n", |
| | | entryID.longValue(), parentID.longValue()); |
| | | } |
| | | errorCount++; |
| | |
| | | { |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.trace("File dn2id is missing key %s.%n", |
| | | dn.toString()); |
| | | logger.trace("File dn2id is missing key %s.%n", dn); |
| | | } |
| | | errorCount++; |
| | | } |
| | |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | logger.trace("File dn2id has error reading key %s: %s.%n", |
| | | dn.toString(), |
| | | e.getMessage()); |
| | | logger.trace("File dn2id has error reading key %s: %s.%n", dn, e.getMessage()); |
| | | } |
| | | errorCount++; |
| | | } |
| | |
| | | { |
| | | try |
| | | { |
| | | if(vlvIndex.shouldInclude(entry)) |
| | | { |
| | | if (!vlvIndex.containsValues(null, entryID.longValue(), |
| | | if (vlvIndex.shouldInclude(entry) |
| | | && !vlvIndex.containsValues(null, entryID.longValue(), |
| | | vlvIndex.getSortValues(entry), vlvIndex.getSortTypes())) |
| | | { |
| | | if(logger.isTraceEnabled()) |
| | |
| | | errorCount++; |
| | | } |
| | | } |
| | | } |
| | | catch (DirectoryException e) |
| | | { |
| | | if (logger.isTraceEnabled()) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | logger.trace("Error checking entry %s against filter or " + |
| | | "base DN for VLV index %s: %s", |
| | | logger.trace("Error checking entry %s against filter or base DN for VLV index %s: %s", |
| | | entry.getName(), vlvIndex.getName(), e.getMessageObject()); |
| | | } |
| | | errorCount++; |
| | |
| | | /** |
| | | * This class reports progress of the verify job at fixed intervals. |
| | | */ |
| | | class ProgressTask extends TimerTask |
| | | private class ProgressTask extends TimerTask |
| | | { |
| | | /** |
| | | * The total number of records to process. |
| | |
| | | * The number of records that had been processed at the time of the |
| | | * previous progress report. |
| | | */ |
| | | private long previousCount = 0; |
| | | private long previousCount; |
| | | |
| | | /** |
| | | * The time in milliseconds of the previous progress report. |
| | |
| | | * @throws DatabaseException An error occurred while accessing the JE |
| | | * database. |
| | | */ |
| | | public ProgressTask(boolean indexIterator) throws DatabaseException |
| | | private ProgressTask(boolean indexIterator) throws DatabaseException |
| | | { |
| | | previousTime = System.currentTimeMillis(); |
| | | prevEnvStats = |
| | | rootContainer.getEnvironmentStats(new StatsConfig()); |
| | | prevEnvStats = rootContainer.getEnvironmentStats(new StatsConfig()); |
| | | |
| | | if (indexIterator) |
| | | { |
| | |
| | | { |
| | | totalCount = id2s.getRecordCount(); |
| | | } |
| | | else |
| | | { |
| | | if(attrIndexList.size() > 0) |
| | | else if(attrIndexList.size() > 0) |
| | | { |
| | | AttributeIndex attrIndex = attrIndexList.get(0); |
| | | totalCount = 0; |
| | |
| | | totalCount += attrIndex.getApproximateIndex().getRecordCount(); |
| | | } |
| | | // TODO: Add support for Extended Matching Rules indexes. |
| | | } else if(vlvIndexList.size() > 0) |
| | | } |
| | | else if (vlvIndexList.size() > 0) |
| | | { |
| | | totalCount = vlvIndexList.get(0).getRecordCount(); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | totalCount = rootContainer.getEntryContainer( |
| | |
| | | public void run() |
| | | { |
| | | long latestCount = keyCount; |
| | | long deltaCount = (latestCount - previousCount); |
| | | long deltaCount = latestCount - previousCount; |
| | | long latestTime = System.currentTimeMillis(); |
| | | long deltaTime = latestTime - previousTime; |
| | | |