/*
 * 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: anupama@google.com (Anupama Dutta)

#include "net/instaweb/rewriter/public/downstream_cache_purger.h"

#include "net/instaweb/http/public/async_fetch.h"
#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/http/public/url_async_fetcher.h"
#include "net/instaweb/public/global_constants.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/rewrite_stats.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/thread_annotations.h"
#include "pagespeed/kernel/http/google_url.h"
#include "pagespeed/kernel/http/http_names.h"
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/kernel/http/response_headers.h"

namespace net_instaweb {

namespace {

class StringAsyncFetchWithAsyncCountUpdates : public StringAsyncFetch {
 public:
  StringAsyncFetchWithAsyncCountUpdates(const RequestContextPtr& ctx,
                                        RewriteDriver* driver)
      : StringAsyncFetch(ctx),
        driver_(driver) {
    driver_->IncrementAsyncEventsCount();
  }

  virtual ~StringAsyncFetchWithAsyncCountUpdates() { }

  virtual void HandleDone(bool success) {
    if (response_headers()->status_code() == HttpStatus::kOK) {
      driver_->server_context()->rewrite_stats()->
          successful_downstream_cache_purges()->Add(1);
    }
    StringAsyncFetch::HandleDone(success);
    driver_->DecrementAsyncEventsCount();
    delete this;
  }

 private:
  RewriteDriver* driver_;

  DISALLOW_COPY_AND_ASSIGN(StringAsyncFetchWithAsyncCountUpdates);
};

}  // namespace

DownstreamCachePurger::DownstreamCachePurger(RewriteDriver* driver)
    : driver_(driver),
      made_downstream_purge_attempt_(false) {
}

DownstreamCachePurger::~DownstreamCachePurger() {}

void DownstreamCachePurger::Clear() {
  purge_url_.clear();
  purge_method_.clear();
  made_downstream_purge_attempt_ = false;
}

bool DownstreamCachePurger::GeneratePurgeRequestParameters(
    const GoogleUrl& page_url) {
  purge_url_ = StrCat(
      driver_->options()->downstream_cache_purge_location_prefix(),
      page_url.PathAndLeaf());
  purge_method_ = driver_->options()->downstream_cache_purge_method();
  return (!purge_url_.empty() && !purge_method_.empty());
}

// This function uses a few variables gaurded by rewrite_mutex() without locking
// it, but we should not have concurrent responses at this point so thread
// safety analysis is disabled.
bool DownstreamCachePurger::ShouldPurgeRewrittenResponse(
    const GoogleUrl& google_url) NO_THREAD_SAFETY_ANALYSIS {
  if (!driver_->options()->IsDownstreamCacheIntegrationEnabled()) {
    // Downstream caching is not enabled.
    return false;
  }
  if (driver_->num_initiated_rewrites() == 0) {
    // No rewrites were initiated. Could happen if the rewriters
    // enabled don't apply on the page, or apply instantly (e.g.
    // collapse whitespace).
    return false;
  }
  // Figure out what percentage of the rewriting was done before the
  // response was served out, so that we can initiate a cache purge if there
  // was significant amount of rewriting remaining to be done.
  float served_rewritten_percentage =
      ((driver_->num_initiated_rewrites() - driver_->num_detached_rewrites()) *
       100.0) /
       driver_->num_initiated_rewrites();
  if (served_rewritten_percentage <
      driver_->options()->downstream_cache_rewritten_percentage_threshold()) {
    driver_->message_handler()->Message(
        kInfo,
        "Should purge \"%s\" which was served with only %d%% rewriting done.",
        google_url.spec_c_str(),
        static_cast<int>(served_rewritten_percentage));
    return true;
  }
  return false;
}

void DownstreamCachePurger::PurgeDownstreamCache() {
  // TODO(anupama): Use purge_method actually.
  StringAsyncFetchWithAsyncCountUpdates* dummy_fetch =
      new StringAsyncFetchWithAsyncCountUpdates(driver_->request_context(),
                                                driver_);
  // Add a purge-related header so that the purge request does not
  // get us into a loop.
  dummy_fetch->request_headers()->CopyFrom(*driver_->request_headers());
  dummy_fetch->request_headers()->Add(kPsaPurgeRequest, "1");
  if (purge_method_ == "PURGE") {
    dummy_fetch->request_headers()->set_method(RequestHeaders::kPurge);
  }
  // Record the fact that a purge attempt has been made so that we do not
  // issue multiple purges using the same RewriteDriver object.
  made_downstream_purge_attempt_ = true;

  driver_->message_handler()->Message(kInfo,
                                      "Purge url is %s", purge_url_.c_str());
  driver_->async_fetcher()->Fetch(purge_url_, driver_->message_handler(),
                                  dummy_fetch);
}

bool DownstreamCachePurger::MaybeIssuePurge(const GoogleUrl& google_url) {
  // If any of the following conditions are satisfied, we do not issue a purge:
  // a) a purge attempt has already been made
  // b) request headers have not been set
  // c) this is a looped back purge request
  // d) rewritten response is not optimized enough to warrant a purge
  // e) valid purge URL or method are unavailable
  if (!made_downstream_purge_attempt_ &&
      driver_->request_headers() != NULL &&
      driver_->request_headers()->Lookup1(kPsaPurgeRequest) == NULL &&
      driver_->request_headers()->method() == RequestHeaders::kGet &&
      google_url.IsWebValid() &&
      ShouldPurgeRewrittenResponse(google_url) &&
      GeneratePurgeRequestParameters(google_url)) {
    driver_->server_context()->rewrite_stats()->
         downstream_cache_purge_attempts()->Add(1);
    // Purge old version from cache since we will have a better rewritten
    // version available on the next request. The purge request will
    // use the same request headers as the request (and hence the same
    // UserAgent etc.).
    PurgeDownstreamCache();
    return true;
  }
  return false;
}

}  // namespace net_instaweb
