chunks: code cleanups

  * Introduce getSegmentFromPacket() helper function
  * Use signed arithmetic for some quantities to avoid conversion issues
  * Move start time handling to PipelineInterests base class

Change-Id: I275acac1ad93e4a72374d03fad0a1d7348d70976
diff --git a/tools/chunks/catchunks/consumer.cpp b/tools/chunks/catchunks/consumer.cpp
index 6ecd630..306cc16 100644
--- a/tools/chunks/catchunks/consumer.cpp
+++ b/tools/chunks/catchunks/consumer.cpp
@@ -1,8 +1,8 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2016,  Regents of the University of California,
- *                      Colorado State University,
- *                      University Pierre & Marie Curie, Sorbonne University.
+ * Copyright (c) 2016-2017, Regents of the University of California,
+ *                          Colorado State University,
+ *                          University Pierre & Marie Curie, Sorbonne University.
  *
  * This file is part of ndn-tools (Named Data Networking Essential Tools).
  * See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -82,7 +82,7 @@
     throw ApplicationNackError(*data);
   }
 
-  m_bufferedData[data->getName()[-1].toSegment()] = data;
+  m_bufferedData[getSegmentFromPacket(*data)] = data;
   writeInOrderData();
 }
 
diff --git a/tools/chunks/catchunks/pipeline-interests-aimd.cpp b/tools/chunks/catchunks/pipeline-interests-aimd.cpp
index 2b7af06..622eb43 100644
--- a/tools/chunks/catchunks/pipeline-interests-aimd.cpp
+++ b/tools/chunks/catchunks/pipeline-interests-aimd.cpp
@@ -1,3 +1,4 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
  * Copyright (c) 2016-2017, Regents of the University of California,
  *                          Colorado State University,
@@ -65,9 +66,6 @@
 void
 PipelineInterestsAimd::doRun()
 {
-  // record the start time of running pipeline
-  m_startTime = time::steady_clock::now();
-
   // count the excluded segment
   m_nReceived++;
 
@@ -187,7 +185,9 @@
 void
 PipelineInterestsAimd::schedulePackets()
 {
-  int availableWindowSize = static_cast<int>(m_cwnd) - m_nInFlight;
+  BOOST_ASSERT(m_nInFlight >= 0);
+  auto availableWindowSize = static_cast<int64_t>(m_cwnd) - m_nInFlight;
+
   while (availableWindowSize > 0) {
     if (!m_retxQueue.empty()) { // do retransmission first
       uint64_t retxSegNo = m_retxQueue.front();
@@ -228,7 +228,7 @@
     }
   }
 
-  uint64_t recvSegNo = data.getName()[-1].toSegment();
+  uint64_t recvSegNo = getSegmentFromPacket(data);
   if (m_highData < recvSegNo) {
     m_highData = recvSegNo;
   }
@@ -261,8 +261,9 @@
 
   if (segInfo.state == SegmentState::FirstTimeSent ||
       segInfo.state == SegmentState::InRetxQueue) { // do not sample RTT for retransmitted segments
-    size_t nExpectedSamples = std::max(static_cast<int>(std::ceil(m_nInFlight / 2.0)), 1);
-    m_rttEstimator.addMeasurement(recvSegNo, rtt, nExpectedSamples);
+    auto nExpectedSamples = std::max<int64_t>((m_nInFlight + 1) >> 1, 1);
+    BOOST_ASSERT(nExpectedSamples > 0);
+    m_rttEstimator.addMeasurement(recvSegNo, rtt, static_cast<size_t>(nExpectedSamples));
     m_segmentInfo.erase(recvSegNo); // remove the entry associated with the received segment
   }
   else { // retransmission
@@ -270,7 +271,8 @@
   }
 
   BOOST_ASSERT(m_nReceived > 0);
-  if (m_hasFinalBlockId && m_nReceived - 1 >= m_lastSegmentNo) { // all segments have been received
+  if (m_hasFinalBlockId &&
+      static_cast<uint64_t>(m_nReceived - 1) >= m_lastSegmentNo) { // all segments have been received
     cancel();
     if (m_options.isVerbose) {
       printSummary();
@@ -291,7 +293,7 @@
     std::cerr << "Received Nack with reason " << nack.getReason()
               << " for Interest " << interest << std::endl;
 
-  uint64_t segNo = interest.getName()[-1].toSegment();
+  uint64_t segNo = getSegmentFromPacket(interest);
 
   switch (nack.getReason()) {
     case lp::NackReason::DUPLICATE: {
@@ -317,7 +319,7 @@
   if (isStopping())
     return;
 
-  uint64_t segNo = interest.getName()[-1].toSegment();
+  uint64_t segNo = getSegmentFromPacket(interest);
   m_retxQueue.push(segNo); // put on retx queue
   m_segmentInfo[segNo].state = SegmentState::InRetxQueue; // update state
   handleTimeout(1);
@@ -343,11 +345,7 @@
     }
   }
 
-  if (m_nInFlight > static_cast<uint64_t>(timeoutCount))
-    m_nInFlight -= timeoutCount;
-  else
-    m_nInFlight = 0;
-
+  m_nInFlight = std::max<int64_t>(0, m_nInFlight - timeoutCount);
   schedulePackets();
 }
 
@@ -386,7 +384,7 @@
   } else {
     m_cwnd += m_options.aiStep / std::floor(m_cwnd); // congestion avoidance
   }
-  afterCwndChange(time::steady_clock::now() - m_startTime, m_cwnd);
+  afterCwndChange(time::steady_clock::now() - getStartTime(), m_cwnd);
 }
 
 void
@@ -395,7 +393,7 @@
   // please refer to RFC 5681, Section 3.1 for the rationale behind it
   m_ssthresh = std::max(2.0, m_cwnd * m_options.mdCoef); // multiplicative decrease
   m_cwnd = m_options.resetCwndToInit ? m_options.initCwnd : m_ssthresh;
-  afterCwndChange(time::steady_clock::now() - m_startTime, m_cwnd);
+  afterCwndChange(time::steady_clock::now() - getStartTime(), m_cwnd);
 }
 
 uint64_t
@@ -427,8 +425,8 @@
 void
 PipelineInterestsAimd::printSummary() const
 {
-  Milliseconds timePassed = time::steady_clock::now() - m_startTime;
-  double throughput = (8 * m_receivedSize * 1000) / timePassed.count();
+  Milliseconds timeElapsed = time::steady_clock::now() - getStartTime();
+  double throughput = (8 * m_receivedSize * 1000) / timeElapsed.count();
 
   int pow = 0;
   std::string throughputUnit;
@@ -455,9 +453,9 @@
   }
 
   std::cerr << "\nAll segments have been received.\n"
+            << "Time elapsed: " << timeElapsed << "\n"
             << "Total # of segments received: " << m_nReceived << "\n"
-            << "Time used: " << timePassed.count() << " ms" << "\n"
-            << "Total # of packet loss burst: " << m_nLossEvents << "\n"
+            << "Total # of packet loss events: " << m_nLossEvents << "\n"
             << "Packet loss rate: "
             << static_cast<double>(m_nLossEvents) / static_cast<double>(m_nReceived) << "\n"
             << "Total # of retransmitted segments: " << m_nRetransmitted << "\n"
diff --git a/tools/chunks/catchunks/pipeline-interests-aimd.hpp b/tools/chunks/catchunks/pipeline-interests-aimd.hpp
index c67d5bc..1670fda 100644
--- a/tools/chunks/catchunks/pipeline-interests-aimd.hpp
+++ b/tools/chunks/catchunks/pipeline-interests-aimd.hpp
@@ -1,3 +1,4 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
  * Copyright (c) 2016-2017, Regents of the University of California,
  *                          Colorado State University,
@@ -196,12 +197,10 @@
   uint64_t m_recPoint; ///< the value of m_highInterest when a packet loss event occurred,
                        ///< it remains fixed until the next packet loss event happens
 
-  uint64_t m_nInFlight; ///< # of segments in flight
-  uint64_t m_nReceived; ///< # of segments received
-  uint64_t m_nLossEvents; ///< # of loss events occurred
-  uint64_t m_nRetransmitted; ///< # of segments retransmitted
-
-  time::steady_clock::TimePoint m_startTime; ///< start time of pipelining
+  int64_t m_nInFlight; ///< # of segments in flight
+  int64_t m_nReceived; ///< # of segments received
+  int64_t m_nLossEvents; ///< # of loss events occurred
+  int64_t m_nRetransmitted; ///< # of segments retransmitted
 
   double m_cwnd; ///< current congestion window size (in segments)
   double m_ssthresh; ///< current slow start threshold
diff --git a/tools/chunks/catchunks/pipeline-interests-fixed-window.cpp b/tools/chunks/catchunks/pipeline-interests-fixed-window.cpp
index 049d52d..5dcb471 100644
--- a/tools/chunks/catchunks/pipeline-interests-fixed-window.cpp
+++ b/tools/chunks/catchunks/pipeline-interests-fixed-window.cpp
@@ -1,8 +1,8 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2016,  Regents of the University of California,
- *                      Colorado State University,
- *                      University Pierre & Marie Curie, Sorbonne University.
+ * Copyright (c) 2016-2017, Regents of the University of California,
+ *                          Colorado State University,
+ *                          University Pierre & Marie Curie, Sorbonne University.
  *
  * This file is part of ndn-tools (Named Data Networking Essential Tools).
  * See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -120,7 +120,7 @@
   BOOST_ASSERT(data.getName().equals(interest.getName()));
 
   if (m_options.isVerbose)
-    std::cerr << "Received segment #" << data.getName()[-1].toSegment() << std::endl;
+    std::cerr << "Received segment #" << getSegmentFromPacket(data) << std::endl;
 
   onData(interest, data);
 
diff --git a/tools/chunks/catchunks/pipeline-interests.cpp b/tools/chunks/catchunks/pipeline-interests.cpp
index ff817e4..dd6640d 100644
--- a/tools/chunks/catchunks/pipeline-interests.cpp
+++ b/tools/chunks/catchunks/pipeline-interests.cpp
@@ -1,8 +1,8 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2016,  Regents of the University of California,
- *                      Colorado State University,
- *                      University Pierre & Marie Curie, Sorbonne University.
+ * Copyright (c) 2016-2017, Regents of the University of California,
+ *                          Colorado State University,
+ *                          University Pierre & Marie Curie, Sorbonne University.
  *
  * This file is part of ndn-tools (Named Data Networking Essential Tools).
  * See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -50,13 +50,16 @@
   m_onData = std::move(onData);
   m_onFailure = std::move(onFailure);
   m_prefix = data.getName().getPrefix(-1);
-  m_excludedSegmentNo = data.getName()[-1].toSegment();
+  m_excludedSegmentNo = getSegmentFromPacket(data);
 
   if (!data.getFinalBlockId().empty()) {
     m_lastSegmentNo = data.getFinalBlockId().toSegment();
     m_hasFinalBlockId = true;
   }
 
+  // record the start time of the pipeline
+  m_startTime = time::steady_clock::now();
+
   doRun();
 }
 
diff --git a/tools/chunks/catchunks/pipeline-interests.hpp b/tools/chunks/catchunks/pipeline-interests.hpp
index 8921407..8fe349e 100644
--- a/tools/chunks/catchunks/pipeline-interests.hpp
+++ b/tools/chunks/catchunks/pipeline-interests.hpp
@@ -1,8 +1,8 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2016,  Regents of the University of California,
- *                      Colorado State University,
- *                      University Pierre & Marie Curie, Sorbonne University.
+ * Copyright (c) 2016-2017, Regents of the University of California,
+ *                          Colorado State University,
+ *                          University Pierre & Marie Curie, Sorbonne University.
  *
  * This file is part of ndn-tools (Named Data Networking Essential Tools).
  * See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -80,6 +80,12 @@
   cancel();
 
 protected:
+  time::steady_clock::TimePoint
+  getStartTime() const
+  {
+    return m_startTime;
+  }
+
   bool
   isStopping() const
   {
@@ -126,9 +132,17 @@
 private:
   DataCallback m_onData;
   FailureCallback m_onFailure;
+  time::steady_clock::TimePoint m_startTime;
   bool m_isStopping;
 };
 
+template<typename Packet>
+uint64_t
+getSegmentFromPacket(const Packet& packet)
+{
+  return packet.getName().at(-1).toSegment();
+}
+
 } // namespace chunks
 } // namespace ndn