/*
 * Copyright 2012 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: jmarantz@google.com (Joshua Marantz)
//
// Contains DelayCache, which lets one inject progammer-controlled
// delays before lookup callback invocation.
//
// See also: MockTimeCache.

#include "pagespeed/kernel/cache/delay_cache.h"

#include <utility>  // for pair.
#include "base/logging.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/function.h"
#include "pagespeed/kernel/base/shared_string.h"
#include "pagespeed/kernel/base/thread_system.h"

namespace net_instaweb {

// Implements CacheInterface::Callback so underlying cache implementation
// can notify the DelayCache that a value is available.
class DelayCache::DelayCallback : public CacheInterface::Callback {
 public:
  DelayCallback(const GoogleString& key, DelayCache* delay_cache,
                Callback* orig_callback)
      : delay_cache_(delay_cache),
        orig_callback_(orig_callback),
        key_(key),
        state_(kNotFound) {
  }

  virtual ~DelayCallback() {}

  virtual bool ValidateCandidate(const GoogleString& key, KeyState state) {
    *orig_callback_->value() = *value();
    return orig_callback_->DelegatedValidateCandidate(key, state);
  }

  virtual void Done(KeyState state) {
    *orig_callback_->value() = *value();
    state_ = state;
    delay_cache_->LookupComplete(this);
  }

  // Helper method so that DelayCache can call the callback for keys
  // that are not being delayed, or for keys that have been released.
  void Run() {
    Callback* callback = orig_callback_;
    KeyState state = state_;
    delete this;
    callback->DelegatedDone(state);
  }

  const GoogleString& key() const { return key_; }

 private:
  DelayCache* delay_cache_;
  Callback* orig_callback_;
  GoogleString key_;
  KeyState state_;

  DISALLOW_COPY_AND_ASSIGN(DelayCallback);
};

DelayCache::DelayCache(CacheInterface* cache, ThreadSystem* thread_system)
    : cache_(cache),
      mutex_(thread_system->NewMutex()) {
}

DelayCache::~DelayCache() {
  CHECK(delay_requests_.empty());
  CHECK(delay_map_.empty());
}

GoogleString DelayCache::FormatName(StringPiece name) {
  return StrCat("DelayCache(", name, ")");
}

void DelayCache::LookupComplete(DelayCallback* callback) {
  {
    ScopedMutex lock(mutex_.get());
    StringSet::iterator p = delay_requests_.find(callback->key());
    if (p != delay_requests_.end()) {
      CHECK(delay_map_.find(callback->key()) == delay_map_.end());
      delay_map_[callback->key()] = callback;
      callback = NULL;  // Don't run it; we are delaying it.
    }
  }

  // Release lock first; then run callback.
  if (callback != NULL) {
    callback->Run();
  }
}

void DelayCache::DelayKey(const GoogleString& key) {
  ScopedMutex lock(mutex_.get());
  delay_requests_.insert(key);
}

void DelayCache::ReleaseKeyInSequence(const GoogleString& key,
                                      QueuedWorkerPool::Sequence* sequence) {
  DelayCallback* callback = NULL;
  {
    ScopedMutex lock(mutex_.get());
    int erased = delay_requests_.erase(key);
    CHECK_EQ(1, erased);
    DelayMap::iterator p = delay_map_.find(key);

    // If the physical cache lookup has not completed yet, then we can simply
    // simply forget that we tried to delay it.
    if (p != delay_map_.end()) {
      callback = p->second;
      delay_map_.erase(p);
    }
  }

  // Release lock first; then run callback or add it to the sequence.
  if (callback != NULL) {
    if (sequence != NULL) {
      sequence->Add(MakeFunction(callback, &DelayCallback::Run));
    } else {
      callback->Run();
    }
  }
}

void DelayCache::Get(const GoogleString& key, Callback* callback) {
  cache_->Get(key, new DelayCallback(key, this, callback));
}

void DelayCache::MultiGet(MultiGetRequest* request) {
  for (int i = 0, n = request->size(); i < n; ++i) {
    KeyCallback* key_callback = &(*request)[i];
    DelayCallback* cb = new DelayCallback(key_callback->key, this,
                                          key_callback->callback);
    key_callback->callback = cb;
  }
  cache_->MultiGet(request);
}

void DelayCache::Put(const GoogleString& key, SharedString* value) {
  cache_->Put(key, value);
}

void DelayCache::Delete(const GoogleString& key) {
  cache_->Delete(key);
}

}  // namespace net_instaweb
