// Copyright (c) 2006- Facebook
// Distributed under the Thrift Software License
//
// See accompanying file LICENSE or visit the Thrift site at:
// http://developers.facebook.com/thrift/

#include "FacebookBase.h"

using namespace facebook::fb303;
using apache::thrift::concurrency::Guard;

FacebookBase::FacebookBase(std::string name) :
  name_(name) {
  aliveSince_ = (int64_t) time(NULL);
}

inline void FacebookBase::getName(std::string& _return) {
  _return = name_;
}

void FacebookBase::setOption(const std::string& key, const std::string& value) {
  Guard g(optionsLock_);
  options_[key] = value;
}

void FacebookBase::getOption(std::string& _return, const std::string& key) {
  Guard g(optionsLock_);
  _return = options_[key];
}

void FacebookBase::getOptions(std::map<std::string, std::string> & _return) {
  Guard g(optionsLock_);
  _return = options_;
}

int64_t FacebookBase::incrementCounter(const std::string& key, int64_t amount) {
  counters_.acquireRead();

  // if we didn't find the key, we need to write lock the whole map to create it
  ReadWriteCounterMap::iterator it = counters_.find(key);
  if (it == counters_.end()) {
    counters_.release();
    counters_.acquireWrite();

    // we need to check again to make sure someone didn't create this key
    // already while we released the lock
    it = counters_.find(key);
    if(it == counters_.end()){
      counters_[key].value = amount;
      counters_.release();
      return amount;
    }
  }

  it->second.acquireWrite();
  int64_t count = it->second.value + amount;
  it->second.value = count;
  it->second.release();
  counters_.release();
  return count;
}

int64_t FacebookBase::setCounter(const std::string& key, int64_t value) {
  counters_.acquireRead();

  // if we didn't find the key, we need to write lock the whole map to create it
  ReadWriteCounterMap::iterator it = counters_.find(key);
  if (it == counters_.end()) {
    counters_.release();
    counters_.acquireWrite();
    counters_[key].value = value;
    counters_.release();
    return value;
  }

  it->second.acquireWrite();
  it->second.value = value;
  it->second.release();
  counters_.release();
  return value;
}

void FacebookBase::getCounters(std::map<std::string, int64_t>& _return) {
  // we need to lock the whole thing and actually build the map since we don't
  // want our read/write structure to go over the wire
  counters_.acquireRead();
  for(ReadWriteCounterMap::iterator it = counters_.begin();
      it != counters_.end(); it++)
  {
    _return[it->first] = it->second.value;
  }
  counters_.release();
}

int64_t FacebookBase::getCounter(const std::string& key) {
  int64_t rv = 0;
  counters_.acquireRead();
  ReadWriteCounterMap::iterator it = counters_.find(key);
  if (it != counters_.end()) {
    it->second.acquireRead();
    rv = it->second.value;
    it->second.release();
  }
  counters_.release();
  return rv;
}

inline int64_t FacebookBase::aliveSince() {
  return aliveSince_;
}

