blob: 4c0ba021bb7a194928d796b9e90183e01bd79348 [file] [log] [blame]
Alexander Afanasyev8811b352013-01-02 12:51:15 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2012 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
19 * Zhenkai Zhu <zhenkai@cs.ucla.edu>
20 */
21
Alexander Afanasyev49a18522013-01-18 17:49:04 -080022#include "fetch-manager.h"
23#include <boost/make_shared.hpp>
24#include <boost/ref.hpp>
25#include <boost/throw_exception.hpp>
Alexander Afanasyev548d38d2013-01-26 16:36:06 -080026
27#include "simple-interval-generator.h"
Alexander Afanasyevfc720362013-01-24 21:49:48 -080028#include "logging.h"
29
Alexander Afanasyevff8d9dc2013-01-26 00:45:08 -080030INIT_LOGGER ("FetchManager");
Alexander Afanasyev49a18522013-01-18 17:49:04 -080031
32using namespace boost;
33using namespace std;
34using namespace Ccnx;
35
Alexander Afanasyev548d38d2013-01-26 16:36:06 -080036static const Name BROADCAST_DOMAIN = Name ("/ndn/broadcast/chronoshare");
Alexander Afanasyev83531a42013-01-19 16:21:54 -080037//The disposer object function
38struct fetcher_disposer { void operator() (Fetcher *delete_this) { delete delete_this; } };
39
Alexander Afanasyev548d38d2013-01-26 16:36:06 -080040static const string SCHEDULE_FETCHES_TAG = "ScheduleFetches";
41
Alexander Afanasyevf9978f82013-01-23 16:30:31 -080042FetchManager::FetchManager (CcnxWrapperPtr ccnx, const Mapping &mapping, uint32_t parallelFetches/* = 3*/)
Alexander Afanasyev49a18522013-01-18 17:49:04 -080043 : m_ccnx (ccnx)
Zhenkai Zhu3d1beca2013-01-23 14:55:32 -080044 , m_mapping (mapping)
Alexander Afanasyev83531a42013-01-19 16:21:54 -080045 , m_maxParallelFetches (parallelFetches)
46 , m_currentParallelFetches (0)
Alexander Afanasyev548d38d2013-01-26 16:36:06 -080047 , m_scheduler (new Scheduler)
Alexander Afanasyev8811b352013-01-02 12:51:15 -080048{
Alexander Afanasyev548d38d2013-01-26 16:36:06 -080049 m_scheduler->start ();
50
51 m_scheduleFetchesTask = Scheduler::schedulePeriodicTask (m_scheduler,
52 make_shared<SimpleIntervalGenerator> (1),
53 bind (&FetchManager::ScheduleFetches, this), SCHEDULE_FETCHES_TAG);
Alexander Afanasyev49a18522013-01-18 17:49:04 -080054}
Alexander Afanasyeva199f972013-01-02 19:37:26 -080055
Alexander Afanasyev49a18522013-01-18 17:49:04 -080056FetchManager::~FetchManager ()
57{
Alexander Afanasyev548d38d2013-01-26 16:36:06 -080058 m_scheduler->shutdown ();
59
Alexander Afanasyev83531a42013-01-19 16:21:54 -080060 m_fetchList.clear_and_dispose (fetcher_disposer ());
Alexander Afanasyev49a18522013-01-18 17:49:04 -080061}
Alexander Afanasyev8811b352013-01-02 12:51:15 -080062
Alexander Afanasyev49a18522013-01-18 17:49:04 -080063void
Zhenkai Zhu3d1beca2013-01-23 14:55:32 -080064FetchManager::Enqueue (const Ccnx::Name &deviceName, const Ccnx::Name &baseName,
65 const SegmentCallback &segmentCallback, const FinishCallback &finishCallback,
66 uint64_t minSeqNo, uint64_t maxSeqNo, int priority/*PRIORITY_NORMAL*/)
Alexander Afanasyev49a18522013-01-18 17:49:04 -080067{
Zhenkai Zhu454bae22013-01-24 19:27:54 -080068 // Assumption for the following code is minSeqNo <= maxSeqNo
69 if (minSeqNo > maxSeqNo)
70 {
71 return;
72 }
73
Alexander Afanasyev83531a42013-01-19 16:21:54 -080074 // we may need to guarantee that LookupLocator will gives an answer and not throw exception...
Alexander Afanasyev21a166e2013-01-20 16:04:41 -080075 Name forwardingHint;
Zhenkai Zhu3d1beca2013-01-23 14:55:32 -080076 forwardingHint = m_mapping (deviceName);
Alexander Afanasyev21a166e2013-01-20 16:04:41 -080077
78 Fetcher &fetcher = *(new Fetcher (m_ccnx,
Zhenkai Zhu3d1beca2013-01-23 14:55:32 -080079 segmentCallback,
80 finishCallback,
Alexander Afanasyev21a166e2013-01-20 16:04:41 -080081 bind (&FetchManager::DidFetchComplete, this, _1),
82 bind (&FetchManager::DidNoDataTimeout, this, _1),
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080083 deviceName, baseName, minSeqNo, maxSeqNo,
84 boost::posix_time::seconds (30),
85 forwardingHint));
Alexander Afanasyev83531a42013-01-19 16:21:54 -080086
87 switch (priority)
88 {
89 case PRIORITY_HIGH:
90 m_fetchList.push_front (fetcher);
91 break;
92
93 case PRIORITY_NORMAL:
94 default:
95 m_fetchList.push_back (fetcher);
96 break;
97 }
98
Alexander Afanasyevf8b22bf2013-01-26 17:28:11 -080099 _LOG_DEBUG ("Reschedule fetcher task");
Alexander Afanasyev548d38d2013-01-26 16:36:06 -0800100 m_scheduler->rescheduleTaskAt (m_scheduleFetchesTask, 0);
101 // ScheduleFetches (); // will start a fetch if m_currentParallelFetches is less than max, otherwise does nothing
Alexander Afanasyev49a18522013-01-18 17:49:04 -0800102}
Alexander Afanasyeve41e7d22013-01-19 15:13:47 -0800103
Alexander Afanasyev83531a42013-01-19 16:21:54 -0800104void
105FetchManager::ScheduleFetches ()
Alexander Afanasyeve41e7d22013-01-19 15:13:47 -0800106{
Alexander Afanasyev83531a42013-01-19 16:21:54 -0800107 unique_lock<mutex> lock (m_parellelFetchMutex);
108
Alexander Afanasyev548d38d2013-01-26 16:36:06 -0800109 boost::posix_time::ptime currentTime = date_time::second_clock<boost::posix_time::ptime>::universal_time ();
110
Alexander Afanasyev83531a42013-01-19 16:21:54 -0800111 for (FetchList::iterator item = m_fetchList.begin ();
112 m_currentParallelFetches < m_maxParallelFetches && item != m_fetchList.end ();
113 item++)
114 {
Alexander Afanasyev21a166e2013-01-20 16:04:41 -0800115 if (item->IsActive ())
Alexander Afanasyevf8b22bf2013-01-26 17:28:11 -0800116 {
117 _LOG_DEBUG ("Item is active");
118 continue;
119 }
Alexander Afanasyev83531a42013-01-19 16:21:54 -0800120
Alexander Afanasyev548d38d2013-01-26 16:36:06 -0800121 if (currentTime < item->GetNextScheduledRetry ())
Alexander Afanasyevf8b22bf2013-01-26 17:28:11 -0800122 {
123 _LOG_DEBUG ("Item is delayed");
124 continue;
125 }
Alexander Afanasyev548d38d2013-01-26 16:36:06 -0800126
Alexander Afanasyevff8d9dc2013-01-26 00:45:08 -0800127 _LOG_DEBUG ("Start fetching of " << item->GetName ());
128
Alexander Afanasyev83531a42013-01-19 16:21:54 -0800129 m_currentParallelFetches ++;
130 item->RestartPipeline ();
131 }
Alexander Afanasyeve41e7d22013-01-19 15:13:47 -0800132}
133
Alexander Afanasyev83531a42013-01-19 16:21:54 -0800134void
Alexander Afanasyevd6c2a902013-01-19 21:24:30 -0800135FetchManager::DidNoDataTimeout (Fetcher &fetcher)
Alexander Afanasyeve41e7d22013-01-19 15:13:47 -0800136{
Alexander Afanasyevff8d9dc2013-01-26 00:45:08 -0800137 _LOG_DEBUG ("No data timeout for " << fetcher.GetName () << " with forwarding hint: " << fetcher.GetForwardingHint ());
138
Alexander Afanasyev83531a42013-01-19 16:21:54 -0800139 {
140 unique_lock<mutex> lock (m_parellelFetchMutex);
141 m_currentParallelFetches --;
142 // no need to do anything with the m_fetchList
143 }
Alexander Afanasyevd6c2a902013-01-19 21:24:30 -0800144
Alexander Afanasyev548d38d2013-01-26 16:36:06 -0800145 if (fetcher.GetForwardingHint () == BROADCAST_DOMAIN)
146 {
147 // try again directly (hopefully with different forwarding hint
148
149 /// @todo Handle potential exception
150 Name forwardingHint;
151 forwardingHint = m_mapping (fetcher.GetDeviceName ());
152 fetcher.SetForwardingHint (forwardingHint);
153 }
154 else
155 {
156 fetcher.SetForwardingHint (BROADCAST_DOMAIN);
157 }
158
159 double delay = fetcher.GetRetryPause ();
160 if (delay < 1) // first time
161 {
162 delay = 1;
163 }
164 else
165 {
166 delay = std::min (2*delay, 300.0); // 5 minutes max
167 }
168
169 fetcher.SetRetryPause (delay);
170 fetcher.SetNextScheduledRetry (date_time::second_clock<boost::posix_time::ptime>::universal_time () + posix_time::seconds (delay));
Alexander Afanasyev83531a42013-01-19 16:21:54 -0800171}
172
173void
Alexander Afanasyevd6c2a902013-01-19 21:24:30 -0800174FetchManager::DidFetchComplete (Fetcher &fetcher)
Alexander Afanasyev83531a42013-01-19 16:21:54 -0800175{
Alexander Afanasyev83531a42013-01-19 16:21:54 -0800176 {
177 unique_lock<mutex> lock (m_parellelFetchMutex);
178 m_currentParallelFetches --;
179 m_fetchList.erase_and_dispose (FetchList::s_iterator_to (fetcher), fetcher_disposer ());
180 }
Alexander Afanasyevd6c2a902013-01-19 21:24:30 -0800181
Alexander Afanasyeve41e7d22013-01-19 15:13:47 -0800182}