/*
 * Copyright (c) 2017 Cisco and/or its affiliates.
 * 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.
 */

#include <algorithm>

#include "vom/om.hpp"

namespace VOM {
client_db* OM::m_db;

std::unique_ptr<OM::listener_list> OM::m_listeners;

/**
 * Initialse the connection to VPP
 */
void
OM::init()
{
  m_db = new client_db();
}

void
OM::mark(const client_db::key_t& key)
{
  /*
 * Find if the object already stored on behalf of this key.
 * and mark them stale
 */
  object_ref_list& objs = m_db->find(key);

  auto mark_obj = [](const object_ref& oref) { oref.mark(); };

  std::for_each(objs.begin(), objs.end(), mark_obj);
}

void
OM::sweep(const client_db::key_t& key)
{
  /*
   * Find if the object already stored on behalf of this key.
   * and mark them stale
   */
  object_ref_list& objs = m_db->find(key);

  for (auto it = objs.begin(); it != objs.end();) {
    if (it->stale()) {
      it = objs.erase(it);
    } else {
      ++it;
    }
  }

  HW::write();
}

void
OM::remove(const client_db::key_t& key)
{
  /*
   * Simply reset the list for this key. This will desctruct the
   * object list and shared_ptrs therein. When the last shared_ptr
   * goes the objects desctructor is called and the object is
   * removed from OM
   */
  m_db->flush(key);

  HW::write();
}

void
OM::replay()
{
  /*
   * the listeners are sorted in dependency order
   */
  for (listener* l : *m_listeners) {
    l->handle_replay();
  }

  HW::write();
}

void
OM::dump(const client_db::key_t& key, std::ostream& os)
{
  m_db->dump(key, os);
}

void
OM::dump(std::ostream& os)
{
  m_db->dump(os);
}

void
OM::populate(const client_db::key_t& key)
{
  /*
   * the listeners are sorted in dependency order
   */
  for (listener* l : *m_listeners) {
    l->handle_populate(key);
  }

  /*
   * once we have it all, mark it stale.
   */
  mark(key);
}

bool
OM::register_listener(OM::listener* listener)
{
  if (!m_listeners) {
    m_listeners.reset(new listener_list);
  }

  m_listeners->insert(listener);

  return (true);
}

OM::mark_n_sweep::mark_n_sweep(const client_db::key_t& key)
  : m_key(key)
{
  OM::mark(m_key);
}

OM::mark_n_sweep::~mark_n_sweep()
{
  OM::sweep(m_key);
}
}

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "mozilla")
 * End:
 */
