/*=========================================================================
 * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
 * This product is protected by U.S. and international copyright
 * and intellectual property laws. Pivotal products are covered by
 * one or more patents listed at http://www.pivotal.io/patents.
 *=========================================================================
 */
#ifndef __GEMFIRE_IMPL_CONCURRENTENTRIESMAP_H__
#define __GEMFIRE_IMPL_CONCURRENTENTRIESMAP_H__

#include "../gfcpp_globals.hpp"
#include "EntriesMap.hpp"
#include "MapSegment.hpp"
#include "AtomicInc.hpp"
#include "ExpMapEntry.hpp"
#include "../RegionEntry.hpp"

namespace gemfire
{
  class RegionInternal;

  /**
   * @brief Concurrent entries map.
   */
  class CPPCACHE_EXPORT ConcurrentEntriesMap: public EntriesMap
  {
  protected:
    uint8_t m_concurrency;
    MapSegment* m_segments;
    AtomicInc m_size;
    RegionInternal* m_region;
    volatile int m_numDestroyTrackers;
    bool m_concurrencyChecksEnabled;
    // TODO: [sumedh] hashcode() is invoked 3-4 times -- need a better
    // implementation (STLport hash_map?) that will invoke it only once
    /**
     * Return a reference to the segment for which the given key would
     * be stored.
     */
    virtual MapSegment* segmentFor(const CacheableKeyPtr& key) const
    {
      return &(m_segments[segmentIdx(key)]);
    }

    /**
     * Return the segment index number for the given key.
     */
    inline int segmentIdx(const CacheableKeyPtr& key) const
    {
      return segmentIdx(key->hashcode());
    }

    /**
     * Return the segment index number for the given hash.
     */
    inline int segmentIdx(uint32_t hash) const
    {
      return (hash % m_concurrency);
    }

  public:
    /**
     * @brief constructor, must call open before using map.
     */
    ConcurrentEntriesMap(EntryFactory* entryFactory, bool concurrencyChecksEnabled ,
      RegionInternal* region = NULL, uint8_t concurrency = 16);

    /**
     * Initialize segments with proper EntryFactory.
     */
    virtual void open(uint32_t initialCapacity);

    virtual void close();

    virtual ~ConcurrentEntriesMap();
  
    virtual void clear();

    virtual GfErrType put(const CacheableKeyPtr& key,
        const CacheablePtr& newValue, MapEntryImplPtr& me,
        CacheablePtr& oldValue, int updateCount, int destroyTracker,
        VersionTagPtr versionTag, bool& isUpdate = EntriesMap::boolVal, 
        DataInput* delta = NULL);
    virtual GfErrType invalidate(const CacheableKeyPtr& key,
        MapEntryImplPtr& me, CacheablePtr& oldValue, VersionTagPtr versionTag);
    virtual GfErrType create(const CacheableKeyPtr& key,
        const CacheablePtr& newValue, MapEntryImplPtr& me,
        CacheablePtr& oldValue, int updateCount, int destroyTracker, VersionTagPtr versionTag);
    virtual bool get(const CacheableKeyPtr& key, CacheablePtr& value,
        MapEntryImplPtr& me);

    /**
     * @brief get MapEntry for key.
     * TODO: return GfErrType like other methods
     */
    virtual void getEntry(const CacheableKeyPtr& key, MapEntryImplPtr& result,
        CacheablePtr& value) const;

    /**
     * @brief remove the entry for key from the map.
     */
    virtual GfErrType remove(const CacheableKeyPtr& key, CacheablePtr& result,
        MapEntryImplPtr& me, int updateCount, VersionTagPtr versionTag, bool afterRemote);

    /**
     * @brief return true if there exists an entry for the key.
     */
    virtual bool containsKey(const CacheableKeyPtr& key) const;

    /**
     * @brief return the all the keys in a list.
     */
    virtual void keys(VectorOfCacheableKey& result) const;

    /**
     * @brief return all the entries in a list.
     */
    virtual void entries(VectorOfRegionEntry& result) const;

    /**
     * @brief return all values in a list.
     */
    virtual void values(VectorOfCacheable& result) const;

    /**
     * @brief return the number of entries in the map.
     */
    virtual uint32_t size() const;

    virtual int addTrackerForEntry(const CacheableKeyPtr& key,
        CacheablePtr& oldValue, bool addIfAbsent, bool failIfPresent,
        bool incUpdateCount);

    virtual void removeTrackerForEntry(const CacheableKeyPtr& key);

    virtual int addTrackerForAllEntries(
        MapOfUpdateCounters& updateCounterMap, bool addDestroyTracking);

    virtual void removeDestroyTracking();
    virtual void reapTombstones(std::map<uint16_t, int64_t>& gcVersions);

    virtual void reapTombstones(CacheableHashSetPtr removedKeys);
    
    /**
     * for internal testing, returns if an entry is a tombstone
     */
    virtual GfErrType isTombstone(CacheableKeyPtr& key, MapEntryImplPtr& me, bool& result);

    /**
     * for internal testing, return the number of times any segment
     * has rehashed.
     */
    uint32_t totalSegmentRehashes() const;
  }; // class EntriesMap

} // namespace gemfire

#endif // __GEMFIRE_IMPL_CONCURRENTENTRIESMAP_H__
