Modern, professional-quality directory servers support an LDAP extension called “Modify-Increment”. The extension, if supported, allows the developer or operator to increment an integer or other incrementable value by a specified increment in one operation. If this operation is not supported, clients that require a value to be incremented must be constructed in such a way as to read the values of the attribute and then modify them, then must read the value back to check the desired effect was achieved, since other clients might modify the same attribute at the same time. This type of client operation is undesirable and error-prone.
Determining whether the server supports Modify-Increment extension presents some problems because, even though directory servers should publish the OIDs for supported features in the
supportedFeatures attribute in the root DSE, RFC 4525 merely states that servers should publish the OID of the Modify-Increment extension in the root DSE, not that servers must publish the OID. For more information about the root DSE see the article “The Root DSE”.
Before using the Modify-increment extension, query the root DSE for the
supportedFeatures attribute containing the value
126.96.36.199.1.14. See IANA LDAP Parameters for the full list of LDAP parameters.
See ModifyIncrementDemo.java at code.google.com for an demonstration of the modify-increment extension using Java and the UnboundID LDAP SDK. The code in the provides a demonstration of the use of the modify-increment extension defined in RFC4525. This extension lets LDAP clients increment an ‘increment-able’ attribute value by a specified amount, either positive or negative. The modify-increment extension aids in producing robust client code that is not dependent on timing and replication by performing an increment in an atomic transaction (as opposed to read-increment). The demonstration searches for the entry (which is not strictly necessary but given as an example of constructing and transmitting a search request), then transmits a modify request with the pre-read and post-read request controls attached. If the pre-read request control is permitted by the server, the pre-read response will contain the value of the specified attribute before the modification occurs. If the post-read request control is permitted by the server, the post-read response will contain the value of the attribute after the modification occurs.
Examples using the
# # Using the modern ldapsearch # syntax: # ldapsearch --hostname localhost --port 1389 \ --baseDn '' --searchScope base \ '(objectClass=*)' supportedFeatures | \ perl -lane 'print if /188.8.131.52.1.14/' supportedFeatures: 184.108.40.206.1.14 # # Same search using the old # OpenLDAP ldapsearch tool: # /usr/bin/ldapsearch -x -h localhost -p 1389 -b '' \ -s base '(objectClass=*)' supportedFeatures | \ perl -lane 'print if /220.127.116.11.1.14/' supportedFeatures: 18.104.22.168.1.14
The above search results show that this directory server does in fact support the Modify-Increment extension. If your directory server does not publish the OID as a value of the
supportedFeatures attribute, ask your friendly neighborhood LDAP administrator if the server supports it. Clients must not use the Modify-Increment extension if the server does not support it.
The following example assumes that the server supports the Modify-Increment extension, and that an entry
uid=user.0,ou=people,dc=example,dc=com exists and has an attribute
employeeNumber to increment. This example uses the root DN (in this case
"cn=directory manager" though this could be any value that is a valid root DN) so that there is no question that the operation will be allowed. The root DN is not subject to access controls and resource limits, generally speaking. The attribute must exist and have an integer or other value that can be incremented. If the attribute has multiple values the server must return a protocol error.
The following example increments the value of the
employeeNumber attribute by 5 (five) and uses the pre-read and post-read controls to verify the value.
# # First, using the older # OpenLDAP ldapmodify tool: # /usr/bin/ldapmodify -x -h localhost -p 1389 \ -D 'cn=directory manager' -W \ -e preread=employeeNumber \ -e postread=employeeNumber Enter LDAP Password: dn: uid=user.0,ou=people,dc=example,dc=com changetype: modify increment: employeeNumber employeeNumber: 5 modifying entry "uid=user.0,ou=people,dc=example,dc=com" control: 22.214.171.124.1.13.1 false ZEIEJnVpZD11c2VyLjAsb3U9cGVvcGxlLGRjPWV4YW1wbGUs ZGM9Y29tMBgwFgQOZW1wbG95ZWVOdW1iZXIxBAQCMTA= # ==> preread dn: uid=user.0,ou=people,dc=example,dc=com employeeNumber: 10 # postread dn: uid=user.0,ou=people,dc=example,dc=com employeeNumber: 15 # <== postread # # Second, the modern ldapmodify syntax # ldapmodify --hostname localhost --port 1389 \ --bindDn 'cn=directory manager' --bindPasswordFile ~/.pwdFile \ --preReadAttributes employeeNumber \ --postReadAttributes employeeNumber dn: uid=user.0,ou=people,dc=example,dc=com changetype: modify increment: employeeNumber employeeNumber: 5 # Processing MODIFY request for uid=user.0,ou=people,dc=example,dc=com # MODIFY operation successful for DN uid=user.0,ou=people,dc=example,dc=com # Target entry before the operation: # dn: uid=user.0,ou=people,dc=example,dc=com # employeeNumber: 15 # Target entry after the operation: # dn: uid=user.0,ou=people,dc=example,dc=com # employeeNumber: 20