ndnSIM学习(六)——内容缓存CS、cs.cpp、cs.hpp

前言

因为我们组要对内容缓存CS部分的代码进行修改,虽然我还是个萌新,对整个NDN框架还没入门,然而还是尝试看了下CS部分的代码。

从今往后,不做特殊声明,约定

  • 定义: <ns-3-folder>~/ndnSIM/ns-3 路径
  • 定义: <ndnSIM-folder>~/ndnSIM/ns-3/src/ndnSIM 路径
  • 定义: <build-ndnSIM-folder>~/ndnSIM/ns-3/build/ns3/ndnSIM 路径

今天要看的代码是:

  • <ndnSIM-folder>/NFD/daemon/table/cs.hpp
  • <ndnSIM-folder>/NFD/daemon/table/cs.cpp
  • <ndnSIM-folder>/NFD/daemon/table/cs-entry.hpp
  • <ndnSIM-folder>/NFD/daemon/table/cs-entry.cpp
  • <ndnSIM-folder>/NFD/daemon/table/cs-policy.hpp
  • <ndnSIM-folder>/NFD/daemon/table/cs-policy.cpp

cs.hpp与cs.cpp

cs.hpp 代码如下(我手动添加了部分注释,并且为了简短性,将部分单行return函数合并为了一行

class Cs : noncopyable
{
public:
  // 构造函数,默认最大存10个包
  explicit
  Cs(size_t nMaxPackets = 10);

  // 识别数据的缓存策略+把data塞进m_table且Fresh data+
  // +使用当前FIFO缓存策略处理data在队列中的位置
  void
  insert(const Data& data, bool isUnsolicited = false);

  // 异步擦除前缀名为prefix下的条目,得到擦除的条目数nErased
  // 擦除后执行回调函数cb
  template<typename AfterEraseCallback>
  void
  erase(const Name& prefix, size_t limit, AfterEraseCallback&& cb)
  {
    size_t nErased = eraseImpl(prefix, limit);
    cb(nErased);
  }

  // 用发的interest在CS中最匹配的data包,得到目标对应m_table中的迭代器
  // 如果找到,执行回调函数hit,否则执行回调函数miss
  template<typename HitCallback, typename MissCallback>
  void
  find(const Interest& interest, HitCallback&& hit, MissCallback&& miss) const
  {
    auto match = findImpl(interest);
    if (match == m_table.end()) {
      miss(interest);
      return;
    }
    hit(interest, match->getData());
  }

  // 返回m_table的size,即CS储存的条目数
  size_t size() const { return m_table.size(); }

public: // configuration
  // 返回储存上限
  size_t getLimit() const { return m_policy->getLimit(); }

  // 设置储存上限
  void setLimit(size_t nMaxPackets) { return m_policy->setLimit(nMaxPackets); }

  // 获取缓存替换策略
  Policy* getPolicy() const { return m_policy.get(); }

  // 更改缓存策略(必须size() == 0才能执行)
  void setPolicy(unique_ptr<Policy> policy);

  // 返回m_shouldAdmit (if false, no Data will be admitted)
  bool shouldAdmit() const { return m_shouldAdmit; }

  // Set m_shouldAdmit
  void enableAdmit(bool shouldAdmit);

  // 返回m_shouldServe (if false, all lookups will miss)
  bool shouldServe() const { return m_shouldServe; }

  // Set m_shouldServe
  void enableServe(bool shouldServe);

public: // enumeration
  using const_iterator = Table::const_iterator;

  // 头尾迭代器,应该不必多说吧,很简单
  const_iterator begin() const { return m_table.begin(); }
  const_iterator end() const { return m_table.end(); }

private:
  // 用Table进行二分查找,获得前缀为prefix的区间
  std::pair<const_iterator, const_iterator>
  findPrefixRange(const Name& prefix) const;

  // 前面的erase函数会调用eraseImpl函数作为具体实现
  // 擦除方式是调用findPrefixRange函数获得区间,然后擦掉所有元素
  // limit是擦除的上限,超过了就不擦了,不然全擦
  size_t
  eraseImpl(const Name& prefix, size_t limit);

  // 前面的find函数会调用findImpl函数作为具体实现
  // 擦除方式是调用findPrefixRange函数获得区间,然后用find_if函数遍历查找
  const_iterator
  findImpl(const Interest& interest) const;

  // 前面的setPolicy函数会调用setPolicyImpl函数作为具体实现
  void
  setPolicyImpl(unique_ptr<Policy> policy);

PUBLIC_WITH_TESTS_ELSE_PRIVATE:  // 测试public,运行时private
  void dump();  // 显示m_table里全部内容,仅测试时可用

private:
  Table m_table;  // 存CS内容的表
  unique_ptr<Policy> m_policy;  // 存缓存策略
  signal::ScopedConnection m_beforeEvictConnection;

  bool m_shouldAdmit = true; ///< if false, no Data will be admitted
  bool m_shouldServe = true; ///< if false, all lookups will miss
};

cs.cpp的Cs::insert函数详解

整个 cs.hpp 都很简单,对应的函数功能我都给了详细注释。对于 cs.cpp ,我只对 Cs::insert 这一个函数进行一些分析说明,具体说明以注释的形式给出——

void
Cs::insert(const Data& data, bool isUnsolicited)
{
  // 如果不Admit或者缓存上限为0,直接返回
  if (!m_shouldAdmit || m_policy->getLimit() == 0) {
    return;
  }
  NFD_LOG_DEBUG("insert " << data.getName());

  // 尝试取出data的CachePolicyType,如果data没Tag,视为要求缓存
  // 如果有Tag,Tag上的Type都说不缓存,那还insert个鬼,直接return吧
  shared_ptr<lp::CachePolicyTag> tag = data.getTag<lp::CachePolicyTag>();
  if (tag != nullptr) {
    lp::CachePolicyType policy = tag->get().getPolicy();
    if (policy == lp::CachePolicyType::NO_CACHE) {
      return;
    }
  }

  // 尝试把(data, isUnsolicited)压入m_table表
  // 压入后把自己在表中的迭代器返回给it(无论是否重复)
  // 因为是set类型,所以会调用data的重载operator==分析是否重复
  // 如果有重复元素,说明不是NewEntry,isNewEntry=false
  const_iterator it;
  bool isNewEntry = false;
  std::tie(it, isNewEntry) = m_table.emplace(data.shared_from_this(), isUnsolicited);
  Entry& entry = const_cast<Entry&>(*it);

  // Fresh一下新来的包
  entry.updateFreshUntil();

  // 善后工作
  if (!isNewEntry) { // existing entry
    // 刷新新来的包的isUnsolicited
    if (entry.isUnsolicited() && !isUnsolicited) {
      entry.clearUnsolicited();
    }

    m_policy->afterRefresh(it);
  }
  else {
    m_policy->afterInsert(it);
  }
}

总结

  • Cs 就是一个内容缓存器,其中缓存内容都存放在一个 m_table 中。
  • m_table 的类型为 Table ,相当于 std::set 。因为是集合,所以禁止存在相同元素。
  • std::set 的底层实现用到了红黑树,需要重载 operator < ,所以在文件 cs-entry.cppEntry 类型重载了 < 符号。
  • 缓存策略由 m_policy 进行维护,其中维护了缓存策略和缓存上限。

cs.hpp 的类 Cs 的数据成员如下——

private:
  Table m_table;  // 存CS内容的表
  unique_ptr<Policy> m_policy;  // 存缓存策略
  signal::ScopedConnection m_beforeEvictConnection;

  bool m_shouldAdmit = true; ///< if false, no Data will be admitted
  bool m_shouldServe = true; ///< if false, all lookups will miss

cs-entry.hpp 的类 Entry 的数据成员如下——

private:
  shared_ptr<const Data> m_data;  // 数据内容
  bool m_isUnsolicited;  // 未经请求的数据?(PIT里没有就是未经请求的)
  time::steady_clock::TimePoint m_freshUntil;  // Fresh截止时间

cs-policy.hpp 的类 Policy 的数据成员如下——

private:
  std::string m_policyName;  // 策略名
  size_t m_limit;  // 容量
  Cs* m_cs;  // 指向被维护的Cs的指针
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值