/*
 * Copyright 2013 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: pulkitg@google.com (Pulkit Goyal)

#include "pagespeed/opt/http/two_level_property_store.h"

#include "base/logging.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/callback.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/opt/http/abstract_property_store_get_callback.h"
#include "pagespeed/opt/http/property_cache.pb.h"

namespace net_instaweb {

namespace {

// This class manages the lookup across two property stores. This class ensures
// following things:
// - If lookup was successful and all cohorts are available in
//   primary_property_store, then call the done_ callback without calling
//   lookup on secondary_property_store.
// - If lookup was not successful or some of the cohorts are not available in
//   primary_property_store, then issue a lookup on secondary_property_store.
// - If FastFinishLookup is called, it checks:
//   - If primary_property_store lookup is not yet finished, then wait until
//     primary lookup is finished and after it is finished, call the the done_
//     callback even if all the cohort are not available and don't issue
//     secondary lookup.
//   - If primary_property_store lookup is finished and secondary lookup is in
//     progress, then call FinishFastLookup on secondary property store, so
//     that done_ callback can be called as soon as possible.
//   - If both lookups are finished, do nothing.
// - If DeleteWhenDone() is called, it checks:
//   - If both lookups are done, delete itself.
//   - If lookup is in progress, mark a bit delete_when_done_ to true, so that
//     it deletes itself whenever lookup is finished.
class TwoLevelPropertyStoreGetCallback
    : public AbstractPropertyStoreGetCallback {
 public:
  typedef Callback1<bool> BoolCallback;
  TwoLevelPropertyStoreGetCallback(
      const GoogleString& url,
      const GoogleString& options_signature_hash,
      const GoogleString& cache_key_suffix,
      const PropertyCache::CohortVector& cohort_list,
      PropertyPage* page,
      BoolCallback* done,
      AbstractMutex* mutex,
      PropertyStore* primary_property_store,
      PropertyStore* secondary_property_store)
      : url_(url),
        options_signature_hash_(options_signature_hash),
        cache_key_suffix_(cache_key_suffix),
        page_(page),
        done_(done),
        mutex_(mutex),
        primary_property_store_(primary_property_store),
        secondary_property_store_(secondary_property_store),
        secondary_property_store_get_callback_(NULL),
        fast_finish_lookup_called_(false),
        lookup_level_(kFirstLevelLooking),
        delete_when_done_(false),
        first_level_result_(false),
        secondary_lookup_(false) {
    for (int j = 0, n = cohort_list.size(); j < n; ++j) {
      const PropertyCache::Cohort* cohort = cohort_list[j];
      cohort_list_.push_back(cohort);
    }
  }

  virtual ~TwoLevelPropertyStoreGetCallback() {
    if (secondary_property_store_get_callback_ != NULL) {
      secondary_property_store_get_callback_->DeleteWhenDone();
    }
  }

  virtual void FastFinishLookup() {
    AbstractPropertyStoreGetCallback* secondary_property_store_get_callback =
        NULL;
    {
      ScopedMutex lock(mutex_.get());
      fast_finish_lookup_called_ = true;
      if (lookup_level_ != kSecondLevelLooking) {
        // Return without calling the done_ callback if:
        // First level lookup is in progress : We always want first level lookup
        //     to be completed.
        // Both lookup are completed: done_ callback was already called by
        //     Done() function.
        return;
      }

      DCHECK(secondary_property_store_get_callback_ != NULL);
      secondary_property_store_get_callback =
          secondary_property_store_get_callback_;
    }

    // Fast finish the lookup from secondary property store.
    secondary_property_store_get_callback->FastFinishLookup();
  }

  virtual void DeleteWhenDone() {
    {
      ScopedMutex lock(mutex_.get());
      delete_when_done_ = true;
      // We should only ever delete ourselves if lookup is done.
      if (!ShouldDeleteLocked()) {
        return;
      }
    }

    delete this;
  }

  // Called after the primary lookup is done.
  void PrimaryLookupDone(bool success) {
    bool should_delete = false;
    BoolCallback* done = NULL;
    {
      ScopedMutex lock(mutex_.get());
      first_level_result_ = success;

      // Check if it is FastFinishLookup() is called or lookup for any cohort
      // ended up in a miss.
      for (int j = 0, n = cohort_list_.size(); j < n; ++j) {
        // Collect all the cohorts which is not present after lookup in
        // primary_property_store is done.
        const PropertyCache::Cohort* cohort = cohort_list_[j];
        if (!page_->IsCohortPresent(cohort)) {
          secondary_lookup_cohort_list_.push_back(cohort);
        }
      }

      if (fast_finish_lookup_called_ || secondary_lookup_cohort_list_.empty()) {
        lookup_level_ = kDone;
        done = done_;
        done_ = NULL;

        // We should only ever delete ourselves if we've been canceled or we got
        // results for all cohorts from the first level property store.
        should_delete = ShouldDeleteLocked();
      } else {
        secondary_lookup_ = true;
        // Do not issue the secondary level lookup while holding mutex as it may
        // lead to deadlock if secondary lookup finishes in the same thread and
        // call Done which also tries to get the Mutex.
      }
      DCHECK(!(should_delete && (lookup_level_ != kDone)));
    }

    if (!secondary_lookup_) {
      // Run the done_ callback if secondary lookup is not needed and the delete
      // the callback if DeleteWhenDone is already called.
      done->Run(success);
      if (should_delete) {
        delete this;
      }
      return;
    }

    // Second level lookup will be initiated only if FastFinishLookup() is not
    // called and some cohorts are not found in first level lookup.
    IssueSecondaryGet();
  }

  void SecondaryLookupDone(bool success) {
    bool should_delete = false;
    BoolCallback* done = NULL;
    {
      ScopedMutex lock(mutex_.get());
      DCHECK(done_ != NULL);

      // Second Level lookup finished.
      lookup_level_ = kDone;
      success |= first_level_result_;
      done = done_;
      done_ = NULL;

      // We should only ever delete ourselves if all internal states are
      // updated.
      should_delete = ShouldDeleteLocked();
    }
    if (success) {
      for (int j = 0, n = secondary_lookup_cohort_list_.size(); j < n; ++j) {
        const PropertyCache::Cohort* cohort = secondary_lookup_cohort_list_[j];
        PropertyCacheValues values;
        if (page_->EncodePropertyCacheValues(cohort, &values)) {
          primary_property_store_->Put(
              url_,
              options_signature_hash_,
              cache_key_suffix_,
              cohort,
              &values,
              NULL);
        }
      }
    }

    // No class level variable is safe to use beyond this point.
    done->Run(success);
    if (should_delete) {
      delete this;
    }
  }

 private:
  // Issue lookup from secondary_primary_store.
  void IssueSecondaryGet() {
    AbstractPropertyStoreGetCallback* secondary_property_store_get_callback =
        NULL;
    secondary_property_store_->Get(
        url_,
        options_signature_hash_,
        cache_key_suffix_,
        secondary_lookup_cohort_list_,
        page_,
        NewCallback(this,
                    &TwoLevelPropertyStoreGetCallback::SecondaryLookupDone),
        &secondary_property_store_get_callback);

    bool fast_finish_lookup_called = false;
    bool should_delete = false;
    {
      ScopedMutex lock(mutex_.get());
      secondary_property_store_get_callback_ =
          secondary_property_store_get_callback;
      // lookup_level_ will be kDone if secondary lookup finishes immediately.
      if (lookup_level_ != kDone) {
        lookup_level_ = kSecondLevelLooking;
        fast_finish_lookup_called = fast_finish_lookup_called_;
      } else {
        // We'll only delete ourselves if the second level lookup finished
        // inline.
        should_delete = ShouldDeleteLocked();
      }
    }

    if (fast_finish_lookup_called) {
      // FastFinishLookup() is called before
      // secondary_property_store_get_callback is assigned.
      secondary_property_store_get_callback->FastFinishLookup();
    }

    if (should_delete) {
      delete this;
    }
  }

  // Returns true if it is safe to delete this callback, false otherwise.
  bool ShouldDeleteLocked() {
    mutex_->DCheckLocked();
    if (secondary_lookup_ &&
        secondary_property_store_get_callback_ == NULL) {
      // We've decided to issue the second lookup but haven't yet updated our
      // internal state.
      return false;
    }

    if (lookup_level_ != kDone) {
      // Lookup is not yet finished.
      return false;
    }

    if (!delete_when_done_) {
      // DeleteWhenDone() is not yet called.
      return false;
    }

    // Safe to delete the callback.
    return true;
  }

  enum LookupLevel {
    kFirstLevelLooking,   // Lookup from primary_property_store is in progress.
    kSecondLevelLooking,  // Lookup from secondary_property_store is in
                          // progress.
    kDone,                // Lookup is finished.
  };

  GoogleString url_;
  GoogleString options_signature_hash_;
  const GoogleString& cache_key_suffix_;
  PropertyCache::CohortVector cohort_list_;
  PropertyPage* page_;  // page_ becomes NULL as soon as Done() is called.
  BoolCallback* done_;
  scoped_ptr<AbstractMutex> mutex_;
  PropertyStore* primary_property_store_;
  PropertyStore* secondary_property_store_;
  AbstractPropertyStoreGetCallback* secondary_property_store_get_callback_;
  bool fast_finish_lookup_called_;
  LookupLevel lookup_level_;
  bool delete_when_done_;
  bool first_level_result_;
  bool secondary_lookup_;
  PropertyCache::CohortVector secondary_lookup_cohort_list_;
  DISALLOW_COPY_AND_ASSIGN(TwoLevelPropertyStoreGetCallback);
};

}  // namespace

TwoLevelPropertyStore::TwoLevelPropertyStore(
    PropertyStore* primary_property_store,
    PropertyStore* secondary_property_store,
    ThreadSystem* thread_system)
    : primary_property_store_(primary_property_store),
      secondary_property_store_(secondary_property_store),
      thread_system_(thread_system) {
  CHECK(primary_property_store_ != NULL);
  CHECK(secondary_property_store_ != NULL);
  secondary_property_store_->set_enable_get_cancellation(true);
}

TwoLevelPropertyStore::~TwoLevelPropertyStore() {
}

void TwoLevelPropertyStore::Get(
    const GoogleString& url,
    const GoogleString& options_signature_hash,
    const GoogleString& cache_key_suffix,
    const PropertyCache::CohortVector& cohort_list,
    PropertyPage* page,
    BoolCallback* done,
    AbstractPropertyStoreGetCallback** callback) {
  TwoLevelPropertyStoreGetCallback* two_level_property_store_get_callback =
      new TwoLevelPropertyStoreGetCallback(
          url,
          options_signature_hash,
          cache_key_suffix,
          cohort_list,
          page,
          done,
          thread_system_->NewMutex(),
          primary_property_store_,
          secondary_property_store_);
  *callback = two_level_property_store_get_callback;

  AbstractPropertyStoreGetCallback* primary_property_store_get_callback = NULL;
  primary_property_store_->Get(
      url,
      options_signature_hash,
      cache_key_suffix,
      cohort_list,
      page,
      NewCallback(two_level_property_store_get_callback,
                  &TwoLevelPropertyStoreGetCallback::PrimaryLookupDone),
      &primary_property_store_get_callback);

  if (primary_property_store_get_callback != NULL) {
    // Delete the primary store get callback when it is done as it is not needed
    // any more.
    primary_property_store_get_callback->DeleteWhenDone();
  }
}

void TwoLevelPropertyStore::Put(
    const GoogleString& url,
    const GoogleString& options_signature_hash,
    const GoogleString& cache_key_suffix,
    const PropertyCache::Cohort* cohort,
    const PropertyCacheValues* values,
    BoolCallback* done) {
  // TODO(pulkitg): Pass actual callback instead of NULL.
  primary_property_store_->Put(
      url, options_signature_hash, cache_key_suffix, cohort, values, NULL);
  secondary_property_store_->Put(
      url, options_signature_hash, cache_key_suffix, cohort, values, NULL);
  if (done != NULL) {
    done->Run(true);
  }
}

GoogleString TwoLevelPropertyStore::Name() const {
  return StrCat(
      "1:", primary_property_store_->Name(),
      ",2:", secondary_property_store_->Name());
}

}  // namespace net_instaweb
