A non-transitory computer readable storage medium storing instructions executable by a user device and upon such execution cause the user device to perform operations comprising:
- accessing an object hierarchy for a plurality of objects, each object being representative of one of a storage location or a file, wherein each storage location may store one or more subordinate storage locations or files, wherein the hierarchy comprises:
- for each object, a respective node;
- for each object that is a parent object having a child object, a directed edge connecting the node representing the parent object to the node representing the child object;
- wherein at least one object is represented by a root object, and at least one object is represented by a leaf object;
- and
- for each object that is not an access control list root object, wherein an access control list root object is an object for which an access control list is owned by the object:
- metadata that includes an access control list identifier that identifies an access control list for the object and that is owned by an access control list root object;
- receiving updates to an access control list for particular objects, and determining, for each update, whether the particular object is an access control list root object;
- for each update for a particular object not determined to be an access control list root object:
- generating a new access control list based on the update and the access control list referenced by the access control list identifier for the node and setting ownership of the new access control list to the particular object to cause the particular object to become an access control list root object;
- generating a new access control list identifier that identifies the new access control list;
- storing the new access control list identifier in metadata for each object that descends from the particular object and that inherits the access control list from the particular object;
- and
- storing the new access control list identifier as a divergent object in the access control list root object that the particular object descended from to indicate that updates to the access control list for the access control list root object are to be propagated to the new access control list identified by the new access control list identifier;
- for each update for a particular object determined to be an access control list root object:
- updating the access control list owned by the access control list root object, wherein the updated access control list is identified by the access control list identifier;
- for each access control list identifier stored as a divergent object in the access control list root object, updating the access control list identified by the access control list identifier stored as the divergent object;
- generating, for a first update request for an update to an access control list of a child object that references an access control list of an access control list root object by use of an access control list identifier, an asynchronous task event that specifies particular operations included in the update to the access control list of the child object;
- generating, for the access control list of the access control list root object, a conflicting access control list update that specifies that the access control list of the child object has started to diverge;
- in response to a second update request for an update to the access control list of the child object, wherein the second update request is received after the first update request and before an update specified by the first update request is completed, and based on the conflicting access control list update that specifies that the access control list of the child object has started to diverge:
- precluding performance of the update specified by the second update request until the update specified by the first update request is completed;
- after the update specified by the first update request is completed:
- removing the second update request from the conflicting access control list;
- determining whether the second update request is allowable;
- and
- performing the update specified by the second update request only if the second update request is allowable.