From e7b404afeefaf9589c85fe107f70dc98d442783b Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Thu, 25 Apr 2024 15:30:24 +0900 Subject: [PATCH] Improve db busy handler Threre is a possibility that db operation cannot be performed for more than 5 seconds on low performance devices so increase busy handler waiting count and print the process that owns the lock of database Change-Id: Iba95a14fb2a41450cf011e98c83a61a1295e6c23 Signed-off-by: Ilho Kim --- src/server/database/abstract_db_handler.cc | 103 +++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 28 deletions(-) diff --git a/src/server/database/abstract_db_handler.cc b/src/server/database/abstract_db_handler.cc index e580d96..7e829a3 100644 --- a/src/server/database/abstract_db_handler.cc +++ b/src/server/database/abstract_db_handler.cc @@ -37,53 +37,100 @@ namespace { constexpr useconds_t BUSY_WAITING_USEC = (1000000 / 10 / 2); /* 0.05 sec */ -constexpr int BUSY_WAITING_MAX = 100; /* wait for max 5 sec */ +constexpr int BUSY_WAITING_MAX = 300; /* wait for max 15 sec */ +constexpr int BUSY_LOG_INTERVAL = 1000000 / BUSY_WAITING_USEC; /* interval 1 sec */ + +static void CheckDbLock(const std::string& dbpath) { + struct stat sb; + int pid; + unsigned int maj; + unsigned int min; + unsigned long long ino; + char cmdline[BUFSIZE]; + char name[BUFSIZE]; + char type[1024]; + + if (stat(dbpath.c_str(), &sb) == -1) { + LOG(ERROR) << "get db file(" << dbpath << ") status failed: " << errno; + return; + } + + FILE* fp = fopen("/proc/locks", "r"); + if (fp == NULL) { + LOG(ERROR) << "Failed to open lock info: " << errno; + return; + } + + while (fscanf(fp, "%*s %*s %*s %5s %d %x:%x:%llu %*s %*s", + type, &pid, &maj, &min, &ino) != EOF) { + if (maj != major(sb.st_dev) || min != minor(sb.st_dev) || + ino != sb.st_ino || pid == getpid()) + continue; + + snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid); + FILE* fp_cmdline = fopen(cmdline, "r"); + name[0] = '\0'; + if (fp_cmdline != NULL) { + size_t len = fread(name, sizeof(char), sizeof(name) - 1, + fp_cmdline); + if (len > 0) { + if (name[len - 1] == '\n') + name[len - 1] = '\0'; + else + name[len] = '\0'; + } + fclose(fp_cmdline); + } + + LOG(WARNING) << name << "(" << pid << ")" << "has lock(" + << type << ") on pkgmgr db(" << dbpath << ")"; + } + + fclose(fp); +} + +bool DbBusyHandler(int count, const std::string& path) { + if ((count + 1) % BUSY_LOG_INTERVAL == 0 ) { + LOG(WARNING) << "Database is busy, waiting count : " << count; + CheckDbLock(path); + } -bool ReadDbBusyHandler(int count) { if (count < BUSY_WAITING_MAX) { usleep(BUSY_WAITING_USEC); return true; - } else { - return false; } + + LOG(ERROR) << "Try to access db[" << path << "] " + << BUSY_WAITING_MAX << " times, but can't access"; + return false; } tizen_base::Database OpenReadDb(const std::string& path) { tizen_base::Database db(path.c_str(), SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, - ReadDbBusyHandler); + [path = path] (int count) -> bool { + return DbBusyHandler(count, path); + }); return db; } -constexpr const char RESOURCED_BUS_NAME[] = "org.tizen.resourced"; -constexpr const char RESOURCED_PROC_PATH[] = "/Org/Tizen/ResourceD/Process"; -constexpr const char RESOURCED_PROC_INTERFACE[] = "org.tizen.resourced.process"; -constexpr const char RESOURCED_PROC_METHOD[] = "ProcExclude"; - -bool WriteDbBusyHandler(int count) { - if (count < (BUSY_WAITING_MAX / 2)) { - usleep(BUSY_WAITING_USEC); - return true; - } else if (count < BUSY_WAITING_MAX) { - usleep(BUSY_WAITING_USEC); - return true; - } else { - return false; - } -} - -tizen_base::Database OpenWriteDb(uid_t uid, const std::string& path) { +tizen_base::Database OpenWriteDb(const std::string& path) { tizen_base::Database db(path.c_str(), SQLITE_OPEN_READWRITE, - WriteDbBusyHandler); + [path = path] (int count) -> bool { + return DbBusyHandler(count, path); + }); db.OneStepExec({ "PRAGMA foreign_keys=ON" }); db.OneStepExec({ "PRAGMA recursive_triggers=ON" }); return db; } -tizen_base::Database OpenCreateDb(uid_t uid, const std::string& path) { +tizen_base::Database OpenCreateDb(const std::string& path) { tizen_base::Database db(path.c_str(), SQLITE_OPEN_READWRITE | - SQLITE_OPEN_CREATE, WriteDbBusyHandler); + SQLITE_OPEN_CREATE, + [path = path] (int count) -> bool { + return DbBusyHandler(count, path); + }); return db; } @@ -138,7 +185,7 @@ bool AbstractDBHandler::Connect() { op_type_ == pkgmgr_common::DBOperationType::OPERATION_TYPE_WRITE) { if (ConvertUID(uid) != ConvertUID(uid_)) continue; - db_handle_list_.emplace_back(OpenWriteDb(uid_, path), uid); + db_handle_list_.emplace_back(OpenWriteDb(path), uid); } else { if (ConvertUID(uid) != ConvertUID(uid_)) continue; @@ -148,7 +195,7 @@ bool AbstractDBHandler::Connect() { return false; } - db_handle_list_.emplace_back(OpenCreateDb(uid_, path), uid); + db_handle_list_.emplace_back(OpenCreateDb(path), uid); } } } catch (const tizen_base::DbException& e) { -- 2.7.4