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 */
+
+void __check_db_lock(const char* 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, &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);
+}
+
+int __db_busy_handler(void *data, int count) {
+ if ((count + 1) % BUSY_LOG_INTERVAL == 0 ) {
+ LOG(WARNING) << "Database is busy, waiting count : " << count;
+
+ __check_db_lock(static_cast<const char*>(data));
+ }
-int __readdb_busy_handler(void *data, int count) {
if (count < BUSY_WAITING_MAX) {
usleep(BUSY_WAITING_USEC);
- return 1;
- } else {
- /* sqlite3_prepare_v2 will return SQLITE_BUSY */
- return 0;
+ return true;
}
+
+ LOG(ERROR) << "Try to access db[" << static_cast<const char*>(data) << "] "
+ << BUSY_WAITING_MAX << " times, but can't access";
+ return false;
}
int __open_read_db(const char *path, sqlite3 **db) {
return ret;
}
- ret = sqlite3_busy_handler(*db, __readdb_busy_handler, NULL);
+ ret = sqlite3_busy_handler(*db, __db_busy_handler, (void*)path);
if (ret != SQLITE_OK) {
LOG(ERROR) << "failed to register busy handler:" << sqlite3_errmsg(*db);
sqlite3_close_v2(*db);
return ret;
}
-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";
-
-int __writedb_busy_handler(void *data, int count) {
- if (count < (BUSY_WAITING_MAX / 2)) {
- usleep(BUSY_WAITING_USEC);
- return 1;
- } else if (count < BUSY_WAITING_MAX) {
- usleep(BUSY_WAITING_USEC);
- return 1;
- } else {
- /* sqlite3_prepare_v2 will return SQLITE_BUSY */
- return 0;
- }
-}
-
int __open_write_db(uid_t uid, const char* path,
sqlite3** db) {
int ret;
return ret;
}
- ret = sqlite3_busy_handler(*db, __writedb_busy_handler,
- reinterpret_cast<void*>(const_cast<char*>(path)));
+ ret = sqlite3_busy_handler(*db, __db_busy_handler, (void*)path);
if (ret != SQLITE_OK) {
LOG(ERROR) << "failed to register busy handler:" << sqlite3_errmsg(*db);
sqlite3_close_v2(*db);
return ret;
}
- ret = sqlite3_busy_handler(*db, __writedb_busy_handler,
- reinterpret_cast<void*>(const_cast<char*>(path)));
+ ret = sqlite3_busy_handler(*db, __db_busy_handler, (void*)path);
if (ret != SQLITE_OK) {
LOG(ERROR) << "failed to register busy handler:" << sqlite3_errmsg(*db);
sqlite3_close_v2(*db);
return false;
db_handle_list_.emplace_back(std::make_pair(db, dbpath.second));
+ db_paths_.emplace_back(std::move(dbpath.first));
}
return true;
sqlite3_close_v2(db_handle.first);
db_handle_list_.clear();
+ db_paths_.clear();
}
std::vector<std::pair<sqlite3*, uid_t>> AbstractDBHandler::GetConnection() {