/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014,  Regents of the University of California,
 *                      Arizona Board of Regents,
 *                      Colorado State University,
 *                      University Pierre & Marie Curie, Sorbonne University,
 *                      Washington University in St. Louis,
 *                      Beijing Institute of Technology,
 *                      The University of Memphis
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "rib.hpp"

#include "core/logger.hpp"

NFD_LOG_INIT("Rib");

namespace nfd {
namespace rib {

static inline bool
sortFace(const FaceEntry& entry1, const FaceEntry& entry2)
{
  return entry1.faceId < entry2.faceId;
}

static inline bool
isChildInheritFlagSet(uint64_t flags)
{
  return flags & ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;
}

static inline bool
isCaptureFlagSet(uint64_t flags)
{
  return flags & ndn::nfd::ROUTE_FLAG_CAPTURE;
}

static inline bool
isAnyFlagSet(uint64_t flags)
{
  return isChildInheritFlagSet(flags) || isCaptureFlagSet(flags);
}

static inline bool
areBothFlagsSet(uint64_t flags)
{
  return isChildInheritFlagSet(flags) && isCaptureFlagSet(flags);
}

Rib::Rib()
  : m_nItems(0)
{
}


Rib::~Rib()
{
}

Rib::const_iterator
Rib::find(const Name& prefix) const
{
  return m_rib.find(prefix);
}

FaceEntry*
Rib::find(const Name& prefix, const FaceEntry& face) const
{
  RibTable::const_iterator ribIt = m_rib.find(prefix);

  // Name prefix exists
  if (ribIt != m_rib.end())
    {
      shared_ptr<RibEntry> entry(ribIt->second);

      RibEntry::iterator faceIt = std::find_if(entry->begin(), entry->end(),
                                                     bind(&compareFaceIdAndOrigin, _1, face));

      if (faceIt != entry->end())
        {
          return &((*faceIt));
        }
    }
  return 0;
}

void
Rib::insert(const Name& prefix, const FaceEntry& face)
{
  RibTable::iterator ribIt = m_rib.find(prefix);

  // Name prefix exists
  if (ribIt != m_rib.end())
    {
      shared_ptr<RibEntry> entry(ribIt->second);

      RibEntry::iterator faceIt = std::find_if(entry->getFaces().begin(),
                                               entry->getFaces().end(),
                                               bind(&compareFaceIdAndOrigin, _1, face));

      if (faceIt == entry->end())
        {
          // Will the new face change the namespace's capture flag?
          bool captureWasTurnedOn = (entry->hasCapture() == false && isCaptureFlagSet(face.flags));

          // New face
          entry->insertFace(face);
          m_nItems++;

          // Register with face lookup table
          m_faceMap[face.faceId].push_back(entry);

          createFibUpdatesForNewFaceEntry(*entry, face, captureWasTurnedOn);
        }
      else // Entry exists, update fields
        {
          // First cancel old scheduled event, if any, then set the EventId to new one
          if (static_cast<bool>(faceIt->getExpirationEvent()))
            {
              NFD_LOG_TRACE("Cancelling expiration event for " << entry->getName() << " "
                                                               << *faceIt);
              scheduler::cancel(faceIt->getExpirationEvent());
            }

          // No checks are required here as the iterator needs to be updated in all cases.
          faceIt->setExpirationEvent(face.getExpirationEvent());

          // Save flags for update processing
          uint64_t previousFlags = faceIt->flags;

          // If the entry's cost didn't change and child inherit is not set,
          // no need to traverse subtree.
          uint64_t previousCost = faceIt->cost;

          faceIt->flags = face.flags;
          faceIt->cost = face.cost;
          faceIt->expires = face.expires;

          createFibUpdatesForUpdatedEntry(*entry, face, previousFlags, previousCost);
        }
    }
  else // New name prefix
    {
      shared_ptr<RibEntry> entry(make_shared<RibEntry>(RibEntry()));

      m_rib[prefix] = entry;
      m_nItems++;

      entry->setName(prefix);
      entry->insertFace(face);

      // Find prefix's parent
      shared_ptr<RibEntry> parent = findParent(prefix);

      // Add self to parent's children
      if (static_cast<bool>(parent))
        {
          parent->addChild(entry);
        }

      RibEntryList children = findDescendants(prefix);

      for (std::list<shared_ptr<RibEntry> >::iterator child = children.begin();
           child != children.end(); ++child)
        {
          if ((*child)->getParent() == parent)
            {
              // Remove child from parent and inherit parent's child
              if (static_cast<bool>(parent))
                {
                  parent->removeChild((*child));
                }
              entry->addChild((*child));
            }
        }

      // Register with face lookup table
      m_faceMap[face.faceId].push_back(entry);

      createFibUpdatesForNewRibEntry(*entry, face);
    }
}

void
Rib::erase(const Name& prefix, const FaceEntry& face)
{
  RibTable::iterator ribIt = m_rib.find(prefix);

  // Name prefix exists
  if (ribIt != m_rib.end())
    {
      shared_ptr<RibEntry> entry(ribIt->second);

      const bool hadCapture = entry->hasCapture();

      // Need to copy face to do FIB updates with correct cost and flags since nfdc does not
      // pass flags or cost
      RibEntry::iterator faceIt = entry->findFace(face);

      if (faceIt != entry->end())
        {
          FaceEntry faceToErase = *faceIt;
          faceToErase.flags = faceIt->flags;
          faceToErase.cost = faceIt->cost;

          entry->eraseFace(faceIt);

          m_nItems--;

          const bool captureWasTurnedOff = (hadCapture && !entry->hasCapture());

          createFibUpdatesForErasedFaceEntry(*entry, faceToErase, captureWasTurnedOff);

          // If this RibEntry no longer has this faceId, unregister from face lookup table
          if (!entry->hasFaceId(face.faceId))
            {
              m_faceMap[face.faceId].remove(entry);
            }
          else
            {
              // The RibEntry still has the face ID; need to update FIB
              // with lowest cost for the same face instead of removing the face from the FIB
              shared_ptr<FaceEntry> lowCostFace = entry->getFaceWithLowestCostByFaceId(face.faceId);

              BOOST_ASSERT(static_cast<bool>(lowCostFace));

              createFibUpdatesForNewFaceEntry(*entry, *lowCostFace, false);
            }

          // If a RibEntry's facelist is empty, remove it from the tree
          if (entry->getFaces().size() == 0)
            {
              eraseEntry(ribIt);
            }
        }
    }
}

void
Rib::erase(const uint64_t faceId)
{
  FaceLookupTable::iterator lookupIt = m_faceMap.find(faceId);

  // No RIB entries have this face
  if (lookupIt == m_faceMap.end())
    {
      return;
    }

  RibEntryList& ribEntries = lookupIt->second;

  // For each RIB entry that has faceId, remove the face from the entry
  for (RibEntryList::iterator entryIt = ribEntries.begin(); entryIt != ribEntries.end(); ++entryIt)
    {
      shared_ptr<RibEntry> entry = *entryIt;

      const bool hadCapture = entry->hasCapture();

      // Find the faces in the entry
      for (RibEntry::iterator faceIt = entry->begin(); faceIt != entry->end(); ++faceIt)
        {
          if (faceIt->faceId == faceId)
            {
              FaceEntry copy = *faceIt;

              faceIt = entry->eraseFace(faceIt);
              m_nItems--;

              const bool captureWasTurnedOff = (hadCapture && !entry->hasCapture());
              createFibUpdatesForErasedFaceEntry(*entry, copy, captureWasTurnedOff);
            }
        }

        // If a RibEntry's facelist is empty, remove it from the tree
        if (entry->getFaces().size() == 0)
          {
            eraseEntry(m_rib.find(entry->getName()));
          }
    }

  // Face no longer exists, remove from face lookup table
  FaceLookupTable::iterator entryToDelete = m_faceMap.find(faceId);

  if (entryToDelete != m_faceMap.end())
    {
      m_faceMap.erase(entryToDelete);
    }
}

shared_ptr<RibEntry>
Rib::findParent(const Name& prefix) const
{
  for (int i = prefix.size() - 1; i >= 0; i--)
    {
      RibTable::const_iterator it = m_rib.find(prefix.getPrefix(i));
      if (it != m_rib.end())
        {
          return (it->second);
        }
    }

  return shared_ptr<RibEntry>();
}

std::list<shared_ptr<RibEntry> >
Rib::findDescendants(const Name& prefix) const
{
  std::list<shared_ptr<RibEntry> > children;

  RibTable::const_iterator it = m_rib.find(prefix);

  if (it != m_rib.end())
    {
      ++it;
      for (; it != m_rib.end(); ++it)
        {
          if (prefix.isPrefixOf(it->first))
            {
              children.push_back((it->second));
            }
          else
            {
              break;
            }
        }
    }

  return children;
}

Rib::RibTable::iterator
Rib::eraseEntry(RibTable::iterator it)
{
  // Entry does not exist
  if (it == m_rib.end())
    {
      return m_rib.end();
    }

  shared_ptr<RibEntry> entry(it->second);

  // Remove inherited routes from namespace
  createFibUpdatesForErasedRibEntry(*entry);

  shared_ptr<RibEntry> parent = entry->getParent();

  // Remove self from parent's children
  if (static_cast<bool>(parent))
    {
      parent->removeChild(entry);
    }

  std::list<shared_ptr<RibEntry> > children = entry->getChildren();

  for (RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
    {
      // Remove children from self
      entry->removeChild(*child);

      // Update parent's children
      if (static_cast<bool>(parent))
        {
          parent->addChild(*child);
        }
    }

  // Must save and advance iterator to return a valid iterator
  RibTable::iterator nextIt = it;
  nextIt++;

  m_rib.erase(it);

  return nextIt;
}

bool
compareFibUpdates(const shared_ptr<const FibUpdate> lhs, const shared_ptr<const FibUpdate> rhs)
{
  return ((lhs->name == rhs->name) &&
          (lhs->faceId == rhs->faceId));
}

void
Rib::insertFibUpdate(shared_ptr<FibUpdate> update)
{
  // If an update with the same name and face already exists,
  // replace it
  FibUpdateList::iterator it = std::find_if(m_fibUpdateList.begin(), m_fibUpdateList.end(),
                                            bind(&compareFibUpdates, _1, update));

  if (it != m_fibUpdateList.end())
    {
      // Get rid of the const to alter the action, prevents copying or removal and
      // insertion
      FibUpdate& entry = const_cast<FibUpdate&>(*(*it));
      entry.action = update->action;
      entry.cost = update->cost;
    }
  else
    {
      m_fibUpdateList.push_back(update);
    }
}

void
Rib::createFibUpdatesForNewRibEntry(RibEntry& entry, const FaceEntry& face)
{
  // Create FIB update for new entry
  insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), face.faceId, face.cost));

  // No flags are set
  if (!isAnyFlagSet(face.flags))
    {
      // Add ancestor faces to self
      addInheritedFacesToEntry(entry, getAncestorFaces(entry));
    }
  else if (areBothFlagsSet(face.flags))
    {
      // Add face to children
      FaceSet facesToAdd;
      facesToAdd.insert(face);

      // Remove faces blocked by capture and add self to children
      modifyChildrensInheritedFaces(entry, facesToAdd, getAncestorFaces(entry));
    }
  else if (isChildInheritFlagSet(face.flags))
    {
      FaceSet ancestorFaces = getAncestorFaces(entry);

      // Add ancestor faces to self
      addInheritedFacesToEntry(entry, ancestorFaces);

      // If there is an ancestor face which is the same as the new face, replace it
      // with the new face
      FaceSet::iterator it = ancestorFaces.find(face);

      // There is a face that needs to be overwritten, erase and then replace
      if (it != ancestorFaces.end())
        {
          ancestorFaces.erase(it);
        }

      // Add new face to ancestor list so it can be added to children
      ancestorFaces.insert(face);

      // Add ancestor faces to children
      modifyChildrensInheritedFaces(entry, ancestorFaces, FaceSet());
    }
  else if (isCaptureFlagSet(face.flags))
    {
      // Remove faces blocked by capture
      modifyChildrensInheritedFaces(entry, FaceSet(), getAncestorFaces(entry));
    }
}

void
Rib::createFibUpdatesForNewFaceEntry(RibEntry& entry, const FaceEntry& face,
                                     bool captureWasTurnedOn)
{
  // Only update if the new face has a lower cost than a previously installed face
  shared_ptr<FaceEntry> prevFace = entry.getFaceWithLowestCostAndChildInheritByFaceId(face.faceId);

  FaceSet facesToAdd;
  if (isChildInheritFlagSet(face.flags))
    {
      // Add to children if this new face doesn't override a previous lower cost, or
      // add to children if this new is lower cost than a previous face.
      // Less than equal, since entry may find this face
      if (!static_cast<bool>(prevFace) || face.cost <= prevFace->cost)
        {
          // Add self to children
          facesToAdd.insert(face);
        }
    }

  FaceSet facesToRemove;
  if (captureWasTurnedOn)
    {
      // Capture flag on
      facesToRemove = getAncestorFaces(entry);

      // Remove ancestor faces from self
      removeInheritedFacesFromEntry(entry, facesToRemove);
    }

  modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);

  // If another face with same faceId and lower cost, don't update.
  // Must be done last so that add updates replace removal updates
  // Create FIB update for new entry
  if (face.cost <= entry.getFaceWithLowestCostByFaceId(face.faceId)->cost)
    {
      insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), face.faceId, face.cost));
    }
}

void
Rib::createFibUpdatesForUpdatedEntry(RibEntry& entry, const FaceEntry& face,
                                     const uint64_t previousFlags, const uint64_t previousCost)
{
  const bool costDidChange = (face.cost != previousCost);

  // Look for an installed face with the lowest cost and child inherit set
  shared_ptr<FaceEntry> prevFace = entry.getFaceWithLowestCostAndChildInheritByFaceId(face.faceId);

  // No flags changed and cost didn't change, no change in FIB
  if (face.flags == previousFlags && !costDidChange)
    {
      return;
    }

  // Cost changed so create update for the entry itself
  if (costDidChange)
    {
      // Create update if this face's cost is lower than other faces
       if (face.cost <= entry.getFaceWithLowestCostByFaceId(face.faceId)->cost)
        {
          // Create FIB update for the updated entry
         insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), face.faceId, face.cost));
        }
      else if (previousCost < entry.getFaceWithLowestCostByFaceId(face.faceId)->cost)
        {
          // Create update if this face used to be the lowest face but is no longer
          // the lowest cost face.
          insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), prevFace->faceId,
                                                                          prevFace->cost));
        }

      // If another face with same faceId and lower cost and ChildInherit exists,
      // don't update children.
      if (!static_cast<bool>(prevFace) || face.cost <= prevFace->cost)
        {
          // If no flags changed but child inheritance is set, need to update children
          // with new cost
          if ((face.flags == previousFlags) && isChildInheritFlagSet(face.flags))
          {
            // Add self to children
            FaceSet facesToAdd;
            facesToAdd.insert(face);
            modifyChildrensInheritedFaces(entry, facesToAdd, FaceSet());

            return;
          }
        }
    }

  // Child inherit was turned on
  if (!isChildInheritFlagSet(previousFlags) && isChildInheritFlagSet(face.flags))
    {
      // If another face with same faceId and lower cost and ChildInherit exists,
      // don't update children.
      if (!static_cast<bool>(prevFace) || face.cost <= prevFace->cost)
        {
          // Add self to children
          FaceSet facesToAdd;
          facesToAdd.insert(face);
          modifyChildrensInheritedFaces(entry, facesToAdd, FaceSet());
        }

    } // Child inherit was turned off
  else if (isChildInheritFlagSet(previousFlags) && !isChildInheritFlagSet(face.flags))
    {
      // Remove self from children
      FaceSet facesToRemove;
      facesToRemove.insert(face);

      FaceSet facesToAdd;
      // If another face with same faceId and ChildInherit exists, update children with this face.
      if (static_cast<bool>(prevFace))
        {
          facesToAdd.insert(*prevFace);
        }
      else
        {
          // Look for an ancestor that was blocked previously
          const FaceSet ancestorFaces = getAncestorFaces(entry);
          FaceSet::iterator it = ancestorFaces.find(face);

          // If an ancestor is found, add it to children
          if (it != ancestorFaces.end())
            {
              facesToAdd.insert(*it);
            }
        }

      modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);
    }

  // Capture was turned on
  if (!isCaptureFlagSet(previousFlags) && isCaptureFlagSet(face.flags))
    {
      FaceSet ancestorFaces = getAncestorFaces(entry);

      // Remove ancestor faces from self
      removeInheritedFacesFromEntry(entry, ancestorFaces);

      // Remove ancestor faces from children
      modifyChildrensInheritedFaces(entry, FaceSet(), ancestorFaces);
    }  // Capture was turned off
  else if (isCaptureFlagSet(previousFlags) && !isCaptureFlagSet(face.flags))
    {
      FaceSet ancestorFaces = getAncestorFaces(entry);

      // Add ancestor faces to self
      addInheritedFacesToEntry(entry, ancestorFaces);

      // Add ancestor faces to children
      modifyChildrensInheritedFaces(entry, ancestorFaces, FaceSet());
    }
}

void
Rib::createFibUpdatesForErasedFaceEntry(RibEntry& entry, const FaceEntry& face,
                                        const bool captureWasTurnedOff)
{
  insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), face.faceId));

  if (areBothFlagsSet(face.flags))
    {
      // Remove self from children
      FaceSet facesToRemove;
      facesToRemove.insert(face);

      // If capture is turned off for the route, need to add ancestors
      // to self and children
      FaceSet facesToAdd;
      if (captureWasTurnedOff)
        {
          // Look for an ancestors that were blocked previously
          facesToAdd = getAncestorFaces(entry);

          // Add ancestor faces to self
          addInheritedFacesToEntry(entry, facesToAdd);
        }

      modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);
    }
  else if (isChildInheritFlagSet(face.flags))
    {
      // If not blocked by capture, add inherited routes to children
      FaceSet facesToAdd;
      if (!entry.hasCapture())
        {
          facesToAdd = getAncestorFaces(entry);
        }

      FaceSet facesToRemove;
      facesToRemove.insert(face);

      // Add ancestor faces to children
      modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);
    }
  else if (isCaptureFlagSet(face.flags))
    {
      // If capture is turned off for the route, need to add ancestors
      // to self and children
      FaceSet facesToAdd;
      if (captureWasTurnedOff)
        {
          // Look for an ancestors that were blocked previously
          facesToAdd = getAncestorFaces(entry);

          // Add ancestor faces to self
          addInheritedFacesToEntry(entry, facesToAdd);
        }

      modifyChildrensInheritedFaces(entry, facesToAdd, FaceSet());
    }

  // Need to check if the removed face was blocking an inherited route
  FaceSet ancestorFaces = getAncestorFaces(entry);

  if (!entry.hasCapture())
  {
    // If there is an ancestor face which is the same as the erased face, add that face
    // to the current entry
    FaceSet::iterator it = ancestorFaces.find(face);

    if (it != ancestorFaces.end())
      {
        entry.addInheritedFace(*it);
        insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), it->faceId, it->cost));
      }
  }
}

void
Rib::createFibUpdatesForErasedRibEntry(RibEntry& entry)
{
  for (RibEntry::FaceList::iterator it = entry.getInheritedFaces().begin();
       it != entry.getInheritedFaces().end(); ++it)
    {
      insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), it->faceId));
    }
}

Rib::FaceSet
Rib::getAncestorFaces(const RibEntry& entry) const
{
  FaceSet ancestorFaces(&sortFace);

  shared_ptr<RibEntry> parent = entry.getParent();

  while (static_cast<bool>(parent))
    {
      for (RibEntry::iterator it = parent->getFaces().begin();
           it != parent->getFaces().end(); ++it)
        {
          if (isChildInheritFlagSet(it->flags))
            {
              ancestorFaces.insert(*it);
            }
        }

      if (parent->hasCapture())
        {
          break;
        }

      parent = parent->getParent();
    }

    return ancestorFaces;
}

void
Rib::addInheritedFacesToEntry(RibEntry& entry, const Rib::FaceSet& facesToAdd)
{
  for (FaceSet::const_iterator it = facesToAdd.begin(); it != facesToAdd.end(); ++it)
    {
      // Don't add an ancestor faceId if the namespace has an entry for that faceId
      if (!entry.hasFaceId(it->faceId))
        {
          entry.addInheritedFace(*it);
          insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), it->faceId, it->cost));
        }
    }
}

void
Rib::removeInheritedFacesFromEntry(RibEntry& entry, const Rib::FaceSet& facesToRemove)
{
  for (FaceSet::const_iterator it = facesToRemove.begin(); it != facesToRemove.end(); ++it)
    {
      // Only remove if the face has been inherited
      if (entry.hasInheritedFace(*it))
        {
          entry.removeInheritedFace(*it);
          insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), it->faceId));
        }
    }
}

void
Rib::modifyChildrensInheritedFaces(RibEntry& entry, const Rib::FaceSet& facesToAdd,
                                                    const Rib::FaceSet& facesToRemove)
{
  RibEntryList children = entry.getChildren();

  for (RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
    {
      traverseSubTree(*(*child), facesToAdd, facesToRemove);
    }
}

void
Rib::traverseSubTree(RibEntry& entry, Rib::FaceSet facesToAdd,
                                      Rib::FaceSet facesToRemove)
{
  // If a route on the namespace has the capture flag set, ignore self and children
  if (entry.hasCapture())
    {
      return;
    }

  // Remove inherited faces from current namespace
  for (Rib::FaceSet::const_iterator removeIt = facesToRemove.begin();
       removeIt != facesToRemove.end(); )
    {
      // If a route on the namespace has the same face and child inheritance set, ignore this face
      if (entry.hasChildInheritOnFaceId(removeIt->faceId))
        {
          facesToRemove.erase(removeIt++);
          continue;
        }

      // Only remove face if it removes an existing inherited route
      if (entry.hasInheritedFace(*removeIt))
        {
          entry.removeInheritedFace(*removeIt);
          insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), removeIt->faceId));
        }

      ++removeIt;
    }

  // Add inherited faces to current namespace
  for (Rib::FaceSet::const_iterator addIt = facesToAdd.begin();
       addIt != facesToAdd.end(); )
    {
      // If a route on the namespace has the same face and child inherit set, ignore this face
      if (entry.hasChildInheritOnFaceId(addIt->faceId))
      {
        facesToAdd.erase(addIt++);
        continue;
      }

      // Only add face if it does not override an existing route
      if (!entry.hasFaceId(addIt->faceId))
        {
          RibEntry::FaceList::iterator faceIt = entry.findInheritedFace(*addIt);

          // If the entry already has the inherited face, just update the face
          if (faceIt != entry.getInheritedFaces().end())
            {
              faceIt->cost = addIt->cost;
            }
          else // Otherwise, this is a newly inherited face
            {
              entry.addInheritedFace(*addIt);
            }

          insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), addIt->faceId, addIt->cost));
        }

      ++addIt;
    }

  Rib::RibEntryList children = entry.getChildren();

  // Apply face operations to current namespace's children
  for (Rib::RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
    {
      traverseSubTree(*(*child), facesToAdd, facesToRemove);
    }
}

std::ostream&
operator<<(std::ostream& os, const Rib& rib)
{
  for (Rib::RibTable::const_iterator it = rib.begin(); it != rib.end(); ++it)
    {
      os << *(it->second) << "\n";
    }

  return os;
}

} // namespace rib
} // namespace nfd
