| | |
| | | private boolean forceBadDataSet = false; |
| | | |
| | | /** |
| | | * This flag is used by the fractional replication ldif import plugin to |
| | | * stop the (online) import process if a fractional configuration |
| | | * inconsistency is detected by it. |
| | | */ |
| | | private boolean followImport = true; |
| | | |
| | | /** |
| | | * The message id to be used when an import is stopped with error by |
| | | * the fractional replication ldif import plugin. |
| | | */ |
| | |
| | | storeECLConfiguration(configuration); |
| | | solveConflictFlag = isSolveConflict(configuration); |
| | | |
| | | Backend backend = retrievesBackend(getBaseDN()); |
| | | Backend backend = getBackend(); |
| | | if (backend == null) |
| | | { |
| | | throw new ConfigException(ERR_SEARCHING_DOMAIN_BACKEND.get( |
| | |
| | | * error by the fractional replication ldif import plugin. |
| | | * @param importErrorMessageId The message to use. |
| | | */ |
| | | public void setImportErrorMessageId(int importErrorMessageId) |
| | | void setImportErrorMessageId(int importErrorMessageId) |
| | | { |
| | | this.importErrorMessageId = importErrorMessageId; |
| | | } |
| | | |
| | | /** |
| | | * Sets the boolean telling if the online import currently in progress should |
| | | * continue. |
| | | * @param followImport The boolean telling if the online import currently in |
| | | * progress should continue. |
| | | * This flag is used by the fractional replication ldif import plugin to stop |
| | | * the (online) import process if a fractional configuration inconsistency is |
| | | * detected by it. |
| | | * |
| | | * @return true if the online import currently in progress should continue, |
| | | * false otherwise. |
| | | */ |
| | | public void setFollowImport(boolean followImport) |
| | | private boolean isFollowImport() |
| | | { |
| | | this.followImport = followImport; |
| | | return importErrorMessageId == -1; |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return true if the operation contains some attributes subject to filtering |
| | | * by the fractional configuration |
| | | */ |
| | | public boolean fractionalFilterOperation( |
| | | private boolean fractionalFilterOperation( |
| | | PreOperationAddOperation addOperation, boolean performFiltering) |
| | | { |
| | | return fractionalRemoveAttributesFromEntry(fractionalConfig, |
| | |
| | | * @return true if the operation is inconsistent with fractional |
| | | * configuration |
| | | */ |
| | | public boolean fractionalFilterOperation( |
| | | private boolean fractionalFilterOperation( |
| | | PreOperationModifyDNOperation modifyDNOperation, boolean performFiltering) |
| | | { |
| | | // Quick exit if not called for analyze and |
| | |
| | | * @return FRACTIONAL_HAS_FRACTIONAL_FILTERED_ATTRIBUTES, |
| | | * FRACTIONAL_HAS_NO_FRACTIONAL_FILTERED_ATTRIBUTES or FRACTIONAL_BECOME_NO_OP |
| | | */ |
| | | public int fractionalFilterOperation(PreOperationModifyOperation |
| | | private int fractionalFilterOperation(PreOperationModifyOperation |
| | | modifyOperation, boolean performFiltering) |
| | | { |
| | | /* |
| | |
| | | @Override |
| | | protected byte[] receiveEntryBytes() |
| | | { |
| | | if (followImport) |
| | | if (isFollowImport()) |
| | | { |
| | | // Ok, next entry is allowed to be received |
| | | return super.receiveEntryBytes(); |
| | |
| | | // process: |
| | | // This is an error termination during the import |
| | | // The error is stored and the import is ended by returning null |
| | | final IEContext ieCtx = getImportExportContext(); |
| | | Message msg = null; |
| | | switch (importErrorMessageId) |
| | | { |
| | | case IMPORT_ERROR_MESSAGE_BAD_REMOTE: |
| | | msg = NOTE_ERR_FULL_UPDATE_IMPORT_FRACTIONAL_BAD_REMOTE.get( |
| | | getBaseDNString(), Integer.toString(ieContext.getImportSource())); |
| | | getBaseDNString(), Integer.toString(ieCtx.getImportSource())); |
| | | break; |
| | | case IMPORT_ERROR_MESSAGE_REMOTE_IS_FRACTIONAL: |
| | | msg = NOTE_ERR_FULL_UPDATE_IMPORT_FRACTIONAL_REMOTE_IS_FRACTIONAL.get( |
| | | getBaseDNString(), Integer.toString(ieContext.getImportSource())); |
| | | getBaseDNString(), Integer.toString(ieCtx.getImportSource())); |
| | | break; |
| | | } |
| | | ieContext.setException(new DirectoryException(UNWILLING_TO_PERFORM, msg)); |
| | | ieCtx.setException(new DirectoryException(UNWILLING_TO_PERFORM, msg)); |
| | | return null; |
| | | } |
| | | |
| | |
| | | * @return A SynchronizationProviderResult indicating if the operation |
| | | * can continue. |
| | | */ |
| | | public SynchronizationProviderResult handleConflictResolution( |
| | | SynchronizationProviderResult handleConflictResolution( |
| | | PreOperationDeleteOperation deleteOperation) |
| | | { |
| | | if (!deleteOperation.isSynchronizationOperation() && !brokerIsConnected()) |
| | |
| | | * @return A SynchronizationProviderResult indicating if the operation |
| | | * can continue. |
| | | */ |
| | | public SynchronizationProviderResult handleConflictResolution( |
| | | SynchronizationProviderResult handleConflictResolution( |
| | | PreOperationAddOperation addOperation) |
| | | { |
| | | if (!addOperation.isSynchronizationOperation() && !brokerIsConnected()) |
| | |
| | | * @return A SynchronizationProviderResult indicating if the operation |
| | | * can continue. |
| | | */ |
| | | public SynchronizationProviderResult handleConflictResolution( |
| | | SynchronizationProviderResult handleConflictResolution( |
| | | PreOperationModifyDNOperation modifyDNOperation) |
| | | { |
| | | if (!modifyDNOperation.isSynchronizationOperation() && !brokerIsConnected()) |
| | |
| | | * @param modifyOperation the operation |
| | | * @return code indicating is operation must proceed |
| | | */ |
| | | public SynchronizationProviderResult handleConflictResolution( |
| | | SynchronizationProviderResult handleConflictResolution( |
| | | PreOperationModifyOperation modifyOperation) |
| | | { |
| | | if (!modifyOperation.isSynchronizationOperation() && !brokerIsConnected()) |
| | |
| | | * |
| | | * @return The number of updates in the pending list |
| | | */ |
| | | public int getPendingUpdatesCount() |
| | | private int getPendingUpdatesCount() |
| | | { |
| | | if (pendingChanges != null) |
| | | return pendingChanges.size(); |
| | |
| | | * |
| | | * @return The number of updates replayed successfully |
| | | */ |
| | | public int getNumReplayedPostOpCalled() |
| | | private int getNumReplayedPostOpCalled() |
| | | { |
| | | return numReplayedPostOpCalled; |
| | | } |
| | |
| | | * |
| | | * @param csn the CSN of the operation with error. |
| | | */ |
| | | public void updateError(CSN csn) |
| | | private void updateError(CSN csn) |
| | | { |
| | | try |
| | | { |
| | |
| | | * Get the number of modify conflicts successfully resolved. |
| | | * @return The number of modify conflicts successfully resolved. |
| | | */ |
| | | public int getNumResolvedModifyConflicts() |
| | | private int getNumResolvedModifyConflicts() |
| | | { |
| | | return numResolvedModifyConflicts.get(); |
| | | } |
| | |
| | | * Get the number of naming conflicts successfully resolved. |
| | | * @return The number of naming conflicts successfully resolved. |
| | | */ |
| | | public int getNumResolvedNamingConflicts() |
| | | private int getNumResolvedNamingConflicts() |
| | | { |
| | | return numResolvedNamingConflicts.get(); |
| | | } |
| | |
| | | * Get the number of unresolved conflicts. |
| | | * @return The number of unresolved conflicts. |
| | | */ |
| | | public int getNumUnresolvedNamingConflicts() |
| | | private int getNumUnresolvedNamingConflicts() |
| | | { |
| | | return numUnresolvedNamingConflicts.get(); |
| | | } |
| | |
| | | * @return The computed generationId. |
| | | * @throws DirectoryException When an error occurs. |
| | | */ |
| | | public long computeGenerationId() throws DirectoryException |
| | | private long computeGenerationId() throws DirectoryException |
| | | { |
| | | long genId = exportBackend(null, true); |
| | | |
| | |
| | | * Do whatever is needed when a backup is started. |
| | | * We need to make sure that the serverState is correctly save. |
| | | */ |
| | | public void backupStart() |
| | | void backupStart() |
| | | { |
| | | state.save(); |
| | | } |
| | |
| | | /** |
| | | * Do whatever is needed when a backup is finished. |
| | | */ |
| | | public void backupEnd() |
| | | void backupEnd() |
| | | { |
| | | // Nothing is needed at the moment |
| | | } |
| | |
| | | private long exportBackend(OutputStream output, boolean checksumOutput) |
| | | throws DirectoryException |
| | | { |
| | | Backend backend = retrievesBackend(getBaseDN()); |
| | | Backend backend = getBackend(); |
| | | |
| | | // Acquire a shared lock for the backend. |
| | | try |
| | |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the backend related to the domain. |
| | | * |
| | | * @return The backend of that domain. |
| | | * @param baseDN The baseDN to retrieve the backend |
| | | */ |
| | | protected static Backend retrievesBackend(DN baseDN) |
| | | { |
| | | // Retrieves the backend related to this domain |
| | | return DirectoryServer.getBackend(baseDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Process backend before import. |
| | | * |
| | | * @param backend |
| | |
| | | { |
| | | LDIFImportConfig importConfig = null; |
| | | |
| | | Backend backend = retrievesBackend(getBaseDN()); |
| | | Backend backend = getBackend(); |
| | | |
| | | IEContext ieCtx = getImportExportContext(); |
| | | try |
| | | { |
| | | if (!backend.supportsLDIFImport()) |
| | | { |
| | | ieContext.setExceptionIfNoneSet(new DirectoryException(OTHER, |
| | | ieCtx.setExceptionIfNoneSet(new DirectoryException(OTHER, |
| | | ERR_INIT_IMPORT_NOT_SUPPORTED.get(backend.getBackendID()))); |
| | | } |
| | | else |
| | |
| | | importConfig.setInvokeImportPlugins(true); |
| | | // Reset the follow import flag and message before starting the import |
| | | importErrorMessageId = -1; |
| | | followImport = true; |
| | | |
| | | // TODO How to deal with rejected entries during the import |
| | | importConfig.writeRejectedEntries( |
| | |
| | | } |
| | | catch(Exception e) |
| | | { |
| | | ieContext.setExceptionIfNoneSet(new DirectoryException(ResultCode.OTHER, |
| | | ieCtx.setExceptionIfNoneSet(new DirectoryException(ResultCode.OTHER, |
| | | ERR_INIT_IMPORT_FAILURE.get(stackTraceToSingleLineString(e)))); |
| | | } |
| | | finally |
| | |
| | | { |
| | | importConfig.close(); |
| | | closeBackendImport(backend); // Re-enable backend |
| | | backend = retrievesBackend(getBaseDN()); |
| | | backend = getBackend(); |
| | | } |
| | | |
| | | loadDataState(); |
| | | |
| | | if (ieContext.getException() != null) |
| | | if (ieCtx.getException() != null) |
| | | { |
| | | // When an error occurred during an import, most of times |
| | | // the generationId coming in the root entry of the imported data, |
| | |
| | | // so we don't bother about the new Exception. |
| | | // However if there was no Exception before we want |
| | | // to return this Exception to the task creator. |
| | | ieContext.setExceptionIfNoneSet(new DirectoryException( |
| | | ieCtx.setExceptionIfNoneSet(new DirectoryException( |
| | | ResultCode.OTHER, |
| | | ERR_INIT_IMPORT_FAILURE.get(stackTraceToSingleLineString(fe)))); |
| | | } |
| | | } |
| | | |
| | | if (ieContext.getException() != null) |
| | | throw ieContext.getException(); |
| | | if (ieCtx.getException() != null) |
| | | throw ieCtx.getException(); |
| | | } |
| | | |
| | | /** |
| | |
| | | * Returns the backend associated to this domain. |
| | | * @return The associated backend. |
| | | */ |
| | | public Backend getBackend() |
| | | private Backend getBackend() |
| | | { |
| | | return retrievesBackend(getBaseDN()); |
| | | return DirectoryServer.getBackend(getBaseDN()); |
| | | } |
| | | |
| | | /* |
| | |
| | | } |
| | | |
| | | // Check that the base DN is configured as a base-dn of the directory server |
| | | if (retrievesBackend(dn) == null) |
| | | if (DirectoryServer.getBackend(dn) == null) |
| | | { |
| | | unacceptableReasons.add(ERR_UNKNOWN_DN.get(dn.toString())); |
| | | return false; |
| | |
| | | ReplicationDomainCfg configuration, List<Message> unacceptableReasons) |
| | | { |
| | | // Check that a import/export is not in progress |
| | | if (importInProgress() || exportInProgress()) |
| | | if (ieRunning()) |
| | | { |
| | | unacceptableReasons.add( |
| | | NOTE_ERR_CANNOT_CHANGE_CONFIG_DURING_TOTAL_UPDATE.get()); |
| | |
| | | * Remove from this domain configuration, the configuration of the |
| | | * external change log. |
| | | */ |
| | | public void removeECLDomainCfg() |
| | | private void removeECLDomainCfg() |
| | | { |
| | | try |
| | | { |
| | |
| | | * @param domCfg The provided configuration. |
| | | * @throws ConfigException When an error occurred. |
| | | */ |
| | | public void storeECLConfiguration(ReplicationDomainCfg domCfg) |
| | | throws ConfigException |
| | | private void storeECLConfiguration(ReplicationDomainCfg domCfg) |
| | | throws ConfigException |
| | | { |
| | | ExternalChangelogDomainCfg eclDomCfg = null; |
| | | // create the ecl config if it does not exist |
| | |
| | | @Override |
| | | public long countEntries() throws DirectoryException |
| | | { |
| | | Backend backend = retrievesBackend(getBaseDN()); |
| | | Backend backend = getBackend(); |
| | | if (!backend.supportsLDIFExport()) |
| | | { |
| | | Message msg = ERR_INIT_EXPORT_NOT_SUPPORTED.get(backend.getBackendID()); |
| | |
| | | * Specifies whether this domain is enabled/disabled regarding the ECL. |
| | | * @return enabled/disabled for the ECL. |
| | | */ |
| | | public boolean isECLEnabled() |
| | | boolean isECLEnabled() |
| | | { |
| | | return this.eclDomain.isEnabled(); |
| | | } |
| | |
| | | * |
| | | * @return the purge delay. |
| | | */ |
| | | public long getHistoricalPurgeDelay() |
| | | long getHistoricalPurgeDelay() |
| | | { |
| | | return config.getConflictsHistoricalPurgeDelay() * 60 * 1000; |
| | | } |