| 254 | // --------------------------------------------------------------------------- |
| 255 | |
| 256 | bool DiskChunkCache::initialize() { |
| 257 | std::string vfsName; |
| 258 | if (ctx_->custom_sqlite3_vfs_name.empty()) { |
| 259 | vfs_ = SQLite3VFS::create(true, false, false); |
| 260 | if (vfs_ == nullptr) { |
| 261 | return false; |
| 262 | } |
| 263 | vfsName = vfs_->name(); |
| 264 | } else { |
| 265 | vfsName = ctx_->custom_sqlite3_vfs_name; |
| 266 | } |
| 267 | sqlite3_open_v2(path_.c_str(), &hDB_, |
| 268 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, |
| 269 | vfsName.c_str()); |
| 270 | if (!hDB_) { |
| 271 | pj_log(ctx_, PJ_LOG_ERROR, "Cannot open %s", path_.c_str()); |
| 272 | return false; |
| 273 | } |
| 274 | |
| 275 | // Cannot run more than 30 times / a bit more than one second. |
| 276 | for (int i = 0;; i++) { |
| 277 | int ret = |
| 278 | sqlite3_exec(hDB_, "BEGIN EXCLUSIVE", nullptr, nullptr, nullptr); |
| 279 | if (ret == SQLITE_OK) { |
| 280 | break; |
| 281 | } |
| 282 | if (ret != SQLITE_BUSY) { |
| 283 | pj_log(ctx_, PJ_LOG_ERROR, "%s", sqlite3_errmsg(hDB_)); |
| 284 | sqlite3_close(hDB_); |
| 285 | hDB_ = nullptr; |
| 286 | return false; |
| 287 | } |
| 288 | const char *max_iters = getenv("PROJ_LOCK_MAX_ITERS"); |
| 289 | if (i >= (max_iters && max_iters[0] ? atoi(max_iters) |
| 290 | : 30)) { // A bit more than 1 second |
| 291 | pj_log(ctx_, PJ_LOG_ERROR, "Cannot take exclusive lock on %s", |
| 292 | path_.c_str()); |
| 293 | sqlite3_close(hDB_); |
| 294 | hDB_ = nullptr; |
| 295 | return false; |
| 296 | } |
| 297 | pj_log(ctx_, PJ_LOG_TRACE, "Lock taken on cache. Waiting a bit..."); |
| 298 | // Retry every 5 ms for 50 ms, then every 10 ms for 100 ms, then |
| 299 | // every 100 ms |
| 300 | sleep_ms(i < 10 ? 5 : i < 20 ? 10 : 100); |
| 301 | } |
| 302 | char **pasResult = nullptr; |
| 303 | int nRows = 0; |
| 304 | int nCols = 0; |
| 305 | sqlite3_get_table(hDB_, |
| 306 | "SELECT 1 FROM sqlite_master WHERE name = 'properties'", |
| 307 | &pasResult, &nRows, &nCols, nullptr); |
| 308 | sqlite3_free_table(pasResult); |
| 309 | if (nRows == 0) { |
| 310 | if (!createDBStructure()) { |
| 311 | sqlite3_close(hDB_); |
| 312 | hDB_ = nullptr; |
| 313 | return false; |