memory (file): avoid race condition when creating parent path directories.

This commit is contained in:
Goffi 2024-06-18 12:06:45 +02:00
commit 56319cbad3

View file

@ -251,6 +251,7 @@ class Memory:
self._cache_path = Path(self.config_get("", "local_dir"), C.CACHE_DIR)
self.admins = self.config_get("", "admins_list", [])
self.admin_jids = set()
self._file_path_lock = defer.DeferredLock()
async def initialise(self):
@ -1706,28 +1707,36 @@ class Memory:
owner = self.get_files_owner(client, owner, peer_jid, file_id, parent)
if path is not None:
path = str(path)
# _get_parent_dir will check permissions if peer_jid is set, so we use owner
parent, remaining_path_elts = await self._get_parent_dir(
client, path, parent, namespace, owner, owner, perms_to_check
)
# if remaining directories don't exist, we have to create them
for new_dir in remaining_path_elts:
new_dir_id = shortuuid.uuid()
await self.storage.set_file(
client,
name=new_dir,
file_id=new_dir_id,
version="",
parent=parent,
type_=C.FILE_TYPE_DIRECTORY,
namespace=namespace,
created=time.time(),
owner=owner,
access=access,
extra={},
# We use a lock to avoid race condition leading to duplicate directories with
# same name and parent.
await self._file_path_lock.acquire()
try:
path = str(path)
# _get_parent_dir will check permissions if peer_jid is set, so we use owner
parent, remaining_path_elts = await self._get_parent_dir(
client, path, parent, namespace, owner, owner, perms_to_check
)
parent = new_dir_id
# if remaining directories don't exist, we have to create them
for new_dir in remaining_path_elts:
new_dir_id = shortuuid.uuid()
await self.storage.set_file(
client,
name=new_dir,
file_id=new_dir_id,
version="",
parent=parent,
type_=C.FILE_TYPE_DIRECTORY,
namespace=namespace,
created=time.time(),
owner=owner,
access=access,
extra={},
)
parent = new_dir_id
finally:
self._file_path_lock.release()
elif parent is None:
parent = ""