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;
}
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;
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) {