LDAP: Modify-Increment Extension

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 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 ldapsearch tool:

# Using the modern ldapsearch
# syntax:
ldapsearch --hostname localhost --port 1389 \
 --baseDn '' --searchScope base \
 '(objectClass=*)' supportedFeatures | \
 perl -lane 'print if /'
# 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 /'

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: false ZEIEJnVpZD11c2VyLjAsb3U9cGVvcGxlLGRjPWV4YW1wbGUs
# ==> 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


About Terry Gardner

Terry Gardner was a leading directory services architect with experience with many large scale directory services installations and messaging server installations, and was a Subject Matter Expert in the field of Directory Services and Solaris (operating system) performance. Mr. Gardner also participated in the open-source software community. Mr. Gardner passed away in December, 2013.
This entry was posted in computing, LDAP and tagged , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s