blob: a398f0bed7127b24cbf9692230b2f6346f828133 [file] [log] [blame]
Shuo Chen29c77fe2014-03-18 11:29:41 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev42290b22017-03-09 12:58:29 -08003 * Copyright (c) 2014-2017, Regents of the University of California.
Alexander Afanasyeve1e6f2a2014-04-25 11:28:12 -07004 *
5 * This file is part of NDN repo-ng (Next generation of NDN repository).
6 * See AUTHORS.md for complete list of repo-ng authors and contributors.
7 *
8 * repo-ng is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * repo-ng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Shuo Chen29c77fe2014-03-18 11:29:41 -070018 */
19
20#include "write-handle.hpp"
21
22namespace repo {
23
24static const int RETRY_TIMEOUT = 3;
25static const int DEFAULT_CREDIT = 12;
Weiqi Shi098f91c2014-07-23 17:41:35 -070026static const milliseconds NOEND_TIMEOUT(10000);
27static const milliseconds PROCESS_DELETE_TIME(10000);
28static const milliseconds DEFAULT_INTEREST_LIFETIME(4000);
Shuo Chen29c77fe2014-03-18 11:29:41 -070029
Weiqi Shif0330d52014-07-09 10:54:27 -070030WriteHandle::WriteHandle(Face& face, RepoStorage& storageHandle, KeyChain& keyChain,
Junxiao Shi047a6fb2017-06-08 16:16:05 +000031 Scheduler& scheduler,
32 Validator& validator)
Shuo Chen29c77fe2014-03-18 11:29:41 -070033 : BaseHandle(face, storageHandle, keyChain, scheduler)
34 , m_validator(validator)
35 , m_retryTime(RETRY_TIMEOUT)
36 , m_credit(DEFAULT_CREDIT)
37 , m_noEndTimeout(NOEND_TIMEOUT)
Weiqi Shi098f91c2014-07-23 17:41:35 -070038 , m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
Shuo Chen29c77fe2014-03-18 11:29:41 -070039{
40}
41
42void
43WriteHandle::deleteProcess(ProcessId processId)
44{
45 m_processes.erase(processId);
46}
47
48// Interest.
49void
50WriteHandle::onInterest(const Name& prefix, const Interest& interest)
51{
52 m_validator.validate(interest,
Shuo Chenc88c87d2014-06-25 20:21:02 +080053 bind(&WriteHandle::onValidated, this, _1, prefix),
54 bind(&WriteHandle::onValidationFailed, this, _1, _2));
Shuo Chen29c77fe2014-03-18 11:29:41 -070055}
56
Shuo Chen29c77fe2014-03-18 11:29:41 -070057void
Wentao Shanga8f3c402014-10-30 14:03:27 -070058WriteHandle::onValidated(const std::shared_ptr<const Interest>& interest, const Name& prefix)
Shuo Chen29c77fe2014-03-18 11:29:41 -070059{
60 //m_validResult = 1;
61 RepoCommandParameter parameter;
62 try {
63 extractParameter(*interest, prefix, parameter);
64 }
65 catch (RepoCommandParameter::Error) {
66 negativeReply(*interest, 403);
67 return;
68 }
69
70 if (parameter.hasStartBlockId() || parameter.hasEndBlockId()) {
71 if (parameter.hasSelectors()) {
72 negativeReply(*interest, 402);
73 return;
74 }
75 processSegmentedInsertCommand(*interest, parameter);
76 }
77 else {
78 processSingleInsertCommand(*interest, parameter);
79 }
Weiqi Shi098f91c2014-07-23 17:41:35 -070080 if (parameter.hasInterestLifetime())
81 m_interestLifetime = parameter.getInterestLifetime();
Shuo Chen29c77fe2014-03-18 11:29:41 -070082}
83
84void
Wentao Shanga8f3c402014-10-30 14:03:27 -070085WriteHandle::onValidationFailed(const std::shared_ptr<const Interest>& interest,
86 const std::string& reason)
Shuo Chen29c77fe2014-03-18 11:29:41 -070087{
Shuo Chen028dcd32014-06-21 16:36:44 +080088 std::cerr << reason << std::endl;
Shuo Chen29c77fe2014-03-18 11:29:41 -070089 negativeReply(*interest, 401);
90}
91
92void
Alexander Afanasyev42290b22017-03-09 12:58:29 -080093WriteHandle::onData(const Interest& interest, const Data& data, ProcessId processId)
Shuo Chen29c77fe2014-03-18 11:29:41 -070094{
Shuo Chenc88c87d2014-06-25 20:21:02 +080095 m_validator.validate(data,
96 bind(&WriteHandle::onDataValidated, this, interest, _1, processId),
97 bind(&WriteHandle::onDataValidationFailed, this, _1, _2));
98}
99
100void
Wentao Shanga8f3c402014-10-30 14:03:27 -0700101WriteHandle::onDataValidated(const Interest& interest,
102 const std::shared_ptr<const Data>& data,
Shuo Chenc88c87d2014-06-25 20:21:02 +0800103 ProcessId processId)
104{
Shuo Chen29c77fe2014-03-18 11:29:41 -0700105 if (m_processes.count(processId) == 0) {
106 return;
107 }
108
109 ProcessInfo& process = m_processes[processId];
110 RepoCommandResponse& response = process.response;
111
112 if (response.getInsertNum() == 0) {
Shuo Chenc88c87d2014-06-25 20:21:02 +0800113 getStorageHandle().insertData(*data);
Weiqi Shif0330d52014-07-09 10:54:27 -0700114 // getStorageHandle().insertEntry(*data);
115 // getStoreIndex().insert(*data);
Shuo Chen29c77fe2014-03-18 11:29:41 -0700116 response.setInsertNum(1);
117 }
118
119 deferredDeleteProcess(processId);
120}
121
122void
Wentao Shanga8f3c402014-10-30 14:03:27 -0700123WriteHandle::onDataValidationFailed(const std::shared_ptr<const Data>& data,
124 const std::string& reason)
Shuo Chenc88c87d2014-06-25 20:21:02 +0800125{
126 std::cerr << reason << std::endl;
127}
128
129void
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800130WriteHandle::onSegmentData(const Interest& interest, const Data& data, ProcessId processId)
Shuo Chen29c77fe2014-03-18 11:29:41 -0700131{
Shuo Chenc88c87d2014-06-25 20:21:02 +0800132 m_validator.validate(data,
133 bind(&WriteHandle::onSegmentDataValidated, this, interest, _1, processId),
134 bind(&WriteHandle::onDataValidationFailed, this, _1, _2));
135}
136
137void
138WriteHandle::onSegmentDataValidated(const Interest& interest,
Wentao Shanga8f3c402014-10-30 14:03:27 -0700139 const std::shared_ptr<const Data>& data,
Shuo Chenc88c87d2014-06-25 20:21:02 +0800140 ProcessId processId)
141{
Shuo Chen29c77fe2014-03-18 11:29:41 -0700142 if (m_processes.count(processId) == 0) {
143 return;
144 }
145 RepoCommandResponse& response = m_processes[processId].response;
146
147 //refresh endBlockId
Shuo Chenc88c87d2014-06-25 20:21:02 +0800148 Name::Component finalBlockId = data->getFinalBlockId();
Shuo Chen29c77fe2014-03-18 11:29:41 -0700149
150 if (!finalBlockId.empty()) {
151 SegmentNo final = finalBlockId.toSegment();
152 if (response.hasEndBlockId()) {
153 if (final < response.getEndBlockId()) {
154 response.setEndBlockId(final);
155 }
156 }
157 else {
158 response.setEndBlockId(final);
159 }
160 }
161
162 //insert data
Shuo Chenc88c87d2014-06-25 20:21:02 +0800163 if (getStorageHandle().insertData(*data)) {
Shuo Chen29c77fe2014-03-18 11:29:41 -0700164 response.setInsertNum(response.getInsertNum() + 1);
165 }
Shuo Chen29c77fe2014-03-18 11:29:41 -0700166
167 onSegmentDataControl(processId, interest);
168}
169
170void
Wentao Shanga8f3c402014-10-30 14:03:27 -0700171WriteHandle::onTimeout(const Interest& interest, ProcessId processId)
Shuo Chen29c77fe2014-03-18 11:29:41 -0700172{
Shuo Chen028dcd32014-06-21 16:36:44 +0800173 std::cerr << "Timeout" << std::endl;
Shuo Chen29c77fe2014-03-18 11:29:41 -0700174 m_processes.erase(processId);
175}
176
177void
178WriteHandle::onSegmentTimeout(const Interest& interest, ProcessId processId)
179{
Shuo Chen028dcd32014-06-21 16:36:44 +0800180 std::cerr << "SegTimeout" << std::endl;
Shuo Chen29c77fe2014-03-18 11:29:41 -0700181
182 onSegmentTimeoutControl(processId, interest);
183}
184
185void
186WriteHandle::listen(const Name& prefix)
187{
Junxiao Shi2b7b8312017-06-16 03:43:24 +0000188 getFace().setInterestFilter(Name(prefix).append("insert"),
189 bind(&WriteHandle::onInterest, this, _1, _2));
190 getFace().setInterestFilter(Name(prefix).append("insert check"),
191 bind(&WriteHandle::onCheckInterest, this, _1, _2));
Shuo Chen29c77fe2014-03-18 11:29:41 -0700192}
193
194void
195WriteHandle::segInit(ProcessId processId, const RepoCommandParameter& parameter)
196{
197 ProcessInfo& process = m_processes[processId];
198 process.credit = 0;
199
200 map<SegmentNo, int>& processRetry = process.retryCounts;
201
202 Name name = parameter.getName();
203 SegmentNo startBlockId = parameter.getStartBlockId();
204
205 uint64_t initialCredit = m_credit;
206
207 if (parameter.hasEndBlockId()) {
208 initialCredit =
Shuo Chen39fe8da2014-04-30 00:00:35 +0800209 std::min(initialCredit, parameter.getEndBlockId() - parameter.getStartBlockId() + 1);
Shuo Chen29c77fe2014-03-18 11:29:41 -0700210 }
211 else {
212 // set noEndTimeout timer
213 process.noEndTime = ndn::time::steady_clock::now() +
214 m_noEndTimeout;
215 }
216 process.credit = initialCredit;
217 SegmentNo segment = startBlockId;
Weiqi Shi098f91c2014-07-23 17:41:35 -0700218
Shuo Chen29c77fe2014-03-18 11:29:41 -0700219 for (; segment < startBlockId + initialCredit; ++segment) {
220 Name fetchName = name;
221 fetchName.appendSegment(segment);
222 Interest interest(fetchName);
Weiqi Shi098f91c2014-07-23 17:41:35 -0700223 interest.setInterestLifetime(m_interestLifetime);
Shuo Chen29c77fe2014-03-18 11:29:41 -0700224 getFace().expressInterest(interest,
225 bind(&WriteHandle::onSegmentData, this, _1, _2, processId),
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800226 bind(&WriteHandle::onSegmentTimeout, this, _1, processId), // Nack
Shuo Chen29c77fe2014-03-18 11:29:41 -0700227 bind(&WriteHandle::onSegmentTimeout, this, _1, processId));
228 process.credit--;
229 processRetry[segment] = 0;
230 }
231
232 queue<SegmentNo>& nextSegmentQueue = process.nextSegmentQueue;
233
Shuo Chen29c77fe2014-03-18 11:29:41 -0700234 process.nextSegment = segment;
235 nextSegmentQueue.push(segment);
236}
237
238void
239WriteHandle::onSegmentDataControl(ProcessId processId, const Interest& interest)
240{
Shuo Chen29c77fe2014-03-18 11:29:41 -0700241 if (m_processes.count(processId) == 0) {
242 return;
243 }
244 ProcessInfo& process = m_processes[processId];
245 RepoCommandResponse& response = process.response;
246 int& processCredit = process.credit;
247 //onSegmentDataControl is called when a data returns.
248 //When data returns, processCredit++
249 processCredit++;
250 SegmentNo& nextSegment = process.nextSegment;
251 queue<SegmentNo>& nextSegmentQueue = process.nextSegmentQueue;
252 map<SegmentNo, int>& retryCounts = process.retryCounts;
253
254 //read whether notime timeout
255 if (!response.hasEndBlockId()) {
256
257 ndn::time::steady_clock::TimePoint& noEndTime = process.noEndTime;
258 ndn::time::steady_clock::TimePoint now = ndn::time::steady_clock::now();
259
260 if (now > noEndTime) {
Shuo Chen028dcd32014-06-21 16:36:44 +0800261 std::cerr << "noEndtimeout: " << processId << std::endl;
Shuo Chen29c77fe2014-03-18 11:29:41 -0700262 //m_processes.erase(processId);
263 //StatusCode should be refreshed as 405
264 response.setStatusCode(405);
265 //schedule a delete event
266 deferredDeleteProcess(processId);
267 return;
268 }
269 }
270
271 //read whether this process has total ends, if ends, remove control info from the maps
272 if (response.hasEndBlockId()) {
273 uint64_t nSegments =
274 response.getEndBlockId() - response.getStartBlockId() + 1;
275 if (response.getInsertNum() >= nSegments) {
276 //m_processes.erase(processId);
277 //All the data has been inserted, StatusCode is refreshed as 200
278 response.setStatusCode(200);
279 deferredDeleteProcess(processId);
280 return;
281 }
282 }
283
284 //check whether there is any credit
285 if (processCredit == 0)
286 return;
287
288
289 //check whether sent queue empty
290 if (nextSegmentQueue.empty()) {
291 //do not do anything
292 return;
293 }
294
295 //pop the queue
296 SegmentNo sendingSegment = nextSegmentQueue.front();
297 nextSegmentQueue.pop();
298
299 //check whether sendingSegment exceeds
Shuo Chenccfbe242014-04-29 23:57:51 +0800300 if (response.hasEndBlockId() && sendingSegment > response.getEndBlockId()) {
Shuo Chen29c77fe2014-03-18 11:29:41 -0700301 //do not do anything
302 return;
303 }
304
305 //read whether this is retransmitted data;
306 SegmentNo fetchedSegment =
307 interest.getName().get(interest.getName().size() - 1).toSegment();
308
309 BOOST_ASSERT(retryCounts.count(fetchedSegment) != 0);
310
311 //find this fetched data, remove it from this map
312 //rit->second.erase(oit);
313 retryCounts.erase(fetchedSegment);
314 //express the interest of the top of the queue
315 Name fetchName(interest.getName().getPrefix(-1));
316 fetchName.appendSegment(sendingSegment);
317 Interest fetchInterest(fetchName);
Weiqi Shi098f91c2014-07-23 17:41:35 -0700318 fetchInterest.setInterestLifetime(m_interestLifetime);
Shuo Chen29c77fe2014-03-18 11:29:41 -0700319 getFace().expressInterest(fetchInterest,
320 bind(&WriteHandle::onSegmentData, this, _1, _2, processId),
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800321 bind(&WriteHandle::onSegmentTimeout, this, _1, processId), // Nack
Shuo Chen29c77fe2014-03-18 11:29:41 -0700322 bind(&WriteHandle::onSegmentTimeout, this, _1, processId));
323 //When an interest is expressed, processCredit--
324 processCredit--;
Shuo Chen29c77fe2014-03-18 11:29:41 -0700325 if (retryCounts.count(sendingSegment) == 0) {
326 //not found
327 retryCounts[sendingSegment] = 0;
328 }
329 else {
330 //found
331 retryCounts[sendingSegment] = retryCounts[sendingSegment] + 1;
332 }
333 //increase the next seg and put it into the queue
Shuo Chenccfbe242014-04-29 23:57:51 +0800334 if (!response.hasEndBlockId() || (nextSegment + 1) <= response.getEndBlockId()) {
Shuo Chen29c77fe2014-03-18 11:29:41 -0700335 nextSegment++;
336 nextSegmentQueue.push(nextSegment);
337 }
338}
339
340void
341WriteHandle::onSegmentTimeoutControl(ProcessId processId, const Interest& interest)
342{
343 if (m_processes.count(processId) == 0) {
344 return;
345 }
346 ProcessInfo& process = m_processes[processId];
Shuo Chen09f09bb2014-03-18 15:37:11 -0700347 // RepoCommandResponse& response = process.response;
348 // SegmentNo& nextSegment = process.nextSegment;
349 // queue<SegmentNo>& nextSegmentQueue = process.nextSegmentQueue;
Shuo Chen29c77fe2014-03-18 11:29:41 -0700350 map<SegmentNo, int>& retryCounts = process.retryCounts;
351
352 SegmentNo timeoutSegment = interest.getName().get(-1).toSegment();
353
Shuo Chen028dcd32014-06-21 16:36:44 +0800354 std::cerr << "timeoutSegment: " << timeoutSegment << std::endl;
Shuo Chen29c77fe2014-03-18 11:29:41 -0700355
356 BOOST_ASSERT(retryCounts.count(timeoutSegment) != 0);
357
358 //read the retry time. If retry out of time, fail the process. if not, plus
359 int& retryTime = retryCounts[timeoutSegment];
360 if (retryTime >= m_retryTime) {
361 //fail this process
Shuo Chen028dcd32014-06-21 16:36:44 +0800362 std::cerr << "Retry timeout: " << processId << std::endl;
Shuo Chen29c77fe2014-03-18 11:29:41 -0700363 m_processes.erase(processId);
364 return;
365 }
366 else {
367 //Reput it in the queue, retryTime++
368 retryTime++;
369 Interest retryInterest(interest.getName());
Weiqi Shi098f91c2014-07-23 17:41:35 -0700370 retryInterest.setInterestLifetime(m_interestLifetime);
Shuo Chen29c77fe2014-03-18 11:29:41 -0700371 getFace().expressInterest(retryInterest,
372 bind(&WriteHandle::onSegmentData, this, _1, _2, processId),
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800373 bind(&WriteHandle::onSegmentTimeout, this, _1, processId), // Nack
Shuo Chen29c77fe2014-03-18 11:29:41 -0700374 bind(&WriteHandle::onSegmentTimeout, this, _1, processId));
375 }
376
377}
378
379void
380WriteHandle::onCheckInterest(const Name& prefix, const Interest& interest)
381{
382 m_validator.validate(interest,
Shuo Chenc88c87d2014-06-25 20:21:02 +0800383 bind(&WriteHandle::onCheckValidated, this, _1, prefix),
384 bind(&WriteHandle::onCheckValidationFailed, this, _1, _2));
Shuo Chen29c77fe2014-03-18 11:29:41 -0700385
386}
387
388void
389WriteHandle::onCheckValidated(const shared_ptr<const Interest>& interest, const Name& prefix)
390{
391 RepoCommandParameter parameter;
392 try {
393 extractParameter(*interest, prefix, parameter);
394 }
395 catch (RepoCommandParameter::Error) {
396 negativeReply(*interest, 403);
397 return;
398 }
399
400 if (!parameter.hasProcessId()) {
401 negativeReply(*interest, 403);
402 return;
403 }
404 //check whether this process exists
405 ProcessId processId = parameter.getProcessId();
406 if (m_processes.count(processId) == 0) {
Shuo Chen028dcd32014-06-21 16:36:44 +0800407 std::cerr << "no such processId: " << processId << std::endl;
Shuo Chen29c77fe2014-03-18 11:29:41 -0700408 negativeReply(*interest, 404);
409 return;
410 }
411
412 ProcessInfo& process = m_processes[processId];
413
414 RepoCommandResponse& response = process.response;
415
416 //Check whether it is single data fetching
417 if (!response.hasStartBlockId() &&
418 !response.hasEndBlockId()) {
419 reply(*interest, response);
420 return;
421 }
422
423 //read if noEndtimeout
424 if (!response.hasEndBlockId()) {
425 extendNoEndTime(process);
426 reply(*interest, response);
427 return;
428 }
429 else {
430 reply(*interest, response);
431 }
432}
433
434void
Shuo Chenc88c87d2014-06-25 20:21:02 +0800435WriteHandle::onCheckValidationFailed(const shared_ptr<const Interest>& interest,
436 const std::string& reason)
Shuo Chen29c77fe2014-03-18 11:29:41 -0700437{
Shuo Chenc88c87d2014-06-25 20:21:02 +0800438 std::cerr << reason << std::endl;
Shuo Chen29c77fe2014-03-18 11:29:41 -0700439 negativeReply(*interest, 401);
440}
441
442void
443WriteHandle::deferredDeleteProcess(ProcessId processId)
444{
445 getScheduler().scheduleEvent(PROCESS_DELETE_TIME,
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800446 bind(&WriteHandle::deleteProcess, this, processId));
Shuo Chen29c77fe2014-03-18 11:29:41 -0700447}
448
449void
450WriteHandle::processSingleInsertCommand(const Interest& interest,
451 RepoCommandParameter& parameter)
452{
453 ProcessId processId = generateProcessId();
454
455 ProcessInfo& process = m_processes[processId];
456
457 RepoCommandResponse& response = process.response;
458 response.setStatusCode(100);
459 response.setProcessId(processId);
460 response.setInsertNum(0);
461
462 reply(interest, response);
463
464 response.setStatusCode(300);
465
466 Interest fetchInterest(parameter.getName());
Weiqi Shi098f91c2014-07-23 17:41:35 -0700467 fetchInterest.setInterestLifetime(m_interestLifetime);
Shuo Chen29c77fe2014-03-18 11:29:41 -0700468 if (parameter.hasSelectors()) {
469 fetchInterest.setSelectors(parameter.getSelectors());
470 }
471 getFace().expressInterest(fetchInterest,
472 bind(&WriteHandle::onData, this, _1, _2, processId),
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800473 bind(&WriteHandle::onTimeout, this, _1, processId), // Nack
Shuo Chen29c77fe2014-03-18 11:29:41 -0700474 bind(&WriteHandle::onTimeout, this, _1, processId));
475}
476
477void
478WriteHandle::processSegmentedInsertCommand(const Interest& interest,
479 RepoCommandParameter& parameter)
480{
481 if (parameter.hasEndBlockId()) {
482 //normal fetch segment
483 if (!parameter.hasStartBlockId()) {
484 parameter.setStartBlockId(0);
485 }
486
487 SegmentNo startBlockId = parameter.getStartBlockId();
488 SegmentNo endBlockId = parameter.getEndBlockId();
Shuo Chen29c77fe2014-03-18 11:29:41 -0700489 if (startBlockId > endBlockId) {
490 negativeReply(interest, 403);
491 return;
492 }
493
494 ProcessId processId = generateProcessId();
495 ProcessInfo& process = m_processes[processId];
Shuo Chen29c77fe2014-03-18 11:29:41 -0700496 RepoCommandResponse& response = process.response;
497 response.setStatusCode(100);
498 response.setProcessId(processId);
499 response.setInsertNum(0);
500 response.setStartBlockId(startBlockId);
501 response.setEndBlockId(endBlockId);
502
503 reply(interest, response);
504
505 //300 means data fetching is in progress
506 response.setStatusCode(300);
507
508 segInit(processId, parameter);
509 }
510 else {
511 //no EndBlockId, so fetch FinalBlockId in data, if timeout, stop
512 ProcessId processId = generateProcessId();
513 ProcessInfo& process = m_processes[processId];
Shuo Chen29c77fe2014-03-18 11:29:41 -0700514 RepoCommandResponse& response = process.response;
515 response.setStatusCode(100);
516 response.setProcessId(processId);
517 response.setInsertNum(0);
518 response.setStartBlockId(parameter.getStartBlockId());
519 reply(interest, response);
520
521 //300 means data fetching is in progress
522 response.setStatusCode(300);
523
524 segInit(processId, parameter);
525 }
526}
527
528void
529WriteHandle::extendNoEndTime(ProcessInfo& process)
530{
531 ndn::time::steady_clock::TimePoint& noEndTime = process.noEndTime;
532 ndn::time::steady_clock::TimePoint now = ndn::time::steady_clock::now();
533 RepoCommandResponse& response = process.response;
534 if (now > noEndTime) {
535 response.setStatusCode(405);
536 return;
537 }
538 //extends noEndTime
539 process.noEndTime =
540 ndn::time::steady_clock::now() + m_noEndTimeout;
541
542}
543
544void
545WriteHandle::negativeReply(const Interest& interest, int statusCode)
546{
547 RepoCommandResponse response;
548 response.setStatusCode(statusCode);
549 reply(interest, response);
550}
551
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800552} // namespace repo