| 379 | } |
| 380 | |
| 381 | Status LibCache::RefreshCacheEntry(const string& hdfs_lib_file, LibType type, |
| 382 | time_t exp_mtime, const LibMap::iterator& iter, unique_lock<mutex>* entry_lock, |
| 383 | LibCacheEntry** entry) { |
| 384 | // Check if an error occurred on another thread while loading the library. |
| 385 | { |
| 386 | unique_lock<mutex> local_entry_lock((iter->second)->lock); |
| 387 | if (!(iter->second)->loading_status.ok()) { |
| 388 | // If loading_status is already set, the returned *entry should be nullptr. |
| 389 | DCHECK(*entry == nullptr); |
| 390 | return (iter->second)->loading_status; |
| 391 | } |
| 392 | } |
| 393 | |
| 394 | // Refresh the cache entry if needed. A refresh is needed if check_needs_refresh is set |
| 395 | // (e.g., set by ddl) or if the exp_mtime argument is more recent. |
| 396 | // If refreshed or an error occurred, remove the entry and set the returned entry to |
| 397 | // nullptr. |
| 398 | *entry = iter->second; |
| 399 | if ((*entry)->check_needs_refresh || (*entry)->last_mod_time < exp_mtime) { |
| 400 | // Check if file has been modified since loading the cached copy. If so, remove the |
| 401 | // cached entry and create a new one. |
| 402 | (*entry)->check_needs_refresh = false; |
| 403 | hdfsFS hdfs_conn; |
| 404 | Status status = HdfsFsCache::instance()->GetConnection(hdfs_lib_file, &hdfs_conn); |
| 405 | if (!status.ok()) { |
| 406 | RemoveEntryInternal(hdfs_lib_file, iter); |
| 407 | *entry = nullptr; |
| 408 | return status; |
| 409 | } |
| 410 | time_t fs_last_modified_time; |
| 411 | status = |
| 412 | GetLastModificationTime(hdfs_conn, hdfs_lib_file.c_str(), &fs_last_modified_time); |
| 413 | |
| 414 | // Check that the expected last_modified_time is the same as what's on the filesystem. |
| 415 | if (status.ok() && exp_mtime >= 0 && fs_last_modified_time != exp_mtime) { |
| 416 | status = Status(TErrorCode::LIB_VERSION_MISMATCH, hdfs_lib_file, |
| 417 | fs_last_modified_time, exp_mtime); |
| 418 | } |
| 419 | if (!status.ok() || (*entry)->last_mod_time < fs_last_modified_time) { |
| 420 | RemoveEntryInternal(hdfs_lib_file, iter); |
| 421 | *entry = nullptr; |
| 422 | } |
| 423 | RETURN_IF_ERROR(status); |
| 424 | } |
| 425 | |
| 426 | // No refresh needed, the entry can be used. |
| 427 | if (*entry != nullptr) { |
| 428 | // The cache level lock continues to be held while the entry lock is obtained |
| 429 | // so that some other thread does not access the entry and delete it. |
| 430 | unique_lock<mutex> local_entry_lock((*entry)->lock); |
| 431 | entry_lock->swap(local_entry_lock); |
| 432 | |
| 433 | // Let the caller propagate any error that occurred when loading the entry. |
| 434 | RETURN_IF_ERROR((*entry)->copy_file_status); |
| 435 | DCHECK_EQ((*entry)->type, type) << (*entry)->local_path; |
| 436 | DCHECK(!(*entry)->local_path.empty()); |
| 437 | } |
| 438 | return Status::OK(); |
nothing calls this directly
no test coverage detected