/*
 * 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: x.dinic@gmail.com(Junmin Xiong)
//
// Fetch the resources asynchronously in Nginx. The fetcher is called in
// the rewrite thread.
//
// It can communicate with Nginx by pipe. One pipe for one fetcher.
// When new url fetch comes, Fetcher will add it to the pending queue and
// notify the Nginx thread to start the Fetch event. All the events are hooked
// in the main thread's epoll structure.

#ifndef NET_INSTAWEB_NGX_URL_ASYNC_FETCHER_H_
#define NET_INSTAWEB_NGX_URL_ASYNC_FETCHER_H_

extern "C" {
  #include <ngx_config.h>
  #include <ngx_core.h>
}

#include <vector>
#include "net/instaweb/http/public/url_async_fetcher.h"
#include "net/instaweb/util/public/basictypes.h"
#include "net/instaweb/util/public/pool.h"
#include "net/instaweb/util/public/string.h"
#include "net/instaweb/util/public/thread_system.h"


namespace net_instaweb {

class AsyncFetch;
class MessageHandler;
class Statistics;
class NgxFetch;
class Variable;

class NgxUrlAsyncFetcher : public UrlAsyncFetcher {
 public:
  NgxUrlAsyncFetcher(
      const char* proxy, ngx_log_t* log, ngx_msec_t resolver_timeout,
      ngx_msec_t fetch_timeout, ngx_resolver_t* resolver,
      int max_keepalive_requests, ThreadSystem* thread_system,
      MessageHandler* handler);

  ~NgxUrlAsyncFetcher();

  // It should be called in the module init_process callback function. Do some
  // initializations which can't be done in the master process
  bool Init();

  // shutdown all the fetches.
  virtual void ShutDown();

  virtual bool SupportsHttps() const { return false; }

  virtual void Fetch(const GoogleString& url,
                     MessageHandler* message_handler,
                     AsyncFetch* callback);

  // send the command from the current thread to main thread
  bool SendCmd(const char command);
  // the read handler in the main thread
  static void CommandHandler(ngx_event_t* cmdev);
  bool StartFetch(NgxFetch* fetch);

  // Remove the completed fetch from the active fetch set, and put it into a
  // completed fetch list to be cleaned up.
  void FetchComplete(NgxFetch* fetch);
  void PrintActiveFetches(MessageHandler* handler) const;

  // Indicates that it should track the original content length for
  // fetched resources.
  bool track_original_content_length() {
    return track_original_content_length_;
  }
  void set_track_original_content_length(bool x) {
    track_original_content_length_ = x;
  }

  typedef Pool<NgxFetch> NgxFetchPool;

  // AnyPendingFetches is accurate only at the time of call; this is
  // used conservatively during shutdown.  It counts fetches that have been
  // requested by some thread, and can include fetches for which no action
  // has yet been taken (ie fetches that are not active).
  virtual bool AnyPendingFetches() {
    return !active_fetches_.empty();
  }

  // ApproximateNumActiveFetches can under- or over-count and is used only for
  // error reporting.
  int ApproximateNumActiveFetches() {
    return active_fetches_.size();
  }

  void CancelActiveFetches();

  // These must be accessed with mutex_ held.
  bool shutdown() const { return shutdown_; }
  void set_shutdown(bool s) { shutdown_ = s; }


 private:
  static void TimeoutHandler(ngx_event_t* tev);
  static bool ParseUrl(ngx_url_t* url, ngx_pool_t* pool);
  friend class NgxFetch;

  NgxFetchPool active_fetches_;
  // Add the pending task to this list
  NgxFetchPool pending_fetches_;
  NgxFetchPool completed_fetches_;
  ngx_url_t proxy_;

  int fetchers_count_;
  bool shutdown_;
  bool track_original_content_length_;
  int64 byte_count_;
  ThreadSystem* thread_system_;
  MessageHandler* message_handler_;
  // Protect the member variable in this class
  // active_fetches, pending_fetches
  ThreadSystem::CondvarCapableMutex* mutex_;

  ngx_pool_t* pool_;
  ngx_log_t* log_;
  ngx_connection_t* command_connection_;  // the command pipe
  int pipe_fd_;  // the write pipe end
  ngx_resolver_t* resolver_;
  int max_keepalive_requests_;
  ngx_msec_t resolver_timeout_;
  ngx_msec_t fetch_timeout_;

  DISALLOW_COPY_AND_ASSIGN(NgxUrlAsyncFetcher);
};

}  // namespace net_instaweb

#endif  // NET_INSTAWEB_NGX_URL_ASYNC_FETCHER_H_$
