/*
 * 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: jmarantz@google.com (Joshua Marantz)

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

#include <memory>
#include <vector>

#include "pagespeed/kernel/base/condvar.h"
#include "pagespeed/kernel/base/dynamic_annotations.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/shared_string.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/thread.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/cache/cache_interface.h"
#include "pagespeed/kernel/cache/cache_test_base.h"

namespace net_instaweb {

CacheSpammer::CacheSpammer(ThreadSystem* runtime,
                           ThreadSystem::ThreadFlags flags,
                           CacheInterface* cache,
                           bool expecting_evictions,
                           bool do_deletes,
                           const char* value_prefix,
                           int index,
                           int num_iters,
                           int num_inserts)
    : Thread(runtime, "cache_spammer", flags),
      cache_(cache),
      expecting_evictions_(expecting_evictions),
      do_deletes_(do_deletes),
      value_prefix_(value_prefix),
      index_(index),
      num_iters_(num_iters),
      num_inserts_(num_inserts),
      mutex_(runtime->NewMutex()),
      condvar_(mutex_->NewCondvar()),
      pending_gets_(0) {
}

CacheSpammer::~CacheSpammer() {
}

namespace {

class SpammerCallback : public CacheInterface::Callback {
 public:
  SpammerCallback(CacheSpammer* spammer, StringPiece key, StringPiece expected)
      : spammer_(spammer),
        validate_candidate_called_(false),
        key_(key.data(), key.size()),
        expected_(expected.data(), expected.size()) {
  }

  virtual ~SpammerCallback() {
  }

  virtual void Done(CacheInterface::KeyState state) {
    DCHECK(validate_candidate_called_);
    bool found = (state == CacheInterface::kAvailable);
    if (found) {
      EXPECT_STREQ(expected_, value()->Value());
    }
    spammer_->GetDone(found, key_);
    delete this;
  }

  virtual bool ValidateCandidate(const GoogleString& key,
                                 CacheInterface::KeyState state) {
    validate_candidate_called_ = true;
    return true;
  }

 private:
  CacheSpammer* spammer_;
  bool validate_candidate_called_;
  GoogleString key_;
  GoogleString expected_;

  DISALLOW_COPY_AND_ASSIGN(SpammerCallback);
};

}  // namespace

void CacheSpammer::RunTests(int num_threads,
                            int num_iters,
                            int num_inserts,
                            bool expecting_evictions, bool do_deletes,
                            const char* value_prefix,
                            CacheInterface* cache,
                            ThreadSystem* thread_runtime) {
  std::vector<CacheSpammer*> spammers(num_threads);

  // First, create all the threads.
  for (int i = 0; i < num_threads; ++i) {
    spammers[i] = new CacheSpammer(
        thread_runtime, ThreadSystem::kJoinable,
        cache,  // lru_cache_.get() will make this fail.
        expecting_evictions, do_deletes, value_prefix, i, num_iters,
        num_inserts);
  }

  // Then, start them.
  for (int i = 0; i < num_threads; ++i) {
    spammers[i]->Start();
  }

  // Finally, wait for them to complete by joining them.
  for (int i = 0; i < num_threads; ++i) {
    spammers[i]->Join();
    delete spammers[i];
  }
}

void CacheSpammer::Run() {
  const char name_pattern[] = "name%d";
  std::vector<SharedString> inserts(num_inserts_);
  for (int j = 0; j < num_inserts_; ++j) {
    inserts[j].Assign(StringPrintf("%s%d", value_prefix_, j));
  }

  int iter_limit = RunningOnValgrind() ? num_iters_ / 100 : num_iters_;
  for (int i = 0; i < iter_limit; ++i) {
    for (int j = 0; j < num_inserts_; ++j) {
      cache_->Put(StringPrintf(name_pattern, j), &inserts[j]);
    }
    {
      ScopedMutex lock(mutex_.get());
      pending_gets_ = num_inserts_;
    }
    for (int j = 0; j < num_inserts_; ++j) {
      // Ignore the result.  Thread interactions will make it hard to
      // predict if the Get will succeed or not.
      GoogleString key = StringPrintf(name_pattern, j);
      cache_->Get(key, new SpammerCallback(this, key, inserts[j].Value()));
    }
    {
      ScopedMutex lock(mutex_.get());
      while (pending_gets_ != 0) {
        condvar_->Wait();
      }
    }
    if (do_deletes_) {
      for (int j = 0; j < num_inserts_; ++j) {
        cache_->Delete(StringPrintf(name_pattern, j));
      }
    }
  }
}

void CacheSpammer::GetDone(bool found, StringPiece key) {
  ScopedMutex lock(mutex_.get());
  --pending_gets_;
  // We cannot assume that a Get succeeds if there are evictions
  // or deletions going on.  But we are still verifying that the code
  // will not crash, and that after the threads have all quiesced,
  // that the cache is still sane.
  EXPECT_TRUE(found || expecting_evictions_ || do_deletes_)
      << "Failed on key " << key;
  if (pending_gets_ == 0) {
    condvar_->Signal();
  }
}

}  // namespace net_instaweb
