joel reed wrote:
Howard Chu wrote:
Joel Reed wrote:
The attached uidnumber.c overlay intercepts ADD requests for entries with a posixAccount objectclass that do not have a uidNumber. When such ADD requests are found, the overlay searches the directory for the largest uidNumber, then automatically adds a uidNumber attribute of largest+1 to the entry being added.
Interesting. Perhaps instead, your overlay should just maintain a fixed entry with a copy of the largest uidNumber in it, instead of searching the entire tree all the time.
I did consider this, but didn't implement it because I was thinking about running in an N-Way Multi-Master configuration. On further reflection, this scheme would probably still not support such a configuration under load.
Obviously, the approach I took doesn't scale well as you point out. I think I will punt on supporting N-Way Multi-Master configs and either use the approach you note above or the sambaUnixIdPool approach noted elsewhere in this thread.
It seems the sambaUnixIdPool approach is essentually the same thing, they just have a dedicated entry with uidNumber and gidNumber attributes, recording the next available values.
Thanks to everyone who provided feedback. Greatly appreciated.
In a multimaster scenario the only sane way to handle things is to partition the namespace such that each master is allocating numbers from a totally disjoint range. I would try an approach like this:
Each server allocates uids in blocks, say 1000 at a time. There is an attribute that records the last used (or next available) block. This attribute resides in a dedicated entry that is read and written by all the servers. Each server then records, in a server-specific entry, the last used (or next available) number within that block. You can use the slap_serverID variable to obtain the current server's ID.
so, with 3 masters:
dn: cn=idblock,dc=example,dc=com objectclass: idblock cn: idblock uidNumber: 3000
dn: cn=server1,dc=example,dc=com objectclass: idblock cn: server1 uidNumber: 5
dn: cn=server2,dc=example,dc=com objectclass: idblock cn: server2 uidNumber: 1003
dn: cn=server3,dc=example,dc=com objectclass: idblock cn: server3 uidNumber: 2008
When a particular server allocates all 1000 of the IDs in its current block it will have to go back to the idblock entry and bump that up to the next range. At that point there's the potential for two servers to try to grab the same range, and the resulting conflict would create a big mess.
Another alternative, if you will never change the number of servers involved, is to do away with the central idblock entry and just allocate every-other-Nth ID. E.g., with 3 servers, server1 will allocate 0, 3, 6, 9 ... server2 will allocate 1,4,7,10,... server3 will allocate 2,5,8,11...
That guarantees there will never be conflicts, unless you decide to change the number of masters.