// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.


#ifndef IMPALA_UTIL_STOPWATCH_H
#define IMPALA_UTIL_STOPWATCH_H

#include <boost/cstdint.hpp>
#include <boost/thread/lock_guard.hpp>
#include <util/os-info.h>
#include <util/spinlock.h>
#include <util/time.h>
#include <time.h>

namespace impala {

#define SCOPED_STOP_WATCH(c) \
  ScopedStopWatch<MonotonicStopWatch> \
  MACRO_CONCAT(STOP_WATCH, __COUNTER__)(c)

#define CONDITIONAL_SCOPED_STOP_WATCH(c, enabled) \
  ScopedStopWatch<MonotonicStopWatch> \
  MACRO_CONCAT(STOP_WATCH, __COUNTER__)(c, enabled)

#define SCOPED_CONCURRENT_STOP_WATCH(c) \
  ScopedStopWatch<ConcurrentStopWatch> \
  MACRO_CONCAT(CONCURRENT_STOP_WATCH, __COUNTER__)(c)

/// Utility class to measure time.  This is measured using the cpu tick counter which
/// is very low overhead but can be inaccurate if the thread is switched away.  This
/// is useful for measuring cpu time at the row batch level (too much overhead at the
/// row granularity).
class StopWatch {
 public:
  StopWatch() {
    total_time_ = 0;
    running_ = false;
  }

  void Start() {
    if (!running_) {
      start_ = Rdtsc();
      running_ = true;
    }
  }

  void Stop() {
    total_time_ += RunningTime();
    running_ = false;
  }

  /// Returns total time in cpu ticks for which the stopwatch was running, including
  /// the time since Start() was called, if it is currently running.
  uint64_t ElapsedTime() const {
    return total_time_ + RunningTime();
  }

  static uint64_t Rdtsc() {
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax,%%eax \n        cpuid"
      ::: "%rax", "%rbx", "%rcx", "%rdx");
    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
    return (uint64_t)hi << 32 | lo;
  }

 private:
  /// Returns total time in cpu ticks since Start() was called. If not running, returns 0.
  uint64_t RunningTime() const {
    return running_ ? Rdtsc() - start_ : 0;
  }

  uint64_t start_, total_time_;
  bool running_;
};

/// Stop watch for reporting elapsed time in nanosec based on clock_gettime (Linux) or
/// MonotonicNanos (Apple).  It is not affected by cpu frequency changes and it is not
/// affected by user setting the system clock.  A monotonic clock represents monotonic
/// time since some unspecified starting point.  It is good for computing elapsed time.
///
/// The time values are in nanoseconds.  For most machine configurations, the clock
/// resolution will be 1 nanosecond.  We fall back to low resolution in configurations
/// where the clock is expensive.  For those machine configurations (notably EC2), the
/// clock resolution will be that of the system jiffy, which is between 1 and 10
/// milliseconds.
class MonotonicStopWatch {
 public:
  MonotonicStopWatch() : start_(0), total_time_(0),
                         time_ceiling_(0), running_(false) {
  }

  void Start() {
    if (!running_) {
      start_ = Now();
      running_ = true;
    }
  }

  void Stop() {
    total_time_ += RunningTime();
    running_ = false;
  }

  /// Set the time ceiling of the stop watch to Now(). The stop watch won't run past the
  /// ceiling.
  void SetTimeCeiling() { time_ceiling_ = Now(); }

  /// Restarts the timer. Returns the elapsed time until this point.
  uint64_t Reset() {
    uint64_t ret = RunningTime();
    if (running_) {
      start_ = Now();
      time_ceiling_ = 0;
    }
    return ret;
  }

  /// Returns total time in nanoseconds for which the stopwatch was running, including
  /// the time since Start() was called, if it is currently running.
  uint64_t ElapsedTime() const {
    return total_time_ + RunningTime();
  }

  /// Returns an representation of the current time in nanoseconds. It can be used to
  /// measure time durations by repeatedly calling this function and comparing the result.
  /// While this function returns nanoseconds, its resolution may be as large as
  /// milliseconds, depending on OsInfo::fast_clock().
  static inline int64_t Now() {
#if defined(__APPLE__)
    // Apple does not support clock_gettime.
    return MonotonicNanos();
#else
    // Use a fast but low-resolution clock if the high-resolution clock is slow because
    // Now() can be called frequently (IMPALA-2407).
    timespec ts;
    clock_gettime(OsInfo::fast_clock(), &ts);
    return ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec;
#endif
  }

 private:
  /// Start epoch value.
  uint64_t start_;

  /// Total elapsed time in nanoseconds.
  uint64_t total_time_;

  /// Upper bound of the running time as a epoch value. If the value is larger than 0,
  /// the stopwatch interprets this as a time ceiling is set.
  uint64_t time_ceiling_;

  /// True if stopwatch is running.
  bool running_;

  /// Returns the time since Start() was called, if running. Otherwise return 0.
  /// If time_ceiling_ is set, the stop watch won't run pass the ceiling.
  uint64_t RunningTime() const {
    if (!running_) return 0;
    uint64_t end = Now();
    if (time_ceiling_ > 0) {
      if (time_ceiling_ < start_) return 0;
      if (time_ceiling_ < end) end = time_ceiling_;
    }
    // IMPALA-7963: On some buggy kernels, time can go backwards slightly. Log a warning
    // and return 0 in this case.
    if (end < start_) {
      LOG(INFO) << "WARNING: time went backwards from " << start_ << " to " << end;
      return 0;
    }
    return end - start_;
  }
};

/// Utility class to measure multiple threads concurrent wall time.
/// If a thread is already running, the following thread won't reset the stop watch.
/// The stop watch is stopped only when all threads finish their work.
class ConcurrentStopWatch {
 public:
  ConcurrentStopWatch() : busy_threads_(0), last_lap_start_(0) {}

  void Start() {
    boost::lock_guard<SpinLock> l(thread_counter_lock_);
    if (busy_threads_ == 0) {
      msw_.Start();
    }
    ++busy_threads_;
  }

  void Stop() {
    boost::lock_guard<SpinLock> l(thread_counter_lock_);
    DCHECK_GT(busy_threads_, 0);
    --busy_threads_;
    if (busy_threads_ == 0) {
      msw_.Stop();
    }
  }

  /// Returns delta wall time since last time LapTime() is called.
  uint64_t LapTime() {
    boost::lock_guard<SpinLock> l(thread_counter_lock_);
    uint64_t now = msw_.ElapsedTime();
    uint64_t lap_duration = now - last_lap_start_;
    last_lap_start_ = now;
    return lap_duration;
  }

  uint64_t TotalRunningTime() const {  return msw_.ElapsedTime(); }

 private:
  MonotonicStopWatch msw_;

  /// Lock with busy_threads_.
  SpinLock thread_counter_lock_;

  /// Track how many threads are currently busy.
  int busy_threads_;

  /// Track when the last time LapTime() is called so we can calculate lap time.
  uint64_t last_lap_start_;
};

/// Utility class that starts the stop watch in the constructor and stops the watch when
/// the object goes out of scope. If the optional argument 'enabled' is false, the
/// stopwatch is not updated.
/// 'T' must implement the StopWatch interface "Start", "Stop".
template<class T>
class ScopedStopWatch {
 public:
  ScopedStopWatch(T* sw, bool enabled = true) :
    sw_(sw), enabled_(enabled) {
    DCHECK(sw != NULL);
    if (enabled_) sw_->Start();
  }

  ~ScopedStopWatch() {
    if (enabled_) sw_->Stop();
  }

 private:
  T* sw_;
  bool enabled_;
};

}

#endif
