Index: chromeos/printing/ppd_cache.cc |
diff --git a/chromeos/printing/ppd_cache.cc b/chromeos/printing/ppd_cache.cc |
index 44abfd9565168c4122bf1cf794be57929bea3c7b..918b0e84cf9426a14b1565dab0dc7520354cf35a 100644 |
--- a/chromeos/printing/ppd_cache.cc |
+++ b/chromeos/printing/ppd_cache.cc |
@@ -15,6 +15,8 @@ |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/string_util.h" |
#include "base/synchronization/lock.h" |
+#include "base/task_runner_util.h" |
+#include "base/task_scheduler/post_task.h" |
#include "base/threading/sequenced_task_runner_handle.h" |
#include "base/threading/thread_restrictions.h" |
#include "base/time/time.h" |
@@ -28,138 +30,125 @@ namespace chromeos { |
namespace printing { |
namespace { |
-class PpdCacheImpl : public PpdCache { |
- public: |
- PpdCacheImpl(const base::FilePath& cache_base_dir, |
- const scoped_refptr<base::SequencedTaskRunner>& disk_task_runner) |
- : cache_base_dir_(cache_base_dir), disk_task_runner_(disk_task_runner) {} |
- |
- // Public API functions. |
- void Find(const std::string& key, const FindCallback& cb) override { |
- // Ensure the cache lives until the op is over. |
- AddRef(); |
- ++inflight_ops_; |
- disk_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&PpdCacheImpl::FindImpl, this, key, |
- base::SequencedTaskRunnerHandle::Get(), cb)); |
- } |
+// Return the (full) path to the file we expect to find the given key at. |
+base::FilePath FilePathForKey(const base::FilePath& base_dir, |
+ const std::string& key) { |
+ std::string hashed_key = crypto::SHA256HashString(key); |
+ return base_dir.Append(base::HexEncode(hashed_key.data(), hashed_key.size())); |
+} |
- // Store the given contents at the given key. If cb is non-null, it will |
- // be invoked on completion. |
- void Store(const std::string& key, |
- const std::string& contents, |
- const base::Callback<void()>& cb) override { |
- AddRef(); |
- ++inflight_ops_; |
- disk_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&PpdCacheImpl::StoreImpl, this, key, contents, |
- base::SequencedTaskRunnerHandle::Get(), cb)); |
+// If the cache doesn't already exist, create it. |
+void MaybeCreateCache(const base::FilePath& base_dir) { |
+ if (!base::PathExists(base_dir)) { |
+ base::CreateDirectory(base_dir); |
} |
+} |
- bool Idle() const override { return inflight_ops_ == 0; } |
- |
- private: |
- ~PpdCacheImpl() override {} |
- |
- // If the cache doesn't already exist, create it. |
- void MaybeCreateCache() { |
- if (!base::PathExists(cache_base_dir_)) { |
- base::CreateDirectory(cache_base_dir_); |
- } |
+// Find implementation, blocks on file access. Must be run on a thread that |
+// allows I/O. |
+PpdCache::FindResult FindImpl(const base::FilePath& cache_dir, |
+ const std::string& key) { |
+ base::ThreadRestrictions::AssertIOAllowed(); |
+ |
+ PpdCache::FindResult result; |
+ result.success = false; |
+ if (!base::PathExists(cache_dir)) { |
+ // If the cache dir was missing, we'll miss anyway. |
+ return result; |
} |
- // Find implementation, runs on the i/o thread. |
- void FindImpl(const std::string& key, |
- const scoped_refptr<base::SequencedTaskRunner>& callback_runner, |
- const FindCallback& cb) { |
- base::ThreadRestrictions::AssertIOAllowed(); |
- FindResult result; |
- result.success = false; |
- MaybeCreateCache(); |
- base::File file(FilePathForKey(key), |
- base::File::FLAG_OPEN | base::File::FLAG_READ); |
- |
- if (file.IsValid()) { |
- int64_t len = file.GetLength(); |
- if (len >= static_cast<int64_t>(crypto::kSHA256Length) && |
- len <= static_cast<int64_t>(kMaxPpdSizeBytes) + |
- static_cast<int64_t>(crypto::kSHA256Length)) { |
- std::unique_ptr<char[]> buf(new char[len]); |
- if (file.ReadAtCurrentPos(buf.get(), len) == len) { |
- base::StringPiece contents(buf.get(), len - crypto::kSHA256Length); |
- base::StringPiece checksum(buf.get() + len - crypto::kSHA256Length, |
- crypto::kSHA256Length); |
- if (crypto::SHA256HashString(contents) == checksum) { |
- base::File::Info info; |
- if (file.GetInfo(&info)) { |
- result.success = true; |
- result.age = base::Time::Now() - info.last_modified; |
- contents.CopyToString(&result.contents); |
- } |
- } else { |
- LOG(ERROR) << "Bad checksum for cache key " << key; |
+ base::File file(FilePathForKey(cache_dir, key), |
+ base::File::FLAG_OPEN | base::File::FLAG_READ); |
+ |
+ if (file.IsValid()) { |
+ int64_t len = file.GetLength(); |
+ if (len >= static_cast<int64_t>(crypto::kSHA256Length) && |
+ len <= static_cast<int64_t>(kMaxPpdSizeBytes) + |
+ static_cast<int64_t>(crypto::kSHA256Length)) { |
+ std::unique_ptr<char[]> buf(new char[len]); |
+ if (file.ReadAtCurrentPos(buf.get(), len) == len) { |
+ base::StringPiece contents(buf.get(), len - crypto::kSHA256Length); |
+ base::StringPiece checksum(buf.get() + len - crypto::kSHA256Length, |
+ crypto::kSHA256Length); |
+ if (crypto::SHA256HashString(contents) == checksum) { |
+ base::File::Info info; |
+ if (file.GetInfo(&info)) { |
+ result.success = true; |
+ result.age = base::Time::Now() - info.last_modified; |
+ contents.CopyToString(&result.contents); |
} |
+ } else { |
+ LOG(ERROR) << "Bad checksum for cache key " << key; |
} |
} |
} |
- callback_runner->PostTask(FROM_HERE, |
- base::Bind(&PpdCacheImpl::ReplyAndRelease, this, |
- base::Bind(cb, result))); |
} |
- // If |cb| is non-null, invoke it on this thread, then decrement the refcount. |
- void ReplyAndRelease(const base::Callback<void()>& cb) { |
- if (!cb.is_null()) { |
- cb.Run(); |
- } |
- --inflight_ops_; |
- Release(); |
- // Object may be destroyed here, so no further access to object data |
- // allowed. |
- } |
+ return result; |
+} |
- // Store implementation, runs on the i/o thread. |
- void StoreImpl( |
- const std::string& key, |
- const std::string& contents, |
- const scoped_refptr<base::SequencedTaskRunner>& callback_runner, |
- const base::Callback<void()> cb) { |
- base::ThreadRestrictions::AssertIOAllowed(); |
- MaybeCreateCache(); |
- if (contents.size() > kMaxPpdSizeBytes) { |
- LOG(ERROR) << "Ignoring attempt to cache large object"; |
- } else { |
- auto path = FilePathForKey(key); |
- base::File file(path, |
- base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); |
- std::string checksum = crypto::SHA256HashString(contents); |
- if (!file.IsValid() || |
- file.WriteAtCurrentPos(contents.data(), contents.size()) != |
- static_cast<int>(contents.size()) || |
- file.WriteAtCurrentPos(checksum.data(), checksum.size()) != |
- static_cast<int>(checksum.size())) { |
- LOG(ERROR) << "Failed to create ppd cache file"; |
- file.Close(); |
- if (!base::DeleteFile(path, false)) { |
- LOG(ERROR) << "Failed to cleanup failed creation."; |
- } |
+// Store implementation, blocks on file access. Must be run on a thread that |
+// allows I/O. |
+void StoreImpl(const base::FilePath& cache_dir, |
+ const std::string& key, |
+ const std::string& contents) { |
+ base::ThreadRestrictions::AssertIOAllowed(); |
+ |
+ MaybeCreateCache(cache_dir); |
+ if (contents.size() > kMaxPpdSizeBytes) { |
+ LOG(ERROR) << "Ignoring attempt to cache large object"; |
+ } else { |
+ auto path = FilePathForKey(cache_dir, key); |
+ base::File file(path, |
+ base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); |
+ std::string checksum = crypto::SHA256HashString(contents); |
+ if (!file.IsValid() || |
+ file.WriteAtCurrentPos(contents.data(), contents.size()) != |
+ static_cast<int>(contents.size()) || |
+ file.WriteAtCurrentPos(checksum.data(), checksum.size()) != |
+ static_cast<int>(checksum.size())) { |
+ LOG(ERROR) << "Failed to create ppd cache file"; |
+ file.Close(); |
+ if (!base::DeleteFile(path, false)) { |
+ LOG(ERROR) << "Failed to cleanup failed creation."; |
} |
} |
- callback_runner->PostTask( |
- FROM_HERE, base::Bind(&PpdCacheImpl::ReplyAndRelease, this, cb)); |
} |
+} |
- // Return the (full) path to the file we expect to find the given key at. |
- base::FilePath FilePathForKey(const std::string& key) { |
- std::string hashed_key = crypto::SHA256HashString(key); |
- return cache_base_dir_.Append( |
- base::HexEncode(hashed_key.data(), hashed_key.size())); |
+class PpdCacheImpl : public PpdCache { |
+ public: |
+ explicit PpdCacheImpl(const base::FilePath& cache_base_dir) |
+ : cache_base_dir_(cache_base_dir), |
+ fetch_task_runner_(base::CreateSequencedTaskRunnerWithTraits( |
+ {base::TaskPriority::USER_VISIBLE, base::MayBlock(), |
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), |
+ store_task_runner_(base::CreateSequencedTaskRunnerWithTraits( |
+ {base::TaskPriority::BACKGROUND, base::MayBlock(), |
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN})) {} |
+ |
+ // Public API functions. |
+ void Find(const std::string& key, const FindCallback& cb) override { |
+ base::PostTaskAndReplyWithResult( |
+ fetch_task_runner_.get(), FROM_HERE, |
+ base::Bind(&FindImpl, cache_base_dir_, key), cb); |
} |
- int inflight_ops_ = 0; |
+ // Store the given contents at the given key. If cb is non-null, it will |
+ // be invoked on completion. |
+ void Store(const std::string& key, |
+ const std::string& contents, |
+ const base::Closure& cb) override { |
+ store_task_runner_->PostTaskAndReply( |
+ FROM_HERE, base::Bind(&StoreImpl, cache_base_dir_, key, contents), cb); |
+ } |
+ |
+ private: |
+ ~PpdCacheImpl() override {} |
base::FilePath cache_base_dir_; |
- scoped_refptr<base::SequencedTaskRunner> disk_task_runner_; |
+ scoped_refptr<base::SequencedTaskRunner> fetch_task_runner_; |
+ scoped_refptr<base::SequencedTaskRunner> store_task_runner_; |
DISALLOW_COPY_AND_ASSIGN(PpdCacheImpl); |
}; |
@@ -167,11 +156,8 @@ class PpdCacheImpl : public PpdCache { |
} // namespace |
// static |
-scoped_refptr<PpdCache> PpdCache::Create( |
- const base::FilePath& cache_base_dir, |
- scoped_refptr<base::SequencedTaskRunner> disk_task_runner) { |
- return scoped_refptr<PpdCache>( |
- new PpdCacheImpl(cache_base_dir, disk_task_runner)); |
+scoped_refptr<PpdCache> PpdCache::Create(const base::FilePath& cache_base_dir) { |
+ return scoped_refptr<PpdCache>(new PpdCacheImpl(cache_base_dir)); |
} |
} // namespace printing |