/*
 * Copyright 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Author: lsong@google.com (Libo Song)

#ifndef PAGESPEED_KERNEL_CACHE_FILE_CACHE_H_
#define PAGESPEED_KERNEL_CACHE_FILE_CACHE_H_

#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/cache_interface.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/thread_system.h"

namespace net_instaweb {

class FileSystem;
class Hasher;
class MessageHandler;
class SharedString;
class SlowWorker;
class Statistics;
class Timer;
class Variable;

// Simple C++ implementation of file cache.
class FileCache : public CacheInterface {
 public:
  struct CachePolicy {
    CachePolicy(Timer* timer, Hasher* hasher, int64 clean_interval_ms,
                int64 target_size_bytes, int64 target_inode_count)
        : timer(timer), hasher(hasher), clean_interval_ms(clean_interval_ms),
          target_size_bytes(target_size_bytes),
          target_inode_count(target_inode_count) {}
    const Timer* timer;
    const Hasher* hasher;
    int64 clean_interval_ms;
    int64 target_size_bytes;
    int64 target_inode_count;
    bool cleaning_enabled() { return clean_interval_ms != kDisableCleaning; }
   private:
    DISALLOW_COPY_AND_ASSIGN(CachePolicy);
  };

  FileCache(const GoogleString& path, FileSystem* file_system,
            ThreadSystem* thread_system, SlowWorker* worker,
            CachePolicy* policy, Statistics* stats, MessageHandler* handler);
  virtual ~FileCache();

  static void InitStats(Statistics* statistics);

  virtual void Get(const GoogleString& key, Callback* callback);
  virtual void Put(const GoogleString& key, SharedString* value);
  virtual void Delete(const GoogleString& key);
  void set_worker(SlowWorker* worker) { worker_ = worker; }
  SlowWorker* worker() { return worker_; }

  static GoogleString FormatName() { return "FileCache"; }
  virtual GoogleString Name() const { return FormatName(); }

  virtual bool IsBlocking() const { return true; }
  virtual bool IsHealthy() const { return true; }
  virtual void ShutDown() {}  // TODO(jmarantz): implement.

  const CachePolicy* cache_policy() const { return cache_policy_.get(); }
  CachePolicy* mutable_cache_policy() { return cache_policy_.get(); }
  const GoogleString& path() const { return path_; }

  // Variable names.
  static const char kBytesFreedInCleanup[];
  // Number of times we actually cleaned cache because usage was high enough.
  static const char kCleanups[];
  // Number of times we checked disk usage in preparation from cleanup.
  static const char kDiskChecks[];
  // Files evicted from cache during cleanup.
  static const char kEvictions[];
  static const char kWriteErrors[];

  // What to set clean_interval_ms to in order to disable cleaning.  This needs
  // to be -1, because that's what we have in our public documentation.
  static const int kDisableCleaning = -1;

 private:
  class CacheCleanFunction;
  friend class FileCacheTest;
  friend class CacheCleanFunction;

  // Attempts to clean the cache. Returns false if we failed and the cache still
  // needs to be cleaned. Returns true if everything's fine. This may take a
  // while. It's OK for others to write and read from the cache while this is
  // going on, but try to avoid Cleaning from two threads at the same time. A
  // target_inode_count of 0 means no inode limit is applied.
  bool Clean(int64 target_size_bytes, int64 target_inode_count);

  // Clean the cache, taking care of interprocess locking, as well as timestamp
  // update.
  void CleanWithLocking(int64 next_clean_time_ms) LOCKS_EXCLUDED(mutex_);

  // Return true if we need to clean the cache, and updates the next
  // clean time if cleaning does not need to be run.
  bool ShouldClean(int64* suggested_next_clean_time_ms) LOCKS_EXCLUDED(mutex_);

  // Check to see if it's time to clean the cache, and if so ask
  // worker_ to do it in a thread if it's not busy. Stores 'true' into
  // last_conditional_clean_result_ if it actually cleaned successfully,
  // false otherwise.
  void CleanIfNeeded() LOCKS_EXCLUDED(mutex_);

  bool EncodeFilename(const GoogleString& key, GoogleString* filename);

  const GoogleString path_;
  FileSystem* file_system_;
  SlowWorker* worker_;
  MessageHandler* message_handler_;
  const scoped_ptr<CachePolicy> cache_policy_;
  scoped_ptr<AbstractMutex> mutex_;
  int64 next_clean_ms_ GUARDED_BY(mutex_);
  int path_length_limit_;  // Maximum total length of path file_system_ supports
  // The full paths to our cleanup timestamp and lock files.
  GoogleString clean_time_path_;
  GoogleString clean_lock_path_;

  Variable* disk_checks_;
  Variable* cleanups_;
  Variable* evictions_;
  Variable* bytes_freed_in_cleanup_;
  Variable* write_errors_;

  // The filename where we keep the next scheduled cleanup time in seconds.
  static const char kCleanTimeName[];
  // The name of the global mutex protecting reads and writes to that file.
  static const char kCleanLockName[];

  DISALLOW_COPY_AND_ASSIGN(FileCache);
};

}  // namespace net_instaweb

#endif  // PAGESPEED_KERNEL_CACHE_FILE_CACHE_H_
