Migrate the BackendConfigManager to the new configuration framework.
6 files added
29 files modified
| | |
| | | or $value = 'ldap' or $value = 'ldaps' or $value = 'ldif' |
| | | or $value = 'jdbc' or $value = 'tcp' or $value = 'tls' |
| | | or $value = 'pkcs11' or $value = 'sasl' or $value = 'gssapi' |
| | | or $value = 'md5' " /> |
| | | or $value = 'md5' or $value = 'je' or $value = 'dse' " /> |
| | | </xsl:template> |
| | | </xsl:stylesheet> |
| | |
| | | Sizes can be specified using both decimal and binary units. |
| | | For example, "1kb" represents 1000 bytes, and "1kib" |
| | | represents 1024 bytes. Values must always specify the unit |
| | | and can included a fractionaly part (e.g. 1.5mb). Both short |
| | | and can include a fractional part (e.g. 1.5mb). Both short |
| | | and long unit names are supported (e.g. "kb" and |
| | | "kilobytes"). |
| | | </xsd:documentation> |
| | |
| | | ds-cfg-backend-import-thread-count: 8 |
| | | ds-cfg-backend-entries-compressed: false |
| | | ds-cfg-backend-deadlock-retry-limit: 10 |
| | | ds-cfg-database-cache-percent: 10 |
| | | ds-cfg-database-cache-size: 0 megabytes |
| | | ds-cfg-database-txn-no-sync: false |
| | | ds-cfg-database-txn-write-no-sync: true |
| | | ds-cfg-database-run-cleaner: true |
| | | ds-cfg-database-cleaner-num-threads: 1 |
| | | ds-cfg-database-cleaner-min-utilization: 75 |
| | | ds-cfg-database-evictor-lru-only: true |
| | | ds-cfg-database-evictor-nodes-per-scan: 10 |
| | | ds-cfg-database-log-file-max: 50 megabytes |
| | | ds-cfg-database-logging-file-handler-on: true |
| | | ds-cfg-database-logging-level: CONFIG |
| | | ds-cfg-database-checkpointer-bytes-interval: 20 megabytes |
| | | ds-cfg-database-checkpointer-wakeup-interval: 30 seconds |
| | | ds-cfg-database-lock-num-lock-tables: 19 |
| | | |
| | | dn: cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config |
| | | objectClass: top |
| | |
| | | ds-cfg-index-attribute: entryuuid |
| | | ds-cfg-index-type: equality |
| | | |
| | | dn: cn=JE Database,ds-cfg-backend-id=userRoot,cn=Backends,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-database |
| | | cn: JE Database |
| | | ds-cfg-database-cache-percent: 10 |
| | | ds-cfg-database-cache-size: 0 megabytes |
| | | ds-cfg-database-txn-no-sync: false |
| | | ds-cfg-database-txn-write-no-sync: true |
| | | ds-cfg-database-run-cleaner: true |
| | | ds-cfg-database-cleaner-num-threads: 1 |
| | | ds-cfg-database-cleaner-min-utilization: 75 |
| | | ds-cfg-database-evictor-lru-only: true |
| | | ds-cfg-database-evictor-nodes-per-scan: 10 |
| | | ds-cfg-database-log-file-max: 50 megabytes |
| | | ds-cfg-database-logging-file-handler-on: true |
| | | ds-cfg-database-logging-level: CONFIG |
| | | ds-cfg-database-checkpointer-bytes-interval: 20 megabytes |
| | | ds-cfg-database-checkpointer-wakeup-interval: 30 seconds |
| | | ds-cfg-database-lock-num-lock-tables: 19 |
| | | |
| | | dn: ds-cfg-backend-id=backup,cn=Backends,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-backend |
| | |
| | | ds-cfg-backend-import-temp-directory $ ds-cfg-backend-import-buffer-size $ |
| | | ds-cfg-backend-import-queue-size $ ds-cfg-backend-import-thread-count $ |
| | | ds-cfg-backend-entries-compressed $ ds-cfg-backend-deadlock-retry-limit $ |
| | | ds-cfg-backend-import-pass-size $ ds-cfg-backend-mode ) |
| | | ds-cfg-backend-import-pass-size $ ds-cfg-backend-mode $ |
| | | ds-cfg-database-cache-percent $ |
| | | ds-cfg-database-cache-size $ ds-cfg-database-txn-no-sync $ |
| | | ds-cfg-database-txn-write-no-sync $ ds-cfg-database-run-cleaner $ |
| | | ds-cfg-database-cleaner-min-utilization $ ds-cfg-database-evictor-lru-only $ |
| | | ds-cfg-database-evictor-nodes-per-scan $ ds-cfg-database-log-file-max $ |
| | | ds-cfg-database-logging-file-handler-on $ ds-cfg-database-logging-level $ |
| | | ds-cfg-database-checkpointer-bytes-interval $ |
| | | ds-cfg-database-checkpointer-wakeup-interval $ |
| | | ds-cfg-database-lock-num-lock-tables $ ds-cfg-database-cleaner-num-threads ) |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.7 NAME 'ds-cfg-je-database' |
| | | SUP top STRUCTURAL MAY ( cn $ ds-cfg-database-cache-percent $ |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <adm:managed-object |
| | | name="backend" |
| | | plural-name="backends" |
| | | package="org.opends.server.admin.std" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap"> |
| | | <adm:synopsis> |
| | | <adm:user-friendly-plural-name/> are responsible for providing access |
| | | to the underlying data presented by the server. The data may be stored |
| | | locally (e.g., in an embedded database), remotely (e.g., in an |
| | | external system), or generated on the fly (e.g., calculated from other |
| | | information that is available). |
| | | </adm:synopsis> |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.5</ldap:oid> |
| | | <ldap:name>ds-cfg-backend</ldap:name> |
| | | <ldap:superior>top</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | <adm:property name="backend-enabled" |
| | | mandatory="true" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Indicates whether the backend is enabled for use in the server. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | If a backend is not enabled, then its contents will not be accessible |
| | | when processing operations. |
| | | </adm:description> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.13</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-enabled</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-class" |
| | | mandatory="true" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | The fully-qualified name of the Java class that provides the |
| | | backend implementation. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The specified class must be a subclass of the |
| | | org.opends.server.api.Backend superclass. The backend must be disabled |
| | | and re-enabled for changes to the handler class to take effect. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:component-restart/> |
| | | </adm:requires-admin-action> |
| | | <adm:syntax> |
| | | <adm:java-class> |
| | | <adm:instance-of>org.opends.server.api.Backend</adm:instance-of> |
| | | </adm:java-class> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.11</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-class</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-id" |
| | | mandatory="true" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Provides a name that will be used to identify the associated backend. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The name must be unique among all backends in the server. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:other> |
| | | <adm:synopsis> |
| | | The backend ID may not be altered after the backend is created in |
| | | the server. |
| | | </adm:synopsis> |
| | | </adm:other> |
| | | </adm:requires-admin-action> |
| | | <adm:syntax> |
| | | <adm:string /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.14</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-id</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-writability-mode" |
| | | mandatory="true" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the behavior that the backend should use when processing write |
| | | operations. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | A value of "enabled" will allow write operations to be |
| | | performed in that backend (if the requested operation is valid, the user |
| | | has permission to perform the operation, the backend supports that type |
| | | of write operation, and the global writability mode property is also |
| | | enabled). A value of "disabled" will cause all write attempts to |
| | | fail, and a value of "internal-only" will cause external write attempts |
| | | to fail but will allow writes by replication and internal operations. |
| | | </adm:description> |
| | | <adm:syntax> |
| | | <adm:enumeration> |
| | | <adm:value name="enabled"> |
| | | <adm:synopsis> |
| | | Allows write operations to be performed in that backend. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="disabled"> |
| | | <adm:synopsis> |
| | | Causes all write attempts to fail. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="internal-only"> |
| | | <adm:synopsis> |
| | | Causes external write attempts to fail but allows writes by |
| | | replication and internal operations. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | </adm:enumeration> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.162</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-writability-mode</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-base-dn" |
| | | mandatory="true" |
| | | multi-valued="true"> |
| | | <adm:synopsis> |
| | | Specifies the base DN(s) for the data that the backend will handle. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | A single backend may be responsible for one or more base DNs. Note |
| | | that no two backends may have the same base DN, although one backend |
| | | may have a base DN that is below a base DN provided by another |
| | | backend (similar to the use of sub-suffixes in the Sun Java System |
| | | Directory Server). Note that if any of the base DNs is subordinate |
| | | to a base DN for another backend, then all base DNs for that backend |
| | | must be subordinate to that same base DN. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:other> |
| | | <adm:synopsis> |
| | | No administrative action is required by default, although some action |
| | | may be required on a per-backend basis before the new base DN may |
| | | be used. |
| | | </adm:synopsis> |
| | | </adm:other> |
| | | </adm:requires-admin-action> |
| | | <adm:syntax> |
| | | <adm:dn /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.10</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-base-dn</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | </adm:managed-object> |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <adm:managed-object name="backup-backend" plural-name="backup-backends" |
| | | package="org.opends.server.admin.std" |
| | | extends="backend" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap"> |
| | | <adm:synopsis> |
| | | The backup backend provides read-only access to the set of backups that |
| | | are available for the OpenDS Directory Server. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The backup backend is provided as a convenience feature that makes it |
| | | easier to determine what backups are available to be restored if necessary. |
| | | The org.opends.server.backends.BackupBackend class provides the |
| | | implementation for this backend. |
| | | </adm:description> |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.68</ldap:oid> |
| | | <ldap:name>ds-cfg-backup-backend</ldap:name> |
| | | <ldap:superior>ds-cfg-backend</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | <adm:property name="backup-directory" |
| | | mandatory="true" |
| | | multi-valued="true"> |
| | | <adm:synopsis> |
| | | Specifies the path to a backup directory containing one or more backups |
| | | for a particular backend. It may be either an absolute path or one that |
| | | is relative to the base of the OpenDS Directory Server installation. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | This is a multivalued attribute, and each value may specify a different |
| | | backup directory if desired (e.g., one for each backend for which backups |
| | | are taken). |
| | | </adm:description> |
| | | <adm:syntax> |
| | | <adm:string /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.228</ldap:oid> |
| | | <ldap:name>ds-cfg-backup-directory</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | </adm:managed-object> |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <adm:managed-object name="je-backend" plural-name="je-backends" |
| | | package="org.opends.server.admin.std" |
| | | extends="backend" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap"> |
| | | <adm:synopsis> |
| | | The primary backend provided by the OpenDS Directory Server uses the |
| | | Berkeley DB Java Edition to store user-provided data in a local repository. |
| | | It is the traditional "directory server" backend and is similar to the |
| | | backends provided by the Sun Java System Directory Server. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The <adm:user-friendly-name/> stores the entries in an encoded form and |
| | | also provides indexes that can be used to quickly locate target entries |
| | | based on different kinds of criteria. |
| | | The org.opends.server.backends.jeb.BackendImpl class provides the |
| | | implementation for this backend, and therefore should be used as the |
| | | value of the ds-cfg-backend-class-name property. |
| | | </adm:description> |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.6</ldap:oid> |
| | | <ldap:name>ds-cfg-je-backend</ldap:name> |
| | | <ldap:superior>ds-cfg-backend</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | <adm:property name="backend-deadlock-retry-limit" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the number of times that the server should retry an attempted |
| | | operation in the backend if a deadlock results from two concurrent |
| | | requests that interfere with each other in a conflicting manner. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | A value of "0" indicates no limit. |
| | | </adm:description> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>10</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="0" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.267</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-deadlock-retry-limit</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-directory" |
| | | mandatory="true" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the path to the filesystem directory that will be used to hold |
| | | the Berkeley DB Java Edition database files containing the data for this |
| | | backend. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The path may be either an absolute path or a path relative to the |
| | | directory containing the base of the OpenDS Directory Server installation. |
| | | The path may be any valid directory path in which the server has |
| | | appropriate permissions to read and write files and has sufficient space |
| | | to hold the database contents. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:component-restart/> |
| | | </adm:requires-admin-action> |
| | | <adm:syntax> |
| | | <adm:string /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.12</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-directory</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-entries-compressed" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Indicates whether the backend should attempt to compress entries before |
| | | storing them in the database. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Note that this property applies only to the entries themselves |
| | | and does not impact the index data. Further, the effectiveness of the |
| | | compression will be based on the type of data contained in the entry. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:other> |
| | | <adm:synopsis> |
| | | Changes to this setting will only take effect for writes that occur |
| | | after the change is made. It will not be retroactively applied to |
| | | existing data. |
| | | </adm:synopsis> |
| | | </adm:other> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>false</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.266</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-entries-compressed</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-import-buffer-size" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the amount of memory that should be used as an internal |
| | | buffer for index information when processing an LDIF import. |
| | | </adm:synopsis> |
| | | <adm:requires-admin-action> |
| | | <adm:other> |
| | | <adm:synopsis> |
| | | No admin action required, although changes will not take effect for |
| | | any import that may already be in progress. |
| | | </adm:synopsis> |
| | | </adm:other> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>256mb</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:size lower-limit="10mb"/> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.263</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-import-buffer-size</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-import-pass-size" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the maximum number of entries that should be imported in each |
| | | import pass. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | An import pass consists of the processing required to import a set of |
| | | entries as well as the index post-processing required to index those |
| | | entries. A value of zero for this property indicates that all entries |
| | | should be processed in a single pass, which is the recommended |
| | | configuration for most deployments, although a non-zero value may be |
| | | required when importing a very large number of entries if the amount |
| | | of memory required for index post-processing exceeds the total amount |
| | | available to the server. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:other> |
| | | <adm:synopsis> |
| | | No admin action required, although changes will not take effect for |
| | | any import that may already be in progress. |
| | | </adm:synopsis> |
| | | </adm:other> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>0</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="0" upper-limit="2147483647" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.277</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-import-pass-size</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-import-queue-size" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the size (in number of entries) of the queue that will be used |
| | | to hold the entries read during an LDIF import. |
| | | </adm:synopsis> |
| | | <adm:requires-admin-action> |
| | | <adm:other> |
| | | <adm:synopsis> |
| | | No admin action required, although changes will not take effect for |
| | | any import that may already be in progress. |
| | | </adm:synopsis> |
| | | </adm:other> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>100</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="1" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.264</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-import-queue-size</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-import-temp-directory" |
| | | mandatory="true" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the location of the directory that will be used for the |
| | | files used to hold temporary information that will be used during the |
| | | index post-processing phase of an LDIF import. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The specified directory will only be used while an import is in progress |
| | | and the files created in this directory will be deleted as they are |
| | | processed. It may be an absolute path or one that is relative to the |
| | | instance root directory. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:other> |
| | | <adm:synopsis> |
| | | No admin action required, although changes will not take effect for |
| | | any import that may already be in progress. |
| | | </adm:synopsis> |
| | | </adm:other> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:undefined/> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:string /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.262</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-import-temp-directory</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-import-thread-count" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the number of threads that will be used for concurrent |
| | | processing during an LDIF import. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | This should generally be a small multiple (e.g., 2x) of the number of CPUs |
| | | in the system for a traditional system, or equal to the number of CPU |
| | | strands for a CMT system. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:other> |
| | | <adm:synopsis> |
| | | No admin action required, although changes will not take effect for |
| | | any import that may already be in progress. |
| | | </adm:synopsis> |
| | | </adm:other> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>8</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="1" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.265</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-import-thread-count</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-index-entry-limit" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the maximum number of entries that will be allowed to |
| | | match a given index key before that particular index key is no longer |
| | | maintained (i.e., it is analogous to the ALL IDs threshold in the Sun |
| | | Java System Directory Server). Note that this is the default limit for |
| | | the backend, and it may be overridden on a per-attribute basis. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Note that this is the default limit for the backend, and it may be |
| | | overridden on a per-attribute basis. A value of 0 means there is no limit. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:other> |
| | | <adm:synopsis> |
| | | No admin action is required, although if any index keys have already |
| | | reached this limit, indexes will need to be rebuilt before they will |
| | | be allowed to use the new limit. |
| | | </adm:synopsis> |
| | | </adm:other> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>4000</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="0" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.15</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-index-entry-limit</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-mode" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the permissions that should be applied to the directory |
| | | containing the server database files. They should be expressed as |
| | | three-digit octal values, which is the traditional representation for |
| | | UNIX file permissions. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The three digits represent the permissions that will be available for the |
| | | directory's owner, group members, and other users (in that order), and |
| | | each digit is the octal representation of the read, write, and execute |
| | | bits. |
| | | Note that this only impacts permissions on the database directory and |
| | | not on the files written into that directory. On UNIX systems, the |
| | | user's umask will control permissions given to the database files. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:server-restart/> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>700</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:string> |
| | | <adm:pattern> |
| | | <adm:regex>7[0-7][0-7]</adm:regex> |
| | | <adm:synopsis> |
| | | Any octal value between 700 and 777 (the owner must always have |
| | | read, write, and execute permissions on the directory). |
| | | </adm:synopsis> |
| | | </adm:pattern> |
| | | </adm:string> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.287</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-mode</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-preload-time-limit" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the length of time that the backend will be allowed to |
| | | spend "pre-loading" data when it is initialized. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The pre-load process may be used to pre-populate the database cache so |
| | | that it can be more quickly available when the server is processing |
| | | requests. A duration of zero means there will be no pre-load. |
| | | </adm:description> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>0s</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:duration base-unit="ms" lower-limit="0"/> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.261</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-preload-time-limit</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="backend-subtree-delete-size-limit" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the maximum number of entries that may be deleted from the |
| | | backend when using the subtree delete control. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | If a subtree delete operation targets a subtree with more than this |
| | | number of entries, then multiple passes may be required to remove all |
| | | entries in that subtree. |
| | | </adm:description> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>100000</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="0" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.16</ldap:oid> |
| | | <ldap:name>ds-cfg-backend-subtree-delete-size-limit</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-cache-percent" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | The percentage of JVM memory to allocate to the database cache. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Specifies the percentage of memory available to the JVM that should |
| | | be used for caching database contents. Note that this will only be used |
| | | if the value of the database-cache-size property is set to "0 MB". |
| | | Otherwise, the value of that property will be used instead to control |
| | | the cache size configuration. |
| | | </adm:description> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>10</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="1" upper-limit="90" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.25</ldap:oid> |
| | | <ldap:name>ds-cfg-database-cache-percent</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-cache-size" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | The amount of JVM memory to allocate to the database cache. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Specifies the amount of memory that should be used for caching database |
| | | contents. A value of "0 MB" indicates that the database-cache-percent |
| | | property should be used instead to specify the cache size. |
| | | </adm:description> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>0 MB</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:size lower-limit="0 MB" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.27</ldap:oid> |
| | | <ldap:name>ds-cfg-database-cache-size</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-cleaner-min-utilization" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the minimum percentage of "live" data that the database cleaner |
| | | will attempt to keep in database log files. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | If the amount of live data in any database log file drops below this |
| | | percentage, then the cleaner will move the remaining live data in that |
| | | file to the end of the database and will delete the original file in |
| | | order to keep the database relatively compact. |
| | | </adm:description> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>75</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="0" upper-limit="90" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.26</ldap:oid> |
| | | <ldap:name>ds-cfg-database-cleaner-min-utilization</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-run-cleaner" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | This indicates whether the database cleaner threads should be enabled. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The cleaner threads will be used to periodically compact the database by |
| | | identifying database files with a low (i.e., less than the amount |
| | | specified by the database-cleaner-min-utilization property) |
| | | percentage of live data, moving the remaining live data to the end of the |
| | | log and deleting that file. |
| | | </adm:description> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>true</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.28</ldap:oid> |
| | | <ldap:name>ds-cfg-database-run-cleaner</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-evictor-lru-only" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Indicates whether the database should evict existing data from the cache |
| | | based on an LRU policy (where the least recently used information will be |
| | | evicted first). |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | If the value of this configuration property is set to "false", then |
| | | eviction will prefer to keep internal nodes of the underlying Btree in |
| | | the cache over leaf notes, even if the leaf nodes have been accessed |
| | | more recently, which may be a better configuration for databases in |
| | | which only a very small portion of the data is cached. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:component-restart/> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>true</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.268</ldap:oid> |
| | | <ldap:name>ds-cfg-database-evictor-lru-only</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-evictor-nodes-per-scan" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the number of Btree nodes that should be evicted from the |
| | | cache in a single pass if it is determined that it is necessary to |
| | | free existing data in order to make room for new information. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Changes to this property do not take effect until the backend is |
| | | restarted. It is recommended that you also change this property when you |
| | | set database-evictor-lru-only to false. This setting controls the number |
| | | of Btree nodes that are considered, or sampled, each time a node is |
| | | evicted. A setting of 100 often produces good results, but this may vary |
| | | from application to application. The larger the nodesPerScan, the more |
| | | accurate the algorithm. However, setting it too high is detrimental; |
| | | the need to consider larger numbers of nodes for each eviction may |
| | | delay the completion of a given database operation, which will impact |
| | | the response time of the application thread. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:component-restart/> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>10</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="1" upper-limit="1000" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.269</ldap:oid> |
| | | <ldap:name>ds-cfg-database-evictor-nodes-per-scan</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-log-file-max" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the maximum size that may be used for a database log file. |
| | | </adm:synopsis> |
| | | <adm:requires-admin-action> |
| | | <adm:component-restart/> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>50mb</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:size lower-limit="1mb" upper-limit="4gib"/> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.270</ldap:oid> |
| | | <ldap:name>ds-cfg-database-log-file-max</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-logging-file-handler-on" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Indicates whether the database should maintain a je.info file in the same |
| | | directory as the database log directory. This file will contain |
| | | information about the internal processing performed by the underlying |
| | | database. |
| | | </adm:synopsis> |
| | | <adm:requires-admin-action> |
| | | <adm:component-restart/> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>true</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.271</ldap:oid> |
| | | <ldap:name>ds-cfg-database-logging-file-handler-on</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-logging-level" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | This specifies the log level that should be used by the database when |
| | | it is writing information into the je.info file. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The database trace logging level is (in increasing order of verbosity) |
| | | chosen from: OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:component-restart/> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>CONFIG</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:string /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.272</ldap:oid> |
| | | <ldap:name>ds-cfg-database-logging-level</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-checkpointer-bytes-interval" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the maximum number of bytes that may be written to the database |
| | | before it will be forced to perform a checkpoint. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | This can be used to bound the recovery time that may be required if the |
| | | database environment is opened without having been properly closed. |
| | | If this propertyis set to a non-zero value, the checkpointer wakeup |
| | | interval is not used. To use time based checkpointing, set this |
| | | property to zero. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:server-restart/> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>20mb</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:size lower-limit="0b" upper-limit="9223372036854775807b"/> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.273</ldap:oid> |
| | | <ldap:name>ds-cfg-database-checkpointer-bytes-interval</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-checkpointer-wakeup-interval" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the maximum length of time that may pass between checkpoints. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Note that this will only be used if the value of the checkpointer bytes |
| | | interval is zero. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:component-restart/> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>30s</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:duration base-unit="s" lower-limit="1" upper-limit="4294"/> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.274</ldap:oid> |
| | | <ldap:name>ds-cfg-database-checkpointer-wakeup-interval</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-lock-num-lock-tables" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | This specifies the number of lock tables that should be used by the |
| | | underlying database. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | This can be particularly important to help improve scalability by |
| | | avoiding contention on systems with large numbers of CPUs. The value of |
| | | this configuration property should be set to a prime number that is less |
| | | than or equal to the number of worker threads configured for use in the |
| | | server. |
| | | </adm:description> |
| | | <adm:requires-admin-action> |
| | | <adm:component-restart/> |
| | | </adm:requires-admin-action> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>19</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="1" upper-limit="32767" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.275</ldap:oid> |
| | | <ldap:name>ds-cfg-database-lock-num-lock-tables</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-cleaner-num-threads" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Specifies the number of threads that the backend should maintain to |
| | | keep the database log files at or near the desired utilization. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | In environments with high write throughput, multiple cleaner threads may |
| | | be required to maintain the desired utilization. |
| | | </adm:description> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>1</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="1" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.284</ldap:oid> |
| | | <ldap:name>ds-cfg-database-cleaner-num-threads</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-txn-no-sync" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Indicates whether database writes should be primarily written to an |
| | | internal buffer but not immediately written to disk. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Setting the value of this configuration attribute to "true" may improve |
| | | write performance but could cause some number of the most recent changes |
| | | to be lost if the OpenDS Directory Server or the underlying JVM exits |
| | | abnormally, or if an OS or hardware failure occurs (a behavior similar |
| | | to running with transaction durability disabled in the Sun Java System |
| | | Directory Server). |
| | | </adm:description> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>false</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.29</ldap:oid> |
| | | <ldap:name>ds-cfg-database-txn-no-sync</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="database-txn-write-no-sync" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Indicates whether the database should synchronously flush data as it is |
| | | written to disk. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | If this value is set to "false", then all data written to disk will be |
| | | synchronously flushed to persistent storage and thereby providing full |
| | | durability. If it is set to "true", then data may be cached for a period |
| | | of time by the underlying operating system before actually being written |
| | | to disk. This may improve performance, but could cause some number of |
| | | the most recent changes to be lost in the event of an underlying OS or |
| | | hardware failure (but not in the case that the OpenDS Directory Server |
| | | or the JVM exits abnormally). |
| | | </adm:description> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>true</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.30</ldap:oid> |
| | | <ldap:name>ds-cfg-database-txn-write-no-sync</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | </adm:managed-object> |
| | |
| | | </ldap:rdn-sequence> |
| | | </adm:profile> |
| | | </adm:relation> |
| | | <adm:relation name="backend"> |
| | | <adm:one-to-many /> |
| | | <adm:profile name="ldap"> |
| | | <ldap:rdn-sequence> |
| | | cn=Backends,cn=config |
| | | </ldap:rdn-sequence> |
| | | <ldap:naming-attribute>ds-cfg-backend-id</ldap:naming-attribute> |
| | | </adm:profile> |
| | | </adm:relation> |
| | | <adm:relation name="root-dse-backend"> |
| | | <adm:one-to-one /> |
| | | <adm:profile name="ldap"> |
| | | <ldap:rdn-sequence> |
| | | cn=config |
| | | </ldap:rdn-sequence> |
| | | </adm:profile> |
| | | </adm:relation> |
| | | <adm:product-name>OpenDS Directory Server</adm:product-name> |
| | | </adm:root-managed-object> |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <adm:managed-object name="root-dse-backend" plural-name="root-dse-backends" |
| | | package="org.opends.server.admin.std" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap"> |
| | | <adm:synopsis> |
| | | This class defines a backend to hold the Directory Server root DSE. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | This is a special meta-backend that will dynamically generate the root DSE |
| | | entry for base-level searches, and will simply redirect to other backends |
| | | for operations in other scopes. |
| | | </adm:description> |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.42</ldap:oid> |
| | | <ldap:name>ds-cfg-root-dse</ldap:name> |
| | | <ldap:superior>top</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | <adm:property name="subordinate-base-dn" |
| | | mandatory="false" |
| | | multi-valued="true"> |
| | | <adm:synopsis> |
| | | Specifies the set of base DNs that will be used for singleLevel, |
| | | wholeSubtree, and subordinateSubtree searches based at the root DSE. If |
| | | this is not provided, then the set of all user-defined suffixes will be |
| | | used. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:undefined/> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:dn /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.122</ldap:oid> |
| | | <ldap:name>ds-cfg-subordinate-base-dn</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="show-all-attributes" |
| | | mandatory="true" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Indicates whether all attributes in the root DSE should be treated like |
| | | user attributes (and therefore returned to clients by default) |
| | | regardless of the Directory Server schema configuration. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.141</ldap:oid> |
| | | <ldap:name>ds-cfg-show-all-attributes</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | </adm:managed-object> |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <adm:managed-object name="schema-backend" plural-name="schema-backends" |
| | | package="org.opends.server.admin.std" |
| | | extends="backend" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap"> |
| | | <adm:synopsis> |
| | | The schema backend provides access to the OpenDS Directory Server schema |
| | | information, including the attribute types, object classes, attribute |
| | | syntaxes, matching rules, matching rule uses, DIT content rules, and |
| | | DIT structure rules that it contains. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The server will allow modify operations in this backend to alter the server |
| | | schema definitions. The org.opends.server.backends.SchemaBackend class |
| | | provides the implementation for this backend. |
| | | The configuration entry for this backend is based on the |
| | | ds-cfg-schema-backend structural object class. Note that any attribute |
| | | types included in this entry that are not included in this object class |
| | | (or the parent ds-cfg-backend class) will appear directly in the schema |
| | | entry. |
| | | </adm:description> |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.9</ldap:oid> |
| | | <ldap:name>ds-cfg-schema-backend</ldap:name> |
| | | <ldap:superior>ds-cfg-backend</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | <adm:property name="schema-entry-dn" |
| | | mandatory="false" |
| | | multi-valued="true"> |
| | | <adm:synopsis> |
| | | This defines the base DN(s) at which the schema information will be |
| | | published, in addition to the value included in the ds-cfg-backend-base-dn |
| | | configuration attribute. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | The value provided in the ds-cfg-backend-base-dn configuration attribute |
| | | is the only one that will appear in the subschemaSubentry operational |
| | | attribute of the server's root DSE (which is necessary because that is a |
| | | single-valued attribute) and as a virtual attribute in other entries, |
| | | but the ds-cfg-schema-entry-dn attribute may be used to make the schema |
| | | information available in other locations as well in case certain client |
| | | applications have been hard-coded to expect the schema to reside in a |
| | | specific location. |
| | | </adm:description> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>cn=schema</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:dn /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.113</ldap:oid> |
| | | <ldap:name>ds-cfg-schema-entry-dn</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="show-all-attributes" |
| | | mandatory="true" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | Indicates whether to treat all attributes in the schema entry as if they |
| | | were user attributes regardless of their configuration. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | This may provide compatibility with some applications that expect schema |
| | | attributes like attributeType and objectClasses to be included by default |
| | | even if they are not requested. Note that the ldapSyntaxes attribute |
| | | will always be treated as operational in order to avoid problems with |
| | | attempts to modify the schema over protocol. |
| | | </adm:description> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.141</ldap:oid> |
| | | <ldap:name>ds-cfg-show-all-attributes</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | </adm:managed-object> |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <adm:managed-object name="task-backend" plural-name="task-backends" |
| | | package="org.opends.server.admin.std" |
| | | extends="backend" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap"> |
| | | <adm:synopsis> |
| | | The task backend provides a mechanism for processing tasks in the |
| | | OpenDS Directory Server. Tasks are intended to provide access to certain |
| | | types of administrative functions in the server that may not otherwise be |
| | | convenient to perform remotely. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Tasks that are currently available for use provide the ability to backup |
| | | and restore backends, to import and export LDIF files, and to stop and |
| | | restart the server. The details of the task to perform are held in an |
| | | entry that is added below the root of the task backend, and then the |
| | | task backend is responsible for decoding that task entry and ensuring |
| | | that it is processed as requested. Tasks may be invoked immediately, |
| | | but they may also be scheduled for execution at some future time. |
| | | It is also expected that task backend will be given the ability process |
| | | recurring tasks, which can be used to help ensure that maintenance |
| | | operations (e.g., backups) are performed automatically on a regular basis. |
| | | The org.opends.server.backends.task.TaskBackend class provides the entry |
| | | point for the task backend implementation. |
| | | </adm:description> |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.10</ldap:oid> |
| | | <ldap:name>ds-cfg-task-backend</ldap:name> |
| | | <ldap:superior>ds-cfg-backend</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | <adm:property name="task-backing-file" |
| | | mandatory="true" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | This specifies the path to the backing file for storing information about |
| | | the tasks configured in the server. It may be either an absolute path or |
| | | a path that is relative to the base of the OpenDS Directory Server |
| | | instance. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:string /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.97</ldap:oid> |
| | | <ldap:name>ds-cfg-task-backing-file</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="task-retention-time" |
| | | mandatory="false" |
| | | multi-valued="false"> |
| | | <adm:synopsis> |
| | | This specifies the length of time that task entries should be retained |
| | | after processing on the associated task has been completed. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>24 hours</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:duration /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.106</ldap:oid> |
| | | <ldap:name>ds-cfg-task-retention-time</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | </adm:managed-object> |
| | |
| | | /** |
| | | * A utility class for converting admin exceptions to config exceptions. |
| | | */ |
| | | final class ConfigExceptionFactory { |
| | | public final class ConfigExceptionFactory { |
| | | |
| | | // The singleton instance. |
| | | private static final ConfigExceptionFactory INSTANCE = |
| | |
| | | * If one or more of the managed object's properties could |
| | | * not be decoded. |
| | | */ |
| | | static <S extends Configuration> ServerManagedObject<? extends S> decode( |
| | | public static <S extends Configuration> |
| | | ServerManagedObject<? extends S> decode( |
| | | ManagedObjectPath path, |
| | | AbstractManagedObjectDefinition<?, S> definition, |
| | | final ConfigEntry configEntry) |
| | |
| | | |
| | | |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.*; |
| | | |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.core.AddOperation; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.core.ModifyDNOperation; |
| | | import org.opends.server.core.SearchOperation; |
| | | import org.opends.server.core.BackendConfigManager; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.schema.BooleanSyntax; |
| | | import org.opends.server.schema.GeneralizedTimeSyntax; |
| | |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.server.BackupBackendCfg; |
| | | import org.opends.server.admin.std.meta.BackupBackendCfgDefn; |
| | | |
| | | |
| | | /** |
| | |
| | | */ |
| | | public class BackupBackend |
| | | extends Backend |
| | | implements ConfigurableComponent |
| | | implements ConfigurationChangeListener<BackupBackendCfg> |
| | | { |
| | | // The DN of the configuration entry for this backend. |
| | | private DN configEntryDN; |
| | | // The current configuration state. |
| | | private BackupBackendCfg currentConfig; |
| | | |
| | | // The DN for the base backup entry. |
| | | private DN backupBaseDN; |
| | |
| | | |
| | | |
| | | /** |
| | | * Initializes this backend based on the information in the provided |
| | | * configuration entry. |
| | | * |
| | | * @param configEntry The configuration entry that contains the information |
| | | * to use to initialize this backend. |
| | | * @param baseDNs The set of base DNs that have been configured for this |
| | | * backend. |
| | | * |
| | | * @throws ConfigException If an unrecoverable problem arises in the |
| | | * process of performing the initialization. |
| | | * |
| | | * @throws InitializationException If a problem occurs during initialization |
| | | * that is not related to the server |
| | | * configuration. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeBackend(ConfigEntry configEntry, DN[] baseDNs) |
| | | throws ConfigException, InitializationException |
| | |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | configEntryDN = configEntry.getDN(); |
| | | BackupBackendCfg cfg = getBackupBackendCfg(configEntry); |
| | | |
| | | |
| | | // Create the set of base DNs that we will handle. In this case, it's just |
| | |
| | | |
| | | |
| | | // Determine the set of backup directories that we will use by default. |
| | | int msgID = MSGID_BACKUP_DESCRIPTION_BACKUP_DIR_LIST; |
| | | StringConfigAttribute backupDirStub = |
| | | new StringConfigAttribute(ATTR_BACKUP_DIR_LIST, getMessage(msgID), |
| | | true, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute backupDirAttr = |
| | | (StringConfigAttribute) |
| | | configEntry.getConfigAttribute(backupDirStub); |
| | | if (backupDirAttr == null) |
| | | { |
| | | backupDirectories = new LinkedHashSet<File>(); |
| | | } |
| | | else |
| | | { |
| | | List<String> values = backupDirAttr.activeValues(); |
| | | Set<String> values = cfg.getBackupDirectory(); |
| | | backupDirectories = new LinkedHashSet<File>(values.size()); |
| | | for (String s : values) |
| | | { |
| | | backupDirectories.add(getFileForPath(s)); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_BACKUP_CANNOT_DETERMINE_BACKUP_DIR_LIST; |
| | | String message = getMessage(msgID, stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | |
| | | // Construct the backup base entry. |
| | |
| | | supportedFeatures = new HashSet<String>(0); |
| | | |
| | | |
| | | // Register with the Directory Server as a configurable component. |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | // Register this as a change listener. |
| | | currentConfig = cfg; |
| | | cfg.addBackupChangeListener(this); |
| | | |
| | | |
| | | // Register the backup base as a private suffix. |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_BACKEND_CANNOT_REGISTER_BASEDN; |
| | | int msgID = MSGID_BACKEND_CANNOT_REGISTER_BASEDN; |
| | | String message = getMessage(msgID, backupBaseDN.toString(), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | |
| | | */ |
| | | public void finalizeBackend() |
| | | { |
| | | DirectoryServer.deregisterConfigurableComponent(this); |
| | | currentConfig.removeBackupChangeListener(this); |
| | | |
| | | try |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry with which this component is |
| | | * associated. |
| | | * |
| | | * @return The DN of the configuration entry with which this component is |
| | | * associated. |
| | | * {@inheritDoc} |
| | | */ |
| | | public DN getConfigurableComponentEntryDN() |
| | | { |
| | | return configEntryDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | * |
| | | * @return The set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | */ |
| | | public List<ConfigAttribute> getConfigurationAttributes() |
| | | { |
| | | LinkedList<ConfigAttribute> attrs = new LinkedList<ConfigAttribute>(); |
| | | |
| | | |
| | | ArrayList<String> backupDirs = |
| | | new ArrayList<String>(backupDirectories.size()); |
| | | for (File f : backupDirectories) |
| | | { |
| | | backupDirs.add(f.getAbsolutePath()); |
| | | } |
| | | |
| | | int msgID = MSGID_BACKUP_DESCRIPTION_BACKUP_DIR_LIST; |
| | | attrs.add(new StringConfigAttribute(ATTR_BACKUP_DIR_LIST, getMessage(msgID), |
| | | true, true, false, backupDirs)); |
| | | |
| | | return attrs; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an acceptable |
| | | * configuration for this component. If it does not, then detailed |
| | | * information about the problem(s) should be added to the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to make the |
| | | * determination. |
| | | * @param unacceptableReasons A list that can be used to hold messages about |
| | | * why the provided entry does not have an |
| | | * acceptable configuration. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided entry has an acceptable |
| | | * configuration for this component, or <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | public boolean isConfigurationChangeAcceptable( |
| | | BackupBackendCfg configEntry, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | // We'll accept anything here. The only configurable attribute is the |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained in the |
| | | * provided entry. Information about the result of this processing should be |
| | | * added to the provided message list. Information should always be added to |
| | | * this list if a configuration change could not be applied. If detailed |
| | | * results are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not changed) should |
| | | * also be included. |
| | | * |
| | | * @param configEntry The entry containing the new configuration to |
| | | * apply for this component. |
| | | * @param detailedResults Indicates whether detailed information about the |
| | | * processing should be added to the list. |
| | | * |
| | | * @return Information about the result of the configuration update. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | BackupBackendCfg configEntry) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | |
| | | int msgID = MSGID_BACKUP_DESCRIPTION_BACKUP_DIR_LIST; |
| | | StringConfigAttribute backupDirStub = |
| | | new StringConfigAttribute(ATTR_BACKUP_DIR_LIST, getMessage(msgID), |
| | | true, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute backupDirAttr = |
| | | (StringConfigAttribute) |
| | | configEntry.getConfigAttribute(backupDirStub); |
| | | if (backupDirAttr == null) |
| | | { |
| | | backupDirectories = new LinkedHashSet<File>(); |
| | | } |
| | | else |
| | | { |
| | | List<String> values = backupDirAttr.activeValues(); |
| | | Set<String> values = configEntry.getBackupDirectory(); |
| | | backupDirectories = new LinkedHashSet<File>(values.size()); |
| | | for (String s : values) |
| | | { |
| | | backupDirectories.add(getFileForPath(s)); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_BACKUP_CANNOT_DETERMINE_BACKUP_DIR_LIST; |
| | | messages.add(getMessage(msgID, stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | |
| | | |
| | | currentConfig = configEntry; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | |
| | | new AttributeValue(rdnAttrType, rdnStringValue); |
| | | return parentDN.concat(RDN.create(rdnAttrType, attrValue)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Gets the backup backend configuration corresponding to a backup |
| | | * backend config entry. |
| | | * |
| | | * @param configEntry A backup backend config entry. |
| | | * @return Returns the backup backend configuration. |
| | | * @throws ConfigException If the config entry could not be decoded. |
| | | */ |
| | | static BackupBackendCfg getBackupBackendCfg(ConfigEntry configEntry) |
| | | throws ConfigException { |
| | | return BackendConfigManager.getConfiguration( |
| | | BackupBackendCfgDefn.getInstance(), configEntry); |
| | | } |
| | | } |
| | | |
| | |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.api.MonitorProvider; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.AddOperation; |
| | |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.core.ModifyDNOperation; |
| | | import org.opends.server.core.SearchOperation; |
| | | import org.opends.server.core.BackendConfigManager; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import static org.opends.server.messages.BackendMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.messages.ConfigMessages.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.server.BackendCfg; |
| | | |
| | | |
| | | /** |
| | |
| | | */ |
| | | public class MonitorBackend |
| | | extends Backend |
| | | implements ConfigurableComponent |
| | | implements ConfigurationChangeListener<BackendCfg> |
| | | { |
| | | // The set of user-defined attributes that will be included in the base |
| | | // monitor entry. |
| | |
| | | // The DN of the configuration entry for this backend. |
| | | private DN configEntryDN; |
| | | |
| | | // The current configuration state. |
| | | private BackendCfg currentConfig; |
| | | |
| | | // The DN for the base monitor entry. |
| | | private DN baseMonitorDN; |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Initializes this backend based on the information in the provided |
| | | * configuration entry. |
| | | * |
| | | * @param configEntry The configuration entry that contains the information |
| | | * to use to initialize this backend. |
| | | * @param baseDNs The set of base DNs that have been configured for this |
| | | * backend. |
| | | * |
| | | * @throws ConfigException If an unrecoverable problem arises in the |
| | | * process of performing the initialization. |
| | | * |
| | | * @throws InitializationException If a problem occurs during initialization |
| | | * that is not related to the server |
| | | * configuration. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeBackend(ConfigEntry configEntry, DN[] baseDNs) |
| | | throws ConfigException, InitializationException |
| | |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | BackendCfg cfg = BackendConfigManager.getBackendCfg(configEntry); |
| | | configEntryDN = configEntry.getDN(); |
| | | |
| | | |
| | |
| | | |
| | | |
| | | // Register with the Directory Server as a configurable component. |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | currentConfig = cfg; |
| | | cfg.addChangeListener(this); |
| | | |
| | | |
| | | // Register the monitor base as a private suffix. |
| | |
| | | */ |
| | | public void finalizeBackend() |
| | | { |
| | | DirectoryServer.deregisterConfigurableComponent(this); |
| | | currentConfig.removeChangeListener(this); |
| | | |
| | | try |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Exports the contents of this backend to LDIF. This method should only be |
| | | * called if <CODE>supportsLDIFExport</CODE> returns <CODE>true</CODE>. Note |
| | | * that the server will not explicitly initialize this backend before calling |
| | | * this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param baseDNs The set of base DNs configured for this backend. |
| | | * @param exportConfig The configuration to use when performing the export. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the LDIF |
| | | * export. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void exportLDIF(ConfigEntry configEntry, DN[] baseDNs, |
| | | LDIFExportConfig exportConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Imports information from an LDIF file into this backend. This method |
| | | * should only be called if <CODE>supportsLDIFImport</CODE> returns |
| | | * <CODE>true</CODE>. Note that the server will not explicitly initialize |
| | | * this backend before calling this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param baseDNs The set of base DNs configured for this backend. |
| | | * @param importConfig The configuration to use when performing the import. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the LDIF |
| | | * import. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void importLDIF(ConfigEntry configEntry, DN[] baseDNs, |
| | | LDIFImportConfig importConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Creates a backup of the contents of this backend in a form that may be |
| | | * restored at a later date if necessary. This method should only be called |
| | | * if <CODE>supportsBackup</CODE> returns <CODE>true</CODE>. Note that the |
| | | * server will not explicitly initialize this backend before calling this |
| | | * method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param backupConfig The configuration to use when performing the backup. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the |
| | | * backup. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void createBackup(ConfigEntry configEntry, BackupConfig backupConfig) |
| | | throws DirectoryException |
| | |
| | | |
| | | |
| | | /** |
| | | * Restores a backup of the contents of this backend. This method should only |
| | | * be called if <CODE>supportsRestore</CODE> returns <CODE>true</CODE>. Note |
| | | * that the server will not explicitly initialize this backend before calling |
| | | * this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param restoreConfig The configuration to use when performing the |
| | | * restore. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the |
| | | * restore. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void restoreBackup(ConfigEntry configEntry, |
| | | RestoreConfig restoreConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry with which this component is |
| | | * associated. |
| | | * |
| | | * @return The DN of the configuration entry with which this component is |
| | | * associated. |
| | | */ |
| | | public DN getConfigurableComponentEntryDN() |
| | | { |
| | | return configEntryDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | * |
| | | * @return The set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | */ |
| | | public List<ConfigAttribute> getConfigurationAttributes() |
| | | { |
| | | // There are no configurable attributes that will be explicitly advertised. |
| | | return new LinkedList<ConfigAttribute>(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an acceptable |
| | | * configuration for this component. If it does not, then detailed |
| | | * information about the problem(s) should be added to the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to make the |
| | | * @param backendCfg The configuration entry for which to make the |
| | | * determination. |
| | | * @param unacceptableReasons A list that can be used to hold messages about |
| | | * why the provided entry does not have an |
| | |
| | | * @return <CODE>true</CODE> if the provided entry has an acceptable |
| | | * configuration for this component, or <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | public boolean isConfigurationChangeAcceptable( |
| | | BackendCfg backendCfg, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | // We'll pretty much accept anything here as long as it isn't one of our |
| | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained in the |
| | | * provided entry. Information about the result of this processing should be |
| | | * added to the provided message list. Information should always be added to |
| | | * this list if a configuration change could not be applied. If detailed |
| | | * results are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not changed) should |
| | | * also be included. |
| | | * |
| | | * @param configEntry The entry containing the new configuration to |
| | | * apply for this component. |
| | | * @param detailedResults Indicates whether detailed information about the |
| | | * processing should be added to the list. |
| | | * |
| | | * @return Information about the result of the configuration update. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | public ConfigChangeResult applyConfigurationChange(BackendCfg backendCfg) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | |
| | | |
| | | // Check to see if there is a new set of user-defined attributes. |
| | | ArrayList<Attribute> userAttrs = new ArrayList<Attribute>(); |
| | | try |
| | | { |
| | | ConfigEntry configEntry = DirectoryServer.getConfigEntry(configEntryDN); |
| | | for (List<Attribute> attrs : |
| | | configEntry.getEntry().getUserAttributes().values()) |
| | | { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | userDefinedAttributes = userAttrs; |
| | | if (detailedResults) |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | int msgID = MSGID_MONITOR_USING_NEW_USER_ATTRS; |
| | | String message = getMessage(msgID); |
| | | messages.add(message); |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_BACKEND_ERROR_INTERACTING_WITH_BACKEND_ENTRY; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | |
| | | |
| | | userDefinedAttributes = userAttrs; |
| | | |
| | | int msgID = MSGID_MONITOR_USING_NEW_USER_ATTRS; |
| | | String message = getMessage(msgID); |
| | | messages.add(message); |
| | | |
| | | |
| | | currentConfig = backendCfg; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | } |
| | |
| | | import java.util.Collection; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.Iterator; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.config.BooleanConfigAttribute; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.DNConfigAttribute; |
| | | import org.opends.server.core.AddOperation; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.core.ModifyDNOperation; |
| | | import org.opends.server.core.SearchOperation; |
| | | import org.opends.server.core.BackendConfigManager; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | |
| | | import static org.opends.server.loggers.Error.*; |
| | | import static org.opends.server.messages.BackendMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.messages.ConfigMessages. |
| | | MSGID_CONFIG_BACKEND_ERROR_INTERACTING_WITH_BACKEND_ENTRY; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import org.opends.server.admin.std.server.RootDSEBackendCfg; |
| | | import org.opends.server.admin.std.meta.RootDSEBackendCfgDefn; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | |
| | | |
| | | /** |
| | |
| | | */ |
| | | public class RootDSEBackend |
| | | extends Backend |
| | | implements ConfigurableComponent |
| | | implements ConfigurationChangeListener<RootDSEBackendCfg> |
| | | { |
| | | // The set of standard "static" attributes that we will always include in the |
| | | // root DSE entry and won't change while the server is running. |
| | |
| | | // The set of objectclasses that will be used in the root DSE entry. |
| | | private HashMap<ObjectClass,String> dseObjectClasses; |
| | | |
| | | // The current configuration state. |
| | | private RootDSEBackendCfg currentConfig; |
| | | |
| | | // The DN of the configuration entry for this backend. |
| | | private DN configEntryDN; |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Initializes this backend based on the information in the provided |
| | | * configuration entry. |
| | | * |
| | | * @param configEntry The configuration entry that contains the information |
| | | * to use to initialize this backend. |
| | | * @param baseDNs The set of base DNs that have been configured for this |
| | | * backend. |
| | | * |
| | | * @throws ConfigException If an unrecoverable problem arises in the |
| | | * process of performing the initialization. |
| | | * |
| | | * @throws InitializationException If a problem occurs during initialization |
| | | * that is not related to the server |
| | | * configuration. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeBackend(ConfigEntry configEntry, DN[] baseDNs) |
| | | throws ConfigException, InitializationException |
| | |
| | | } |
| | | |
| | | configEntryDN = configEntry.getDN(); |
| | | RootDSEBackendCfg cfg = getRootDSEBackendCfg(configEntry); |
| | | |
| | | |
| | | // Get the set of user-defined attributes for the configuration entry. Any |
| | |
| | | // Create the set of subordinate base DNs. If this is specified in the |
| | | // configuration, then use that set. Otherwise, use the set of non-private |
| | | // backends defined in the server. |
| | | String description = getMessage(MSGID_ROOTDSE_SUBORDINATE_BASE_DESCRIPTION); |
| | | DNConfigAttribute subDNsStub = |
| | | new DNConfigAttribute(ATTR_ROOT_DSE_SUBORDINATE_BASE_DN, description, |
| | | false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute subDNsAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(subDNsStub); |
| | | if (subDNsAttr == null) |
| | | Set<DN> subDNs = cfg.getSubordinateBaseDN(); |
| | | if (subDNs.isEmpty()) |
| | | { |
| | | // This is fine -- we'll just use the set of user-defined suffixes. |
| | | subordinateBaseDNs = null; |
| | |
| | | else |
| | | { |
| | | subordinateBaseDNs = new ConcurrentHashMap<DN,Backend>(); |
| | | for (DN baseDN : subDNsAttr.activeValues()) |
| | | for (DN baseDN : subDNs) |
| | | { |
| | | Backend backend = DirectoryServer.getBackend(baseDN); |
| | | if (backend == null) |
| | |
| | | |
| | | // Determine whether all root DSE attributes should be treated as user |
| | | // attributes. |
| | | showAllAttributes = DEFAULT_ROOTDSE_SHOW_ALL_ATTRIBUTES; |
| | | int msgID = MSGID_ROOTDSE_DESCRIPTION_SHOW_ALL_ATTRIBUTES; |
| | | BooleanConfigAttribute showAllStub = |
| | | new BooleanConfigAttribute(ATTR_ROOTDSE_SHOW_ALL_ATTRIBUTES, |
| | | getMessage(msgID), false); |
| | | try |
| | | { |
| | | BooleanConfigAttribute showAllAttr = |
| | | (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(showAllStub); |
| | | if (showAllAttr != null) |
| | | { |
| | | showAllAttributes = showAllAttr.activeValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_ROOTDSE_CANNOT_DETERMINE_ALL_USER_ATTRIBUTES; |
| | | String message = getMessage(msgID, ATTR_ROOTDSE_SHOW_ALL_ATTRIBUTES, |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR, message, |
| | | msgID); |
| | | } |
| | | showAllAttributes = cfg.isShowAllAttributes(); |
| | | |
| | | |
| | | // Construct the set of "static" attributes that will always be present in |
| | |
| | | setBackendID("rootdse"); |
| | | |
| | | |
| | | // Register with the Directory Server as a configurable component. |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | // Register as a change listener. |
| | | currentConfig = cfg; |
| | | cfg.addChangeListener(this); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | public void finalizeBackend() |
| | | { |
| | | DirectoryServer.deregisterConfigurableComponent(this); |
| | | currentConfig.removeChangeListener(this); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Exports the contents of this backend to LDIF. This method should only be |
| | | * called if <CODE>supportsLDIFExport</CODE> returns <CODE>true</CODE>. Note |
| | | * that the server will not explicitly initialize this backend before calling |
| | | * this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param baseDNs The set of base DNs configured for this backend. |
| | | * @param exportConfig The configuration to use when performing the export. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the LDIF |
| | | * export. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void exportLDIF(ConfigEntry configEntry, DN[] baseDNs, |
| | | LDIFExportConfig exportConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Imports information from an LDIF file into this backend. This method |
| | | * should only be called if <CODE>supportsLDIFImport</CODE> returns |
| | | * <CODE>true</CODE>. Note that the server will not explicitly initialize |
| | | * this backend before calling this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param baseDNs The set of base DNs configured for this backend. |
| | | * @param importConfig The configuration to use when performing the import. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the LDIF |
| | | * import. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void importLDIF(ConfigEntry configEntry, DN[] baseDNs, |
| | | LDIFImportConfig importConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Creates a backup of the contents of this backend in a form that may be |
| | | * restored at a later date if necessary. This method should only be called |
| | | * if <CODE>supportsBackup</CODE> returns <CODE>true</CODE>. Note that the |
| | | * server will not explicitly initialize this backend before calling this |
| | | * method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param backupConfig The configuration to use when performing the backup. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the |
| | | * backup. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void createBackup(ConfigEntry configEntry, BackupConfig backupConfig) |
| | | throws DirectoryException |
| | |
| | | |
| | | |
| | | /** |
| | | * Restores a backup of the contents of this backend. This method should only |
| | | * be called if <CODE>supportsRestore</CODE> returns <CODE>true</CODE>. Note |
| | | * that the server will not explicitly initialize this backend before calling |
| | | * this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param restoreConfig The configuration to use when performing the |
| | | * restore. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the |
| | | * restore. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void restoreBackup(ConfigEntry configEntry, |
| | | RestoreConfig restoreConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry with which this component is |
| | | * associated. |
| | | * |
| | | * @return The DN of the configuration entry with which this component is |
| | | * associated. |
| | | * {@inheritDoc} |
| | | */ |
| | | public DN getConfigurableComponentEntryDN() |
| | | { |
| | | return configEntryDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | * |
| | | * @return The set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | */ |
| | | public List<ConfigAttribute> getConfigurationAttributes() |
| | | { |
| | | LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>(); |
| | | |
| | | String description = getMessage(MSGID_ROOTDSE_SUBORDINATE_BASE_DESCRIPTION); |
| | | |
| | | ArrayList<DN> values = new ArrayList<DN>(); |
| | | if (subordinateBaseDNs != null) |
| | | { |
| | | values.addAll(subordinateBaseDNs.keySet()); |
| | | } |
| | | |
| | | attrList.add(new DNConfigAttribute(ATTR_ROOT_DSE_SUBORDINATE_BASE_DN, |
| | | description, false, true, false, |
| | | values)); |
| | | |
| | | |
| | | description = getMessage(MSGID_ROOTDSE_DESCRIPTION_SHOW_ALL_ATTRIBUTES); |
| | | attrList.add(new BooleanConfigAttribute(ATTR_ROOTDSE_SHOW_ALL_ATTRIBUTES, |
| | | description, showAllAttributes)); |
| | | |
| | | |
| | | return attrList; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an acceptable |
| | | * configuration for this component. If it does not, then detailed |
| | | * information about the problem(s) should be added to the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to make the |
| | | * determination. |
| | | * @param unacceptableReasons A list that can be used to hold messages about |
| | | * why the provided entry does not have an |
| | | * acceptable configuration. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided entry has an acceptable |
| | | * configuration for this component, or <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | public boolean isConfigurationChangeAcceptable( |
| | | RootDSEBackendCfg cfg, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | boolean configIsAcceptable = true; |
| | | |
| | | |
| | | String description = getMessage(MSGID_ROOTDSE_SUBORDINATE_BASE_DESCRIPTION); |
| | | DNConfigAttribute subDNsStub = |
| | | new DNConfigAttribute(ATTR_ROOT_DSE_SUBORDINATE_BASE_DN, description, |
| | | false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute subDNsAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(subDNsStub); |
| | | if (subDNsAttr == null) |
| | | Set<DN> subDNs = cfg.getSubordinateBaseDN(); |
| | | if (subDNs.isEmpty()) |
| | | { |
| | | // This is fine -- we'll just use the set of user-defined suffixes. |
| | | } |
| | | else |
| | | { |
| | | for (DN baseDN : subDNsAttr.activeValues()) |
| | | for (DN baseDN : subDNs) |
| | | { |
| | | Backend backend = DirectoryServer.getBackend(baseDN); |
| | | if (backend == null) |
| | |
| | | } |
| | | |
| | | |
| | | description = getMessage(MSGID_ROOTDSE_DESCRIPTION_SHOW_ALL_ATTRIBUTES); |
| | | BooleanConfigAttribute showAllStub = |
| | | new BooleanConfigAttribute(ATTR_ROOTDSE_SHOW_ALL_ATTRIBUTES, |
| | | description, false); |
| | | try |
| | | { |
| | | BooleanConfigAttribute showAllAttr = |
| | | (BooleanConfigAttribute) configEntry.getConfigAttribute(showAllStub); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_ROOTDSE_CANNOT_DETERMINE_ALL_USER_ATTRIBUTES; |
| | | String message = getMessage(msgID, ATTR_ROOTDSE_SHOW_ALL_ATTRIBUTES, |
| | | stackTraceToSingleLineString(e)); |
| | | unacceptableReasons.add(message); |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | return configIsAcceptable; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained in the |
| | | * provided entry. Information about the result of this processing should be |
| | | * added to the provided message list. Information should always be added to |
| | | * this list if a configuration change could not be applied. If detailed |
| | | * results are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not changed) should |
| | | * also be included. |
| | | * |
| | | * @param configEntry The entry containing the new configuration to |
| | | * apply for this component. |
| | | * @param detailedResults Indicates whether detailed information about the |
| | | * processing should be added to the list. |
| | | * |
| | | * @return Information about the result of the configuration update. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | public ConfigChangeResult applyConfigurationChange(RootDSEBackendCfg cfg) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | |
| | | |
| | | // Check to see if we should apply a new set of base DNs. |
| | | ConcurrentHashMap<DN,Backend> subBases; |
| | | String description = getMessage(MSGID_ROOTDSE_SUBORDINATE_BASE_DESCRIPTION); |
| | | DNConfigAttribute subDNsStub = |
| | | new DNConfigAttribute(ATTR_ROOT_DSE_SUBORDINATE_BASE_DN, description, |
| | | false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute subDNsAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(subDNsStub); |
| | | if (subDNsAttr == null) |
| | | Set<DN> subDNs = cfg.getSubordinateBaseDN(); |
| | | if (subDNs.isEmpty()) |
| | | { |
| | | // This is fine -- we'll just use the set of user-defined suffixes. |
| | | subBases = null; |
| | |
| | | else |
| | | { |
| | | subBases = new ConcurrentHashMap<DN,Backend>(); |
| | | for (DN baseDN : subDNsAttr.activeValues()) |
| | | for (DN baseDN : subDNs) |
| | | { |
| | | Backend backend = DirectoryServer.getBackend(baseDN); |
| | | if (backend == null) |
| | |
| | | } |
| | | |
| | | |
| | | boolean newShowAll = DEFAULT_ROOTDSE_SHOW_ALL_ATTRIBUTES; |
| | | description = getMessage(MSGID_ROOTDSE_DESCRIPTION_SHOW_ALL_ATTRIBUTES); |
| | | BooleanConfigAttribute showAllStub = |
| | | new BooleanConfigAttribute(ATTR_ROOTDSE_SHOW_ALL_ATTRIBUTES, |
| | | description, false); |
| | | try |
| | | { |
| | | BooleanConfigAttribute showAllAttr = |
| | | (BooleanConfigAttribute) configEntry.getConfigAttribute(showAllStub); |
| | | if (showAllAttr != null) |
| | | { |
| | | newShowAll = showAllAttr.pendingValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_ROOTDSE_CANNOT_DETERMINE_ALL_USER_ATTRIBUTES; |
| | | String message = getMessage(msgID, ATTR_ROOTDSE_SHOW_ALL_ATTRIBUTES, |
| | | stackTraceToSingleLineString(e)); |
| | | messages.add(message); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | } |
| | | boolean newShowAll = cfg.isShowAllAttributes(); |
| | | |
| | | |
| | | // Check to see if there is a new set of user-defined attributes. |
| | | ArrayList<Attribute> userAttrs = new ArrayList<Attribute>(); |
| | | try |
| | | { |
| | | ConfigEntry configEntry = DirectoryServer.getConfigEntry(configEntryDN); |
| | | |
| | | for (List<Attribute> attrs : |
| | | configEntry.getEntry().getUserAttributes().values()) |
| | | { |
| | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (ConfigException e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_BACKEND_ERROR_INTERACTING_WITH_BACKEND_ENTRY; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | subordinateBaseDNs = subBases; |
| | | |
| | | if (detailedResults) |
| | | { |
| | | if (subordinateBaseDNs == null) |
| | | { |
| | | int msgID = MSGID_ROOTDSE_USING_SUFFIXES_AS_BASE_DNS; |
| | |
| | | else |
| | | { |
| | | StringBuilder basesStr = new StringBuilder(); |
| | | Iterator<DN> iterator = subordinateBaseDNs.keySet().iterator(); |
| | | while (iterator.hasNext()) |
| | | for (DN dn : subordinateBaseDNs.keySet()) |
| | | { |
| | | if (basesStr.length() > 0) |
| | | { |
| | |
| | | basesStr.append("{ "); |
| | | } |
| | | |
| | | basesStr.append(iterator.next()); |
| | | basesStr.append(dn); |
| | | } |
| | | |
| | | basesStr.append(" }"); |
| | |
| | | String message = getMessage(msgID, basesStr.toString()); |
| | | messages.add(message); |
| | | } |
| | | } |
| | | |
| | | |
| | | if (showAllAttributes != newShowAll) |
| | | { |
| | | showAllAttributes = newShowAll; |
| | | if (detailedResults) |
| | | { |
| | | int msgID = MSGID_ROOTDSE_UPDATED_SHOW_ALL_ATTRS; |
| | | String message = getMessage(msgID, ATTR_ROOTDSE_SHOW_ALL_ATTRIBUTES, |
| | | showAllAttributes); |
| | | messages.add(message); |
| | | } |
| | | } |
| | | |
| | | |
| | | userDefinedAttributes = userAttrs; |
| | | if (detailedResults) |
| | | { |
| | | int msgID = MSGID_ROOTDSE_USING_NEW_USER_ATTRS; |
| | | String message = getMessage(msgID); |
| | | messages.add(message); |
| | | } |
| | | } |
| | | |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | |
| | | private static RootDSEBackendCfg getRootDSEBackendCfg(ConfigEntry configEntry) |
| | | throws ConfigException { |
| | | return BackendConfigManager.getConfiguration( |
| | | RootDSEBackendCfgDefn.getInstance(), configEntry); |
| | | } |
| | | } |
| | | |
| | |
| | | import org.opends.server.api.AlertGenerator; |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.ClientConnection; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.api.MatchingRule; |
| | | import org.opends.server.config.BooleanConfigAttribute; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.DNConfigAttribute; |
| | | import org.opends.server.core.AddOperation; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | |
| | | import org.opends.server.core.ModifyDNOperation; |
| | | import org.opends.server.core.SchemaConfigManager; |
| | | import org.opends.server.core.SearchOperation; |
| | | import org.opends.server.core.BackendConfigManager; |
| | | import org.opends.server.schema.AttributeTypeSyntax; |
| | | import org.opends.server.schema.DITContentRuleSyntax; |
| | | import org.opends.server.schema.DITStructureRuleSyntax; |
| | |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import org.opends.server.admin.std.server.SchemaBackendCfg; |
| | | import org.opends.server.admin.std.meta.SchemaBackendCfgDefn; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import static org.opends.server.messages.ConfigMessages.*; |
| | | |
| | | |
| | | /** |
| | |
| | | */ |
| | | public class SchemaBackend |
| | | extends Backend |
| | | implements ConfigurableComponent, AlertGenerator |
| | | implements ConfigurationChangeListener<SchemaBackendCfg>, AlertGenerator |
| | | { |
| | | /** |
| | | * The fully-qualified name of this class. |
| | |
| | | // The DN of the configuration entry for this backend. |
| | | private DN configEntryDN; |
| | | |
| | | // The current configuration state. |
| | | private SchemaBackendCfg currentConfig; |
| | | |
| | | // The set of base DNs for this backend. |
| | | private DN[] baseDNs; |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Initializes this backend based on the information in the provided |
| | | * configuration entry. |
| | | * |
| | | * @param configEntry The configuration entry that contains the information |
| | | * to use to initialize this backend. |
| | | * @param baseDNs The set of base DNs that have been configured for this |
| | | * backend. |
| | | * |
| | | * @throws ConfigException If an unrecoverable problem arises in the |
| | | * process of performing the initialization. |
| | | * |
| | | * @throws InitializationException If a problem occurs during initialization |
| | | * that is not related to the server |
| | | * configuration. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeBackend(ConfigEntry configEntry, DN[] baseDNs) |
| | | throws ConfigException, InitializationException |
| | |
| | | } |
| | | |
| | | configEntryDN = configEntry.getDN(); |
| | | |
| | | SchemaBackendCfg cfg = getSchemaBackendCfg(configEntry); |
| | | |
| | | // Get all of the attribute types that we will use for schema elements. |
| | | attributeTypesType = |
| | |
| | | |
| | | |
| | | // Determine whether to show all attributes. |
| | | showAllAttributes = DEFAULT_SCHEMA_SHOW_ALL_ATTRIBUTES; |
| | | int msgID = MSGID_SCHEMA_DESCRIPTION_SHOW_ALL_ATTRIBUTES; |
| | | BooleanConfigAttribute showAllStub = |
| | | new BooleanConfigAttribute(ATTR_SCHEMA_SHOW_ALL_ATTRIBUTES, |
| | | getMessage(msgID), false); |
| | | try |
| | | { |
| | | BooleanConfigAttribute showAllAttr = |
| | | (BooleanConfigAttribute) configEntry.getConfigAttribute(showAllStub); |
| | | if (showAllAttr != null) |
| | | { |
| | | showAllAttributes = showAllAttr.activeValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_SCHEMA_CANNOT_DETERMINE_SHOW_ALL; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new ConfigException(msgID, message, e); |
| | | } |
| | | showAllAttributes = cfg.isShowAllAttributes(); |
| | | |
| | | |
| | | // Register each of the suffixes with the Directory Server. Also, register |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_BACKEND_CANNOT_REGISTER_BASEDN; |
| | | int msgID = MSGID_BACKEND_CANNOT_REGISTER_BASEDN; |
| | | String message = getMessage(msgID, baseDNs[i].toString(), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | |
| | | } |
| | | else |
| | | { |
| | | msgID = MSGID_SCHEMA_CANNOT_FIND_CONCAT_FILE; |
| | | int msgID = MSGID_SCHEMA_CANNOT_FIND_CONCAT_FILE; |
| | | String message = getMessage(msgID, |
| | | upgradeDirectory.getAbsolutePath(), |
| | | SCHEMA_CONCAT_FILE_NAME, |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_SCHEMA_ERROR_DETERMINING_SCHEMA_CHANGES; |
| | | int msgID = MSGID_SCHEMA_ERROR_DETERMINING_SCHEMA_CHANGES; |
| | | String message = getMessage(msgID, stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_ERROR, message, |
| | | msgID); |
| | |
| | | |
| | | |
| | | // Register with the Directory Server as a configurable component. |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | currentConfig = cfg; |
| | | cfg.addSchemaChangeListener(this); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | public void finalizeBackend() |
| | | { |
| | | DirectoryServer.deregisterConfigurableComponent(this); |
| | | currentConfig.removeSchemaChangeListener(this); |
| | | |
| | | for (DN baseDN : baseDNs) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Exports the contents of this backend to LDIF. This method should only be |
| | | * called if <CODE>supportsLDIFExport</CODE> returns <CODE>true</CODE>. Note |
| | | * that the server will not explicitly initialize this backend before calling |
| | | * this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param baseDNs The set of base DNs configured for this backend. |
| | | * @param exportConfig The configuration to use when performing the export. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the LDIF |
| | | * export. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void exportLDIF(ConfigEntry configEntry, DN[] baseDNs, |
| | | LDIFExportConfig exportConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Imports information from an LDIF file into this backend. This method |
| | | * should only be called if <CODE>supportsLDIFImport</CODE> returns |
| | | * <CODE>true</CODE>. Note that the server will not explicitly initialize |
| | | * this backend before calling this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param baseDNs The set of base DNs configured for this backend. |
| | | * @param importConfig The configuration to use when performing the import. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the LDIF |
| | | * import. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void importLDIF(ConfigEntry configEntry, DN[] baseDNs, |
| | | LDIFImportConfig importConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Creates a backup of the contents of this backend in a form that may be |
| | | * restored at a later date if necessary. This method should only be called |
| | | * if <CODE>supportsBackup</CODE> returns <CODE>true</CODE>. Note that the |
| | | * server will not explicitly initialize this backend before calling this |
| | | * method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param backupConfig The configuration to use when performing the backup. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the |
| | | * backup. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void createBackup(ConfigEntry configEntry, BackupConfig backupConfig) |
| | | throws DirectoryException |
| | |
| | | |
| | | |
| | | /** |
| | | * Restores a backup of the contents of this backend. This method should only |
| | | * be called if <CODE>supportsRestore</CODE> returns <CODE>true</CODE>. Note |
| | | * that the server will not explicitly initialize this backend before calling |
| | | * this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param restoreConfig The configuration to use when performing the |
| | | * restore. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the |
| | | * restore. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void restoreBackup(ConfigEntry configEntry, |
| | | RestoreConfig restoreConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry with which this component is |
| | | * associated. |
| | | * |
| | | * @return The DN of the configuration entry with which this component is |
| | | * associated. |
| | | * {@inheritDoc} |
| | | */ |
| | | public DN getConfigurableComponentEntryDN() |
| | | { |
| | | return configEntryDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | * |
| | | * @return The set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | */ |
| | | public List<ConfigAttribute> getConfigurationAttributes() |
| | | { |
| | | LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>(); |
| | | |
| | | String description = getMessage(MSGID_SCHEMA_DESCRIPTION_ENTRY_DN); |
| | | |
| | | ArrayList<DN> values = new ArrayList<DN>(baseDNs.length); |
| | | for (DN baseDN : baseDNs) |
| | | { |
| | | values.add(baseDN); |
| | | } |
| | | |
| | | attrList.add(new DNConfigAttribute(ATTR_SCHEMA_ENTRY_DN, description, |
| | | false, true, false, values)); |
| | | |
| | | |
| | | description = getMessage(MSGID_SCHEMA_DESCRIPTION_SHOW_ALL_ATTRIBUTES); |
| | | attrList.add(new BooleanConfigAttribute(ATTR_SCHEMA_SHOW_ALL_ATTRIBUTES, |
| | | description, false, |
| | | showAllAttributes)); |
| | | |
| | | |
| | | return attrList; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an acceptable |
| | | * configuration for this component. If it does not, then detailed |
| | | * information about the problem(s) should be added to the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to make the |
| | | * determination. |
| | | * @param unacceptableReasons A list that can be used to hold messages about |
| | | * why the provided entry does not have an |
| | | * acceptable configuration. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided entry has an acceptable |
| | | * configuration for this component, or <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | public boolean isConfigurationChangeAcceptable( |
| | | SchemaBackendCfg configEntry, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | boolean configIsAcceptable = true; |
| | | return true; |
| | | } |
| | | |
| | | |
| | | String description = getMessage(MSGID_SCHEMA_DESCRIPTION_ENTRY_DN); |
| | | DNConfigAttribute baseDNStub = |
| | | new DNConfigAttribute(ATTR_SCHEMA_ENTRY_DN, description, false, true, |
| | | false); |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | SchemaBackendCfg backendCfg) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | |
| | | // Check to see if we should apply a new set of base DNs. |
| | | Set<DN> newBaseDNs; |
| | | try |
| | | { |
| | | // We don't care what the DNs are as long as we can parse them. |
| | | DNConfigAttribute baseDNAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseDNStub); |
| | | newBaseDNs = backendCfg.getSchemaEntryDN(); |
| | | if (newBaseDNs.isEmpty()) |
| | | { |
| | | newBaseDNs.add(DN.decode(DN_DEFAULT_SCHEMA_ROOT)); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | } |
| | | |
| | | int msgID = MSGID_SCHEMA_CANNOT_DETERMINE_BASE_DN; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | unacceptableReasons.add(message); |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | description = getMessage(MSGID_SCHEMA_DESCRIPTION_SHOW_ALL_ATTRIBUTES); |
| | | BooleanConfigAttribute showAllStub = |
| | | new BooleanConfigAttribute(ATTR_SCHEMA_SHOW_ALL_ATTRIBUTES, |
| | | description, false); |
| | | try |
| | | { |
| | | // We don't care what the value is as long as we can parse it. |
| | | BooleanConfigAttribute showAllAttr = |
| | | (BooleanConfigAttribute) configEntry.getConfigAttribute(showAllStub); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_SCHEMA_CANNOT_DETERMINE_SHOW_ALL; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | unacceptableReasons.add(message); |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | return configIsAcceptable; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained in the |
| | | * provided entry. Information about the result of this processing should be |
| | | * added to the provided message list. Information should always be added to |
| | | * this list if a configuration change could not be applied. If detailed |
| | | * results are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not changed) should |
| | | * also be included. |
| | | * |
| | | * @param configEntry The entry containing the new configuration to |
| | | * apply for this component. |
| | | * @param detailedResults Indicates whether detailed information about the |
| | | * processing should be added to the list. |
| | | * |
| | | * @return Information about the result of the configuration update. |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | |
| | | // Check to see if we should apply a new set of base DNs. |
| | | HashSet<DN> newBaseDNs; |
| | | int msgID = MSGID_SCHEMA_DESCRIPTION_ENTRY_DN; |
| | | DNConfigAttribute baseDNStub = |
| | | new DNConfigAttribute(ATTR_SCHEMA_ENTRY_DN, getMessage(msgID), false, |
| | | true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute baseDNAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseDNStub); |
| | | if (baseDNAttr == null) |
| | | { |
| | | newBaseDNs = new HashSet<DN>(1); |
| | | newBaseDNs.add(DN.decode(DN_DEFAULT_SCHEMA_ROOT)); |
| | | } |
| | | else |
| | | { |
| | | List<DN> newDNList = baseDNAttr.activeValues(); |
| | | if ((newDNList == null) || newDNList.isEmpty()) |
| | | { |
| | | newBaseDNs = new HashSet<DN>(1); |
| | | newBaseDNs.add(DN.decode(DN_DEFAULT_SCHEMA_ROOT)); |
| | | } |
| | | else |
| | | { |
| | | newBaseDNs = new HashSet<DN>(newDNList); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_SCHEMA_CANNOT_DETERMINE_BASE_DN; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | |
| | | |
| | | // Check to see if we should change the behavior regarding whether to show |
| | | // all schema attributes. |
| | | boolean newShowAllAttributes = DEFAULT_SCHEMA_SHOW_ALL_ATTRIBUTES; |
| | | msgID = MSGID_SCHEMA_DESCRIPTION_SHOW_ALL_ATTRIBUTES; |
| | | BooleanConfigAttribute showAllStub = |
| | | new BooleanConfigAttribute(ATTR_SCHEMA_SHOW_ALL_ATTRIBUTES, |
| | | getMessage(msgID), false); |
| | | try |
| | | { |
| | | BooleanConfigAttribute showAllAttr = |
| | | (BooleanConfigAttribute) configEntry.getConfigAttribute(showAllStub); |
| | | if (showAllAttr != null) |
| | | { |
| | | newShowAllAttributes = showAllAttr.activeValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_SCHEMA_CANNOT_DETERMINE_SHOW_ALL; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | newBaseDNs = null; |
| | | } |
| | | boolean newShowAllAttributes = backendCfg.isShowAllAttributes(); |
| | | |
| | | |
| | | // Check to see if there is a new set of user-defined attributes. |
| | | ArrayList<Attribute> newUserAttrs = new ArrayList<Attribute>(); |
| | | try |
| | | { |
| | | ConfigEntry configEntry = DirectoryServer.getConfigEntry(configEntryDN); |
| | | for (List<Attribute> attrs : |
| | | configEntry.getEntry().getUserAttributes().values()) |
| | | { |
| | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (ConfigException e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_BACKEND_ERROR_INTERACTING_WITH_BACKEND_ENTRY; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | |
| | | try |
| | | { |
| | | DirectoryServer.deregisterBaseDN(dn, false); |
| | | if (detailedResults) |
| | | { |
| | | msgID = MSGID_SCHEMA_DEREGISTERED_BASE_DN; |
| | | int msgID = MSGID_SCHEMA_DEREGISTERED_BASE_DN; |
| | | messages.add(getMessage(msgID, String.valueOf(dn))); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_SCHEMA_CANNOT_DEREGISTER_BASE_DN; |
| | | int msgID = MSGID_SCHEMA_CANNOT_DEREGISTER_BASE_DN; |
| | | messages.add(getMessage(msgID, String.valueOf(dn), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | |
| | | try |
| | | { |
| | | DirectoryServer.registerBaseDN(dn, this, true, false); |
| | | if (detailedResults) |
| | | { |
| | | msgID = MSGID_SCHEMA_REGISTERED_BASE_DN; |
| | | int msgID = MSGID_SCHEMA_REGISTERED_BASE_DN; |
| | | messages.add(getMessage(msgID, String.valueOf(dn))); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_SCHEMA_CANNOT_REGISTER_BASE_DN; |
| | | int msgID = MSGID_SCHEMA_CANNOT_REGISTER_BASE_DN; |
| | | messages.add(getMessage(msgID, String.valueOf(dn), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | |
| | | |
| | | |
| | | userDefinedAttributes = newUserAttrs; |
| | | if (detailedResults) |
| | | { |
| | | msgID = MSGID_SCHEMA_USING_NEW_USER_ATTRS; |
| | | int msgID = MSGID_SCHEMA_USING_NEW_USER_ATTRS; |
| | | String message = getMessage(msgID); |
| | | messages.add(message); |
| | | } |
| | | } |
| | | |
| | | |
| | | currentConfig = backendCfg; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | |
| | | |
| | | return alerts; |
| | | } |
| | | |
| | | |
| | | |
| | | private static SchemaBackendCfg getSchemaBackendCfg(ConfigEntry configEntry) |
| | | throws ConfigException { |
| | | return BackendConfigManager.getConfiguration( |
| | | SchemaBackendCfgDefn.getInstance(), configEntry); |
| | | } |
| | | } |
| | | |
| | |
| | | import com.sleepycat.je.DatabaseException; |
| | | |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.api.MonitorProvider; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.DNConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.core.AddOperation; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.core.ModifyDNOperation; |
| | | import org.opends.server.core.SearchOperation; |
| | | import org.opends.server.types.BackupConfig; |
| | | import org.opends.server.types.BackupDirectory; |
| | | import org.opends.server.types.CancelledOperationException; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.ErrorLogCategory; |
| | | import org.opends.server.types.ErrorLogSeverity; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.LDIFImportConfig; |
| | | import org.opends.server.types.LDIFExportConfig; |
| | | import org.opends.server.types.RestoreConfig; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.core.BackendConfigManager; |
| | | import org.opends.server.util.LDIFException; |
| | | import org.opends.server.util.Validator; |
| | | |
| | | import static org.opends.server.messages.BackendMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.messages.MessageHandler.getMessage; |
| | | import static org.opends.server.messages.JebMessages.*; |
| | | import static org.opends.server.loggers.Error.logError; |
| | | import static org.opends.server.messages.ConfigMessages.*; |
| | | import static org.opends.server.config.ConfigConstants.ATTR_BACKEND_BASE_DN; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.*; |
| | | import static org.opends.server.util.ServerConstants.OID_SUBTREE_DELETE_CONTROL; |
| | | import static org.opends.server.util.ServerConstants.OID_PAGED_RESULTS_CONTROL; |
| | | import static org.opends.server.util.ServerConstants.OID_MANAGE_DSAIT_CONTROL; |
| | | import org.opends.server.admin.std.server.JEBackendCfg; |
| | | import org.opends.server.admin.std.meta.JEBackendCfgDefn; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | |
| | | /** |
| | | * This is an implementation of a Directory Server Backend which stores entries |
| | | * locally in a Sleepycat JE database. |
| | | */ |
| | | public class BackendImpl extends Backend implements ConfigurableComponent |
| | | public class BackendImpl |
| | | extends Backend |
| | | implements ConfigurationChangeListener<JEBackendCfg> |
| | | { |
| | | |
| | | /** |
| | | * The DN of the configuration entry for this backend. |
| | | */ |
| | | private DN configDN; |
| | | |
| | | /** |
| | | * The configuration of this JE backend. |
| | | */ |
| | | private Config config; |
| | | private JEBackendCfg currentConfig; |
| | | |
| | | /** |
| | | * The root JE container to use for this backend. |
| | |
| | | private RootContainer rootContainer; |
| | | |
| | | /** |
| | | * A configurable component to handle changes to the configuration of |
| | | * the database environment. |
| | | */ |
| | | private ConfigurableEnvironment configurableEnv = null; |
| | | |
| | | /** |
| | | * A count of the total operation threads currently in the backend. |
| | | */ |
| | | private AtomicInteger threadTotalCount = new AtomicInteger(0); |
| | |
| | | */ |
| | | private static HashSet<String> supportedControls; |
| | | |
| | | /** |
| | | * The set of configuration attributes associated with the backend in its role |
| | | * as a configurable component. |
| | | */ |
| | | private static ArrayList<ConfigAttribute> configAttrs; |
| | | |
| | | /** |
| | | * The configuration attribute stub for the backendBaseDN attribute. |
| | | */ |
| | | private static DNConfigAttribute baseDNStub; |
| | | |
| | | |
| | | |
| | | static |
| | |
| | | supportedControls.add(OID_SUBTREE_DELETE_CONTROL); |
| | | supportedControls.add(OID_PAGED_RESULTS_CONTROL); |
| | | supportedControls.add(OID_MANAGE_DSAIT_CONTROL); |
| | | |
| | | configAttrs = new ArrayList<ConfigAttribute>(); |
| | | |
| | | // ds-cfg-backendBaseDN configuration attribute. |
| | | int msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BASE_DNS; |
| | | baseDNStub = new DNConfigAttribute(ATTR_BACKEND_BASE_DN, |
| | | getMessage(msgID), |
| | | true, true, true); |
| | | |
| | | configAttrs.add(baseDNStub); |
| | | |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Initializes this backend based on the information in the provided |
| | | * configuration entry. |
| | | * |
| | | * @param configEntry The configuration entry that contains the information |
| | | * to use to initialize this backend. |
| | | * @param baseDNs The set of base DNs that have been configured for this |
| | | * backend. |
| | | * |
| | | * @throws ConfigException If an unrecoverable problem arises in the |
| | | * process of performing the initialization. |
| | | * |
| | | * @throws InitializationException If a problem occurs during initialization |
| | | * that is not related to the server |
| | | * configuration. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeBackend(ConfigEntry configEntry, DN[] baseDNs) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | configDN = configEntry.getDN(); |
| | | Validator.ensureNotNull(configEntry); |
| | | JEBackendCfg backendCfg = getJEBackendCfg(configEntry); |
| | | |
| | | // Initialize a config object |
| | | config = new Config(); |
| | | config.initializeConfig(configEntry, baseDNs); |
| | | config.initializeConfig(backendCfg, baseDNs); |
| | | |
| | | for (DN dn : baseDNs) |
| | | { |
| | |
| | | message, databaseException); |
| | | } |
| | | |
| | | // Register this backend as a configurable component. |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | |
| | | // Register the database environment as a configurable component. |
| | | ConfigurableEnvironment configurableEnv = |
| | | rootContainer.getConfigurableEnvironment(); |
| | | if (configurableEnv != null) |
| | | { |
| | | DirectoryServer.registerConfigurableComponent(configurableEnv); |
| | | } |
| | | // Register this backend as a change listener. |
| | | currentConfig = backendCfg; |
| | | backendCfg.addJEChangeListener(this); |
| | | backendCfg.addJEChangeListener(config); |
| | | backendCfg.addJEChangeListener(rootContainer); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public void finalizeBackend() |
| | | { |
| | | // Deregister our configurable components. |
| | | // TODO: configurableEnv is always null and will not be deregistered. |
| | | if (configurableEnv != null) |
| | | { |
| | | DirectoryServer.deregisterConfigurableComponent(configurableEnv); |
| | | configurableEnv = null; |
| | | } |
| | | DirectoryServer.deregisterConfigurableComponent(this); |
| | | // Deregister as a change listener. |
| | | currentConfig.removeJEChangeListener(rootContainer); |
| | | currentConfig.removeJEChangeListener(config); |
| | | currentConfig.removeJEChangeListener(this); |
| | | |
| | | // Deregister our suffixes. |
| | | // FIXME: Currently assuming every base DN is also a suffix. |
| | | // Deregister our base DNs. |
| | | for (DN dn : rootContainer.getBaseDNs()) |
| | | { |
| | | try |
| | |
| | | |
| | | |
| | | /** |
| | | * Exports the contents of this backend to LDIF. This method should only be |
| | | * called if <CODE>supportsLDIFExport</CODE> returns <CODE>true</CODE>. Note |
| | | * that the server will not explicitly initialize this backend before calling |
| | | * this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param baseDNs The set of base DNs configured for this backend. |
| | | * @param exportConfig The configuration to use when performing the export. |
| | | * @throws org.opends.server.types.DirectoryException |
| | | * If a problem occurs while performing the LDIF export. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void exportLDIF(ConfigEntry configEntry, DN[] baseDNs, |
| | | LDIFExportConfig exportConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Imports information from an LDIF file into this backend. This method |
| | | * should only be called if <CODE>supportsLDIFImport</CODE> returns |
| | | * <CODE>true</CODE>. Note that the server will not explicitly initialize |
| | | * this backend before calling this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param baseDNs The set of base DNs configured for this backend. |
| | | * @param importConfig The configuration to use when performing the import. |
| | | * @throws DirectoryException If a problem occurs while performing the LDIF |
| | | * import. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void importLDIF(ConfigEntry configEntry, DN[] baseDNs, |
| | | LDIFImportConfig importConfig) |
| | |
| | | ConfigEntry configEntry, DN[] baseDNs) |
| | | throws InitializationException, ConfigException, DirectoryException |
| | | { |
| | | JEBackendCfg backendCfg = getJEBackendCfg(configEntry); |
| | | |
| | | // If the backend already has the root container open, we must use the same |
| | | // underlying root container |
| | | boolean openRootContainer = rootContainer == null; |
| | | |
| | | // If the rootContainer is open, the backend is initizlied by something else |
| | | // If the rootContainer is open, the backend is initialized by something |
| | | // else. |
| | | // We can't do any rebuild of system indexes while others are using this |
| | | // backend. Throw error. TODO: Need to make baseDNs disablable. |
| | | if(!openRootContainer && rebuildConfig.includesSystemIndex()) |
| | |
| | | { |
| | | // Initialize a config object. |
| | | config = new Config(); |
| | | config.initializeConfig(configEntry, baseDNs); |
| | | config.initializeConfig(backendCfg, baseDNs); |
| | | |
| | | // Open the database environment |
| | | rootContainer = new RootContainer(config, this); |
| | |
| | | |
| | | |
| | | /** |
| | | * Creates a backup of the contents of this backend in a form that may be |
| | | * restored at a later date if necessary. This method should only be called |
| | | * if <CODE>supportsBackup</CODE> returns <CODE>true</CODE>. Note that the |
| | | * server will not explicitly initialize this backend before calling this |
| | | * method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param backupConfig The configuration to use when performing the backup. |
| | | * @throws DirectoryException If a problem occurs while performing the |
| | | * backup. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void createBackup(ConfigEntry configEntry, BackupConfig backupConfig) |
| | | throws DirectoryException |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes the specified backup if it is possible to do so. |
| | | * |
| | | * @param backupDirectory The backup directory structure with which the |
| | | * specified backup is associated. |
| | | * @param backupID The backup ID for the backup to be removed. |
| | | * @throws DirectoryException If it is not possible to remove the specified |
| | | * backup for some reason (e.g., no such backup |
| | | * exists or there are other backups that are |
| | | * dependent upon it). |
| | | * {@inheritDoc} |
| | | */ |
| | | public void removeBackup(BackupDirectory backupDirectory, String backupID) |
| | | throws DirectoryException |
| | |
| | | |
| | | |
| | | /** |
| | | * Restores a backup of the contents of this backend. This method should only |
| | | * be called if <CODE>supportsRestore</CODE> returns <CODE>true</CODE>. Note |
| | | * that the server will not explicitly initialize this backend before calling |
| | | * this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param restoreConfig The configuration to use when performing the restore. |
| | | * @throws DirectoryException If a problem occurs while performing the |
| | | * restore. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void restoreBackup(ConfigEntry configEntry, |
| | | RestoreConfig restoreConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry with which this component is |
| | | * associated. |
| | | * |
| | | * @return The DN of the configuration entry with which this component is |
| | | * associated. |
| | | * {@inheritDoc} |
| | | */ |
| | | public DN getConfigurableComponentEntryDN() |
| | | { |
| | | return configDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | * |
| | | * @return The set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | */ |
| | | public List<ConfigAttribute> getConfigurationAttributes() |
| | | { |
| | | return configAttrs; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an acceptable |
| | | * configuration for this component. If it does not, then detailed |
| | | * information about the problem(s) should be added to the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to make the |
| | | * determination. |
| | | * @param unacceptableReasons A list that can be used to hold messages about |
| | | * why the provided entry does not have an |
| | | * acceptable configuration. |
| | | * @return <CODE>true</CODE> if the provided entry has an acceptable |
| | | * configuration for this component, or <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | public boolean isConfigurationChangeAcceptable( |
| | | JEBackendCfg cfg, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | DN[] baseDNs = null; |
| | | boolean acceptable = true; |
| | | |
| | | try |
| | | { |
| | | DNConfigAttribute baseDNAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseDNStub); |
| | | if (baseDNAttr == null) |
| | | { |
| | | int msgID = MSGID_CONFIG_BACKEND_NO_BASE_DNS; |
| | | String message = getMessage(msgID, String.valueOf(configEntry.getDN())); |
| | | unacceptableReasons.add(message); |
| | | } |
| | | else |
| | | { |
| | | baseDNs = baseDNAttr.activeValues().toArray(new DN[0]); |
| | | } |
| | | } |
| | | catch (ConfigException e) |
| | | { |
| | | unacceptableReasons.add(e.getMessage()); |
| | | acceptable = false; |
| | | } |
| | | |
| | | Config newConfig = new Config(); |
| | | try |
| | | { |
| | | newConfig.initializeConfig(configEntry, baseDNs); |
| | | } |
| | | catch (ConfigException e) |
| | | { |
| | | unacceptableReasons.add(e.getMessage()); |
| | | acceptable = false; |
| | | } |
| | | |
| | | return acceptable; |
| | | // This listener handles only the changes to the base DNs. |
| | | // The base DNs are checked by the backend config manager. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained in the |
| | | * provided entry. Information about the result of this processing should be |
| | | * added to the provided message list. Information should always be added to |
| | | * this list if a configuration change could not be applied. If detailed |
| | | * results are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not changed) should |
| | | * also be included. |
| | | * |
| | | * @param configEntry The entry containing the new configuration to apply |
| | | * for this component. |
| | | * @param detailedResults Indicates whether detailed information about the |
| | | * processing should be added to the list. |
| | | * |
| | | * @return Information about the result of the configuration update. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | public ConfigChangeResult applyConfigurationChange(JEBackendCfg cfg) |
| | | { |
| | | ConfigChangeResult ccr; |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | |
| | | |
| | | try |
| | | { |
| | | DN[] baseDNs = null; |
| | | |
| | | DNConfigAttribute baseDNAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseDNStub); |
| | | |
| | | baseDNs = baseDNAttr.activeValues().toArray(new DN[0]); |
| | | |
| | | // Create a new Config object. |
| | | Config newConfig = new Config(); |
| | | newConfig.initializeConfig(configEntry, baseDNs); |
| | | DN[] baseDNs = new DN[cfg.getBackendBaseDN().size()]; |
| | | baseDNs = cfg.getBackendBaseDN().toArray(baseDNs); |
| | | |
| | | // Check for changes to the base DNs. |
| | | for (DN baseDN : config.getBaseDNs()) |
| | | { |
| | | boolean found = false; |
| | | for (DN dn : newConfig.getBaseDNs()) |
| | | for (DN dn : baseDNs) |
| | | { |
| | | if (dn.equals(baseDN)) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | for (DN baseDN : newConfig.getBaseDNs()) |
| | | for (DN baseDN : baseDNs) |
| | | { |
| | | if (!rootContainer.getBaseDNs().contains(baseDN)) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | // Apply new JE configuration |
| | | rootContainer.applyNewConfig(config); |
| | | |
| | | // Put the new configuration in place. |
| | | config = newConfig; |
| | | currentConfig = cfg; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | config.initializeConfig(configEntry, baseDNs); |
| | | EnvManager.removeFiles(config.getBackendDirectory().getPath()); |
| | | } |
| | | |
| | | /** |
| | | * Gets the JE backend configuration corresponding to a JE |
| | | * backend config entry. |
| | | * |
| | | * @param configEntry A JE backend config entry. |
| | | * @return Returns the JE backend configuration. |
| | | * @throws ConfigException If the config entry could not be decoded. |
| | | */ |
| | | static JEBackendCfg getJEBackendCfg(ConfigEntry configEntry) |
| | | throws ConfigException { |
| | | return BackendConfigManager.getConfiguration( |
| | | JEBackendCfgDefn.getInstance(), configEntry); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | |
| | | import static org.opends.server.messages.MessageHandler.getMessage; |
| | | import static org.opends.server.messages.ConfigMessages. |
| | | MSGID_CONFIG_DESCRIPTION_BACKEND_DIRECTORY; |
| | | import static org.opends.server.messages.ConfigMessages. |
| | | MSGID_CONFIG_DESCRIPTION_BACKEND_MODE; |
| | | import static org.opends.server.messages.ConfigMessages. |
| | | MSGID_CONFIG_BACKEND_MODE_INVALID; |
| | | import static org.opends.server.messages.ConfigMessages. |
| | | MSGID_CONFIG_BACKEND_INSANE_MODE; |
| | | import static org.opends.server.config.ConfigConstants.ATTR_BACKEND_DIRECTORY; |
| | | import static org.opends.server.config.ConfigConstants.ATTR_BACKEND_MODE; |
| | | import static org.opends.server.messages.ConfigMessages. |
| | | MSGID_CONFIG_BACKEND_NO_DIRECTORY; |
| | | import static org.opends.server.messages.JebMessages.*; |
| | | import static org.opends.server.loggers.Error.logError; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.getFileForPath; |
| | | |
| | | import org.opends.server.config.BooleanConfigAttribute; |
| | | import org.opends.server.config.ConfigConstants; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.IntegerConfigAttribute; |
| | | import org.opends.server.config.IntegerWithUnitConfigAttribute; |
| | | import org.opends.server.config.MultiChoiceConfigAttribute; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.ErrorLogCategory; |
| | | import org.opends.server.types.ErrorLogSeverity; |
| | | import org.opends.server.types.RDN; |
| | | import org.opends.server.types.FilePermission; |
| | | import com.sleepycat.je.EnvironmentConfig; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.Collection; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.ArrayList; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.io.File; |
| | | |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.admin.std.server.JEBackendCfg; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | |
| | | /** |
| | | * This class represents the configuration of a JE backend. |
| | | */ |
| | | public class Config |
| | | implements ConfigurationChangeListener<JEBackendCfg> |
| | | { |
| | | |
| | | /** |
| | |
| | | ConfigConstants.NAME_PREFIX_CFG + "je-index"; |
| | | |
| | | /** |
| | | * The name of the object class which configures |
| | | * the database. |
| | | */ |
| | | public static final String OBJECT_CLASS_CONFIG_DATABASE = |
| | | ConfigConstants.NAME_PREFIX_CFG + "je-database"; |
| | | |
| | | /** |
| | | * The name of the attribute which configures |
| | | * the attribute type of an attribute index. |
| | | */ |
| | |
| | | |
| | | /** |
| | | * The name of the attribute which configures |
| | | * the backend index entry limit. |
| | | */ |
| | | public static final String ATTR_BACKEND_INDEX_ENTRY_LIMIT = |
| | | ConfigConstants.NAME_PREFIX_CFG + "backend-index-entry-limit"; |
| | | |
| | | |
| | | /** |
| | | * The name of the attribute which configures |
| | | * the subtree delete size limit. |
| | | */ |
| | | public static final String ATTR_SUBTREE_DELETE_SIZE_LIMIT = |
| | |
| | | |
| | | |
| | | /** |
| | | * A set of units and their multipliers for configuration attributes |
| | | * representing a number of bytes. |
| | | */ |
| | | private static HashMap<String, Double> memoryUnits; |
| | | |
| | | /** |
| | | * A set of units and their multipliers for configuration attributes |
| | | * representing a period of time in milliseconds. |
| | | */ |
| | | private static HashMap<String, Double> timeUnits; |
| | | |
| | | static |
| | | { |
| | | memoryUnits = new HashMap<String, Double>(); |
| | | memoryUnits.put(SIZE_UNIT_BYTES_ABBR, 1D); |
| | | memoryUnits.put(SIZE_UNIT_BYTES_FULL, 1D); |
| | | memoryUnits.put(SIZE_UNIT_KILOBYTES_ABBR, 1000D); |
| | | memoryUnits.put(SIZE_UNIT_KILOBYTES_FULL, 1000D); |
| | | memoryUnits.put(SIZE_UNIT_MEGABYTES_ABBR, 1000000D); |
| | | memoryUnits.put(SIZE_UNIT_MEGABYTES_FULL, 1000000D); |
| | | memoryUnits.put(SIZE_UNIT_GIGABYTES_ABBR, 1000000000D); |
| | | memoryUnits.put(SIZE_UNIT_GIGABYTES_FULL, 1000000000D); |
| | | memoryUnits.put(SIZE_UNIT_KIBIBYTES_ABBR, 1024D); |
| | | memoryUnits.put(SIZE_UNIT_KIBIBYTES_FULL, 1024D); |
| | | memoryUnits.put(SIZE_UNIT_MEBIBYTES_ABBR, (double) (1024 * 1024)); |
| | | memoryUnits.put(SIZE_UNIT_MEBIBYTES_FULL, (double) (1024 * 1024)); |
| | | memoryUnits.put(SIZE_UNIT_GIBIBYTES_ABBR, (double) (1024 * 1024 * 1024)); |
| | | memoryUnits.put(SIZE_UNIT_GIBIBYTES_FULL, (double) (1024 * 1024 * 1024)); |
| | | |
| | | timeUnits = new HashMap<String, Double>(); |
| | | timeUnits.put(TIME_UNIT_MILLISECONDS_ABBR, 1D); |
| | | timeUnits.put(TIME_UNIT_MILLISECONDS_FULL, 1D); |
| | | timeUnits.put(TIME_UNIT_SECONDS_ABBR, 1000D); |
| | | timeUnits.put(TIME_UNIT_SECONDS_FULL, 1000D); |
| | | timeUnits.put(TIME_UNIT_MINUTES_ABBR, (double) (60 * 1000)); |
| | | timeUnits.put(TIME_UNIT_MINUTES_FULL, (double) (60 * 1000)); |
| | | } |
| | | |
| | | /** |
| | | * The set of base DNs. |
| | | */ |
| | | private DN[] baseDNs = null; |
| | |
| | | * The backend directory permission mode. By default, owner has read, write |
| | | * and execute permissions on the database directory. |
| | | */ |
| | | private FilePermission backendPermission = new FilePermission(0700); |
| | | private FilePermission backendPermission; |
| | | |
| | | /** |
| | | * Number of times we should retry database transactions that get aborted |
| | | * due to deadlock. |
| | | * The current configuration. |
| | | */ |
| | | private int deadlockRetryLimit = 0; |
| | | |
| | | /** |
| | | * The backend index entry limit, zero means unlimited. |
| | | */ |
| | | private int backendIndexEntryLimit = 0; |
| | | |
| | | /** |
| | | * The maximum number of entries to process in a single pass through the LDIF |
| | | * file. |
| | | */ |
| | | private int importPassSize = Integer.MAX_VALUE; |
| | | |
| | | /** |
| | | * The subtree delete size limit, zero means unlimited. |
| | | */ |
| | | private int subtreeDeleteSizeLimit = 0; |
| | | |
| | | /** |
| | | * The memory available for import buffering. |
| | | */ |
| | | private long importBufferSize = 100*1024*1024; |
| | | |
| | | /** |
| | | * The pathname of the directory for import temporary files. |
| | | */ |
| | | private String importTempDirectory = "importTmp"; |
| | | private JEBackendCfg currentConfig; |
| | | |
| | | /** |
| | | * The set of configured attribute indexes. |
| | | */ |
| | | private Map<AttributeType, IndexConfig> indexConfigMap = null; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The DN of the JE database environment configuration entry, if any. |
| | | */ |
| | | private DN envConfigDN = null; |
| | | |
| | | /** |
| | | * The JE environment config. |
| | | */ |
| | | private EnvironmentConfig envConfig = null; |
| | | |
| | | /** |
| | | * The import queue size. |
| | | */ |
| | | private int importQueueSize = 100; |
| | | |
| | | /** |
| | | * The number of import threads. |
| | | */ |
| | | private int importThreadCount = 8; |
| | | |
| | | /** |
| | | * The database cache preload time limit in milliseconds. |
| | | */ |
| | | private long preloadTimeLimit = 0; |
| | | |
| | | /** |
| | | * Whether entries should be compressed in the database. |
| | | */ |
| | | private boolean entriesCompressed = false; |
| | | |
| | | |
| | | /** |
| | |
| | | public void initializeConfig(ConfigEntry configEntry, DN[] baseDNs) |
| | | throws ConfigException |
| | | { |
| | | StringConfigAttribute stub; |
| | | IntegerConfigAttribute intStub; |
| | | IntegerWithUnitConfigAttribute intWithUnitStub; |
| | | initializeConfig(BackendImpl.getJEBackendCfg(configEntry), configEntry, |
| | | baseDNs); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Initialize this JE backend configuration from a configuration entry. |
| | | * |
| | | * @param cfg The backend configuration entry. |
| | | * @param baseDNs The set of base DNs that have been configured for this |
| | | * backend. |
| | | * @throws ConfigException If there is an error in the configuration entry. |
| | | */ |
| | | public void initializeConfig(JEBackendCfg cfg, DN[] baseDNs) |
| | | throws ConfigException |
| | | { |
| | | initializeConfig(cfg, DirectoryServer.getConfigEntry(cfg.dn()), baseDNs); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Initialize this JE backend configuration from a configuration object |
| | | * and its configuration entry. |
| | | * |
| | | * @param cfg The backend configuration object. |
| | | * @param configEntry The backend configuration entry. |
| | | * @param baseDNs The set of base DNs that have been configured for this |
| | | * backend. |
| | | * @throws ConfigException If there is an error in the configuration entry. |
| | | */ |
| | | private void initializeConfig(JEBackendCfg cfg, ConfigEntry configEntry, |
| | | DN[] baseDNs) |
| | | throws ConfigException |
| | | { |
| | | // Set the base DNs. |
| | | this.baseDNs = baseDNs; |
| | | |
| | | // Determine the backend database directory. |
| | | // Required, single-valued config attribute requiring admin action on change |
| | | String msg = getMessage(MSGID_CONFIG_DESCRIPTION_BACKEND_DIRECTORY); |
| | | stub = |
| | | new StringConfigAttribute(ATTR_BACKEND_DIRECTORY, |
| | | msg, true, false, true); |
| | | StringConfigAttribute backendDirectoryAttr = (StringConfigAttribute) |
| | | configEntry.getConfigAttribute(stub); |
| | | if (backendDirectoryAttr == null) |
| | | { |
| | | int msgID = MSGID_CONFIG_BACKEND_NO_DIRECTORY; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | backendDirectory = getFileForPath(backendDirectoryAttr.activeValue()); |
| | | backendDirectory = getFileForPath(cfg.getBackendDirectory()); |
| | | |
| | | //Make sure the directory is valid. |
| | | if (!backendDirectory.isDirectory()) |
| | | { |
| | |
| | | throw new ConfigException(MSGID_JEB_DIRECTORY_INVALID, message); |
| | | } |
| | | |
| | | // ds-cfg-backend-mode |
| | | // Optional, single-valued config attribute requiring admin action on change |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_BACKEND_MODE); |
| | | stub = |
| | | new StringConfigAttribute(ATTR_BACKEND_MODE, msg, false,false, true); |
| | | StringConfigAttribute backendModeAttr = (StringConfigAttribute) |
| | | configEntry.getConfigAttribute(stub); |
| | | if (backendModeAttr != null) |
| | | { |
| | | FilePermission newBackendPermission; |
| | | try |
| | | { |
| | | newBackendPermission = FilePermission.decodeUNIXMode( |
| | | backendModeAttr.activeValue()); |
| | | newBackendPermission = |
| | | FilePermission.decodeUNIXMode(cfg.getBackendMode()); |
| | | } |
| | | catch(Exception e) |
| | | { |
| | | int msgID = MSGID_CONFIG_BACKEND_MODE_INVALID; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | String message = getMessage(msgID, cfg.dn().toString()); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | |
| | | { |
| | | backendPermission = newBackendPermission; |
| | | } |
| | | } |
| | | |
| | | // ds-cfg-backendIndexEntryLimit |
| | | // Optional, single-valued config attribute requiring admin action on change |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_BACKEND_INDEX_ENTRY_LIMIT); |
| | | intStub = |
| | | new IntegerConfigAttribute(ATTR_BACKEND_INDEX_ENTRY_LIMIT, msg, false, |
| | | false, true, true, 0, false, 0); |
| | | IntegerConfigAttribute entryLimitAttr = (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(intStub); |
| | | if (entryLimitAttr != null) |
| | | { |
| | | backendIndexEntryLimit = entryLimitAttr.activeIntValue(); |
| | | } |
| | | |
| | | // ds-cfg-backendSubtreeDeleteSizeLimit |
| | | // Optional, single-valued config attribute |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_SUBTREE_DELETE_SIZE_LIMIT); |
| | | intStub = |
| | | new IntegerConfigAttribute(ATTR_SUBTREE_DELETE_SIZE_LIMIT, msg, false, |
| | | false, false, true, 0, false, 0); |
| | | IntegerConfigAttribute sdslAttr = (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(intStub); |
| | | if (sdslAttr != null) |
| | | { |
| | | subtreeDeleteSizeLimit = sdslAttr.activeIntValue(); |
| | | } |
| | | |
| | | // Determine the directory for import temporary files. |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_IMPORT_TEMP_DIRECTORY); |
| | | stub = |
| | | new StringConfigAttribute(ATTR_IMPORT_TEMP_DIRECTORY, |
| | | msg, false, false, false); |
| | | StringConfigAttribute importTempDirAttr = (StringConfigAttribute) |
| | | configEntry.getConfigAttribute(stub); |
| | | if (importTempDirAttr != null) |
| | | { |
| | | this.importTempDirectory = importTempDirAttr.activeValue(); |
| | | } |
| | | |
| | | // Determine the memory available for import buffering. |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_IMPORT_BUFFER_SIZE); |
| | | intWithUnitStub = |
| | | new IntegerWithUnitConfigAttribute(ATTR_IMPORT_BUFFER_SIZE, msg, |
| | | false, memoryUnits, |
| | | true, 10*1024*1024, false, |
| | | 0); |
| | | IntegerWithUnitConfigAttribute importBufferSizeAttr = |
| | | (IntegerWithUnitConfigAttribute) |
| | | configEntry.getConfigAttribute(intWithUnitStub); |
| | | if (importBufferSizeAttr != null) |
| | | { |
| | | importBufferSize = importBufferSizeAttr.activeCalculatedValue(); |
| | | } |
| | | |
| | | // Determine the import queue size. |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_IMPORT_QUEUE_SIZE); |
| | | intStub = |
| | | new IntegerConfigAttribute(ATTR_IMPORT_QUEUE_SIZE, msg, false, |
| | | false, false, true, 1, false, 0); |
| | | IntegerConfigAttribute a = (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(intStub); |
| | | if (a != null) |
| | | { |
| | | importQueueSize = a.activeIntValue(); |
| | | } |
| | | |
| | | |
| | | // Determine the number of import threads. |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_IMPORT_THREAD_COUNT); |
| | | intStub = |
| | | new IntegerConfigAttribute(ATTR_IMPORT_THREAD_COUNT, msg, false, |
| | | false, false, true, 1, false, 0); |
| | | a = (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(intStub); |
| | | if (a != null) |
| | | { |
| | | importThreadCount = a.activeIntValue(); |
| | | } |
| | | |
| | | |
| | | // Determine the import pass size. |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_IMPORT_PASS_SIZE); |
| | | intStub = new IntegerConfigAttribute(ATTR_IMPORT_PASS_SIZE, msg, true, |
| | | false, false, true, 0, true, |
| | | Integer.MAX_VALUE); |
| | | a = (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(intStub); |
| | | if (a != null) |
| | | { |
| | | importPassSize = a.activeIntValue(); |
| | | } |
| | | |
| | | |
| | | // Determine the database cache preload time limit. |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_PRELOAD_TIME_LIMIT); |
| | | intWithUnitStub = |
| | | new IntegerWithUnitConfigAttribute(ATTR_PRELOAD_TIME_LIMIT, msg, |
| | | false, timeUnits, |
| | | true, 0, false, 0); |
| | | IntegerWithUnitConfigAttribute preloadTimeLimitAttr = |
| | | (IntegerWithUnitConfigAttribute) |
| | | configEntry.getConfigAttribute(intWithUnitStub); |
| | | if (preloadTimeLimitAttr != null) |
| | | { |
| | | preloadTimeLimit = preloadTimeLimitAttr.activeCalculatedValue(); |
| | | } |
| | | |
| | | |
| | | // Determine whether entries should be compressed in the database. |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_ENTRIES_COMPRESSED); |
| | | BooleanConfigAttribute booleanStub = |
| | | new BooleanConfigAttribute(ATTR_ENTRIES_COMPRESSED, msg, false); |
| | | BooleanConfigAttribute entriesCompressedAttr = |
| | | (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(booleanStub); |
| | | if (entriesCompressedAttr != null) |
| | | { |
| | | entriesCompressed = entriesCompressedAttr.activeValue(); |
| | | } |
| | | |
| | | |
| | | // Determine the deadlock retry limit. |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_DEADLOCK_RETRY_LIMIT); |
| | | intStub = |
| | | new IntegerConfigAttribute(ATTR_DEADLOCK_RETRY_LIMIT, msg, false, |
| | | false, false, true, 0, false, 0); |
| | | a = (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(intStub); |
| | | if (a != null) |
| | | { |
| | | deadlockRetryLimit = a.activeIntValue(); |
| | | } |
| | | |
| | | |
| | | indexConfigMap = new HashMap<AttributeType, IndexConfig>(); |
| | | |
| | |
| | | ConcurrentHashMap<DN, ConfigEntry> children = configEntry.getChildren(); |
| | | for (ConfigEntry childConfigEntry : children.values()) |
| | | { |
| | | if (childConfigEntry.hasObjectClass(OBJECT_CLASS_CONFIG_DATABASE)) |
| | | { |
| | | // This is a database config entry. |
| | | if (envConfig != null) |
| | | { |
| | | int msgID = MSGID_JEB_DUPLICATE_CONFIG_ENTRY; |
| | | String message = getMessage(msgID, |
| | | childConfigEntry.getDN().toString(), |
| | | OBJECT_CLASS_CONFIG_DATABASE); |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR, |
| | | message, msgID); |
| | | } |
| | | else |
| | | { |
| | | envConfig = |
| | | ConfigurableEnvironment.parseConfigEntry(childConfigEntry); |
| | | envConfigDN = childConfigEntry.getDN(); |
| | | } |
| | | } |
| | | else if (childConfigEntry.getDN().getRDN().equals(indexRDN)) |
| | | if (childConfigEntry.getDN().getRDN().equals(indexRDN)) |
| | | { |
| | | // This is the cn=Index branch entry. |
| | | |
| | | // Determine the index configuration. |
| | | configureIndexEntries(indexConfigMap, backendIndexEntryLimit, |
| | | configureIndexEntries(indexConfigMap, cfg.getBackendIndexEntryLimit(), |
| | | childConfigEntry.getChildren().values()); |
| | | } |
| | | else |
| | |
| | | } |
| | | } |
| | | |
| | | // Create a database configuration with defaults if we don't have one. |
| | | if (envConfig == null) |
| | | { |
| | | envConfig = ConfigurableEnvironment.defaultConfig(); |
| | | } |
| | | envConfig = ConfigurableEnvironment.parseConfigEntry(cfg); |
| | | |
| | | currentConfig = cfg; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public int getDeadlockRetryLimit() |
| | | { |
| | | return deadlockRetryLimit; |
| | | return currentConfig.getBackendDeadlockRetryLimit(); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public int getBackendIndexEntryLimit() |
| | | { |
| | | return backendIndexEntryLimit; |
| | | return currentConfig.getBackendIndexEntryLimit(); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public int getSubtreeDeleteSizeLimit() |
| | | { |
| | | return subtreeDeleteSizeLimit; |
| | | return currentConfig.getBackendSubtreeDeleteSizeLimit(); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public String getImportTempDirectory() |
| | | { |
| | | return importTempDirectory; |
| | | return currentConfig.getBackendImportTempDirectory(); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public long getImportBufferSize() |
| | | { |
| | | return importBufferSize; |
| | | return currentConfig.getBackendImportBufferSize(); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public int getImportQueueSize() |
| | | { |
| | | return importQueueSize; |
| | | return currentConfig.getBackendImportQueueSize(); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public int getImportThreadCount() |
| | | { |
| | | return importThreadCount; |
| | | return currentConfig.getBackendImportThreadCount(); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public int getImportPassSize() |
| | | { |
| | | return importPassSize; |
| | | return currentConfig.getBackendImportPassSize(); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | public boolean isEntriesCompressed() |
| | | { |
| | | return entriesCompressed; |
| | | return currentConfig.isBackendEntriesCompressed(); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | public long getPreloadTimeLimit() |
| | | { |
| | | return preloadTimeLimit; |
| | | return currentConfig.getBackendPreloadTimeLimit(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get the DN of the configuration entry for the JE environment, if any. |
| | | * |
| | | * @return The configuration entry DN, or null if there is none. |
| | | * {@inheritDoc} |
| | | */ |
| | | public DN getEnvConfigDN() |
| | | public boolean isConfigurationChangeAcceptable( |
| | | JEBackendCfg cfg, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | return envConfigDN; |
| | | boolean acceptable = true; |
| | | |
| | | // This listener does not handle the changes to JE properties. |
| | | |
| | | //Make sure the directory is valid. |
| | | if (!backendDirectory.isDirectory()) |
| | | { |
| | | int msgID = MSGID_JEB_DIRECTORY_INVALID; |
| | | String message = getMessage(msgID, backendDirectory.getPath()); |
| | | unacceptableReasons.add(message); |
| | | acceptable = false; |
| | | } |
| | | |
| | | try |
| | | { |
| | | FilePermission newBackendPermission = |
| | | FilePermission.decodeUNIXMode(cfg.getBackendMode()); |
| | | |
| | | //Make sure the mode will allow the server itself access to |
| | | //the database |
| | | if(!newBackendPermission.isOwnerWritable() || |
| | | !newBackendPermission.isOwnerReadable() || |
| | | !newBackendPermission.isOwnerExecutable()) |
| | | { |
| | | int msgID = MSGID_CONFIG_BACKEND_INSANE_MODE; |
| | | String message = getMessage(msgID); |
| | | unacceptableReasons.add(message); |
| | | acceptable = false; |
| | | } |
| | | } |
| | | catch(Exception e) |
| | | { |
| | | int msgID = MSGID_CONFIG_BACKEND_MODE_INVALID; |
| | | String message = getMessage(msgID, cfg.dn().toString()); |
| | | unacceptableReasons.add(message); |
| | | acceptable = false; |
| | | } |
| | | |
| | | return acceptable; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange(JEBackendCfg cfg) |
| | | { |
| | | ConfigChangeResult ccr; |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | try |
| | | { |
| | | // Set the base DNs. |
| | | baseDNs = new DN[cfg.getBackendBaseDN().size()]; |
| | | baseDNs = cfg.getBackendBaseDN().toArray(baseDNs); |
| | | |
| | | // Determine the backend database directory. |
| | | backendDirectory = getFileForPath(cfg.getBackendDirectory()); |
| | | |
| | | FilePermission newPermission = |
| | | FilePermission.decodeUNIXMode(cfg.getBackendMode()); |
| | | |
| | | // Check for changes to the database directory permissions |
| | | FilePermission oldPermission = backendPermission; |
| | | |
| | | if(FilePermission.canSetPermissions() && |
| | | !FilePermission.toUNIXMode(oldPermission).equals( |
| | | FilePermission.toUNIXMode(newPermission))) |
| | | { |
| | | try |
| | | { |
| | | if(!FilePermission.setPermissions(backendDirectory, |
| | | newPermission)) |
| | | { |
| | | throw new Exception(); |
| | | } |
| | | } |
| | | catch(Exception e) |
| | | { |
| | | // Log a warning that the permissions were not set. |
| | | int msgID = MSGID_JEB_SET_PERMISSIONS_FAILED; |
| | | String message = getMessage(msgID, |
| | | backendDirectory.getPath()); |
| | | logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_WARNING, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | backendPermission = newPermission; |
| | | |
| | | currentConfig = cfg; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | messages.add(e.getMessage()); |
| | | ccr = new ConfigChangeResult(DirectoryServer.getServerErrorResultCode(), |
| | | false, messages); |
| | | return ccr; |
| | | } |
| | | |
| | | ccr = new ConfigChangeResult(resultCode, false, messages); |
| | | return ccr; |
| | | } |
| | | |
| | | } |
| | |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import com.sleepycat.je.Environment; |
| | | import com.sleepycat.je.EnvironmentConfig; |
| | | import com.sleepycat.je.config.ConfigParam; |
| | | import com.sleepycat.je.config.EnvironmentParams; |
| | | |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.config.BooleanConfigAttribute; |
| | | import org.opends.server.config.IntegerConfigAttribute; |
| | | import org.opends.server.config.IntegerWithUnitConfigAttribute; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigConstants; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.lang.reflect.Method; |
| | | |
| | | import static org.opends.server.messages.MessageHandler.getMessage; |
| | | import static org.opends.server.messages.JebMessages.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.admin.std.server.JEBackendCfg; |
| | | import org.opends.server.admin.std.meta.JEBackendCfgDefn; |
| | | import org.opends.server.admin.DurationPropertyDefinition; |
| | | import org.opends.server.admin.BooleanPropertyDefinition; |
| | | import org.opends.server.admin.PropertyDefinition; |
| | | |
| | | /** |
| | | * This class represents a JE environment handle that can be configured by the |
| | | * Directory Server as a configurable component. |
| | | * This class maps JE properties to configuration attributes. |
| | | */ |
| | | public class ConfigurableEnvironment implements ConfigurableComponent |
| | | public class ConfigurableEnvironment |
| | | { |
| | | /** |
| | | * The DN of the configuration entry with which the environment is |
| | | * associated. |
| | | */ |
| | | private DN configDN; |
| | | |
| | | /** |
| | | * The JE environment handle. |
| | | */ |
| | | private Environment environment; |
| | | |
| | | /** |
| | | * The name of the attribute which configures the database cache size as a |
| | | * percentage of Java VM heap size. |
| | | */ |
| | |
| | | |
| | | |
| | | /** |
| | | * A map of JE property names to their associated configuration attribute. |
| | | * A map of JE property names to the corresponding configuration attribute. |
| | | */ |
| | | private static HashMap<String, ConfigAttribute> configAttrMap = |
| | | new HashMap<String, ConfigAttribute>(); |
| | | private static HashMap<String, String> attrMap = |
| | | new HashMap<String, String>(); |
| | | |
| | | /** |
| | | * A list of registered environment configuration attributes. |
| | | * A map of configuration attribute names to the corresponding configuration |
| | | * object getter method. |
| | | */ |
| | | private static ArrayList<ConfigAttribute> configAttrList = |
| | | new ArrayList<ConfigAttribute>(); |
| | | private static HashMap<String,Method> methodMap = |
| | | new HashMap<String, Method>(); |
| | | |
| | | |
| | | private static final ConfigAttribute CONFIG_ATTR_CACHE_PERCENT; |
| | | private static final ConfigAttribute CONFIG_ATTR_CACHE_SIZE; |
| | | private static final ConfigAttribute CONFIG_ATTR_TXN_NO_SYNC; |
| | | private static final ConfigAttribute CONFIG_ATTR_TXN_WRITE_NO_SYNC; |
| | | private static final ConfigAttribute CONFIG_ATTR_RUN_CLEANER; |
| | | private static final ConfigAttribute CONFIG_ATTR_CLEANER_MIN_UTILIZATION; |
| | | private static final ConfigAttribute CONFIG_ATTR_EVICTOR_LRU_ONLY; |
| | | private static final ConfigAttribute CONFIG_ATTR_EVICTOR_NODES_PER_SCAN; |
| | | private static final ConfigAttribute CONFIG_ATTR_LOG_FILE_MAX; |
| | | private static final ConfigAttribute CONFIG_ATTR_LOGGING_FILE_HANDLER_ON; |
| | | private static final ConfigAttribute CONFIG_ATTR_LOGGING_LEVEL; |
| | | private static final ConfigAttribute CONFIG_ATTR_CHECKPOINTER_BYTES_INTERVAL; |
| | | private static final ConfigAttribute CONFIG_ATTR_CHECKPOINTER_WAKEUP_INTERVAL; |
| | | private static final ConfigAttribute CONFIG_ATTR_NUM_LOCK_TABLES; |
| | | private static final ConfigAttribute CONFIG_ATTR_NUM_CLEANER_THREADS; |
| | | /** |
| | | * A map of configuration attribute names to the corresponding configuration |
| | | * PropertyDefinition. |
| | | */ |
| | | private static HashMap<String,PropertyDefinition> defnMap = |
| | | new HashMap<String, PropertyDefinition>(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Register an environment property and its associated configuration |
| | | * attribute. |
| | | * Register a JE property and its corresponding configuration attribute. |
| | | * |
| | | * @param propertyName The name of the JE property to be registered. |
| | | * @param configAttr The configuration attribute associated with the |
| | | * property. |
| | | * @param attrName The name of the configuration attribute associated |
| | | * with the property. |
| | | * @throws Exception If there is an error in the attribute name. |
| | | */ |
| | | private static void registerPropertyAttribute(String propertyName, |
| | | ConfigAttribute configAttr) |
| | | private static void registerProp(String propertyName, String attrName) |
| | | throws Exception |
| | | { |
| | | configAttrMap.put(propertyName, configAttr); |
| | | configAttrList.add(configAttr); |
| | | // Strip off NAME_PREFIX_CFG. |
| | | String baseName = attrName.substring(7); |
| | | |
| | | |
| | | // Convert hyphenated to camel case. |
| | | StringBuilder builder = new StringBuilder(); |
| | | boolean capitalize = true; |
| | | for (int i = 0; i < baseName.length(); i++) |
| | | { |
| | | char c = baseName.charAt(i); |
| | | if (c == '-') |
| | | { |
| | | capitalize = true; |
| | | } |
| | | else |
| | | { |
| | | if (capitalize) |
| | | { |
| | | builder.append(Character.toUpperCase(c)); |
| | | } |
| | | else |
| | | { |
| | | builder.append(c); |
| | | } |
| | | capitalize = false; |
| | | } |
| | | } |
| | | String methodBaseName = builder.toString(); |
| | | |
| | | Class configClass = JEBackendCfg.class; |
| | | JEBackendCfgDefn defn = JEBackendCfgDefn.getInstance(); |
| | | Class defClass = defn.getClass(); |
| | | |
| | | PropertyDefinition propDefn = |
| | | (PropertyDefinition)defClass.getMethod("get" + methodBaseName + |
| | | "PropertyDefinition").invoke(defn); |
| | | |
| | | String methodName; |
| | | if (propDefn instanceof BooleanPropertyDefinition) |
| | | { |
| | | methodName = "is" + methodBaseName; |
| | | } |
| | | else |
| | | { |
| | | methodName = "get" + methodBaseName; |
| | | } |
| | | |
| | | defnMap.put(attrName, propDefn); |
| | | methodMap.put(attrName, configClass.getMethod(methodName)); |
| | | attrMap.put(propertyName, attrName); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Get the name of the configuration attribute associated with a JE property. |
| | | * @param jeProperty The name of the JE property. |
| | | * @return The name of the associated configuration attribute. |
| | | */ |
| | | public static String getAttributeForProperty(String jeProperty) |
| | | { |
| | | return attrMap.get(jeProperty); |
| | | } |
| | | |
| | | /** |
| | | * Get the value of a JE property that is mapped to a configuration attribute. |
| | | * @param cfg The configuration containing the property values. |
| | | * @param attrName The conriguration attribute type name. |
| | | * @return The string value of the JE property. |
| | | */ |
| | | private static String getPropertyValue(JEBackendCfg cfg, String attrName) |
| | | { |
| | | try |
| | | { |
| | | PropertyDefinition propDefn = defnMap.get(attrName); |
| | | Method method = methodMap.get(attrName); |
| | | |
| | | if (propDefn instanceof DurationPropertyDefinition) |
| | | { |
| | | Long value = (Long)method.invoke(cfg); |
| | | |
| | | // JE durations are in microseconds so we must convert. |
| | | DurationPropertyDefinition durationPropDefn = |
| | | (DurationPropertyDefinition)propDefn; |
| | | value = 1000*durationPropDefn.getBaseUnit().getDuration(value); |
| | | |
| | | return String.valueOf(value); |
| | | } |
| | | else |
| | | { |
| | | Object value = method.invoke(cfg); |
| | | return String.valueOf(value); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | return ""; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | static |
| | | { |
| | | HashMap<String, Double> memoryUnits = new HashMap<String, Double>(); |
| | | memoryUnits.put(SIZE_UNIT_BYTES_ABBR, 1D); |
| | | memoryUnits.put(SIZE_UNIT_BYTES_FULL, 1D); |
| | | memoryUnits.put(SIZE_UNIT_KILOBYTES_ABBR, 1000D); |
| | | memoryUnits.put(SIZE_UNIT_KILOBYTES_FULL, 1000D); |
| | | memoryUnits.put(SIZE_UNIT_MEGABYTES_ABBR, 1000000D); |
| | | memoryUnits.put(SIZE_UNIT_MEGABYTES_FULL, 1000000D); |
| | | memoryUnits.put(SIZE_UNIT_GIGABYTES_ABBR, 1000000000D); |
| | | memoryUnits.put(SIZE_UNIT_GIGABYTES_FULL, 1000000000D); |
| | | memoryUnits.put(SIZE_UNIT_KIBIBYTES_ABBR, 1024D); |
| | | memoryUnits.put(SIZE_UNIT_KIBIBYTES_FULL, 1024D); |
| | | memoryUnits.put(SIZE_UNIT_MEBIBYTES_ABBR, (double) (1024 * 1024)); |
| | | memoryUnits.put(SIZE_UNIT_MEBIBYTES_FULL, (double) (1024 * 1024)); |
| | | memoryUnits.put(SIZE_UNIT_GIBIBYTES_ABBR, (double) (1024 * 1024 * 1024)); |
| | | memoryUnits.put(SIZE_UNIT_GIBIBYTES_FULL, (double) (1024 * 1024 * 1024)); |
| | | |
| | | // JE time intervals are expressed in microseconds. |
| | | HashMap<String, Double> timeUnits = new HashMap<String, Double>(); |
| | | timeUnits.put(TIME_UNIT_MICROSECONDS_ABBR, 1D); |
| | | timeUnits.put(TIME_UNIT_MICROSECONDS_FULL, 1D); |
| | | timeUnits.put(TIME_UNIT_MILLISECONDS_ABBR, 1000D); |
| | | timeUnits.put(TIME_UNIT_MILLISECONDS_FULL, 1000D); |
| | | timeUnits.put(TIME_UNIT_SECONDS_ABBR, 1000000D); |
| | | timeUnits.put(TIME_UNIT_SECONDS_FULL, 1000000D); |
| | | timeUnits.put(TIME_UNIT_MINUTES_ABBR, (double) (60 * 1000000)); |
| | | timeUnits.put(TIME_UNIT_MINUTES_FULL, (double) (60 * 1000000)); |
| | | |
| | | String msg; |
| | | |
| | | // Create configuration attributes for the JE properties that |
| | | // can be configured through the Directory Server interfaces. |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_TXN_NO_SYNC); |
| | | CONFIG_ATTR_TXN_NO_SYNC = |
| | | new BooleanConfigAttribute(ATTR_DATABASE_TXN_NO_SYNC, |
| | | msg, false); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_TXN_WRITE_NO_SYNC); |
| | | CONFIG_ATTR_TXN_WRITE_NO_SYNC = |
| | | new BooleanConfigAttribute(ATTR_DATABASE_TXN_WRITE_NO_SYNC, |
| | | msg, false); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_CACHE_PERCENT); |
| | | CONFIG_ATTR_CACHE_PERCENT = |
| | | new IntegerConfigAttribute(ATTR_DATABASE_CACHE_PERCENT, msg, true, |
| | | false, false, true, 1, true, 90); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_CACHE_SIZE); |
| | | CONFIG_ATTR_CACHE_SIZE = |
| | | new IntegerWithUnitConfigAttribute(ATTR_DATABASE_CACHE_SIZE, msg, |
| | | false, memoryUnits, |
| | | true, 0, false, 0); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_RUN_CLEANER); |
| | | CONFIG_ATTR_RUN_CLEANER = |
| | | new BooleanConfigAttribute(ATTR_DATABASE_RUN_CLEANER, |
| | | msg, false); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_CLEANER_MIN_UTILIZATION); |
| | | CONFIG_ATTR_CLEANER_MIN_UTILIZATION = |
| | | new IntegerConfigAttribute(ATTR_CLEANER_MIN_UTILIZATION, msg, true, |
| | | false, true, true, 0, true, 100); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_EVICTOR_LRU_ONLY); |
| | | CONFIG_ATTR_EVICTOR_LRU_ONLY = |
| | | new BooleanConfigAttribute(ATTR_EVICTOR_LRU_ONLY, msg, true); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_EVICTOR_NODES_PER_SCAN); |
| | | CONFIG_ATTR_EVICTOR_NODES_PER_SCAN = |
| | | new IntegerConfigAttribute(ATTR_EVICTOR_NODES_PER_SCAN, msg, false, |
| | | false, true, true, 1, true, 1000); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_LOG_FILE_MAX); |
| | | CONFIG_ATTR_LOG_FILE_MAX = |
| | | new IntegerWithUnitConfigAttribute(ATTR_DATABASE_LOG_FILE_MAX, msg, |
| | | false, memoryUnits, |
| | | true, 1000000, true, 4294967296L); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_LOGGING_FILE_HANDLER_ON); |
| | | CONFIG_ATTR_LOGGING_FILE_HANDLER_ON = |
| | | new BooleanConfigAttribute(ATTR_LOGGING_FILE_HANDLER_ON, msg, true); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_LOGGING_LEVEL); |
| | | CONFIG_ATTR_LOGGING_LEVEL = |
| | | new StringConfigAttribute(ATTR_LOGGING_LEVEL, msg, false, false, true); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_CHECKPOINT_BYTES_INTERVAL); |
| | | CONFIG_ATTR_CHECKPOINTER_BYTES_INTERVAL = |
| | | new IntegerWithUnitConfigAttribute(ATTR_CHECKPOINTER_BYTES_INTERVAL, |
| | | msg, true, memoryUnits, |
| | | true, 0, false, 0); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_CHECKPOINT_WAKEUP_INTERVAL); |
| | | CONFIG_ATTR_CHECKPOINTER_WAKEUP_INTERVAL = |
| | | new IntegerWithUnitConfigAttribute(ATTR_CHECKPOINTER_WAKEUP_INTERVAL, |
| | | msg, true, timeUnits, |
| | | true, 1000000, false, 0); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_NUM_LOCK_TABLES); |
| | | CONFIG_ATTR_NUM_LOCK_TABLES = |
| | | new IntegerConfigAttribute(ATTR_NUM_LOCK_TABLES, msg, false, |
| | | false, true, true, 1, true, 32767); |
| | | |
| | | msg = getMessage(MSGID_CONFIG_DESCRIPTION_NUM_CLEANER_THREADS); |
| | | CONFIG_ATTR_NUM_CLEANER_THREADS = |
| | | new IntegerConfigAttribute(ATTR_NUM_CLEANER_THREADS, msg, false, |
| | | false, false, true, 1, false, 0); |
| | | |
| | | // Register the parameters that have JE property names. |
| | | registerPropertyAttribute("je.maxMemoryPercent", |
| | | CONFIG_ATTR_CACHE_PERCENT); |
| | | registerPropertyAttribute("je.maxMemory", |
| | | CONFIG_ATTR_CACHE_SIZE); |
| | | registerPropertyAttribute("je.cleaner.minUtilization", |
| | | CONFIG_ATTR_CLEANER_MIN_UTILIZATION); |
| | | registerPropertyAttribute("je.env.runCleaner", |
| | | CONFIG_ATTR_RUN_CLEANER); |
| | | registerPropertyAttribute("je.evictor.lruOnly", |
| | | CONFIG_ATTR_EVICTOR_LRU_ONLY); |
| | | registerPropertyAttribute("je.evictor.nodesPerScan", |
| | | CONFIG_ATTR_EVICTOR_NODES_PER_SCAN); |
| | | registerPropertyAttribute("je.log.fileMax", |
| | | CONFIG_ATTR_LOG_FILE_MAX); |
| | | registerPropertyAttribute("java.util.logging.FileHandler.on", |
| | | CONFIG_ATTR_LOGGING_FILE_HANDLER_ON); |
| | | registerPropertyAttribute("java.util.logging.level", |
| | | CONFIG_ATTR_LOGGING_LEVEL); |
| | | registerPropertyAttribute("je.checkpointer.bytesInterval", |
| | | CONFIG_ATTR_CHECKPOINTER_BYTES_INTERVAL); |
| | | registerPropertyAttribute("je.checkpointer.wakeupInterval", |
| | | CONFIG_ATTR_CHECKPOINTER_WAKEUP_INTERVAL); |
| | | registerPropertyAttribute("je.lock.nLockTables", |
| | | CONFIG_ATTR_NUM_LOCK_TABLES); |
| | | registerPropertyAttribute("je.cleaner.threads", |
| | | CONFIG_ATTR_NUM_CLEANER_THREADS); |
| | | |
| | | // These parameters do not have JE property names. |
| | | configAttrList.add(CONFIG_ATTR_TXN_NO_SYNC); |
| | | configAttrList.add(CONFIG_ATTR_TXN_WRITE_NO_SYNC); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Constructs a configurable environment. |
| | | * |
| | | * @param configDN The DN of the configuration entry with which the |
| | | * environment is associated. |
| | | * @param environment The JE environment handle. |
| | | */ |
| | | public ConfigurableEnvironment(DN configDN, Environment environment) |
| | | try |
| | | { |
| | | this.configDN = configDN; |
| | | this.environment = environment; |
| | | registerProp("je.maxMemoryPercent", ATTR_DATABASE_CACHE_PERCENT); |
| | | registerProp("je.maxMemory", ATTR_DATABASE_CACHE_SIZE); |
| | | registerProp("je.cleaner.minUtilization", ATTR_CLEANER_MIN_UTILIZATION); |
| | | registerProp("je.env.runCleaner", ATTR_DATABASE_RUN_CLEANER); |
| | | registerProp("je.evictor.lruOnly", ATTR_EVICTOR_LRU_ONLY); |
| | | registerProp("je.evictor.nodesPerScan", ATTR_EVICTOR_NODES_PER_SCAN); |
| | | registerProp("je.log.fileMax", ATTR_DATABASE_LOG_FILE_MAX); |
| | | registerProp("java.util.logging.FileHandler.on", |
| | | ATTR_LOGGING_FILE_HANDLER_ON); |
| | | registerProp("java.util.logging.level", ATTR_LOGGING_LEVEL); |
| | | registerProp("je.checkpointer.bytesInterval", |
| | | ATTR_CHECKPOINTER_BYTES_INTERVAL); |
| | | registerProp("je.checkpointer.wakeupInterval", |
| | | ATTR_CHECKPOINTER_WAKEUP_INTERVAL); |
| | | registerProp("je.lock.nLockTables", ATTR_NUM_LOCK_TABLES); |
| | | registerProp("je.cleaner.threads", ATTR_NUM_CLEANER_THREADS); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Parse a configuration entry associated with a JE environment and create an |
| | | * Parse a configuration associated with a JE environment and create an |
| | | * environment config from it. |
| | | * |
| | | * @param configEntry The configuration entry to be parsed. |
| | | * @param cfg The configuration to be parsed. |
| | | * @return An environment config instance corresponding to the config entry. |
| | | * @throws ConfigException If there is an error in the provided configuration |
| | | * entry. |
| | | */ |
| | | public static EnvironmentConfig parseConfigEntry(ConfigEntry configEntry) |
| | | public static EnvironmentConfig parseConfigEntry(JEBackendCfg cfg) |
| | | throws ConfigException |
| | | { |
| | | EnvironmentConfig envConfig = defaultConfig(); |
| | | |
| | | // Handle the attributes that do not have a JE property. |
| | | BooleanConfigAttribute booleanAttr; |
| | | booleanAttr = (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(CONFIG_ATTR_TXN_NO_SYNC); |
| | | if (booleanAttr != null) |
| | | { |
| | | envConfig.setTxnNoSync(booleanAttr.activeValue()); |
| | | } |
| | | |
| | | booleanAttr = (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(CONFIG_ATTR_TXN_WRITE_NO_SYNC); |
| | | if (booleanAttr != null) |
| | | { |
| | | envConfig.setTxnWriteNoSync(booleanAttr.activeValue()); |
| | | } |
| | | envConfig.setTxnNoSync(cfg.isDatabaseTxnNoSync()); |
| | | envConfig.setTxnWriteNoSync(cfg.isDatabaseTxnWriteNoSync()); |
| | | |
| | | // Iterate through the config attributes associated with a JE property. |
| | | for (Map.Entry<String, ConfigAttribute> mapEntry : configAttrMap.entrySet()) |
| | | for (Map.Entry<String, String> mapEntry : attrMap.entrySet()) |
| | | { |
| | | String property = mapEntry.getKey(); |
| | | ConfigAttribute stub = mapEntry.getValue(); |
| | | String jeProperty = mapEntry.getKey(); |
| | | String attrName = mapEntry.getValue(); |
| | | |
| | | // Check if the config entry contains this attribute. |
| | | ConfigAttribute configAttr = configEntry.getConfigAttribute(stub); |
| | | if (stub != null) |
| | | { |
| | | // Set the property. |
| | | if (configAttr instanceof BooleanConfigAttribute) |
| | | { |
| | | BooleanConfigAttribute attr = (BooleanConfigAttribute) configAttr; |
| | | boolean value = attr.activeValue(); |
| | | envConfig.setConfigParam(property, String.valueOf(value)); |
| | | } |
| | | else if (configAttr instanceof IntegerConfigAttribute) |
| | | { |
| | | IntegerConfigAttribute attr = (IntegerConfigAttribute) configAttr; |
| | | long value = attr.activeValue(); |
| | | envConfig.setConfigParam(property, String.valueOf(value)); |
| | | } |
| | | else if (configAttr instanceof IntegerWithUnitConfigAttribute) |
| | | { |
| | | IntegerWithUnitConfigAttribute attr = |
| | | (IntegerWithUnitConfigAttribute) configAttr; |
| | | long value = attr.activeCalculatedValue(); |
| | | envConfig.setConfigParam(property, String.valueOf(value)); |
| | | } |
| | | else if (configAttr instanceof StringConfigAttribute) |
| | | { |
| | | StringConfigAttribute attr = (StringConfigAttribute) configAttr; |
| | | String value = attr.activeValue(); |
| | | envConfig.setConfigParam(property, value); |
| | | } |
| | | } |
| | | String value = getPropertyValue(cfg, attrName); |
| | | envConfig.setConfigParam(jeProperty, value); |
| | | } |
| | | |
| | | return envConfig; |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry with which this component is |
| | | * associated. |
| | | * |
| | | * @return The DN of the configuration entry with which this component is |
| | | * associated. |
| | | */ |
| | | public DN getConfigurableComponentEntryDN() |
| | | { |
| | | return configDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | * |
| | | * @return The set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | */ |
| | | public List<ConfigAttribute> getConfigurationAttributes() |
| | | { |
| | | return configAttrList; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an acceptable |
| | | * configuration for this component. If it does not, then detailed |
| | | * information about the problem(s) should be added to the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to make the |
| | | * determination. |
| | | * @param unacceptableReasons A list that can be used to hold messages about |
| | | * why the provided entry does not have an |
| | | * acceptable configuration. |
| | | * @return <CODE>true</CODE> if the provided entry has an acceptable |
| | | * configuration for this component, or <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained in the |
| | | * provided entry. Information about the result of this processing should be |
| | | * added to the provided message list. Information should always be added to |
| | | * this list if a configuration change could not be applied. If detailed |
| | | * results are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not changed) should |
| | | * also be included. |
| | | * |
| | | * @param configEntry The entry containing the new configuration to apply |
| | | * for this component. |
| | | * @param detailedResults Indicates whether detailed information about the |
| | | * processing should be added to the list. |
| | | * |
| | | * @return Information about the result of the configuration update. |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | { |
| | | ConfigChangeResult ccr; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | try |
| | | { |
| | | // Check if any JE non-mutable properties were changed. |
| | | EnvironmentConfig oldEnvConfig = environment.getConfig(); |
| | | EnvironmentConfig newEnvConfig = parseConfigEntry(configEntry); |
| | | Map paramsMap = EnvironmentParams.SUPPORTED_PARAMS; |
| | | for (Object o : paramsMap.values()) |
| | | { |
| | | ConfigParam param = (ConfigParam) o; |
| | | if (!param.isMutable()) |
| | | { |
| | | String oldValue = oldEnvConfig.getConfigParam(param.getName()); |
| | | String newValue = newEnvConfig.getConfigParam(param.getName()); |
| | | if (!oldValue.equalsIgnoreCase(newValue)) |
| | | { |
| | | adminActionRequired = true; |
| | | if (detailedResults) |
| | | { |
| | | ConfigAttribute configAttr = configAttrMap.get(param.getName()); |
| | | if (configAttr != null) |
| | | { |
| | | int msgID = MSGID_JEB_CONFIG_ATTR_REQUIRES_RESTART; |
| | | messages.add(getMessage(msgID, configAttr.getName())); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // This takes care of changes to the JE environment for those |
| | | // properties that are mutable at runtime. |
| | | environment.setMutableConfig(newEnvConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | messages.add(e.getMessage()); |
| | | ccr = new ConfigChangeResult(DirectoryServer.getServerErrorResultCode(), |
| | | adminActionRequired, |
| | | messages); |
| | | return ccr; |
| | | } |
| | | |
| | | ccr = new ConfigChangeResult(ResultCode.SUCCESS, adminActionRequired, |
| | | messages); |
| | | return ccr; |
| | | } |
| | | } |
| | |
| | | import org.opends.server.types.ErrorLogCategory; |
| | | import org.opends.server.types.ErrorLogSeverity; |
| | | import org.opends.server.types.FilePermission; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.ResultCode; |
| | | import static org.opends.server.loggers.Error.logError; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugInfo; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | |
| | | MSGID_JEB_CLEAN_DATABASE_FINISH; |
| | | import static org.opends.server.messages.JebMessages. |
| | | MSGID_JEB_SET_PERMISSIONS_FAILED; |
| | | import static org.opends.server.messages.JebMessages. |
| | | MSGID_JEB_CONFIG_ATTR_REQUIRES_RESTART; |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.admin.std.server.JEBackendCfg; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.core.DirectoryServer; |
| | | |
| | | /** |
| | | * Wrapper class for the JE environment. Root container holds all the entry |
| | |
| | | * of the entry containers. |
| | | */ |
| | | public class RootContainer |
| | | implements ConfigurationChangeListener<JEBackendCfg> |
| | | { |
| | | |
| | | /** |
| | |
| | | private DatabaseEnvironmentMonitor monitor; |
| | | |
| | | /** |
| | | * A configurable component to handle changes to the configuration of |
| | | * the database environment. |
| | | */ |
| | | private ConfigurableEnvironment configurableEnv; |
| | | |
| | | /** |
| | | * The base DNs contained in this entryContainer. |
| | | */ |
| | | private ConcurrentHashMap<DN, EntryContainer> entryContainers; |
| | |
| | | public RootContainer(Config config, Backend backend) |
| | | { |
| | | this.env = null; |
| | | this.configurableEnv = null; |
| | | this.monitor = null; |
| | | this.entryContainers = new ConcurrentHashMap<DN, EntryContainer>(); |
| | | this.backend = backend; |
| | |
| | | */ |
| | | public void openEntryContainers(DN[] baseDNs) throws DatabaseException |
| | | { |
| | | EntryID id = null; |
| | | EntryID id; |
| | | EntryID highestID = null; |
| | | for(DN baseDN : baseDNs) |
| | | { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Get the ConfigurableEnvironment object for JE environment used by this |
| | | * root container. |
| | | * |
| | | * @return The ConfigurableEnvironment object. |
| | | */ |
| | | public ConfigurableEnvironment getConfigurableEnvironment() |
| | | { |
| | | if(configurableEnv == null) |
| | | { |
| | | DN envConfigDN = config.getEnvConfigDN(); |
| | | if (envConfigDN != null) |
| | | { |
| | | configurableEnv = new ConfigurableEnvironment(envConfigDN, env); |
| | | } |
| | | } |
| | | |
| | | return configurableEnv; |
| | | } |
| | | |
| | | /** |
| | | * Get the DatabaseEnvironmentMonitor object for JE environment used by this |
| | | * root container. |
| | | * |
| | |
| | | } |
| | | |
| | | /** |
| | | * Apply new configuration to the JE environment. |
| | | * |
| | | * @param newConfig The new configuration to apply. |
| | | * @throws DatabaseException If an error occurs while applying the new |
| | | * configuration. |
| | | */ |
| | | public void applyNewConfig(Config newConfig) throws DatabaseException |
| | | { |
| | | // Check for changes to the database directory permissions |
| | | FilePermission oldPermission = config.getBackendPermission(); |
| | | FilePermission newPermission = newConfig.getBackendPermission(); |
| | | |
| | | if(FilePermission.canSetPermissions() && |
| | | !FilePermission.toUNIXMode(oldPermission).equals( |
| | | FilePermission.toUNIXMode(newPermission))) |
| | | { |
| | | try |
| | | { |
| | | if(!FilePermission.setPermissions(newConfig.getBackendDirectory(), |
| | | newPermission)) |
| | | { |
| | | throw new Exception(); |
| | | } |
| | | } |
| | | catch(Exception e) |
| | | { |
| | | // Log an warning that the permissions were not set. |
| | | int msgID = MSGID_JEB_SET_PERMISSIONS_FAILED; |
| | | String message = getMessage(msgID, |
| | | config.getBackendDirectory().getPath()); |
| | | logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_WARNING, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | // Check if any JE non-mutable properties were changed. |
| | | EnvironmentConfig oldEnvConfig = this.config.getEnvironmentConfig(); |
| | | EnvironmentConfig newEnvConfig = newConfig.getEnvironmentConfig(); |
| | | Map paramsMap = EnvironmentParams.SUPPORTED_PARAMS; |
| | | for (Object o : paramsMap.values()) |
| | | { |
| | | ConfigParam param = (ConfigParam)o; |
| | | if (!param.isMutable()) |
| | | { |
| | | String oldValue = oldEnvConfig.getConfigParam(param.getName()); |
| | | String newValue = newEnvConfig.getConfigParam(param.getName()); |
| | | if (!oldValue.equalsIgnoreCase(newValue)) |
| | | { |
| | | if(debugEnabled()) |
| | | { |
| | | debugInfo("The change to the following property will " + |
| | | "take effect when the backend is restarted: " + |
| | | param.getName()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // This takes care of changes to the JE environment for those |
| | | // properties that are mutable at runtime. |
| | | env.setMutableConfig(newConfig.getEnvironmentConfig()); |
| | | |
| | | config = newConfig; |
| | | |
| | | if (debugEnabled()) |
| | | { |
| | | debugInfo(env.getConfig().toString()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Get the environment stats of the JE environment used in this root |
| | | * container. |
| | | * |
| | |
| | | { |
| | | return (nextid.get() - 1); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | JEBackendCfg cfg, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | boolean acceptable = true; |
| | | |
| | | // This listener handles only the changes to JE properties. |
| | | |
| | | try |
| | | { |
| | | ConfigurableEnvironment.parseConfigEntry(cfg); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | unacceptableReasons.add(e.getMessage()); |
| | | acceptable = false; |
| | | } |
| | | |
| | | return acceptable; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange(JEBackendCfg cfg) |
| | | { |
| | | ConfigChangeResult ccr; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | try |
| | | { |
| | | // Check if any JE non-mutable properties were changed. |
| | | EnvironmentConfig oldEnvConfig = env.getConfig(); |
| | | EnvironmentConfig newEnvConfig = |
| | | ConfigurableEnvironment.parseConfigEntry(cfg); |
| | | Map paramsMap = EnvironmentParams.SUPPORTED_PARAMS; |
| | | for (Object o : paramsMap.values()) |
| | | { |
| | | ConfigParam param = (ConfigParam) o; |
| | | if (!param.isMutable()) |
| | | { |
| | | String oldValue = oldEnvConfig.getConfigParam(param.getName()); |
| | | String newValue = newEnvConfig.getConfigParam(param.getName()); |
| | | if (!oldValue.equalsIgnoreCase(newValue)) |
| | | { |
| | | adminActionRequired = true; |
| | | String configAttr = ConfigurableEnvironment. |
| | | getAttributeForProperty(param.getName()); |
| | | if (configAttr != null) |
| | | { |
| | | int msgID = MSGID_JEB_CONFIG_ATTR_REQUIRES_RESTART; |
| | | messages.add(getMessage(msgID, configAttr)); |
| | | } |
| | | if(debugEnabled()) |
| | | { |
| | | debugInfo("The change to the following property will " + |
| | | "take effect when the backend is restarted: " + |
| | | param.getName()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // This takes care of changes to the JE environment for those |
| | | // properties that are mutable at runtime. |
| | | env.setMutableConfig(newEnvConfig); |
| | | |
| | | if (debugEnabled()) |
| | | { |
| | | debugInfo(env.getConfig().toString()); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | messages.add(e.getMessage()); |
| | | ccr = new ConfigChangeResult(DirectoryServer.getServerErrorResultCode(), |
| | | adminActionRequired, |
| | | messages); |
| | | return ccr; |
| | | } |
| | | |
| | | |
| | | ccr = new ConfigChangeResult(ResultCode.SUCCESS, adminActionRequired, |
| | | messages); |
| | | return ccr; |
| | | } |
| | | } |
| | |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.concurrent.locks.Lock; |
| | | |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.IntegerWithUnitConfigAttribute; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.core.AddOperation; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.core.ModifyDNOperation; |
| | | import org.opends.server.core.SearchOperation; |
| | | import org.opends.server.core.BackendConfigManager; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.BackupConfig; |
| | |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import static org.opends.server.messages.BackendMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import org.opends.server.util.Validator; |
| | | import org.opends.server.admin.std.server.TaskBackendCfg; |
| | | import org.opends.server.admin.std.meta.TaskBackendCfgDefn; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | |
| | | |
| | | /** |
| | |
| | | */ |
| | | public class TaskBackend |
| | | extends Backend |
| | | implements ConfigurableComponent |
| | | implements ConfigurationChangeListener<TaskBackendCfg> |
| | | { |
| | | /** |
| | | * The set of time units that will be used for expressing the task retention |
| | | * time. |
| | | */ |
| | | private static final LinkedHashMap<String,Double> timeUnits = |
| | | new LinkedHashMap<String,Double>(); |
| | | |
| | | |
| | | // The current configuration state. |
| | | private TaskBackendCfg currentConfig; |
| | | |
| | | // The DN of the configuration entry for this backend. |
| | | private DN configEntryDN; |
| | |
| | | |
| | | |
| | | |
| | | static |
| | | { |
| | | timeUnits.put(TIME_UNIT_SECONDS_ABBR, 1D); |
| | | timeUnits.put(TIME_UNIT_SECONDS_FULL, 1D); |
| | | timeUnits.put(TIME_UNIT_MINUTES_ABBR, 60D); |
| | | timeUnits.put(TIME_UNIT_MINUTES_FULL, 60D); |
| | | timeUnits.put(TIME_UNIT_HOURS_ABBR, (double) (60 * 60)); |
| | | timeUnits.put(TIME_UNIT_HOURS_FULL, (double) (60 * 60)); |
| | | timeUnits.put(TIME_UNIT_DAYS_ABBR, (double) (60 * 60 * 24)); |
| | | timeUnits.put(TIME_UNIT_DAYS_FULL, (double) (60 * 60 * 24)); |
| | | timeUnits.put(TIME_UNIT_WEEKS_ABBR, (double) (60 * 60 * 24 * 7)); |
| | | timeUnits.put(TIME_UNIT_WEEKS_FULL, (double) (60 * 60 * 24 * 7)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new backend with the provided information. All backend |
| | | * implementations must implement a default constructor that use |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Initializes this backend based on the information in the provided |
| | | * configuration entry. |
| | | * |
| | | * @param configEntry The configuration entry that contains the information |
| | | * to use to initialize this backend. |
| | | * @param baseDNs The set of base DNs that have been configured for this |
| | | * backend. |
| | | * |
| | | * @throws ConfigException If an unrecoverable problem arises in the |
| | | * process of performing the initialization. |
| | | * |
| | | * @throws InitializationException If a problem occurs during initialization |
| | | * that is not related to the server |
| | | * configuration. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeBackend(ConfigEntry configEntry, DN[] baseDNs) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // Make sure that a configuration entry was provided. If not, then we will |
| | | // not be able to complete the initialization. |
| | | if (configEntry == null) |
| | | { |
| | | int msgID = MSGID_TASKBE_CONFIG_ENTRY_NULL; |
| | | String message = getMessage(msgID); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | Validator.ensureNotNull(configEntry); |
| | | TaskBackendCfg cfg = getTaskBackendCfg(configEntry); |
| | | |
| | | configEntryDN = configEntry.getDN(); |
| | | configEntryDN = cfg.dn(); |
| | | |
| | | |
| | | // Make sure that the provided set of base DNs contains exactly one value. |
| | |
| | | |
| | | // Get the retention time that will be used to determine how long task |
| | | // information stays around once the associated task is completed. |
| | | int msgID = MSGID_TASKBE_DESCRIPTION_RETENTION_TIME; |
| | | IntegerWithUnitConfigAttribute retentionStub = |
| | | new IntegerWithUnitConfigAttribute(ATTR_TASK_RETENTION_TIME, |
| | | getMessage(msgID), false, timeUnits, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerWithUnitConfigAttribute retentionAttr = |
| | | (IntegerWithUnitConfigAttribute) |
| | | configEntry.getConfigAttribute(retentionStub); |
| | | if (retentionAttr == null) |
| | | { |
| | | retentionTime = DEFAULT_TASK_RETENTION_TIME; |
| | | } |
| | | else |
| | | { |
| | | retentionTime = retentionAttr.activeCalculatedValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_TASKBE_CANNOT_INITIALIZE_RETENTION_TIME; |
| | | String message = getMessage(msgID, stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | retentionTime = cfg.getTaskRetentionTime(); |
| | | |
| | | |
| | | // Get the path to the task data backing file. |
| | | msgID = MSGID_TASKBE_DESCRIPTION_BACKING_FILE; |
| | | StringConfigAttribute taskFileStub = |
| | | new StringConfigAttribute(ATTR_TASK_BACKING_FILE, getMessage(msgID), |
| | | true, false, false); |
| | | try |
| | | { |
| | | StringConfigAttribute taskFileAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(taskFileStub); |
| | | if (taskFileAttr == null) |
| | | { |
| | | taskBackingFile = DirectoryServer.getServerRoot() + File.separator + |
| | | CONFIG_DIR_NAME + File.separator + TASK_FILE_NAME; |
| | | } |
| | | else |
| | | { |
| | | taskBackingFile = taskFileAttr.activeValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_TASKBE_CANNOT_INITIALIZE_BACKING_FILE; |
| | | String message = getMessage(msgID, stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | taskBackingFile = cfg.getTaskBackingFile(); |
| | | |
| | | |
| | | // Create the scheduler and initialize it from the backing file. |
| | |
| | | |
| | | |
| | | // Register with the Directory Server as a configurable component. |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | currentConfig = cfg; |
| | | cfg.addTaskChangeListener(this); |
| | | |
| | | |
| | | // Register the task base as a private suffix. |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_BACKEND_CANNOT_REGISTER_BASEDN; |
| | | int msgID = MSGID_BACKEND_CANNOT_REGISTER_BASEDN; |
| | | String message = getMessage(msgID, taskRootDN.toString(), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | |
| | | */ |
| | | public void finalizeBackend() |
| | | { |
| | | DirectoryServer.deregisterConfigurableComponent(this); |
| | | currentConfig.removeTaskChangeListener(this); |
| | | |
| | | |
| | | try |
| | |
| | | |
| | | |
| | | /** |
| | | * Exports the contents of this backend to LDIF. This method should only be |
| | | * called if <CODE>supportsLDIFExport</CODE> returns <CODE>true</CODE>. Note |
| | | * that the server will not explicitly initialize this backend before calling |
| | | * this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param baseDNs The set of base DNs configured for this backend. |
| | | * @param exportConfig The configuration to use when performing the export. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the LDIF |
| | | * export. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void exportLDIF(ConfigEntry configEntry, DN[] baseDNs, |
| | | LDIFExportConfig exportConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Imports information from an LDIF file into this backend. This method |
| | | * should only be called if <CODE>supportsLDIFImport</CODE> returns |
| | | * <CODE>true</CODE>. Note that the server will not explicitly initialize |
| | | * this backend before calling this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param baseDNs The set of base DNs configured for this backend. |
| | | * @param importConfig The configuration to use when performing the import. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the LDIF |
| | | * import. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void importLDIF(ConfigEntry configEntry, DN[] baseDNs, |
| | | LDIFImportConfig importConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Creates a backup of the contents of this backend in a form that may be |
| | | * restored at a later date if necessary. This method should only be called |
| | | * if <CODE>supportsBackup</CODE> returns <CODE>true</CODE>. Note that the |
| | | * server will not explicitly initialize this backend before calling this |
| | | * method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param backupConfig The configuration to use when performing the backup. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the |
| | | * backup. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void createBackup(ConfigEntry configEntry, BackupConfig backupConfig) |
| | | throws DirectoryException |
| | |
| | | |
| | | |
| | | /** |
| | | * Restores a backup of the contents of this backend. This method should only |
| | | * be called if <CODE>supportsRestore</CODE> returns <CODE>true</CODE>. Note |
| | | * that the server will not explicitly initialize this backend before calling |
| | | * this method. |
| | | * |
| | | * @param configEntry The configuration entry for this backend. |
| | | * @param restoreConfig The configuration to use when performing the |
| | | * restore. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while performing the |
| | | * restore. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void restoreBackup(ConfigEntry configEntry, |
| | | RestoreConfig restoreConfig) |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry with which this component is |
| | | * associated. |
| | | * |
| | | * @return The DN of the configuration entry with which this component is |
| | | * associated. |
| | | * {@inheritDoc} |
| | | */ |
| | | public DN getConfigurableComponentEntryDN() |
| | | { |
| | | return configEntryDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | * |
| | | * @return The set of configuration attributes that are associated with this |
| | | * configurable component. |
| | | */ |
| | | public List<ConfigAttribute> getConfigurationAttributes() |
| | | { |
| | | LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>(); |
| | | |
| | | String description = getMessage(MSGID_TASKBE_DESCRIPTION_BACKING_FILE); |
| | | attrList.add(new StringConfigAttribute(ATTR_TASK_BACKING_FILE, description, |
| | | true, false, false, |
| | | taskBackingFile)); |
| | | |
| | | description = getMessage(MSGID_TASKBE_DESCRIPTION_RETENTION_TIME); |
| | | attrList.add(new IntegerWithUnitConfigAttribute(ATTR_TASK_RETENTION_TIME, |
| | | description, false, |
| | | timeUnits, true, 0, false, |
| | | 0, retentionTime, |
| | | TIME_UNIT_SECONDS_FULL)); |
| | | |
| | | return attrList; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an acceptable |
| | | * configuration for this component. If it does not, then detailed |
| | | * information about the problem(s) should be added to the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to make the |
| | | * determination. |
| | | * @param unacceptableReasons A list that can be used to hold messages about |
| | | * why the provided entry does not have an |
| | | * acceptable configuration. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided entry has an acceptable |
| | | * configuration for this component, or <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | public boolean isConfigurationChangeAcceptable(TaskBackendCfg configEntry, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | boolean configIsAcceptable = true; |
| | | |
| | | |
| | | String description = getMessage(MSGID_TASKBE_DESCRIPTION_BACKING_FILE); |
| | | StringConfigAttribute backingStub = |
| | | new StringConfigAttribute(ATTR_TASK_BACKING_FILE, description, true, |
| | | false, false); |
| | | try |
| | | { |
| | | StringConfigAttribute backingAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(backingStub); |
| | | if (backingAttr == null) |
| | | { |
| | | int msgID = MSGID_TASKBE_NO_BACKING_FILE; |
| | | unacceptableReasons.add(getMessage(msgID, ATTR_TASK_BACKING_FILE)); |
| | | configIsAcceptable = false; |
| | | } |
| | | else |
| | | { |
| | | String tmpBackingFile = backingAttr.pendingValue(); |
| | | String tmpBackingFile = configEntry.getTaskBackingFile(); |
| | | if (! taskBackingFile.equals(tmpBackingFile)) |
| | | { |
| | | File f = getFileForPath(tmpBackingFile); |
| | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | |
| | | } |
| | | |
| | | |
| | | description = getMessage(MSGID_TASKBE_DESCRIPTION_RETENTION_TIME); |
| | | IntegerWithUnitConfigAttribute retentionStub = |
| | | new IntegerWithUnitConfigAttribute(ATTR_TASK_RETENTION_TIME, |
| | | description, false, timeUnits, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerWithUnitConfigAttribute retentionAttr = |
| | | (IntegerWithUnitConfigAttribute) |
| | | configEntry.getConfigAttribute(retentionStub); |
| | | if (retentionAttr == null) |
| | | { |
| | | int msgID = MSGID_TASKBE_NO_RETENTION_TIME; |
| | | unacceptableReasons.add(getMessage(msgID, ATTR_TASK_RETENTION_TIME)); |
| | | configIsAcceptable = false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_TASKBE_ERROR_GETTING_RETENTION_TIME; |
| | | unacceptableReasons.add(getMessage(msgID, ATTR_TASK_RETENTION_TIME, |
| | | stackTraceToSingleLineString(e))); |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | return configIsAcceptable; |
| | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained in the |
| | | * provided entry. Information about the result of this processing should be |
| | | * added to the provided message list. Information should always be added to |
| | | * this list if a configuration change could not be applied. If detailed |
| | | * results are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not changed) should |
| | | * also be included. |
| | | * |
| | | * @param configEntry The entry containing the new configuration to |
| | | * apply for this component. |
| | | * @param detailedResults Indicates whether detailed information about the |
| | | * processing should be added to the list. |
| | | * |
| | | * @return Information about the result of the configuration update. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | public ConfigChangeResult applyConfigurationChange(TaskBackendCfg configEntry) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | |
| | | |
| | | |
| | | String tmpBackingFile = taskBackingFile; |
| | | String description = getMessage(MSGID_TASKBE_DESCRIPTION_BACKING_FILE); |
| | | StringConfigAttribute backingStub = |
| | | new StringConfigAttribute(ATTR_TASK_BACKING_FILE, description, true, |
| | | false, false); |
| | | try |
| | | { |
| | | StringConfigAttribute backingAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(backingStub); |
| | | if (backingAttr == null) |
| | | { |
| | | int msgID = MSGID_TASKBE_NO_BACKING_FILE; |
| | | messages.add(getMessage(msgID, ATTR_TASK_BACKING_FILE)); |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | } |
| | | else |
| | | { |
| | | tmpBackingFile = backingAttr.pendingValue(); |
| | | tmpBackingFile = configEntry.getTaskBackingFile(); |
| | | if (! taskBackingFile.equals(tmpBackingFile)) |
| | | { |
| | | File f = getFileForPath(tmpBackingFile); |
| | |
| | | } |
| | | |
| | | |
| | | long tmpRetentionTime = retentionTime; |
| | | description = getMessage(MSGID_TASKBE_DESCRIPTION_RETENTION_TIME); |
| | | IntegerWithUnitConfigAttribute retentionStub = |
| | | new IntegerWithUnitConfigAttribute(ATTR_TASK_RETENTION_TIME, |
| | | description, false, timeUnits, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerWithUnitConfigAttribute retentionAttr = |
| | | (IntegerWithUnitConfigAttribute) |
| | | configEntry.getConfigAttribute(retentionStub); |
| | | if (retentionAttr == null) |
| | | { |
| | | int msgID = MSGID_TASKBE_NO_RETENTION_TIME; |
| | | messages.add(getMessage(msgID, ATTR_TASK_RETENTION_TIME)); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | tmpRetentionTime = retentionAttr.activeCalculatedValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_TASKBE_ERROR_GETTING_RETENTION_TIME; |
| | | messages.add(getMessage(msgID, ATTR_TASK_RETENTION_TIME, |
| | | stackTraceToSingleLineString(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | } |
| | | long tmpRetentionTime = configEntry.getTaskRetentionTime(); |
| | | |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | |
| | | } |
| | | |
| | | |
| | | currentConfig = configEntry; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | |
| | | { |
| | | return taskScheduler.getRecurringTask(taskEntryDN); |
| | | } |
| | | |
| | | |
| | | |
| | | private static TaskBackendCfg getTaskBackendCfg(ConfigEntry configEntry) |
| | | throws ConfigException { |
| | | return BackendConfigManager.getConfiguration( |
| | | TaskBackendCfgDefn.getInstance(), configEntry); |
| | | } |
| | | } |
| | | |
| | |
| | | import java.util.ArrayList; |
| | | import java.util.Iterator; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.BackendInitializationListener; |
| | | import org.opends.server.api.ConfigAddListener; |
| | | import org.opends.server.api.ConfigChangeListener; |
| | | import org.opends.server.api.ConfigDeleteListener; |
| | | import org.opends.server.api.ConfigHandler; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.config.BooleanConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.DNConfigAttribute; |
| | | import org.opends.server.config.MultiChoiceConfigAttribute; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.ErrorLogCategory; |
| | | import org.opends.server.types.ErrorLogSeverity; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.WritabilityMode; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigConstants; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import static org.opends.server.loggers.Error.*; |
| | | import org.opends.server.types.*; |
| | | import static org.opends.server.loggers.Error.logError; |
| | | import static org.opends.server.messages.ConfigMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.messages.MessageHandler.getMessage; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.server.ConfigurationAddListener; |
| | | import org.opends.server.admin.server.ConfigurationDeleteListener; |
| | | import org.opends.server.admin.server.ServerManagementContext; |
| | | import org.opends.server.admin.server.ServerManagedObject; |
| | | import org.opends.server.admin.server.ConfigExceptionFactory; |
| | | import org.opends.server.admin.server.ServerManagedObjectDecodingException; |
| | | import org.opends.server.admin.std.server.BackendCfg; |
| | | import org.opends.server.admin.std.server.RootCfg; |
| | | import org.opends.server.admin.std.meta.BackendCfgDefn; |
| | | import org.opends.server.admin.Configuration; |
| | | import org.opends.server.admin.AbstractManagedObjectDefinition; |
| | | import org.opends.server.admin.ManagedObjectPath; |
| | | import org.opends.server.admin.DefinitionDecodingException; |
| | | |
| | | |
| | | /** |
| | |
| | | * started, and then will manage any changes to them while the server is |
| | | * running. |
| | | */ |
| | | public class BackendConfigManager |
| | | implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener |
| | | public class BackendConfigManager implements |
| | | ConfigurationChangeListener<BackendCfg>, |
| | | ConfigurationAddListener<BackendCfg>, |
| | | ConfigurationDeleteListener<BackendCfg> |
| | | { |
| | | |
| | | |
| | |
| | | // backend implementations. |
| | | private ConcurrentHashMap<DN,Backend> registeredBackends; |
| | | |
| | | // The DN of the associated configuration entry. |
| | | private DN configEntryDN; |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | registeredBackends = new ConcurrentHashMap<DN,Backend>(); |
| | | |
| | | |
| | | // Create an internal server management context and retrieve |
| | | // the root configuration. |
| | | ServerManagementContext context = ServerManagementContext.getInstance(); |
| | | RootCfg root = context.getRootConfiguration(); |
| | | |
| | | // Register add and delete listeners. |
| | | root.addBackendAddListener(this); |
| | | root.addBackendDeleteListener(this); |
| | | |
| | | // Get the configuration entry that is at the root of all the backends in |
| | | // the server. |
| | | ConfigEntry backendRoot; |
| | | try |
| | | { |
| | | configEntryDN = DN.decode(DN_BACKEND_BASE); |
| | | DN configEntryDN = DN.decode(ConfigConstants.DN_BACKEND_BASE); |
| | | backendRoot = DirectoryServer.getConfigEntry(configEntryDN); |
| | | } |
| | | catch (Exception e) |
| | |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_GET_CONFIG_BASE; |
| | | String message = getMessage(msgID, stackTraceToSingleLineString(e)); |
| | | throw new ConfigException(msgID, message, e); |
| | | |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | // Register as an add and delete listener for the base entry so that we can |
| | | // be notified if new backends are added or existing backends are removed. |
| | | backendRoot.registerAddListener(this); |
| | | backendRoot.registerDeleteListener(this); |
| | | |
| | | |
| | | // Iterate through the set of immediate children below the backend config |
| | | // root. |
| | | for (ConfigEntry backendEntry : backendRoot.getChildren().values()) |
| | | // Initialize existing backends. |
| | | for (String name : root.listBackends()) |
| | | { |
| | | DN backendDN = backendEntry.getDN(); |
| | | // Get the handler's configuration. |
| | | // This will decode and validate its properties. |
| | | BackendCfg backendCfg = root.getBackend(name); |
| | | |
| | | DN backendDN = backendCfg.dn(); |
| | | String backendID = backendCfg.getBackendId(); |
| | | |
| | | // Register as a change listener for this backend entry so that we will |
| | | // be notified of any changes that may be made to it. |
| | | backendEntry.registerChangeListener(this); |
| | | // Register as a change listener for this backend so that we can be |
| | | // notified when it is disabled or enabled. |
| | | backendCfg.addChangeListener(this); |
| | | |
| | | |
| | | // Check to see if this entry appears to contain a backend configuration. |
| | | // If not, log a warning and skip it. |
| | | try |
| | | // Ignore this handler if it is disabled. |
| | | if (backendCfg.isBackendEnabled()) |
| | | { |
| | | SearchFilter backendFilter = |
| | | SearchFilter.createFilterFromString("(objectClass=" + OC_BACKEND + |
| | | ")"); |
| | | if (! backendFilter.matchesEntry(backendEntry.getEntry())) |
| | | { |
| | | int msgID = MSGID_CONFIG_BACKEND_ENTRY_DOES_NOT_HAVE_BACKEND_CONFIG; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, message, msgID); |
| | | continue; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_BACKEND_ERROR_INTERACTING_WITH_BACKEND_ENTRY; |
| | | String message = getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | message, msgID); |
| | | continue; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that indicates whether the |
| | | // backend should be enabled. If it does not, or if it is not set to |
| | | // "true", then skip it. |
| | | int msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_ENABLED; |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_BACKEND_ENABLED, getMessage(msgID), |
| | | false); |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledAttr = |
| | | (BooleanConfigAttribute) |
| | | backendEntry.getConfigAttribute(enabledStub); |
| | | if (enabledAttr == null) |
| | | { |
| | | // The attribute is not present, so this backend will be disabled. |
| | | // Log a message and continue. |
| | | msgID = MSGID_CONFIG_BACKEND_NO_ENABLED_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, message, msgID); |
| | | continue; |
| | | } |
| | | else if (! enabledAttr.activeValue()) |
| | | { |
| | | // The backend is explicitly disabled. Log a mild warning and |
| | | // continue. |
| | | msgID = MSGID_CONFIG_BACKEND_DISABLED; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.INFORMATIONAL, message, msgID); |
| | | continue; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_ENABLED_STATE; |
| | | String message = getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | message, msgID); |
| | | continue; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the backend ID. |
| | | // If it does not, then log an error and skip it. |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BACKEND_ID; |
| | | String backendID = null; |
| | | StringConfigAttribute idStub = |
| | | new StringConfigAttribute(ATTR_BACKEND_ID, getMessage(msgID), |
| | | true, false, true); |
| | | try |
| | | { |
| | | StringConfigAttribute idAttr = |
| | | (StringConfigAttribute) backendEntry.getConfigAttribute(idStub); |
| | | if (idAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_BACKEND_ID; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, message, msgID); |
| | | continue; |
| | | } |
| | | else |
| | | { |
| | | backendID = idAttr.activeValue(); |
| | | |
| | | // If there is already a backend registered with the specified ID, |
| | | // then log an error and skip it. |
| | | if (DirectoryServer.hasBackend(backendID)) |
| | | if (DirectoryServer.hasBackend(backendCfg.getBackendId())) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_DUPLICATE_BACKEND_ID; |
| | | int msgID = MSGID_CONFIG_BACKEND_DUPLICATE_BACKEND_ID; |
| | | String message = getMessage(msgID, backendID, |
| | | String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, message, msgID); |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_BACKEND_ID; |
| | | String message = getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | message, msgID); |
| | | continue; |
| | | } |
| | | |
| | | |
| | | // Get the writability mode for this backend. It must be provided. |
| | | LinkedHashSet<String> writabilityModes = new LinkedHashSet<String>(3); |
| | | writabilityModes.add(WritabilityMode.ENABLED.toString()); |
| | | writabilityModes.add(WritabilityMode.DISABLED.toString()); |
| | | writabilityModes.add(WritabilityMode.INTERNAL_ONLY.toString()); |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_WRITABILITY; |
| | | WritabilityMode writabilityMode = null; |
| | | MultiChoiceConfigAttribute writabilityStub = |
| | | new MultiChoiceConfigAttribute(ATTR_BACKEND_WRITABILITY_MODE, |
| | | getMessage(msgID), true, false, false, |
| | | writabilityModes); |
| | | try |
| | | { |
| | | MultiChoiceConfigAttribute writabilityAttr = |
| | | (MultiChoiceConfigAttribute) |
| | | backendEntry.getConfigAttribute(writabilityStub); |
| | | if (writabilityAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_WRITABILITY_MODE; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, message, msgID); |
| | | continue; |
| | | } |
| | | else |
| | | { |
| | | writabilityMode = |
| | | WritabilityMode.modeForName(writabilityAttr.activeValue()); |
| | | if (writabilityMode == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_INVALID_WRITABILITY_MODE; |
| | | String message = |
| | | getMessage(msgID, String.valueOf(backendDN), |
| | | String.valueOf(writabilityAttr.activeValue())); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, message, msgID); |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_WRITABILITY; |
| | | String message = getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | message, msgID); |
| | | continue; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the base DNs for |
| | | // the backend. If it does not, then log an error and skip it. |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BASE_DNS; |
| | | DN[] baseDNs = null; |
| | | DNConfigAttribute baseDNStub = |
| | | new DNConfigAttribute(ATTR_BACKEND_BASE_DN, getMessage(msgID), |
| | | true, true, true); |
| | | try |
| | | { |
| | | DNConfigAttribute baseDNAttr = |
| | | (DNConfigAttribute) backendEntry.getConfigAttribute(baseDNStub); |
| | | if (baseDNAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_BASE_DNS; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, message, msgID); |
| | | continue; |
| | | } |
| | | else |
| | | { |
| | | List<DN> dnList = baseDNAttr.activeValues(); |
| | | baseDNs = new DN[dnList.size()]; |
| | | dnList.toArray(baseDNs); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_BASE_DNS; |
| | | String message = getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | message, msgID); |
| | | continue; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the class name |
| | | // for the backend implementation. If it does, then load it and make sure |
| | | // that it's a valid backend implementation. There is no such attribute, |
| | | // the specified class cannot be loaded, or it does not contain a valid |
| | | // backend implementation, then log an error and skip it. |
| | | String className; |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_CLASS; |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_BACKEND_CLASS, getMessage(msgID), |
| | | true, false, true); |
| | | try |
| | | { |
| | | StringConfigAttribute classAttr = |
| | | (StringConfigAttribute) backendEntry.getConfigAttribute(classStub); |
| | | if (classAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_CLASS_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, message, msgID); |
| | | continue; |
| | | } |
| | | else |
| | | { |
| | | className = classAttr.activeValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_GET_CLASS; |
| | | String message = getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | message, msgID); |
| | | continue; |
| | | } |
| | | // for the backend implementation. If it does, then load it and make |
| | | // sure that it's a valid backend implementation. There is no such |
| | | // attribute, the specified class cannot be loaded, or it does not |
| | | // contain a valid backend implementation, then log an error and skip |
| | | // it. |
| | | String className = backendCfg.getBackendClass(); |
| | | Class backendClass; |
| | | |
| | | Backend backend; |
| | | try |
| | | { |
| | | Class backendClass = DirectoryServer.loadClass(className); |
| | | backendClass = DirectoryServer.loadClass(className); |
| | | backend = (Backend) backendClass.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_INSTANTIATE; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_INSTANTIATE; |
| | | String message = getMessage(msgID, String.valueOf(className), |
| | | String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | message, msgID); |
| | | continue; |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the writability |
| | | // mode. |
| | | WritabilityMode writabilityMode = WritabilityMode.ENABLED; |
| | | BackendCfgDefn.BackendWritabilityMode bwm = |
| | | backendCfg.getBackendWritabilityMode(); |
| | | switch (bwm) |
| | | { |
| | | case DISABLED: |
| | | writabilityMode = WritabilityMode.DISABLED; |
| | | break; |
| | | case ENABLED: |
| | | writabilityMode = WritabilityMode.ENABLED; |
| | | break; |
| | | case INTERNAL_ONLY: |
| | | writabilityMode = WritabilityMode.INTERNAL_ONLY; |
| | | break; |
| | | } |
| | | |
| | | // Set the backend ID and writability mode for this backend. |
| | | backend.setBackendID(backendID); |
| | | backend.setWritabilityMode(writabilityMode); |
| | | |
| | | |
| | | // Acquire a shared lock on this backend. This will prevent operations |
| | | // like LDIF import or restore from occurring while the backend is active. |
| | | // like LDIF import or restore from occurring while the backend is |
| | | // active. |
| | | try |
| | | { |
| | | String lockFile = LockFileManager.getBackendLockFileName(backend); |
| | | StringBuilder failureReason = new StringBuilder(); |
| | | if (! LockFileManager.acquireSharedLock(lockFile, failureReason)) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | String message = getMessage(msgID, backendID, |
| | | String.valueOf(failureReason)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | String message = getMessage(msgID, backendID, |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | |
| | | |
| | | |
| | | // Perform the necessary initialization for the backend entry. |
| | | DN[] baseDNs = new DN[backendCfg.getBackendBaseDN().size()]; |
| | | baseDNs = backendCfg.getBackendBaseDN().toArray(baseDNs); |
| | | try |
| | | { |
| | | backend.initializeBackend(backendEntry, baseDNs); |
| | | backend.initializeBackend( |
| | | DirectoryServer.getConfigEntry(backendCfg.dn()), baseDNs); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_INITIALIZE; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_INITIALIZE; |
| | | String message = getMessage(msgID, String.valueOf(className), |
| | | String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | message, msgID); |
| | | |
| | | try |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND; |
| | | String message = getMessage(msgID, backendID, |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | message, msgID); |
| | | // FIXME -- Do we need to send an admin alert? |
| | | } |
| | |
| | | // Put this backend in the hash so that we will be able to find it if it |
| | | // is altered. |
| | | registeredBackends.put(backendDN, backend); |
| | | } |
| | | } |
| | | |
| | | } |
| | | else |
| | | { |
| | | // The backend is explicitly disabled. Log a mild warning and |
| | | // continue. |
| | | int msgID = MSGID_CONFIG_BACKEND_DISABLED; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.INFORMATIONAL, message, msgID); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the configuration entry that will result from a proposed |
| | | * modification is acceptable to this change listener. |
| | | * |
| | | * @param configEntry The configuration entry that will result from |
| | | * the requested update. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed change is not acceptable. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry contains an acceptable |
| | | * configuration, or <CODE>false</CODE> if it does not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configChangeIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | public boolean isConfigurationChangeAcceptable( |
| | | BackendCfg configEntry, |
| | | List<String> unacceptableReason) |
| | | { |
| | | DN backendDN = configEntry.getDN(); |
| | | DN backendDN = configEntry.dn(); |
| | | |
| | | |
| | | // Check to see if this entry appears to contain a backend configuration. |
| | | // If not, log a warning and skip it. |
| | | try |
| | | { |
| | | SearchFilter backendFilter = |
| | | SearchFilter.createFilterFromString("(objectClass=" + OC_BACKEND + |
| | | ")"); |
| | | if (! backendFilter.matchesEntry(configEntry.getEntry())) |
| | | { |
| | | int msgID = MSGID_CONFIG_BACKEND_ENTRY_DOES_NOT_HAVE_BACKEND_CONFIG; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_BACKEND_ERROR_INTERACTING_WITH_BACKEND_ENTRY; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that indicates whether the |
| | | // backend should be enabled. If it does not, or if it is not set to |
| | | // "true", then skip it. |
| | | int msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_ENABLED; |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_BACKEND_ENABLED, getMessage(msgID), |
| | | false); |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledAttr = |
| | | (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | if (enabledAttr == null) |
| | | { |
| | | // The attribute is not present, so this backend will be disabled. |
| | | msgID = MSGID_CONFIG_BACKEND_NO_ENABLED_ATTR; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_ENABLED_STATE; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the backend ID. If |
| | | // it does not, then reject it. |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BACKEND_ID; |
| | | StringConfigAttribute idStub = |
| | | new StringConfigAttribute(ATTR_BACKEND_ID, getMessage(msgID), true, |
| | | false, true); |
| | | try |
| | | { |
| | | StringConfigAttribute idAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(idStub); |
| | | if (idAttr == null) |
| | | { |
| | | // The attribute is not present. We will not allow this. |
| | | msgID = MSGID_CONFIG_BACKEND_NO_BACKEND_ID; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_BACKEND_ID; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the writability |
| | | // mode. If it does not, then reject it. |
| | | LinkedHashSet<String> writabilityModes = new LinkedHashSet<String>(3); |
| | | writabilityModes.add(WritabilityMode.ENABLED.toString()); |
| | | writabilityModes.add(WritabilityMode.DISABLED.toString()); |
| | | writabilityModes.add(WritabilityMode.INTERNAL_ONLY.toString()); |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_WRITABILITY; |
| | | MultiChoiceConfigAttribute writabilityStub = |
| | | new MultiChoiceConfigAttribute(ATTR_BACKEND_WRITABILITY_MODE, |
| | | getMessage(msgID), true, false, false, |
| | | writabilityModes); |
| | | try |
| | | { |
| | | MultiChoiceConfigAttribute writabilityAttr = |
| | | (MultiChoiceConfigAttribute) |
| | | configEntry.getConfigAttribute(writabilityStub); |
| | | if (writabilityAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_WRITABILITY_MODE; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_WRITABILITY; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the set of base DNs |
| | | // for the backend. If it does not, then skip it. |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BASE_DNS; |
| | | DNConfigAttribute baseDNStub = |
| | | new DNConfigAttribute(ATTR_BACKEND_BASE_DN, getMessage(msgID), true, |
| | | true, true); |
| | | try |
| | | { |
| | | DNConfigAttribute baseDNAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseDNStub); |
| | | if (baseDNAttr == null) |
| | | { |
| | | // The attribute is not present. We will not allow this. |
| | | msgID = MSGID_CONFIG_BACKEND_NO_BASE_DNS; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | Set<DN> baseDNs = configEntry.getBackendBaseDN(); |
| | | |
| | | // See if the backend is registered with the server. If it is, then |
| | | // see what's changed and whether those changes are acceptable. |
| | | Backend backend = registeredBackends.get(configEntryDN); |
| | | Backend backend = registeredBackends.get(backendDN); |
| | | if (backend != null) |
| | | { |
| | | LinkedHashSet<DN> removedDNs = new LinkedHashSet<DN>(); |
| | |
| | | } |
| | | |
| | | LinkedHashSet<DN> addedDNs = new LinkedHashSet<DN>(); |
| | | for (DN dn : baseDNAttr.pendingValues()) |
| | | for (DN dn : baseDNs) |
| | | { |
| | | addedDNs.add(dn); |
| | | } |
| | |
| | | debugCaught(DebugLogLevel.ERROR, de); |
| | | } |
| | | |
| | | unacceptableReason.append(de.getMessage()); |
| | | unacceptableReason.add(de.getMessage()); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | debugCaught(DebugLogLevel.ERROR, de); |
| | | } |
| | | |
| | | unacceptableReason.append(de.getMessage()); |
| | | unacceptableReason.add(de.getMessage()); |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_BASE_DNS; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the class name |
| | |
| | | // that it's a valid backend implementation. There is no such attribute, |
| | | // the specified class cannot be loaded, or it does not contain a valid |
| | | // backend implementation, then log an error and skip it. |
| | | String className; |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_CLASS; |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_BACKEND_CLASS, getMessage(msgID), |
| | | true, false, true); |
| | | try |
| | | { |
| | | StringConfigAttribute classAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(classStub); |
| | | if (classAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_CLASS_ATTR; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | else |
| | | { |
| | | className = classAttr.pendingValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_GET_CLASS; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | |
| | | String className = configEntry.getBackendClass(); |
| | | try |
| | | { |
| | | Class backendClass = DirectoryServer.loadClass(className); |
| | | if (! Backend.class.isAssignableFrom(backendClass)) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_CLASS_NOT_BACKEND; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(className), |
| | | int msgID = MSGID_CONFIG_BACKEND_CLASS_NOT_BACKEND; |
| | | unacceptableReason.add(getMessage(msgID, String.valueOf(className), |
| | | String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_INSTANTIATE; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(className), |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_INSTANTIATE; |
| | | unacceptableReason.add(getMessage(msgID, String.valueOf(className), |
| | | String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration to this Directory Server component |
| | | * based on the provided changed entry. |
| | | * |
| | | * @param configEntry The configuration entry that containing the updated |
| | | * configuration for this component. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry) |
| | | public ConfigChangeResult applyConfigurationChange(BackendCfg cfg) |
| | | { |
| | | DN backendDN = configEntry.getDN(); |
| | | DN backendDN = cfg.dn(); |
| | | Backend backend = registeredBackends.get(backendDN); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | |
| | | // Check to see if this entry appears to contain a backend configuration. |
| | | // If not, log a warning and skip it. |
| | | try |
| | | { |
| | | SearchFilter backendFilter = |
| | | SearchFilter.createFilterFromString("(objectClass=" + OC_BACKEND + |
| | | ")"); |
| | | if (! backendFilter.matchesEntry(configEntry.getEntry())) |
| | | { |
| | | int msgID = MSGID_CONFIG_BACKEND_ENTRY_DOES_NOT_HAVE_BACKEND_CONFIG; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_BACKEND_ERROR_INTERACTING_WITH_BACKEND_ENTRY; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that indicates whether the |
| | | // backend should be enabled. |
| | | boolean needToEnable = false; |
| | | int msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_ENABLED; |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_BACKEND_ENABLED, getMessage(msgID), |
| | | false); |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledAttr = |
| | | (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | if (enabledAttr == null) |
| | | { |
| | | // The attribute is not present. We won't allow this. |
| | | msgID = MSGID_CONFIG_BACKEND_NO_ENABLED_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else if (enabledAttr.pendingValue()) |
| | | if (cfg.isBackendEnabled()) |
| | | { |
| | | // The backend is marked as enabled. See if that is already true. |
| | | if (backend == null) |
| | |
| | | StringBuilder failureReason = new StringBuilder(); |
| | | if (! LockFileManager.releaseLock(lockFile, failureReason)) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_RELEASE_SHARED_LOCK; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_RELEASE_SHARED_LOCK; |
| | | String message = getMessage(msgID, backend.getBackendID(), |
| | | String.valueOf(failureReason)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e2); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_RELEASE_SHARED_LOCK; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_RELEASE_SHARED_LOCK; |
| | | String message = getMessage(msgID, backend.getBackendID(), |
| | | stackTraceToSingleLineString(e2)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_ENABLED_STATE; |
| | | int msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_ENABLED_STATE; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | |
| | | |
| | | // See if the entry contains an attribute that specifies the backend ID for |
| | | // the backend. |
| | | String backendID = null; |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BACKEND_ID; |
| | | StringConfigAttribute idStub = |
| | | new StringConfigAttribute(ATTR_BACKEND_ID, getMessage(msgID), true, |
| | | false, true); |
| | | try |
| | | { |
| | | StringConfigAttribute idAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(idStub); |
| | | if (idAttr == null) |
| | | { |
| | | // The attribute is not present. We won't allow this. |
| | | msgID = MSGID_CONFIG_BACKEND_NO_BACKEND_ID; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else |
| | | { |
| | | backendID = idAttr.pendingValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_BACKEND_ID; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | String backendID = cfg.getBackendId(); |
| | | |
| | | // See if the entry contains an attribute that specifies the writability |
| | | // mode. |
| | | LinkedHashSet<String> writabilityModes = new LinkedHashSet<String>(3); |
| | | writabilityModes.add(WritabilityMode.ENABLED.toString()); |
| | | writabilityModes.add(WritabilityMode.DISABLED.toString()); |
| | | writabilityModes.add(WritabilityMode.INTERNAL_ONLY.toString()); |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_WRITABILITY; |
| | | WritabilityMode writabilityMode = null; |
| | | MultiChoiceConfigAttribute writabilityStub = |
| | | new MultiChoiceConfigAttribute(ATTR_BACKEND_WRITABILITY_MODE, |
| | | getMessage(msgID), true, false, false, |
| | | writabilityModes); |
| | | try |
| | | WritabilityMode writabilityMode = WritabilityMode.ENABLED; |
| | | BackendCfgDefn.BackendWritabilityMode bwm = |
| | | cfg.getBackendWritabilityMode(); |
| | | switch (bwm) |
| | | { |
| | | MultiChoiceConfigAttribute writabilityAttr = |
| | | (MultiChoiceConfigAttribute) |
| | | configEntry.getConfigAttribute(writabilityStub); |
| | | if (writabilityStub == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_WRITABILITY_MODE; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN))); |
| | | |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else |
| | | { |
| | | writabilityMode = |
| | | WritabilityMode.modeForName(writabilityAttr.activeValue()); |
| | | if (writabilityMode == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_INVALID_WRITABILITY_MODE; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | String.valueOf(writabilityAttr.activeValue()))); |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_WRITABILITY; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | case DISABLED: |
| | | writabilityMode = WritabilityMode.DISABLED; |
| | | break; |
| | | case ENABLED: |
| | | writabilityMode = WritabilityMode.ENABLED; |
| | | break; |
| | | case INTERNAL_ONLY: |
| | | writabilityMode = WritabilityMode.INTERNAL_ONLY; |
| | | break; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the base DNs for |
| | | // the backend. |
| | | DN[] baseDNs = null; |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BASE_DNS; |
| | | DNConfigAttribute baseDNStub = |
| | | new DNConfigAttribute(ATTR_BACKEND_BASE_DN, getMessage(msgID), true, |
| | | true, true); |
| | | try |
| | | { |
| | | DNConfigAttribute baseDNAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseDNStub); |
| | | if (baseDNAttr == null) |
| | | { |
| | | // The attribute is not present. We won't allow this. |
| | | msgID = MSGID_CONFIG_BACKEND_NO_BASE_DNS; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else |
| | | { |
| | | List<DN> baseList = baseDNAttr.pendingValues(); |
| | | baseDNs = new DN[baseList.size()]; |
| | | Set<DN> baseList = cfg.getBackendBaseDN(); |
| | | DN[] baseDNs = new DN[baseList.size()]; |
| | | baseList.toArray(baseDNs); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_BASE_DNS; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the class name |
| | |
| | | // that it's a valid backend implementation. There is no such attribute, |
| | | // the specified class cannot be loaded, or it does not contain a valid |
| | | // backend implementation, then log an error and skip it. |
| | | String className; |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_CLASS; |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_BACKEND_CLASS, getMessage(msgID), |
| | | true, false, true); |
| | | try |
| | | { |
| | | StringConfigAttribute classAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(classStub); |
| | | if (classAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_CLASS_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else |
| | | { |
| | | className = classAttr.pendingValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_GET_CLASS; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | String className = cfg.getBackendClass(); |
| | | |
| | | |
| | | // See if this backend is currently active and if so if the name of the |
| | |
| | | // It appears to be a valid backend class. We'll return that the |
| | | // change is successful, but indicate that some administrative |
| | | // action is required. |
| | | msgID = MSGID_CONFIG_BACKEND_ACTION_REQUIRED_TO_CHANGE_CLASS; |
| | | int msgID = MSGID_CONFIG_BACKEND_ACTION_REQUIRED_TO_CHANGE_CLASS; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | backend.getClass().getName(), className)); |
| | | adminActionRequired = true; |
| | |
| | | else |
| | | { |
| | | // It is not a valid backend class. This is an error. |
| | | msgID = MSGID_CONFIG_BACKEND_CLASS_NOT_BACKEND; |
| | | int msgID = MSGID_CONFIG_BACKEND_CLASS_NOT_BACKEND; |
| | | messages.add(getMessage(msgID, String.valueOf(className), |
| | | String.valueOf(backendDN))); |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_INSTANTIATE; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_INSTANTIATE; |
| | | messages.add(getMessage(msgID, String.valueOf(className), |
| | | String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | |
| | | // backend. Try to do so. |
| | | if (needToEnable) |
| | | { |
| | | Class backendClass; |
| | | try |
| | | { |
| | | Class backendClass = DirectoryServer.loadClass(className); |
| | | backendClass = DirectoryServer.loadClass(className); |
| | | backend = (Backend) backendClass.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | // It is not a valid backend class. This is an error. |
| | | msgID = MSGID_CONFIG_BACKEND_CLASS_NOT_BACKEND; |
| | | int msgID = MSGID_CONFIG_BACKEND_CLASS_NOT_BACKEND; |
| | | messages.add(getMessage(msgID, String.valueOf(className), |
| | | String.valueOf(backendDN))); |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | |
| | | StringBuilder failureReason = new StringBuilder(); |
| | | if (! LockFileManager.acquireSharedLock(lockFile, failureReason)) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | String message = getMessage(msgID, backendID, |
| | | String.valueOf(failureReason)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | String message = getMessage(msgID, backendID, |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | |
| | | |
| | | try |
| | | { |
| | | backend.initializeBackend(configEntry, baseDNs); |
| | | backend.initializeBackend( |
| | | DirectoryServer.getConfigEntry(cfg.dn()), baseDNs); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_INITIALIZE; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_INITIALIZE; |
| | | messages.add(getMessage(msgID, String.valueOf(className), |
| | | String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND; |
| | | String message = getMessage(msgID, backendID, |
| | | stackTraceToSingleLineString(e)); |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the configuration entry that will result from a proposed |
| | | * add is acceptable to this add listener. |
| | | * |
| | | * @param configEntry The configuration entry that will result from |
| | | * the requested add. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed entry is not acceptable. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry contains an acceptable |
| | | * configuration, or <CODE>false</CODE> if it does not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configAddIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | public boolean isConfigurationAddAcceptable( |
| | | BackendCfg configEntry, |
| | | List<String> unacceptableReason) |
| | | { |
| | | DN backendDN = configEntry.getDN(); |
| | | |
| | | |
| | | // Check to see if this entry appears to contain a backend configuration. |
| | | // If not then fail. |
| | | try |
| | | { |
| | | SearchFilter backendFilter = |
| | | SearchFilter.createFilterFromString("(objectClass=" + OC_BACKEND + |
| | | ")"); |
| | | if (! backendFilter.matchesEntry(configEntry.getEntry())) |
| | | { |
| | | int msgID = MSGID_CONFIG_BACKEND_ENTRY_DOES_NOT_HAVE_BACKEND_CONFIG; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_BACKEND_ERROR_INTERACTING_WITH_BACKEND_ENTRY; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that indicates whether the |
| | | // backend should be enabled. If it does not, or if it is not set to |
| | | // "true", then skip it. |
| | | int msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_ENABLED; |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_BACKEND_ENABLED, getMessage(msgID), |
| | | false); |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledAttr = |
| | | (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | if (enabledAttr == null) |
| | | { |
| | | // The attribute is not present. We will not allow this. |
| | | msgID = MSGID_CONFIG_BACKEND_NO_ENABLED_ATTR; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_ENABLED_STATE; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | DN backendDN = configEntry.dn(); |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the backend ID. If |
| | | // it does not, then skip it. |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BACKEND_ID; |
| | | StringConfigAttribute idStub = |
| | | new StringConfigAttribute(ATTR_BACKEND_ID, getMessage(msgID), true, |
| | | false, true); |
| | | try |
| | | { |
| | | StringConfigAttribute idAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(idStub); |
| | | if (idAttr == null) |
| | | { |
| | | // The attribute is not present. We will not allow this. |
| | | msgID = MSGID_CONFIG_BACKEND_NO_BACKEND_ID; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | else |
| | | { |
| | | String backendID = idAttr.activeValue(); |
| | | String backendID = configEntry.getBackendId(); |
| | | if (DirectoryServer.hasBackend(backendID)) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_DUPLICATE_BACKEND_ID; |
| | | unacceptableReason.append(getMessage(msgID, |
| | | int msgID = MSGID_CONFIG_BACKEND_DUPLICATE_BACKEND_ID; |
| | | unacceptableReason.add(getMessage(msgID, |
| | | String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_BACKEND_ID; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the writability |
| | | // mode. If it does not, then reject it. |
| | | LinkedHashSet<String> writabilityModes = new LinkedHashSet<String>(3); |
| | | writabilityModes.add(WritabilityMode.ENABLED.toString()); |
| | | writabilityModes.add(WritabilityMode.DISABLED.toString()); |
| | | writabilityModes.add(WritabilityMode.INTERNAL_ONLY.toString()); |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_WRITABILITY; |
| | | MultiChoiceConfigAttribute writabilityStub = |
| | | new MultiChoiceConfigAttribute(ATTR_BACKEND_WRITABILITY_MODE, |
| | | getMessage(msgID), true, false, false, |
| | | writabilityModes); |
| | | try |
| | | { |
| | | MultiChoiceConfigAttribute writabilityAttr = |
| | | (MultiChoiceConfigAttribute) |
| | | configEntry.getConfigAttribute(writabilityStub); |
| | | if (writabilityAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_WRITABILITY_MODE; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_WRITABILITY; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the set of base DNs |
| | | // for the backend. If it does not, then skip it. |
| | | List<DN> baseDNs = null; |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BASE_DNS; |
| | | DNConfigAttribute baseDNStub = |
| | | new DNConfigAttribute(ATTR_BACKEND_BASE_DN, getMessage(msgID), true, |
| | | true, true); |
| | | try |
| | | { |
| | | DNConfigAttribute baseDNAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseDNStub); |
| | | if (baseDNAttr == null) |
| | | { |
| | | // The attribute is not present. We will not allow this. |
| | | msgID = MSGID_CONFIG_BACKEND_NO_BASE_DNS; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | else |
| | | { |
| | | baseDNs = baseDNAttr.pendingValues(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_BASE_DNS; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | Set<DN> baseList = configEntry.getBackendBaseDN(); |
| | | DN[] baseDNs = new DN[baseList.size()]; |
| | | baseList.toArray(baseDNs); |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the class name |
| | |
| | | // that it's a valid backend implementation. There is no such attribute, |
| | | // the specified class cannot be loaded, or it does not contain a valid |
| | | // backend implementation, then log an error and skip it. |
| | | String className; |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_CLASS; |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_BACKEND_CLASS, getMessage(msgID), |
| | | true, false, true); |
| | | try |
| | | { |
| | | StringConfigAttribute classAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(classStub); |
| | | if (classAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_CLASS_ATTR; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | else |
| | | { |
| | | className = classAttr.pendingValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_GET_CLASS; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | String className = configEntry.getBackendClass(); |
| | | |
| | | Backend backend; |
| | | try |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_INSTANTIATE; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(className), |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_INSTANTIATE; |
| | | unacceptableReason.add(getMessage(msgID, String.valueOf(className), |
| | | String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | |
| | | |
| | | // If the backend is a configurable component, then make sure that its |
| | | // configuration is valid. |
| | | if (backend instanceof ConfigurableComponent) |
| | | { |
| | | ConfigurableComponent cc = (ConfigurableComponent) backend; |
| | | LinkedList<String> errorMessages = new LinkedList<String>(); |
| | | if (! cc.hasAcceptableConfiguration(configEntry, errorMessages)) |
| | | { |
| | | if (errorMessages.isEmpty()) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_UNACCEPTABLE_CONFIG; |
| | | unacceptableReason.append(getMessage(msgID, |
| | | String.valueOf(configEntryDN))); |
| | | } |
| | | else |
| | | { |
| | | Iterator<String> iterator = errorMessages.iterator(); |
| | | unacceptableReason.append(iterator.next()); |
| | | while (iterator.hasNext()) |
| | | { |
| | | unacceptableReason.append(" "); |
| | | unacceptableReason.append(iterator.next()); |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | } |
| | | // if (backend instanceof ConfigurableComponent) |
| | | // { |
| | | // ConfigurableComponent cc = (ConfigurableComponent) backend; |
| | | // LinkedList<String> errorMessages = new LinkedList<String>(); |
| | | // if (! cc.hasAcceptableConfiguration(configEntry, errorMessages)) |
| | | // { |
| | | // if (errorMessages.isEmpty()) |
| | | // { |
| | | // int msgID = MSGID_CONFIG_BACKEND_UNACCEPTABLE_CONFIG; |
| | | // unacceptableReason.add(getMessage(msgID, |
| | | // String.valueOf(configEntryDN))); |
| | | // } |
| | | // else |
| | | // { |
| | | // Iterator<String> iterator = errorMessages.iterator(); |
| | | // unacceptableReason.add(iterator.next()); |
| | | // while (iterator.hasNext()) |
| | | // { |
| | | // unacceptableReason.add(" "); |
| | | // unacceptableReason.add(iterator.next()); |
| | | // } |
| | | // } |
| | | // |
| | | // return false; |
| | | // } |
| | | // } |
| | | |
| | | |
| | | // Make sure that all of the base DNs are acceptable for use in the server. |
| | |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | unacceptableReason.append(de.getMessage()); |
| | | unacceptableReason.add(de.getMessage()); |
| | | return false; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | unacceptableReason.append(stackTraceToSingleLineString(e)); |
| | | unacceptableReason.add(stackTraceToSingleLineString(e)); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration based on the provided added entry. |
| | | * |
| | | * @param configEntry The new configuration entry that contains the |
| | | * configuration to apply. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry) |
| | | public ConfigChangeResult applyConfigurationAdd(BackendCfg cfg) |
| | | { |
| | | DN backendDN = configEntry.getDN(); |
| | | DN backendDN = cfg.dn(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | |
| | | |
| | | // Register as a change listener for this backend entry so that we will |
| | | // be notified of any changes that may be made to it. |
| | | configEntry.registerChangeListener(this); |
| | | |
| | | |
| | | // Check to see if this entry appears to contain a backend configuration. |
| | | // If not then fail. |
| | | try |
| | | { |
| | | SearchFilter backendFilter = |
| | | SearchFilter.createFilterFromString("(objectClass=" + OC_BACKEND + |
| | | ")"); |
| | | if (! backendFilter.matchesEntry(configEntry.getEntry())) |
| | | { |
| | | int msgID = MSGID_CONFIG_BACKEND_ENTRY_DOES_NOT_HAVE_BACKEND_CONFIG; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_BACKEND_ERROR_INTERACTING_WITH_BACKEND_ENTRY; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | cfg.addChangeListener(this); |
| | | |
| | | |
| | | // See if the entry contains an attribute that indicates whether the |
| | | // backend should be enabled. If it does not, or if it is not set to |
| | | // "true", then skip it. |
| | | int msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_ENABLED; |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_BACKEND_ENABLED, getMessage(msgID), |
| | | false); |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledAttr = |
| | | (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | if (enabledAttr == null) |
| | | { |
| | | // The attribute is not present, so this backend will be disabled. We |
| | | // will log a message to indicate that it won't be enabled and return. |
| | | msgID = MSGID_CONFIG_BACKEND_NO_ENABLED_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, message, msgID); |
| | | messages.add(message); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else if (! enabledAttr.activeValue()) |
| | | if (!cfg.isBackendEnabled()) |
| | | { |
| | | // The backend is explicitly disabled. We will log a message to |
| | | // indicate that it won't be enabled and return. |
| | | msgID = MSGID_CONFIG_BACKEND_DISABLED; |
| | | int msgID = MSGID_CONFIG_BACKEND_DISABLED; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.INFORMATIONAL, message, msgID); |
| | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_ENABLED_STATE; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the backend ID. If |
| | | // it does not, then skip it. |
| | | String backendID; |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BACKEND_ID; |
| | | StringConfigAttribute idStub = |
| | | new StringConfigAttribute(ATTR_BACKEND_ID, getMessage(msgID), true, |
| | | false, true); |
| | | try |
| | | { |
| | | StringConfigAttribute idAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(idStub); |
| | | if (idAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_BACKEND_ID; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, message, msgID); |
| | | messages.add(message); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else |
| | | { |
| | | backendID = idAttr.pendingValue(); |
| | | String backendID = cfg.getBackendId(); |
| | | if (DirectoryServer.hasBackend(backendID)) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_DUPLICATE_BACKEND_ID; |
| | | int msgID = MSGID_CONFIG_BACKEND_DUPLICATE_BACKEND_ID; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, message, msgID); |
| | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_BACKEND_ID; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the writability |
| | | // mode. |
| | | LinkedHashSet<String> writabilityModes = new LinkedHashSet<String>(3); |
| | | writabilityModes.add(WritabilityMode.ENABLED.toString()); |
| | | writabilityModes.add(WritabilityMode.DISABLED.toString()); |
| | | writabilityModes.add(WritabilityMode.INTERNAL_ONLY.toString()); |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_WRITABILITY; |
| | | WritabilityMode writabilityMode = null; |
| | | MultiChoiceConfigAttribute writabilityStub = |
| | | new MultiChoiceConfigAttribute(ATTR_BACKEND_WRITABILITY_MODE, |
| | | getMessage(msgID), true, false, false, |
| | | writabilityModes); |
| | | try |
| | | WritabilityMode writabilityMode = WritabilityMode.ENABLED; |
| | | BackendCfgDefn.BackendWritabilityMode bwm = |
| | | cfg.getBackendWritabilityMode(); |
| | | switch (bwm) |
| | | { |
| | | MultiChoiceConfigAttribute writabilityAttr = |
| | | (MultiChoiceConfigAttribute) |
| | | configEntry.getConfigAttribute(writabilityStub); |
| | | if (writabilityAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_WRITABILITY_MODE; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN))); |
| | | |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else |
| | | { |
| | | writabilityMode = |
| | | WritabilityMode.modeForName(writabilityAttr.activeValue()); |
| | | if (writabilityMode == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_INVALID_WRITABILITY_MODE; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | String.valueOf(writabilityAttr.activeValue()))); |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_WRITABILITY; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | case DISABLED: |
| | | writabilityMode = WritabilityMode.DISABLED; |
| | | break; |
| | | case ENABLED: |
| | | writabilityMode = WritabilityMode.ENABLED; |
| | | break; |
| | | case INTERNAL_ONLY: |
| | | writabilityMode = WritabilityMode.INTERNAL_ONLY; |
| | | break; |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the base DNs for |
| | | // the entry. If it does not, then skip it. |
| | | DN[] baseDNs = null; |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BASE_DNS; |
| | | DNConfigAttribute baseDNStub = |
| | | new DNConfigAttribute(ATTR_BACKEND_BASE_DN, getMessage(msgID), |
| | | true, true, true); |
| | | try |
| | | { |
| | | DNConfigAttribute baseDNAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseDNStub); |
| | | if (baseDNAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_BASE_DNS; |
| | | String message = getMessage(msgID, String.valueOf(backendDN)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, message, msgID); |
| | | messages.add(message); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else |
| | | { |
| | | List<DN> dnList = baseDNAttr.pendingValues(); |
| | | baseDNs = new DN[dnList.size()]; |
| | | Set<DN> dnList = cfg.getBackendBaseDN(); |
| | | DN[] baseDNs = new DN[dnList.size()]; |
| | | dnList.toArray(baseDNs); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_UNABLE_TO_DETERMINE_BASE_DNS; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // See if the entry contains an attribute that specifies the class name |
| | |
| | | // that it's a valid backend implementation. There is no such attribute, |
| | | // the specified class cannot be loaded, or it does not contain a valid |
| | | // backend implementation, then log an error and skip it. |
| | | String className; |
| | | msgID = MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_CLASS; |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_BACKEND_CLASS, getMessage(msgID), |
| | | true, false, true); |
| | | try |
| | | { |
| | | StringConfigAttribute classAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(classStub); |
| | | if (classAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_NO_CLASS_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else |
| | | { |
| | | className = classAttr.activeValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_GET_CLASS; |
| | | messages.add(getMessage(msgID, String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | String className = cfg.getBackendClass(); |
| | | Class backendClass; |
| | | |
| | | Backend backend; |
| | | try |
| | | { |
| | | Class backendClass = DirectoryServer.loadClass(className); |
| | | backendClass = DirectoryServer.loadClass(className); |
| | | backend = (Backend) backendClass.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_INSTANTIATE; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_INSTANTIATE; |
| | | messages.add(getMessage(msgID, String.valueOf(className), |
| | | String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | |
| | | StringBuilder failureReason = new StringBuilder(); |
| | | if (! LockFileManager.acquireSharedLock(lockFile, failureReason)) |
| | | { |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | String message = getMessage(msgID, backendID, |
| | | String.valueOf(failureReason)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK; |
| | | String message = getMessage(msgID, backendID, |
| | | stackTraceToSingleLineString(e)); |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | |
| | | // Perform the necessary initialization for the backend entry. |
| | | try |
| | | { |
| | | backend.initializeBackend(configEntry, baseDNs); |
| | | backend.initializeBackend( |
| | | DirectoryServer.getConfigEntry(cfg.dn()), baseDNs); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_INITIALIZE; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_INITIALIZE; |
| | | messages.add(getMessage(msgID, String.valueOf(className), |
| | | String.valueOf(backendDN), |
| | | stackTraceToSingleLineString(e))); |
| | |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND; |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND; |
| | | String message = getMessage(msgID, backendID, |
| | | stackTraceToSingleLineString(e)); |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether it is acceptable to remove the provided configuration |
| | | * entry. |
| | | * |
| | | * @param configEntry The configuration entry that will be removed |
| | | * from the configuration. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed delete is not acceptable. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry may be removed from the |
| | | * configuration, or <CODE>false</CODE> if not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configDeleteIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | public boolean isConfigurationDeleteAcceptable( |
| | | BackendCfg configEntry, |
| | | List<String> unacceptableReason) |
| | | { |
| | | DN backendDN = configEntry.getDN(); |
| | | DN backendDN = configEntry.dn(); |
| | | |
| | | |
| | | // See if this backend config manager has a backend registered with the |
| | |
| | | else |
| | | { |
| | | int msgID = MSGID_CONFIG_BACKEND_CANNOT_REMOVE_BACKEND_WITH_SUBORDINATES; |
| | | unacceptableReason.append(getMessage(msgID, String.valueOf(backendDN))); |
| | | unacceptableReason.add(getMessage(msgID, String.valueOf(backendDN))); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration based on the provided deleted entry. |
| | | * |
| | | * @param configEntry The new configuration entry that has been deleted. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry) |
| | | public ConfigChangeResult applyConfigurationDelete(BackendCfg configEntry) |
| | | { |
| | | DN backendDN = configEntry.getDN(); |
| | | DN backendDN = configEntry.dn(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | |
| | | } |
| | | |
| | | DirectoryServer.deregisterBackend(backend); |
| | | configEntry.deregisterChangeListener(this); |
| | | configEntry.removeChangeListener(this); |
| | | |
| | | // Remove the shared lock for this backend. |
| | | try |
| | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Gets the configuration corresponding to a config entry. |
| | | * |
| | | * @param <S> |
| | | * The type of server configuration. |
| | | * @param definition |
| | | * The required definition of the required managed object. |
| | | * @param configEntry |
| | | * A configuration entry. |
| | | * @return Returns the server-side configuration. |
| | | * @throws ConfigException |
| | | * If the entry could not be decoded. |
| | | */ |
| | | public static <S extends Configuration> S getConfiguration( |
| | | AbstractManagedObjectDefinition<?, S> definition, ConfigEntry configEntry) |
| | | throws ConfigException { |
| | | |
| | | try { |
| | | ServerManagedObject<? extends S> mo = ServerManagedObject |
| | | .decode(ManagedObjectPath.emptyPath(), definition, |
| | | configEntry); |
| | | return mo.getConfiguration(); |
| | | } catch (DefinitionDecodingException e) { |
| | | throw ConfigExceptionFactory.getInstance() |
| | | .createDecodingExceptionAdaptor(configEntry.getDN(), e); |
| | | } catch (ServerManagedObjectDecodingException e) { |
| | | throw ConfigExceptionFactory.getInstance() |
| | | .createDecodingExceptionAdaptor(e); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Gets the backend configuration corresponding to a backend config entry. |
| | | * |
| | | * @param configEntry A backend config entry. |
| | | * @return Returns the backend configuration. |
| | | * @throws ConfigException If the config entry could not be decoded. |
| | | */ |
| | | public static BackendCfg getBackendCfg(ConfigEntry configEntry) |
| | | throws ConfigException |
| | | { |
| | | return getConfiguration(BackendCfgDefn.getInstance(), configEntry); |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | | |
| | |
| | | baseName = "___NAME___"; |
| | | } |
| | | |
| | | lines.add(" <adm:property name=\"" + baseName + "\" mandatory=\"" + |
| | | String.valueOf(attr.isRequired()) + "\">"); |
| | | lines.add(" <adm:property name=\"" + baseName + "\""); |
| | | lines.add(" mandatory=\"" |
| | | + String.valueOf(attr.isRequired()) + "\""); |
| | | lines.add(" multi-valued=\"" |
| | | + String.valueOf(attr.isMultiValued()) + "\">"); |
| | | lines.add(" <adm:synopsis>"); |
| | | lines.add(" ___SYNOPSIS___"); |
| | | lines.add(" </adm:synopsis>"); |
| | |
| | | } |
| | | |
| | | lines.add(" </adm:description>"); |
| | | if (attr.requiresAdminAction()) |
| | | { |
| | | lines.add(" <adm:requires-admin-action>"); |
| | | lines.add(" <adm:server-restart/>"); |
| | | lines.add(" </adm:requires-admin-action>"); |
| | | } |
| | | if (!attr.isRequired()) |
| | | { |
| | | lines.add(" <adm:default-behavior>"); |
| | | lines.add(" <adm:undefined/>"); |
| | | lines.add(" </adm:default-behavior>"); |
| | | } |
| | | lines.add(" <adm:syntax>"); |
| | | |
| | | if (attr instanceof org.opends.server.config.BooleanConfigAttribute) |
| | |
| | | } |
| | | |
| | | |
| | | // Save this configuration for future reference. |
| | | currentConfig = config; |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | } |
| | |
| | | + "retrieve the managed object configuration entry %s: %s."); |
| | | |
| | | registerMessage(MSGID_ADMIN_MANAGED_OBJECT_DOES_NOT_EXIST, |
| | | "The the managed object configuration entry %s does not " |
| | | "The managed object configuration entry %s does not " |
| | | + "appear to exist in the Directory Server " |
| | | + "configuration. This is a required entry."); |
| | | |
| | |
| | | * The message ID for the message that will be used if an attempt is made to |
| | | * normalize the value for an attribute type that does not have an equality |
| | | * matching rule. This takes two arguments, which are the value to normalize |
| | | * and the the name of the attribute type. |
| | | * and the name of the attribute type. |
| | | */ |
| | | public static final int MSGID_ATTR_TYPE_NORMALIZE_NO_MR = |
| | | CATEGORY_MASK_CORE | SEVERITY_MASK_MILD_ERROR | 125; |
| | |
| | | "The Directory Server has completed the configuration " + |
| | | "bootstrapping process."); |
| | | registerMessage(MSGID_CANNOT_LOAD_CONFIG_HANDLER_CLASS, |
| | | "Unable to load class %s to serve as the the Directory " + |
| | | "Unable to load class %s to serve as the Directory " + |
| | | "Server configuration handler: %s."); |
| | | registerMessage(MSGID_CANNOT_INSTANTIATE_CONFIG_HANDLER, |
| | | "Unable to create an instance of class %s to serve as " + |
| | |
| | | registerMessage(MSGID_ADD_ASSERTION_FAILED, |
| | | "Entry %s cannot be added because the request contained " + |
| | | "an LDAP assertion control and the associated filter did " + |
| | | "not match the contents of the the provided entry."); |
| | | "not match the contents of the provided entry."); |
| | | registerMessage(MSGID_ADD_CANNOT_PROCESS_ASSERTION_FILTER, |
| | | "Entry %s cannot be added because the request contained " + |
| | | "an LDAP assertion control, but an error occurred while " + |
| | |
| | | public static final int MSGID_JEB_OPEN_ENV_FAIL = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_SEVERE_ERROR | 3; |
| | | |
| | | /* |
| | | public static final int MSGID_JEB_EMPTY_MESSAGE = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 4; |
| | | */ |
| | | |
| | | /** |
| | | * The message ID of an error indicating that the current highest entry ID |
| | | * in the database could not be determined. This message takes no arguments. |
| | |
| | | public static final int MSGID_JEB_ENTRY_DATABASE_CORRUPT = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_SEVERE_ERROR | 12; |
| | | |
| | | /* |
| | | public static final int MSGID_JEB_SUFFIXES_NOT_SPECIFIED = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_SEVERE_ERROR | 13; |
| | | */ |
| | | |
| | | /** |
| | | * The message ID of an error indicating that an exception was raised by the |
| | | * JE library while accessing the database. This message takes one string |
| | |
| | | public static final int MSGID_JEB_DATABASE_EXCEPTION = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_SEVERE_ERROR | 14; |
| | | |
| | | /* |
| | | public static final int MSGID_JEB_JMX_CANNOT_REGISTER_MBEAN = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_SEVERE_ERROR | 15; |
| | | */ |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the attribute type of an attribute index. |
| | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the database cache size as a percentage of Java VM heap size. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_DATABASE_CACHE_PERCENT = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 19; |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the database cache size as an approximate number of bytes. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_DATABASE_CACHE_SIZE = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 20; |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * whether data updated by a database transaction is forced to disk. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_DATABASE_TXN_NO_SYNC = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 21; |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * whether data updated by a database transaction is written |
| | | * from the Java VM to the O/S. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_DATABASE_TXN_WRITE_NO_SYNC = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 22; |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * whether the database background cleaner thread runs. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_DATABASE_RUN_CLEANER = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 23; |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the backend entry limit for indexing. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_BACKEND_INDEX_ENTRY_LIMIT = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 24; |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the substring length for an attribute index. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_INDEX_SUBSTRING_LENGTH = |
| | |
| | | public static final int MSGID_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_SEVERE_ERROR | 26; |
| | | |
| | | /* |
| | | public static final int MSGID_JEB_CANNOT_ACQUIRE_LOCK = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_MILD_ERROR | 27; |
| | | */ |
| | | |
| | | /** |
| | | * The message ID of an error indicating that an unchecked exception was |
| | | * raised during a database transaction. This message takes no arguments. |
| | |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_NOTICE | 33; |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the minimum percentage of log space that must be used in log files. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_CLEANER_MIN_UTILIZATION = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 34; |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the subtree delete size limit. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_SUBTREE_DELETE_SIZE_LIMIT = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 35; |
| | | |
| | | |
| | | /** |
| | | * The message ID of an error indicating that the JE backend configuration |
| | | * contains more than one configuration entry of a given object class where |
| | | * only one entry of that object class is allowed. This message takes two |
| | |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_MILD_ERROR | 54; |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the pathname of the directory for import temporary files. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_IMPORT_TEMP_DIRECTORY = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 55; |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the amount of memory available for import buffering. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_IMPORT_BUFFER_SIZE = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 56; |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the import queue size. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_IMPORT_QUEUE_SIZE = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 57; |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the number of import worker threads. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_IMPORT_THREAD_COUNT = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 58; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the database cache eviction algorithm. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_EVICTOR_LRU_ONLY = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 59; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the number of nodes in one scan of the database cache evictor. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_EVICTOR_NODES_PER_SCAN = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 60; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to log the size of the database cache after preloading. |
| | | */ |
| | | public static final int MSGID_JEB_CACHE_SIZE_AFTER_PRELOAD = |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the maximum time to spend preloading the database cache. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_PRELOAD_TIME_LIMIT = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 62; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an error occurs while |
| | | * attempting to obtain the MAC provider for the backend backup. This takes |
| | | * two arguments, which are the name of the desired MAC algorithm and a string |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * whether entries should be compressed in the database. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_ENTRIES_COMPRESSED = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 80; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the maximum size of each individual JE log file, in bytes. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_DATABASE_LOG_FILE_MAX = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 81; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to log an informational message in the backup process. |
| | | * This message takes one argument, the name of a file that was not changed |
| | | * since the previous backup. |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * whether the logging file handler will be on or off. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_LOGGING_FILE_HANDLER_ON = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 113; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the trace log message level. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_LOGGING_LEVEL = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 114; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * how many bytes are written to the log before the checkpointer runs. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_CHECKPOINT_BYTES_INTERVAL = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 115; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the amount of time between runs of the checkpointer. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_CHECKPOINT_WAKEUP_INTERVAL = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 116; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the number of times a database transaction will be retried after it is |
| | | * aborted due to deadlock with another thread. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_DEADLOCK_RETRY_LIMIT = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 117; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the number of database lock tables. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_NUM_LOCK_TABLES = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 118; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to log an informational message in the import process. |
| | | * This message takes one argument, a string representation of the JE |
| | | * environment configuration properties. |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the import pass size. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_IMPORT_PASS_SIZE = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 120; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to indicate that an LDIF import pass has completed and |
| | | * it is time to begin the intermediate index merge process. This takes a |
| | | * single argument, which is the pass number that has completed. |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID used to describe the attribute which configures |
| | | * the number of threads allocated by the cleaner for log file processing. |
| | | */ |
| | | public static final int MSGID_CONFIG_DESCRIPTION_NUM_CLEANER_THREADS = |
| | | CATEGORY_MASK_JEB | SEVERITY_MASK_INFORMATIONAL | 125; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID of an error indicating the version of DatabaseEntry is |
| | | * incompatible and can not be decoded. |
| | | */ |
| | |
| | | |
| | | /** |
| | | * The message ID used to indicate that another rebuild process for an index |
| | | * is alreadly in progress. This message takes the name of the conflicting |
| | | * is already in progress. This message takes the name of the conflicting |
| | | * index as the argument. |
| | | */ |
| | | public static final int MSGID_JEB_REBUILD_INDEX_CONFLICT = |
| | |
| | | "The backend does not contain that part of the Directory " + |
| | | "Information Tree pertaining to the entry " + |
| | | "'%s'."); |
| | | |
| | | registerMessage(MSGID_JEB_OPEN_DATABASE_FAIL, |
| | | "The database could not be opened: %s."); |
| | | |
| | | registerMessage(MSGID_JEB_OPEN_ENV_FAIL, |
| | | "The database environment could not be opened: %s."); |
| | | |
| | | /* |
| | | registerMessage(MSGID_JEB_EMPTY_MESSAGE, |
| | | ""); |
| | | */ |
| | | |
| | | registerMessage(MSGID_JEB_HIGHEST_ID_FAIL, |
| | | "The database highest entry identifier could not be " + |
| | | "determined."); |
| | | |
| | | registerMessage(MSGID_JEB_FUNCTION_NOT_SUPPORTED, |
| | | "The requested operation is not supported by this " + |
| | | "backend."); |
| | | |
| | | registerMessage(MSGID_JEB_CREATE_FAIL, |
| | | "The backend database directory could not be created: %s."); |
| | | |
| | | registerMessage(MSGID_JEB_REMOVE_FAIL, |
| | | "The backend database files could not be removed: %s."); |
| | | |
| | | registerMessage(MSGID_JEB_DIRECTORY_INVALID, |
| | | "The backend database directory '%s' is not a valid " + |
| | | "directory."); |
| | | |
| | | registerMessage(MSGID_JEB_MISSING_DN2ID_RECORD, |
| | | "The DN database does not contain a record for '%s'."); |
| | | |
| | | registerMessage(MSGID_JEB_MISSING_ID2ENTRY_RECORD, |
| | | "The entry database does not contain a record for ID %s."); |
| | | |
| | | registerMessage(MSGID_JEB_ENTRY_DATABASE_CORRUPT, |
| | | "The entry database does not contain a valid record " + |
| | | "for ID %s."); |
| | | |
| | | /* |
| | | registerMessage(MSGID_JEB_SUFFIXES_NOT_SPECIFIED, |
| | | "No suffixes specified for the backend."); |
| | | */ |
| | | |
| | | registerMessage(MSGID_JEB_DATABASE_EXCEPTION, |
| | | "Database exception: %s"); |
| | | |
| | | /* |
| | | registerMessage(MSGID_JEB_JMX_CANNOT_REGISTER_MBEAN, |
| | | "The backend could not register a JMX MBean for " + |
| | | "the database in directory '%s': " + |
| | | "%s "); |
| | | */ |
| | | |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_BACKEND_INDEX_ENTRY_LIMIT, |
| | | "A performance tuning parameter for attribute indexes. " + |
| | | "The default entry limit for attribute indexes, where " + |
| | | "a value of 0 means there is no limit. " + |
| | | "When the number of entries " + |
| | | "matching an index value reaches the limit, the " + |
| | | "value is no longer maintained in the index."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_INDEX_ATTRIBUTE, |
| | | "The attribute type name of the attribute index."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_INDEX_TYPE, |
| | |
| | | "When the number of entries " + |
| | | "matching an index value reaches the limit, the " + |
| | | "value is no longer maintained in the index."); |
| | | |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_CACHE_PERCENT, |
| | | "The percentage of JVM memory to allocate to the database" + |
| | | " cache."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_CACHE_SIZE, |
| | | "The approximate amount of JVM memory to allocate to the " + |
| | | "database cache. The default value of zero indicates " + |
| | | "that the database cache is sized by the cachePercent " + |
| | | "configuration attribute. A non-zero value overrides the " + |
| | | "cachePercent configuration attribute."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_TXN_NO_SYNC, |
| | | "If true, do not write or synchronously flush the " + |
| | | "database log on transaction commit. This means that " + |
| | | "transactions exhibit the ACI (Atomicity, Consistency, " + |
| | | "and Isolation) properties, but not D (Durability); " + |
| | | "that is, database integrity is maintained, but if the " + |
| | | "JVM or operating system fails, it is possible some " + |
| | | "number of the most recently committed transactions " + |
| | | "may be undone during recovery. The number of " + |
| | | "transactions at risk is governed by how many " + |
| | | "updates fit into a log buffer, how often the " + |
| | | "operating system flushes dirty buffers to disk, and " + |
| | | "how often the database environment is checkpointed."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_TXN_WRITE_NO_SYNC, |
| | | "If true, write but do not synchronously flush the " + |
| | | "database log on transaction commit. This means that " + |
| | | "transactions exhibit the ACI (Atomicity, Consistency, " + |
| | | "and Isolation) properties, but not D (Durability); " + |
| | | "that is, database integrity is maintained, but if the " + |
| | | "JVM or operating system fails, it is possible some " + |
| | | "number of the most recently committed transactions may " + |
| | | "be undone during recovery. The number of transactions " + |
| | | "at risk is governed by how often the operating system " + |
| | | "flushes dirty buffers to disk, and how often the " + |
| | | "database environment is checkpointed. " + |
| | | "The motivation for this attribute is to provide a " + |
| | | "transaction that has more durability than asynchronous " + |
| | | "(nosync) transactions, but has higher performance than " + |
| | | "synchronous transactions. "); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_RUN_CLEANER, |
| | | "If false, do not run the background cleaner thread " + |
| | | "responsible for freeing up disk space consumed by " + |
| | | "data records no longer in use."); |
| | | |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_INDEX_SUBSTRING_LENGTH, |
| | | "The length of substrings in a substring index."); |
| | | |
| | | registerMessage(MSGID_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE, |
| | | "The attribute '%s' cannot have indexing of type '%s' " + |
| | | "because it does not have a corresponding matching rule."); |
| | | |
| | | /* |
| | | registerMessage(MSGID_JEB_CANNOT_ACQUIRE_LOCK, |
| | | "Unable to acquire a lock on the entry '%s'."); |
| | | */ |
| | | |
| | | registerMessage(MSGID_JEB_UNCHECKED_EXCEPTION, |
| | | "Unchecked exception during database transaction."); |
| | | |
| | | registerMessage(MSGID_JEB_CLEAN_DATABASE_START, |
| | | "Starting database cleaning on %d log file(s) in '%s'."); |
| | | registerMessage(MSGID_JEB_CLEAN_DATABASE_MARKED, |
| | |
| | | registerMessage(MSGID_JEB_CLEAN_DATABASE_FINISH, |
| | | "Finished database cleaning; " + |
| | | "now %d log file(s) remaining."); |
| | | |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_CLEANER_MIN_UTILIZATION, |
| | | "A minimum log utilization property to determine how " + |
| | | "much database cleaning to perform. Changes to this " + |
| | | "property do not take effect until the backend is " + |
| | | "restarted. The log files " + |
| | | "contain both obsolete and utilized records. Obsolete " + |
| | | "records are records that are no longer in use, either " + |
| | | "because they have been modified or because they have " + |
| | | "been deleted. Utilized records are those records that " + |
| | | "are currently in use. This property identifies the " + |
| | | "minimum percentage of log space that must be used by " + |
| | | "utilized records. If this minimum percentage is not " + |
| | | "met, then log files are cleaned until the minimum " + |
| | | "percentage is met."); |
| | | |
| | | registerMessage(MSGID_JEB_SUBTREE_DELETE_SIZE_LIMIT_EXCEEDED, |
| | | "Exceeded the administrative limit on the number of " + |
| | | "entries that may be deleted in a subtree delete " + |
| | |
| | | "in the subtree have been deleted."); |
| | | registerMessage(MSGID_JEB_DELETED_ENTRY_COUNT, |
| | | "The number of entries deleted was %d."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_SUBTREE_DELETE_SIZE_LIMIT, |
| | | "The maximum number of entries that can be deleted " + |
| | | "by a delete entry operation with the subtree delete " + |
| | | "control specified. To delete subtrees containing more " + |
| | | "entries than this value, the operation must be repeated " + |
| | | "as many times as necessary to complete the subtree " + |
| | | "delete."); |
| | | |
| | | registerMessage(MSGID_JEB_DUPLICATE_CONFIG_ENTRY, |
| | | "The configuration entry '%s' will be ignored. " + |
| | | "Only one configuration entry with object class '%s' is " + |
| | |
| | | "because it specifies the attribute type '%s', " + |
| | | "which has already been defined in another " + |
| | | "index configuration entry."); |
| | | |
| | | registerMessage(MSGID_JEB_IO_ERROR, |
| | | "I/O error during backend operation: %s"); |
| | | |
| | | /* |
| | | registerMessage(MSGID_JEB_INDEX_THREAD_EXCEPTION, |
| | | "An index worker thread raised an exception: %s"); |
| | | */ |
| | | |
| | | registerMessage(MSGID_JEB_BACKEND_STARTED, |
| | | "A database backend containing %d entries has started."); |
| | | |
| | | registerMessage(MSGID_JEB_IMPORT_PARENT_NOT_FOUND, |
| | | "The parent entry '%s' does not exist."); |
| | | registerMessage(MSGID_JEB_IMPORT_ENTRY_EXISTS, |
| | | "The entry exists and the import options do not " + |
| | | "allow it to be replaced."); |
| | | |
| | | registerMessage(MSGID_JEB_ATTRIBUTE_INDEX_NOT_CONFIGURED, |
| | | "There is no index configured for attribute type '%s'."); |
| | | |
| | | registerMessage(MSGID_JEB_SEARCH_NO_SUCH_OBJECT, |
| | | "The search base entry '%s' does not exist."); |
| | | registerMessage(MSGID_JEB_ADD_NO_SUCH_OBJECT, |
| | |
| | | registerMessage(MSGID_JEB_NEW_SUPERIOR_NO_SUCH_OBJECT, |
| | | "The entry cannot be moved because the new parent " + |
| | | "entry '%s' does not exist."); |
| | | |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_IMPORT_TEMP_DIRECTORY, |
| | | "The pathname of a directory to hold temporary working " + |
| | | "files generated during an import process."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_IMPORT_BUFFER_SIZE, |
| | | "The amount of memory that is available to an import " + |
| | | "process for its buffers."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_IMPORT_QUEUE_SIZE, |
| | | "The maximum number of entries that can be on the import " + |
| | | "queue waiting to be processed."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_IMPORT_THREAD_COUNT, |
| | | "The number of worker threads that will be created to " + |
| | | "import entries from LDIF."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_IMPORT_PASS_SIZE, |
| | | "The maximum number of entries that can be processed in " + |
| | | "a single pass before index merging occurs."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_EVICTOR_LRU_ONLY, |
| | | "Changes to this property do not take effect until the " + |
| | | "backend is restarted. " + |
| | | "The default database cache eviction algorithm is LRU " + |
| | | "(least recently used) and the default setting for the " + |
| | | "lruOnly parameter is true. With the default algorithm, " + |
| | | "only the LRU of a Btree node is taken into account " + |
| | | "when choosing the next Btree node to be evicted. " + |
| | | "When lruOnly is set to false, the eviction algorithm is " + |
| | | "instead primarily based on the level of the node in " + |
| | | "the Btree. The lowest level nodes (the leaf nodes) are " + |
| | | "always evicted first, even if higher level nodes are " + |
| | | "less recently used. In addition, dirty nodes are " + |
| | | "evicted after non-dirty nodes. " + |
| | | "Setting lruOnly to false benefits random access " + |
| | | "applications because it keeps higher level Btree " + |
| | | "nodes in the tree for as long as possible. For a " + |
| | | "random key, this increases the likelihood that the " + |
| | | "relevant Btree internal nodes will be in the cache."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_EVICTOR_NODES_PER_SCAN, |
| | | "Changes to this property do not take effect until the " + |
| | | "backend is restarted. " + |
| | | "It is recommended that you also change nodesPerScan " + |
| | | "when you set lruOnly to false. This setting controls " + |
| | | "the number of Btree nodes that are considered, or " + |
| | | "sampled, each time a node is evicted. A setting of 100 " + |
| | | "often produces good results, but this may vary from " + |
| | | "application to application. The larger the " + |
| | | "nodesPerScan, the more accurate the algorithm. However, " + |
| | | "setting it too high is detrimental; the need to " + |
| | | "consider larger numbers of nodes for each eviction may " + |
| | | "delay the completion of a given database operation, " + |
| | | "which will impact the response time of the application " + |
| | | "thread."); |
| | | registerMessage(MSGID_JEB_CACHE_SIZE_AFTER_PRELOAD, |
| | | "The database cache is %d MB after pre-loading."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_PRELOAD_TIME_LIMIT, |
| | | "The maximum time to spend pre-loading the database " + |
| | | "cache when the backend starts. The time units may be ms " + |
| | | "(milliseconds), s (seconds) or m (minutes). A value of " + |
| | | "zero means there will be no pre-load."); |
| | | |
| | | registerMessage(MSGID_JEB_BACKUP_CANNOT_GET_MAC, |
| | | "An error occurred while attempting to obtain the %s MAC " + |
| | | "provider to create the signed hash for the backup: %s."); |
| | |
| | | registerMessage(MSGID_JEB_BACKUP_MISSING_BACKUPID, |
| | | "The information for backup %s could not be found in " + |
| | | "the backup directory %s."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_ENTRIES_COMPRESSED, |
| | | "Set to true to indicate that the backend should " + |
| | | "attempt to compress entries when writing " + |
| | | "to the database."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_DATABASE_LOG_FILE_MAX, |
| | | "The maximum size of each individual database log file, " + |
| | | "in bytes. Changes to this property do not take effect " + |
| | | "until the backend is restarted."); |
| | | |
| | | registerMessage(MSGID_JEB_BACKUP_FILE_UNCHANGED, |
| | | "Not changed: %s"); |
| | | registerMessage(MSGID_JEB_BACKUP_CLEANER_ACTIVITY, |
| | |
| | | registerMessage(MSGID_JEB_REFERRAL_RESULT_MESSAGE, |
| | | "A referral entry %s indicates that the operation must " + |
| | | "be processed at a different server."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_LOGGING_FILE_HANDLER_ON, |
| | | "Determines whether database trace logging is written to " + |
| | | "a je.info file in the backend database directory. " + |
| | | "Changes to this property do not take effect until the " + |
| | | "backend is restarted."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_LOGGING_LEVEL, |
| | | "The database trace logging level chosen from: SEVERE, " + |
| | | "WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL or " + |
| | | "OFF. Changes to this property do not take effect until " + |
| | | "the backend is restarted."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_CHECKPOINT_BYTES_INTERVAL, |
| | | "The checkpointer runs every time this number of bytes" + |
| | | "have been written to the database log. If this property" + |
| | | "is set to a non-zero value, the checkpointer wakeup " + |
| | | "interval is not used. To use time based checkpointing, " + |
| | | "set this property to zero."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_CHECKPOINT_WAKEUP_INTERVAL, |
| | | "The checkpointer wakeup interval. If the checkpointer " + |
| | | "bytes interval is zero, the checkpointer runs at time " + |
| | | "intervals determined by this property."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_DEADLOCK_RETRY_LIMIT, |
| | | "The number of times a database transaction will be " + |
| | | "retried after it has been aborted due to deadlock with " + |
| | | "another thread."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_NUM_LOCK_TABLES, |
| | | "The number of database lock tables. It should be set " + |
| | | "to a prime number, and in general not higher than the " + |
| | | "number of server worker threads."); |
| | | registerMessage(MSGID_JEB_IMPORT_ENVIRONMENT_CONFIG, |
| | | "Database environment properties: %s."); |
| | | registerMessage(MSGID_CONFIG_DESCRIPTION_NUM_CLEANER_THREADS, |
| | | "The number of threads allocated by the cleaner for log " + |
| | | "file processing. If the cleaner backlog becomes large, " + |
| | | "increase this number."); |
| | | registerMessage(MSGID_JEB_INCOMPATIBLE_ENTRY_VERSION, |
| | | "Entry record with ID %s is not compatible with this " + |
| | | "version of the backend database. " + |
| | |
| | | "An error occured while inserting entry into the %s " + |
| | | "database/index: %s"); |
| | | registerMessage(MSGID_JEB_REBUILD_INDEX_CONFLICT, |
| | | "Another rebuild of index %s is alreadly in progress."); |
| | | "Another rebuild of index %s is already in progress."); |
| | | registerMessage(MSGID_JEB_REBUILD_BACKEND_ONLINE, |
| | | "Rebuilding system index(es) must be done with the " + |
| | | "backend containing the base DN disabled."); |
| | |
| | | registerMessage(MSGID_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_NAME, |
| | | "There is already another global argument named \"%s\"."); |
| | | registerMessage(MSGID_SUBCMDPARSER_GLOBAL_ARG_NAME_SUBCMD_CONFLICT, |
| | | "The argument name %s conflicts the the name of another " + |
| | | "The argument name %s conflicts with the name of another " + |
| | | "argument associated with the %s subcommand."); |
| | | registerMessage(MSGID_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_SHORT_ID, |
| | | "Short ID -%s for global argument %s conflicts with the " + |
| | |
| | | ds-cfg-index-type: ordering |
| | | ds-cfg-index-type: approximate |
| | | |
| | | dn: cn=JE Database,ds-cfg-backend-id=rebuildRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-database |
| | | cn: JE Database |
| | | ds-cfg-database-cache-percent: 10 |
| | | ds-cfg-database-cache-size: 0 megabytes |
| | | ds-cfg-database-txn-no-sync: false |
| | | ds-cfg-database-txn-write-no-sync: true |
| | | ds-cfg-database-run-cleaner: true |
| | | ds-cfg-database-cleaner-num-threads: 1 |
| | | ds-cfg-database-cleaner-min-utilization: 75 |
| | | ds-cfg-database-evictor-lru-only: true |
| | | ds-cfg-database-evictor-nodes-per-scan: 10 |
| | | ds-cfg-database-log-file-max: 50 megabytes |
| | | ds-cfg-database-logging-file-handler-on: true |
| | | ds-cfg-database-logging-level: CONFIG |
| | | ds-cfg-database-checkpointer-bytes-interval: 20 megabytes |
| | | ds-cfg-database-checkpointer-wakeup-interval: 30 seconds |
| | | ds-cfg-database-lock-num-lock-tables: 19 |
| | | |
| | | |
| | | dn: ds-cfg-backend-id=verifyRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | |
| | | ds-cfg-index-type: equality |
| | | ds-cfg-index-type: substring |
| | | |
| | | |
| | | dn: ds-cfg-index-attribute=uid,cn=Index,ds-cfg-backend-id=verifyRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | |
| | | ds-cfg-index-attribute: entryuuid |
| | | ds-cfg-index-type: equality |
| | | |
| | | dn: cn=JE Database,ds-cfg-backend-id=verifyRoot,cn=Backends,cn=config |
| | | dn: ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-database |
| | | cn: JE Database |
| | | ds-cfg-database-cache-percent: 10 |
| | | ds-cfg-database-cache-size: 0 megabytes |
| | | ds-cfg-database-txn-no-sync: false |
| | | ds-cfg-database-txn-write-no-sync: true |
| | | ds-cfg-database-run-cleaner: true |
| | | ds-cfg-database-cleaner-num-threads: 1 |
| | | ds-cfg-database-cleaner-min-utilization: 75 |
| | | ds-cfg-database-evictor-lru-only: true |
| | | ds-cfg-database-evictor-nodes-per-scan: 10 |
| | | ds-cfg-database-log-file-max: 50 megabytes |
| | | ds-cfg-database-logging-file-handler-on: true |
| | | ds-cfg-database-logging-level: CONFIG |
| | | ds-cfg-database-checkpointer-bytes-interval: 20 megabytes |
| | | ds-cfg-database-checkpointer-wakeup-interval: 30 seconds |
| | | ds-cfg-database-lock-num-lock-tables: 19 |
| | | objectClass: ds-cfg-backend |
| | | objectClass: ds-cfg-je-backend |
| | | ds-cfg-backend-enabled: true |
| | | ds-cfg-backend-class: org.opends.server.backends.jeb.BackendImpl |
| | | ds-cfg-backend-id: indexTestRoot |
| | | ds-cfg-backend-writability-mode: enabled |
| | | ds-cfg-backend-base-dn: dc=test,dc=com |
| | | ds-cfg-backend-base-dn: dc=test1,dc=com |
| | | ds-cfg-backend-directory: db_index_test |
| | | ds-cfg-backend-mode: 700 |
| | | ds-cfg-backend-index-entry-limit: 13 |
| | | ds-cfg-backend-subtree-delete-size-limit: 100000 |
| | | ds-cfg-backend-preload-time-limit: 0 seconds |
| | | ds-cfg-backend-import-temp-directory: importTmp |
| | | ds-cfg-backend-import-buffer-size: 256 megabytes |
| | | ds-cfg-backend-import-queue-size: 100 |
| | | ds-cfg-backend-import-pass-size: 0 |
| | | ds-cfg-backend-import-thread-count: 8 |
| | | ds-cfg-backend-entries-compressed: false |
| | | ds-cfg-backend-deadlock-retry-limit: 10 |
| | | |
| | | dn: cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-branch |
| | | cn: Index |
| | | |
| | | dn: ds-cfg-index-attribute=cn,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-index |
| | | ds-cfg-index-attribute: cn |
| | | ds-cfg-index-type: presence |
| | | ds-cfg-index-type: equality |
| | | ds-cfg-index-type: substring |
| | | ds-cfg-index-type: ordering |
| | | ds-cfg-index-type: approximate |
| | | |
| | | dn: ds-cfg-index-attribute=employeeNumber,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-index |
| | | ds-cfg-index-attribute: employeeNumber |
| | | ds-cfg-index-type: presence |
| | | ds-cfg-index-type: equality |
| | | ds-cfg-index-type: substring |
| | | ds-cfg-index-type: ordering |
| | | |
| | | dn: ds-cfg-index-attribute=title,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-index |
| | | ds-cfg-index-attribute: title |
| | | ds-cfg-index-type: presence |
| | | ds-cfg-index-type: equality |
| | | ds-cfg-index-type: substring |
| | | ds-cfg-index-type: ordering |
| | | |
| | | dn: ds-cfg-index-attribute=givenName,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-index |
| | | ds-cfg-index-attribute: givenName |
| | | ds-cfg-index-type: presence |
| | | ds-cfg-index-type: equality |
| | | ds-cfg-index-type: substring |
| | | |
| | | dn: ds-cfg-index-attribute=mail,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-index |
| | | ds-cfg-index-attribute: mail |
| | | ds-cfg-index-type: presence |
| | | ds-cfg-index-type: equality |
| | | ds-cfg-index-type: substring |
| | | ds-cfg-index-type: ordering |
| | | |
| | | dn: ds-cfg-index-attribute=member,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-index |
| | | ds-cfg-index-attribute: member |
| | | ds-cfg-index-type: equality |
| | | |
| | | dn: ds-cfg-index-attribute=sn,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-index |
| | | ds-cfg-index-attribute: sn |
| | | ds-cfg-index-type: presence |
| | | ds-cfg-index-type: equality |
| | | ds-cfg-index-type: substring |
| | | |
| | | dn: ds-cfg-index-attribute=telephoneNumber,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-index |
| | | ds-cfg-index-attribute: telephoneNumber |
| | | ds-cfg-index-type: presence |
| | | ds-cfg-index-type: equality |
| | | ds-cfg-index-type: substring |
| | | |
| | | dn: ds-cfg-index-attribute=uid,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-index |
| | | ds-cfg-index-attribute: uid |
| | | ds-cfg-index-type: equality |
| | | |
| | | dn: ds-cfg-index-attribute=ds-sync-hist,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-index |
| | | ds-cfg-index-attribute: ds-sync-hist |
| | | ds-cfg-index-type: ordering |
| | | |
| | | dn: ds-cfg-index-attribute=entryuuid,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config |
| | | changetype: add |
| | | objectClass: top |
| | | objectClass: ds-cfg-je-index |
| | | ds-cfg-index-attribute: entryuuid |
| | | ds-cfg-index-type: equality |
| | | |
| | | dn: cn=Virtual Static member,cn=Virtual Attributes,cn=config |
| | | changetype: modify |
| | |
| | | //db_rebuild is the third jeb backend used by the jeb rebuild test cases |
| | | String[] subDirectories = { "bak", "bin", "changelogDb", "classes", |
| | | "config", "db", "db_verify", "ldif", "lib", |
| | | "locks", "logs", "db_rebuild" }; |
| | | "locks", "logs", "db_rebuild", |
| | | "db_index_test" }; |
| | | for (String s : subDirectories) |
| | | { |
| | | new File(testRoot, s).mkdir(); |
| | |
| | | throws Exception |
| | | { |
| | | DN configEntryDN = |
| | | DN.decode("ds-cfg-backend-id=schema,cn=Backends,cn=config"); |
| | | DN.decode("cn=schema,cn=Backends,cn=config"); |
| | | DN[] baseDNs = { DN.decode("cn=schema") }; |
| | | |
| | | ConfigEntry configEntry = |
| | |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import java.io.File; |
| | | import java.util.*; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import static |
| | | org.opends.server.messages.ConfigMessages.MSGID_CONFIG_BACKEND_ATTR_DESCRIPTION_BASE_DNS; |
| | | import static org.opends.server.messages.MessageHandler.getMessage; |
| | | import org.opends.server.admin.std.server.JEBackendCfg; |
| | | import org.opends.server.admin.std.meta.JEBackendCfgDefn; |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.core.ModifyDNOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.protocols.internal.InternalSearchOperation; |
| | | import org.opends.server.protocols.ldap.LDAPFilter; |
| | | import org.opends.server.protocols.ldap.LDAPControl; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.DNConfigAttribute; |
| | | import static org.opends.server.config.ConfigConstants.ATTR_BACKEND_BASE_DN; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.util.Base64; |
| | | import static |
| | | org.opends.server.util.ServerConstants.OID_SUBTREE_DELETE_CONTROL; |
| | | import org.testng.annotations.Test; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.AfterTest; |
| | | import org.testng.annotations.AfterClass; |
| | | |
| | | import static org.testng.Assert.*; |
| | |
| | | * BackendImpl Tester. |
| | | */ |
| | | public class TestBackendImpl extends JebTestCase { |
| | | private File tempDir; |
| | | private String homeDirName; |
| | | |
| | | private DN[] baseDNs; |
| | | private BackendImpl backend; |
| | | |
| | | private List<Entry> topEntries; |
| | |
| | | // sure the server is started. |
| | | TestCaseUtils.startServer(); |
| | | |
| | | tempDir = TestCaseUtils.createTemporaryDirectory("jebimporttest"); |
| | | homeDirName = tempDir.getAbsolutePath(); |
| | | homeDirName = "db_index_test"; |
| | | |
| | | EnvManager.createHomeDir(homeDirName); |
| | | |
| | | Entry configEntry = TestCaseUtils.makeEntry( |
| | | "dn: ds-cfg-backend-id=userRoot,cn=Backends,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-backend", |
| | | "objectClass: ds-cfg-je-backend", |
| | | "ds-cfg-backend-index-entry-limit: 13", |
| | | "ds-cfg-backend-enabled: true", |
| | | "ds-cfg-backend-class: org.opends.server.backends.jeb.BackendImpl", |
| | | "ds-cfg-backend-id: userRoot", |
| | | "ds-cfg-backend-directory:: " + |
| | | Base64.encode(homeDirName.getBytes())); |
| | | |
| | | ConfigEntry backendConfigEntry = new ConfigEntry(configEntry, null); |
| | | |
| | | Entry indexEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config\n" + |
| | | "objectClass: top\n" + |
| | | "objectClass: ds-cfg-branch\n" + |
| | | "cn: Index\n"); |
| | | |
| | | ConfigEntry indexConfigEntry = new ConfigEntry(indexEntry, |
| | | backendConfigEntry); |
| | | backendConfigEntry.addChild(indexConfigEntry); |
| | | |
| | | List<Entry> indexEntries = TestCaseUtils.makeEntries( |
| | | "dn: ds-cfg-index-attribute=cn,cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config\n" + |
| | | "objectClass: top\n" + |
| | | "objectClass: ds-cfg-je-index\n" + |
| | | "ds-cfg-index-attribute: cn\n" + |
| | | "ds-cfg-index-type: presence\n" + |
| | | "ds-cfg-index-type: equality\n" + |
| | | "ds-cfg-index-type: substring\n" + |
| | | "ds-cfg-index-type: ordering\n" + |
| | | "ds-cfg-index-type: approximate\n" + |
| | | "\n" + |
| | | "dn: ds-cfg-index-attribute=employeeNumber,cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config\n" + |
| | | "objectClass: top\n" + |
| | | "objectClass: ds-cfg-je-index\n" + |
| | | "ds-cfg-index-attribute: employeeNumber\n" + |
| | | "ds-cfg-index-type: presence\n" + |
| | | "ds-cfg-index-type: equality\n" + |
| | | "ds-cfg-index-type: substring\n" + |
| | | "ds-cfg-index-type: ordering\n" + |
| | | "\n" + |
| | | "dn: ds-cfg-index-attribute=title,cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config\n" + |
| | | "objectClass: top\n" + |
| | | "objectClass: ds-cfg-je-index\n" + |
| | | "ds-cfg-index-attribute: title\n" + |
| | | "ds-cfg-index-type: presence\n" + |
| | | "ds-cfg-index-type: equality\n" + |
| | | "ds-cfg-index-type: substring\n" + |
| | | "ds-cfg-index-type: ordering\n"); |
| | | |
| | | ConfigEntry attribIndexConfigEntry; |
| | | |
| | | for (Entry attribIndexEntry : indexEntries) { |
| | | attribIndexConfigEntry = new ConfigEntry(attribIndexEntry, |
| | | indexConfigEntry); |
| | | indexConfigEntry.addChild(attribIndexConfigEntry); |
| | | } |
| | | |
| | | |
| | | baseDNs = new DN[] |
| | | { |
| | | DN.decode("dc=test,dc=com"), |
| | | DN.decode("dc=test1,dc=com") |
| | | }; |
| | | |
| | | backend = new BackendImpl(); |
| | | backend.initializeBackend(backendConfigEntry, baseDNs); |
| | | backend = (BackendImpl)DirectoryServer.getBackend("indexTestRoot"); |
| | | |
| | | topEntries = TestCaseUtils.makeEntries( |
| | | "dn: dc=test,dc=com", |
| | |
| | | |
| | | @AfterClass |
| | | public void cleanUp() throws Exception { |
| | | backend.finalizeBackend(); |
| | | TestCaseUtils.deleteDirectory(tempDir); |
| | | } |
| | | |
| | | @Test(expectedExceptions = DirectoryException.class) |
| | |
| | | |
| | | @Test(dependsOnMethods = "testAdd") |
| | | public void testSearchScope() throws Exception { |
| | | ArrayList<Control> noControls = new ArrayList<Control>(0); |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | |
| | |
| | | |
| | | @Test(dependsOnMethods = "testAdd") |
| | | public void testSearchIndex() throws Exception { |
| | | ArrayList<Control> noControls = new ArrayList<Control>(0); |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | LinkedHashSet<String> attribs = new LinkedHashSet<String>(); |
| | |
| | | AttributeIndex index; |
| | | HashSet<ASN1OctetString> addKeys; |
| | | DatabaseEntry key; |
| | | PresenceIndexer presenceIndexer; |
| | | EqualityIndexer equalityIndexer; |
| | | SubstringIndexer substringIndexer; |
| | | OrderingIndexer orderingIndexer; |
| | |
| | | "testModifyDNNewSuperior"}) |
| | | public void testApplyConfig() throws Exception { |
| | | Entry configEntry = TestCaseUtils.makeEntry( |
| | | "dn: ds-cfg-backend-id=userRoot,cn=Backends,cn=config", |
| | | "dn: ds-cfg-backend-id=indexRoot,cn=Backends,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-backend", |
| | | "objectClass: ds-cfg-je-backend", |
| | | "ds-cfg-backend-base-dn: dc=test,dc=com", |
| | | "ds-cfg-backend-base-dn: dc=newsuffix,dc=com", |
| | | "ds-cfg-backend-enabled: true", |
| | | "ds-cfg-backend-writability-mode: enabled", |
| | | "ds-cfg-backend-class: org.opends.server.backends.jeb.BackendImpl", |
| | | "ds-cfg-backend-id: userRoot", |
| | | "ds-cfg-backend-id: indexTestRoot", |
| | | "ds-cfg-backend-directory:: " + |
| | | Base64.encode(homeDirName.getBytes())); |
| | | Base64.encode(homeDirName.getBytes()), |
| | | "ds-cfg-backend-import-temp-directory: importTmp"); |
| | | |
| | | ConfigEntry backendConfigEntry = new ConfigEntry(configEntry, null); |
| | | JEBackendCfg cfg = AdminTestCaseUtils.getConfiguration( |
| | | JEBackendCfgDefn.getInstance(), configEntry); |
| | | |
| | | backend.applyNewConfiguration(backendConfigEntry, true); |
| | | backend.applyConfigurationChange(cfg); |
| | | |
| | | RootContainer rootContainer = backend.getRootContainer(); |
| | | |
| | |
| | | assertNotNull(backend.getEntry(entry.getDN())); |
| | | } |
| | | |
| | | ArrayList<Control> noControls = new ArrayList<Control>(0); |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | LinkedHashSet<String> attribs = new LinkedHashSet<String>(); |
| | | attribs.add(ATTR_DEBUG_SEARCH_INDEX); |
| | | |
| | | String debugString; |
| | | int finalStartPos; |
| | | int finalEndPos; |
| | | int finalCount; |
| | | |
| | | InternalSearchOperation search = |
| | | conn.processSearch(DN.decode("dc=test,dc=com"), |
| | |
| | | |
| | | import static org.testng.AssertJUnit.assertTrue; |
| | | |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.File; |
| | | import java.io.OutputStreamWriter; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.admin.std.server.JEBackendCfg; |
| | | import org.opends.server.admin.std.meta.JEBackendCfgDefn; |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.LDIFImportConfig; |
| | | import org.opends.server.types.FilePermission; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.util.LDIFReader; |
| | | import org.opends.server.util.Base64; |
| | | import org.testng.annotations.Test; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.AfterClass; |
| | | |
| | | import com.sleepycat.je.Environment; |
| | | import com.sleepycat.je.EnvironmentConfig; |
| | | |
| | | /** |
| | | * EntryContainer tester. |
| | | */ |
| | |
| | | private File tempDir; |
| | | private String homeDirName; |
| | | |
| | | private ArrayList<Entry> entryList; |
| | | private List<Entry> entryList; |
| | | |
| | | private long calculatedHighestID = 0; |
| | | |
| | |
| | | tempDir = TestCaseUtils.createTemporaryDirectory("jebtest"); |
| | | homeDirName = tempDir.getAbsolutePath(); |
| | | |
| | | // Convert the test LDIF string to a byte array |
| | | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| | | OutputStreamWriter outputStreamWriter = new OutputStreamWriter( |
| | | byteArrayOutputStream); |
| | | outputStreamWriter.write(ldifString); |
| | | outputStreamWriter.flush(); |
| | | byte[] originalLDIFBytes = byteArrayOutputStream.toByteArray(); |
| | | |
| | | LDIFReader reader = new LDIFReader(new LDIFImportConfig( |
| | | new ByteArrayInputStream(originalLDIFBytes))); |
| | | |
| | | // Create a set of entries |
| | | entryList = new ArrayList<Entry>(); |
| | | long entryID = 0; |
| | | Entry entry; |
| | | while ((entry = reader.readEntry(false)) != null) { |
| | | entryID++; |
| | | entryList.add(entry); |
| | | } |
| | | entryList = TestCaseUtils.entriesFromLdifString(ldifString); |
| | | |
| | | // Remember the highest entryID |
| | | calculatedHighestID = entryID; |
| | | calculatedHighestID = entryList.size(); |
| | | } |
| | | |
| | | /** |
| | |
| | | @Test() |
| | | public void test1() throws Exception { |
| | | EnvManager.createHomeDir(homeDirName); |
| | | RootContainer rootContainer = new RootContainer(new Config(), null); |
| | | Entry configEntry = TestCaseUtils.makeEntry( |
| | | "dn: ds-cfg-backend-id=userRoot,cn=Backends,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-backend", |
| | | "objectClass: ds-cfg-je-backend", |
| | | "ds-cfg-backend-enabled: true", |
| | | "ds-cfg-backend-class: " + |
| | | "org.opends.server.backends.jeb.BackendImpl", |
| | | "ds-cfg-backend-id: userRoot", |
| | | "ds-cfg-backend-writability-mode: enabled", |
| | | "ds-cfg-backend-base-dn: dc=com", |
| | | "ds-cfg-backend-directory:: " + |
| | | Base64.encode(homeDirName.getBytes()), |
| | | "ds-cfg-backend-import-temp-directory: importTmp"); |
| | | JEBackendCfg cfg = AdminTestCaseUtils.getConfiguration( |
| | | JEBackendCfgDefn.getInstance(), configEntry); |
| | | Config backendConfig = new Config(); |
| | | backendConfig.initializeConfig(cfg, |
| | | cfg.getBackendBaseDN().toArray(new DN[0])); |
| | | RootContainer rootContainer = new RootContainer(backendConfig, null); |
| | | rootContainer.open(new File(homeDirName), |
| | | new FilePermission(true, true, true), |
| | | false, true, true, false, true, true); |
| | | |
| | | EntryContainer entryContainer = |
| | | rootContainer.openEntryContainer(DirectoryServer.getSchemaDN()); |
| | | rootContainer.openEntryContainer(DN.decode("dc=com")); |
| | | |
| | | EntryID actualHighestID = entryContainer.getHighestEntryID(); |
| | | assertTrue(actualHighestID.equals(new EntryID(0))); |
| | |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-backend", |
| | | "objectClass: ds-cfg-je-backend", |
| | | "ds-cfg-backend-base-dn: dc=example,dc=com", |
| | | "ds-cfg-backend-base-dn: dc=example1,dc=com", |
| | | "ds-cfg-backend-writability-mode: enabled", |
| | | "ds-cfg-backend-enabled: true", |
| | | "ds-cfg-backend-class: org.opends.server.backends.jeb.BackendImpl", |
| | | "ds-cfg-backend-id: userRoot", |