[elbe-devel] [PATCH 21/22] elbepack: projectmanager: remove cache

Thomas Weißschuh thomas.weissschuh at linutronix.de
Wed Aug 14 15:29:35 CEST 2024


The cache artificially limits each user to one active project at a time.
Retrieving projects by userid instead of their unique builddir, which is
always available has the potential to operate on an incorrect project.
It also introduces a global lock.

The only work that the cache optimizes are small data fetches from a
local database which don't need such a cache, and are cached in the ORM
anyways.

Replace the lock with a dummy contextmanager to avoid to much churn,
in this patch.
A future patch will only remove the lock.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh at linutronix.de>
---
 elbepack/daemons/soap/esoap.py |  2 --
 elbepack/projectmanager.py     | 75 ++----------------------------------------
 2 files changed, 2 insertions(+), 75 deletions(-)

diff --git a/elbepack/daemons/soap/esoap.py b/elbepack/daemons/soap/esoap.py
index 5728473ea40d..56ca97a2c7bb 100644
--- a/elbepack/daemons/soap/esoap.py
+++ b/elbepack/daemons/soap/esoap.py
@@ -139,8 +139,6 @@ class ESoap (ServiceBase):
                 fp.flush()
             self.app.pm.db.reset_busy(builddir, 'has_changes')
             if fname == 'source.xml':
-                # ensure that the project cache is reloaded
-                self.app.pm.close_current_project(uid)
                 self.app.pm.open_project(
                     uid, builddir, url_validation=ValidationMode.NO_CHECK)
                 self.app.pm.set_project_xml(builddir, fn)
diff --git a/elbepack/projectmanager.py b/elbepack/projectmanager.py
index 5353fbdfd23b..dca773875bcb 100644
--- a/elbepack/projectmanager.py
+++ b/elbepack/projectmanager.py
@@ -2,9 +2,9 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 # SPDX-FileCopyrightText: 2014-2018 Linutronix GmbH
 
+import contextlib
 import os
 from os import path
-from threading import Lock
 
 from elbepack.asyncworker import (
     AsyncWorker,
@@ -27,12 +27,6 @@ class ProjectManagerError(Exception):
     pass
 
 
-class AlreadyOpen(ProjectManagerError):
-    def __init__(self, builddir, username):
-        ProjectManagerError.__init__(
-            self, f'project in {builddir} is already opened by {username}')
-
-
 class PermissionDenied(ProjectManagerError):
     def __init__(self, builddir):
         ProjectManagerError.__init__(
@@ -49,10 +43,7 @@ class ProjectManager:
         self.basepath = basepath    # Base path for new projects
         self.db = ElbeDB()          # Database of projects and users
         self.worker = AsyncWorker(self.db)
-        # (userid, ElbeProject) map of open projects
-        self.userid2project = {}
-        self.builddir2userid = {}   # (builddir, userid) map of open projects
-        self.lock = Lock()          # Lock protecting our data
+        self.lock = contextlib.nullcontext()
 
     def stop(self):
         self.worker.stop()
@@ -72,9 +63,6 @@ class ProjectManager:
         builddir = path.join(self.basepath, subdir)
 
         with self.lock:
-            # Try to close old project, if any
-            self._close_current_project(userid)
-
             self.db.create_project(builddir, owner_id=userid)
 
             try:
@@ -84,13 +72,6 @@ class ProjectManager:
                 self.db.del_project(builddir)
                 raise
 
-            # Open the new project
-            ep = self.db.load_project(builddir,
-                                      url_validation=url_validation)
-
-            self.userid2project[userid] = ep
-            self.builddir2userid[builddir] = userid
-
         return builddir
 
     def open_project(
@@ -102,55 +83,17 @@ class ProjectManager:
         self._check_project_permission(userid, builddir)
 
         with self.lock:
-            if builddir in self.builddir2userid:
-                if self.builddir2userid[builddir] == userid:
-                    # Same project selected again by the same user, don't do
-                    # anything
-                    ep = self.userid2project[userid]
-                    if not allow_busy:
-                        self._assert_not_busy(ep)
-                    return ep
-
-                # Already opened by a different user
-                raise AlreadyOpen(builddir,
-                                  self.db.get_username(self.builddir2userid[builddir]))
-
-            # Try to close the old project of the user, if any
-            self._close_current_project(userid)
-
             # Load project from the database
             ep = self.db.load_project(builddir,
                                       url_validation=url_validation)
 
-            # Add project to our dictionaries
-            self.userid2project[userid] = ep
-            self.builddir2userid[builddir] = userid
-
             if not allow_busy:
                 self._assert_not_busy(ep)
             return ep
 
-    def close_current_project(self, userid):
-        with self.lock:
-            self._close_current_project(userid)
-
     def del_project(self, userid, builddir):
         self._check_project_permission(userid, builddir)
 
-        with self.lock:
-            # Does anyone have the project opened right now?
-            if builddir in self.builddir2userid:
-                if self.builddir2userid[builddir] == userid:
-                    # If the calling user has opened it, then close it and
-                    # proceed if closed sucessfully.
-                    self._close_current_project(userid)
-                else:
-                    # TODO: Admin should be allowed to delete projects
-                    # that are currently opened by other users
-                    raise AlreadyOpen(builddir,
-                                      self.db.get_username(
-                                          self.builddir2userid[builddir]))
-
         self.db.del_project(builddir)
 
     def set_project_xml(self, builddir, xml_file):
@@ -281,20 +224,6 @@ class ProjectManager:
         if self.db.is_busy(ep.builddir):
             raise InvalidState(f'project {ep.builddir} is busy')
 
-    def _close_current_project(self, userid):
-        # Must be called with self.lock held
-
-        if userid in self.userid2project:
-            builddir = self.userid2project[userid].builddir
-            if self.db.is_busy(builddir):
-                raise InvalidState(
-                    f'project in directory {builddir} of user '
-                    f'{self.db.get_username(userid)} is '
-                    'currently busy and cannot be closed')
-
-            del self.builddir2userid[builddir]
-            del self.userid2project[userid]
-
     def _check_project_permission(self, userid, builddir):
         if self.db.is_admin(userid):
             # Admin may access all projects

-- 
2.46.0



More information about the elbe-devel mailing list