RDK Documentation (Open Sourced RDK Components)
Manager.cpp
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 
21 
22 /**
23 * @defgroup trm
24 * @{
25 * @defgroup qtapp
26 * @{
27 **/
28 
29 
30 #include "trm/TRM.h"
31 #include "Manager.h"
32 #include "Util.h"
33 #include "Server.h"
34 #include "Executors.h"
35 #include "Connection.h"
36 
37 extern TRM::Server *serverInstance;
38 
39 TRM_BEGIN_NAMESPACE
40 extern std::string GetDeviceId();
41 
42 Manager &Manager::getInstance()
43 {
44  static Manager managerInstance_;
45  return managerInstance_;
46 }
47 
48 Tuner::IdList & Manager::getTunerIds(Tuner::IdList & Ids)
49 {
50  Ids.clear();
51  TunerCT::const_iterator it;
52  for (it = tuners.begin(); it != tuners.end(); it++) {
53  Ids.push_back(it->first);
54  }
55  Assert(tuners.size() == Ids.size());
56  return Ids;
57 }
58 
59 
60 TunerReservation::TokenList & Manager::getReservationTokens(TunerReservation::TokenList &tokens, uint32_t clientId)
61 {
62  ReservationAttributesCT::iterator it = attrs.begin();
63  for (it = attrs.begin(); it != attrs.end(); it++) {
64  if ((it->second).clientId == clientId) {
65  tokens.push_back(it->first);
66  }
67  }
68 
69  return tokens;
70 }
71 
72 TunerReservation::TokenList & Manager::getReservationTokens(TunerReservation::TokenList &tokens, const std::string tunerId)
73 {
74 
75  if(!tunerId.empty()) {
76  getTuner(tunerId).getReservationTokens(tokens);
77  }
78  Log() << "getReservationTokens from tuner " << tunerId << " return " << tokens.size() << std::endl;
79  return tokens;
80 }
81 
82 TunerReservation::TokenList & Manager::getReservationTokens(TunerReservation::TokenList &tokens, const Tuner::IdList & tunerIds)
83 {
84  Tuner::IdList::const_iterator it;
85  for (it = tunerIds.begin(); it != tunerIds.end(); it++) {
86  getTuner(*it).getReservationTokens(tokens);
87  }
88 
89  //Log() << "getReservationTokens return " << tokens.size() << std::endl;
90  return tokens;
91 }
92 
93 void Manager::addReservation(const TunerReservation & reservation, const std::string &tunerId)
94 {
95  Log() << "vManager Adding Reservation " << reservation.getReservationToken() << " To tuner " << tunerId << std::endl;
96 
97  getTuner(tunerId).addReservation((reservation));
98  /* Add start timer and expiration timer*/
99  {
100  PreStartTimerCT::iterator it = preStartTimers.find(reservation.getReservationToken());
101  Assert(it == preStartTimers.end());
102  }
103 
104  {
105  StartTimerCT::iterator it = startTimers.find(reservation.getReservationToken());
106  Assert(it == startTimers.end());
107  }
108 
109  {
110  ExpireTimerCT::iterator it = expireTimers.find(reservation.getReservationToken());
111  Assert(it == expireTimers.end());
112  }
113 
114  preStartTimers.insert (std::pair<std::string, ReservationPreStartTimerTask>(
115  reservation.getReservationToken(),
116  ReservationPreStartTimerTask(*(new Timer(reservation.getReservationToken())), reservation.getReservationToken())) );
117 
118  startTimers.insert (std::pair<std::string, ReservationStartTimerTask>(
119  reservation.getReservationToken(),
120  ReservationStartTimerTask(*(new Timer(reservation.getReservationToken())), reservation.getReservationToken())) );
121 
122 
123  expireTimers.insert (std::pair<std::string, ReservationExpirationTimerTask>(
124  reservation.getReservationToken(),
125  ReservationExpirationTimerTask(*(new Timer(reservation.getReservationToken())), reservation.getReservationToken())) );
126  setTimer(reservation);
127 
128  //emit reservationUpdated();
129 }
130 
131 void Manager::setReservationAttributes(const std::string &token, const ReservationAttributes &attr)
132 {
133  Log() << "setReservationAttributes for " << token;
134  ReservationAttributesCT::iterator it = attrs.find(token);
135  if (it == attrs.end()) {
136  attrs.insert (std::pair<std::string, ReservationAttributes>(token, attr));
137  }
138  else {
139  it->second = attr;
140  }
141 }
142 
143 ReservationAttributes & Manager::getReservationAttributes(const std::string &token)
144 {
145  ReservationAttributesCT::iterator it = attrs.find(token);
146 
147  if (it == attrs.end()) {
148  //@ItemNotFound Exception
149  throw (0);
150  }
151 
152  return it->second;
153 }
154 
155 void Manager::releaseReservation(const std::string &reservationToken, bool notifyClient)
156 {
157  Log() << "vManager Releasing Reservation " << reservationToken << std::endl;
158 
159  TunerReservation &reservation = getReservation(reservationToken);
160  std::string serviceLocator = reservation.getServiceLocator();
161  Activity activity = reservation.getActivity();
162 
163  cancelPreStartTimer(reservationToken);
164  cancelStartTimer(reservationToken);
165  cancelExpireTimer(reservationToken);
166 
167  preStartTimers.erase(reservationToken);
168  startTimers.erase(reservationToken);
169  expireTimers.erase(reservationToken);
170 
171 
172  ReservationAttributesCT::iterator itt = attrs.find(reservationToken);
173  uint32_t clientId = 0;
174  if(itt != attrs.end()) {
175  clientId = (*itt).second.clientId;
176  attrs.erase(reservationToken);
177  }
178  else {
179  Log() << "cannot find ReservationAttributes for " << reservationToken;
180 
181  throw ItemNotFoundException();
182  }
183 
184  getTuner(getParent(reservationToken)).releaseReservation(reservationToken);
185 
186  /* Emit Notification so the pending requests can be retried */
187  emit reservationReleased(clientId, activity, reservationToken, serviceLocator);
188  if (notifyClient) {
189  emit reservationUpdated();
190  }
191 
192 }
193 
194 TunerReservation & Manager::getReservation(const std::string &reservationToken)
195 {
196  //Log() << "Request Reservation from token " << reservationToken << std::endl;
197  TunerCT::iterator itt;
198  for (itt = tuners.begin(); itt != tuners.end(); itt++) {
199  TunerReservation::TokenList tokens;
200  //Log() << "GetReservation of Tuner " << itt->second.getId() << std::endl;
201  itt->second.getReservationTokens(tokens);
202  TunerReservation::TokenList::iterator itr;
203  for (itr = tokens.begin(); itr != tokens.end(); itr++) {
204  //Log() << "GetReservation " << *itr << " of Tuner " << itt->second.getId() << std::endl;
205  if (itr->compare(reservationToken) == 0) {
206  return itt->second.getReservation(reservationToken);
207  }
208  }
209  }
210  Log() << "Throw ItemNotFoundException from Manager::getReservation()" << std::endl;
211  throw ItemNotFoundException();
212 }
213 
214 const std::string & Manager::getParent(const std::string &reservationToken)
215 {
216  TunerCT::iterator itt;
217  for (itt = tuners.begin(); itt != tuners.end(); itt++) {
218  TunerReservation::TokenList tokens;
219  itt->second.getReservationTokens(tokens);
220  TunerReservation::TokenList::iterator itr;
221  for (itr = tokens.begin(); itr != tokens.end(); itr++) {
222  if (itr->compare(reservationToken) == 0) {
223  Log() << "Parent is " << itt->second.getId() << std::endl;
224  return itt->second.getId();
225  }
226  }
227  }
228  throw ItemNotFoundException();
229 }
230 
231 Tuner & Manager::getTuner(const std::string &tunerId)
232 {
233  TunerCT::iterator it = tuners.find(tunerId);
234  if (it == tuners.end()) {
235  throw ItemNotFoundException();
236  //@TODO Throw Exception;
237  }
238 
239  return it->second;
240 
241 }
242 
243 void Manager::addPendingRequest(PendingRequestProcessor *request_, int timeout)
244 {
245  PendingRequestProcessor &request = *request_;
246  Log() << "Manager::addPendingRequest " << request.getUUID() << " " << (void *)&request << std::endl;
247 
248  pendingRequests.push_back(&request);
249 
250  /* Add wait timer */
251  {
252  PedingRequestTimerCT::iterator it = pendingRequestTimers.find(request.getUUID());
253  if (it == pendingRequestTimers.end()) {
254 
255  pendingRequestTimers.insert (std::pair<std::string, PendingRequestTimeoutTimerTask>(
256  request.getUUID(),
257  PendingRequestTimeoutTimerTask(*(new Timer(request.getUUID())), request.getUUID())) );
258 
259  {
260  PedingRequestTimerCT::iterator it = pendingRequestTimers.find(request.getUUID());
261  Assert(it != pendingRequestTimers.end());
262  PendingRequestTimeoutTimerTask &task = it->second;
263  task.getTimer().schedule(task, timeout, false);
264  Log() << "Pending Request " << request.getUUID() << " Add Timer " << task.getTimer().getToken() << std::endl;
265  }
266  }
267 
268  //emit reservationUpdated();
269  }
270 
271 }
272 
273 bool Manager::isPendingConflict(const std::string &reservationToken)
274 {
275  bool found = false;
276  std::list<PendingRequestProcessor *>::iterator it = pendingRequests.begin();
277  while(it != pendingRequests.end() && !found) {
278  if ((*it)->getType() == PendingRequestProcessor::PendingReserveTunerConflicts)
279  {
280  PendingReserveTunerConflictProcessor &pendingRequest = *(static_cast<PendingReserveTunerConflictProcessor *>(*it));
281  std::list<TunerReservation>::iterator itt = (pendingRequest).notification.getConflicts().begin();
282  while(itt != (pendingRequest).notification.getConflicts().end() && !found) {
283  if (reservationToken.compare((*itt).getReservationToken()) == 0) {
284  found = true;
285  }
286  itt++;
287  }
288  }
289  it++;
290  }
291 
292  return found;
293 }
294 
295 bool Manager::isPendingRequest(const std::string &uuid)
296 {
297  std::list<PendingRequestProcessor *>::iterator it = pendingRequests.begin();
298  while(it != pendingRequests.end()) {
299  if ((**it).getUUID().compare(uuid) == 0) {
300  break;
301  }
302  it++;
303  }
304 
305  return (it != pendingRequests.end());
306 }
307 
308 PendingRequestProcessor & Manager::getPendingRequest(const std::string &uuid)
309 {
310  std::list<PendingRequestProcessor *>::iterator it = pendingRequests.begin();
311  while(it != pendingRequests.end()) {
312  if ((**it).getUUID().compare(uuid) == 0) {
313  break;
314  }
315  it++;
316  }
317 
318  if (it == pendingRequests.end()) {
319  Log() << "Throw ItemNotFoundException from Manager::getPendingRequest() for " << uuid << std::endl;
320  throw ItemNotFoundException();
321  }
322 
323  return **it;
324 }
325 
326 void Manager::removePendingRequest(const std::string &uuid)
327 {
328  Log() << "Manager::removePendingRequest " << uuid << std::endl;
329 
330  std::list<PendingRequestProcessor *>::iterator it = pendingRequests.begin();
331  while(it != pendingRequests.end()) {
332  if ((**it).getUUID().compare(uuid) == 0) {
333  cancelPendingTimer(uuid);
334  pendingRequestTimers.erase(uuid);
335  it = pendingRequests.erase(it);
336  break;
337  }
338  it++;
339  }
340 
341  if(it == pendingRequests.end()) {
342  }
343 
344 }
345 
346 void Manager::onReservationReleased(uint32_t clientId, Activity activity, std::string reservationToken, std::string serviceLocator)
347 {
348  Log() << "Manager::onReservationReleased from client " << std::hex << clientId <<
349  " for activity " << (const char *)activity.getActivity() << " for serviceLocator " << serviceLocator << std::endl;
350 }
351 
352 void Manager::onReservationUpdated(void)
353 {
354  Log() << "Manager::onReservationUpdated has pending:" <<pendingRequests.size() <<std::endl;
355  std::list<std::string> timedoutPending;
356  if (pendingRequests.size()) {
357  /* if in the reservationUpdate, there is pendingReserveTunerConflicts
358  * tune to the same channel as the pending request, then re-evaluate pending request
359  */
360  std::list<PendingRequestProcessor *>::iterator it = pendingRequests.begin();
361  while(it != pendingRequests.end()) {
362  if ((*it)->getType() == PendingRequestProcessor::PendingReserveTunerConflicts) {
363  bool grantConflict = false;
364 
365  PendingReserveTunerConflictProcessor &pendingRequest = *(static_cast<PendingReserveTunerConflictProcessor *>(*it));
366  const TunerReservation &liveReservationAtConflict = pendingRequest.notification.getTunerReservation();
367  try {
368  const TunerReservation &liveReservationNow = Manager::getReservation(liveReservationAtConflict.getReservationToken());
369  if (pendingRequest.notification.getConflicts().size() == 1) {
370  if (liveReservationNow.getServiceLocator().compare(pendingRequest.notification.getConflicts().begin()->getServiceLocator()) == 0) {
371  Log() << "Manager::onReservationUpdated conflicting live token "
372  << liveReservationAtConflict.getReservationToken()
373  << " has updated from "
374  << liveReservationAtConflict.getServiceLocator()
375  << " to "
376  << liveReservationNow.getServiceLocator()
377  << std::endl;
378  grantConflict = true;
379  }
380  }
381  else {
382  Log() << "Manager::onReservationUpdated detected conflicts mismatch " << pendingRequest.notification.getConflicts().size() << std::endl;
383  SafeAssert(0);
384  }
385  }
386  catch(...) {
387  Log() << "Manager::onReservationUpdated conflicting live token has expired " << liveReservationAtConflict.getReservationToken() << std::endl;
388  grantConflict = true;
389  }
390 
391  if (grantConflict) {
392  try {
393  Log() << "Manager::onReservationUpdated pending conflict is effectively timedout :" << liveReservationAtConflict.getReservationToken() << std::endl;
394  pendingRequest.timeout();
395  timedoutPending.push_back(pendingRequest.getUUID());
396  }
397  catch(...) {
398  Log() << "Manager::onReservationUpdated pending conflict is already removed" << std::endl;
399  }
400  }
401  }
402  it++;
403  }
404  }
405 
406  if (timedoutPending.size()) {
407  std::list<std::string>::iterator it = timedoutPending.begin();
408  while(it != timedoutPending.end()) {
409  PendingRequestProcessor &pending = Manager::getInstance().getPendingRequest(*it);
410  removePendingRequest(*it);
411  delete &pending;
412  it++;
413  }
414  }
415 }
416 
417 void Manager::onNotifyTunerStatesUpdate(NotifyTunerStatesUpdate update)
418 {
419  Log() << "Manager::onNotifyTunerStatesUpdate" << std::endl;
420 }
421 
422 Manager::Manager(void)
423 {
424  GetDeviceId();
425  tuners.clear();
426  for (int i = 0; i < kNumOfTuners; i++) {
427  std::string id = "TunerId-" + IntToString(i) + "";
428  Log() << Timestamp << "====================Addings TunerId " << id << std::endl;
429  tuners.insert ( std::pair<std::string,Tuner>(id, Tuner(id)) );
430  }
431 
432  setLocalTuner("TunerId-0");
433  QObject::connect(this, SIGNAL(reservationReleased(uint32_t, Activity, std::string, std::string)), this, SLOT(onReservationReleased(uint32_t, Activity, std::string, std::string)));
434  QObject::connect(this, SIGNAL(cancelLiveResponse(CancelLiveResponse, ReserveTuner, const std::string)), this, SLOT(onCancelLiveResponse(CancelLiveResponse, ReserveTuner, const std::string)));
435  QObject::connect(this, SIGNAL(notifyTunerStatesUpdate(NotifyTunerStatesUpdate)), this, SLOT(onNotifyTunerStatesUpdate(NotifyTunerStatesUpdate)));
436  QObject::connect(this, SIGNAL(reservationUpdated(void)), this, SLOT(onReservationUpdated(void)), Qt::QueuedConnection);
437  QObject::connect(this, SIGNAL(timerDeleted(void*)), this, SLOT(onTimerDeleted(void*)), Qt::QueuedConnection);
438 
439 }
440 
441 void Manager::setTimer(const TunerReservation &reservation)
442 {
443  {
444  PreStartTimerCT::iterator it = preStartTimers.find(reservation.getReservationToken());
445  Assert(it != preStartTimers.end());
446  ReservationPreStartTimerTask &task = it->second;
447  task.getTimer().schedule(task, reservation.getStartTime() - 250, true);
448 
449  Log() << "Reservation " << reservation.getReservationToken() << " Add Pre-Start Timer " << task.getTimer().getToken() << std::endl;
450  }
451 
452  {
453  StartTimerCT::iterator it = startTimers.find(reservation.getReservationToken());
454  Assert(it != startTimers.end());
455  ReservationStartTimerTask &task = it->second;
456  task.getTimer().schedule(task, reservation.getStartTime(), true);
457 
458  Log() << "Reservation " << reservation.getReservationToken() << " Add Start Timer " << task.getTimer().getToken() << std::endl;
459  }
460 
461  {
462  ExpireTimerCT::iterator it = expireTimers.find(reservation.getReservationToken());
463  Assert(it != expireTimers.end());
464  ReservationExpirationTimerTask &task = it->second;
465  task.getTimer().schedule(task, reservation.getExpirationTime());
466 
467  Log() << "Reservation " << reservation.getReservationToken() << " Add Expire Timer " << task.getTimer().getToken() << std::endl;
468  }
469 }
470 
471 void Manager::cancelStartTimer(const std::string &reservationToken)
472 {
473  StartTimerCT::iterator it = startTimers.find(reservationToken);
474  if(it != startTimers.end()) {
475  ReservationStartTimerTask &task = it->second;
476  task.getTimer().cancel();
477  emit timerDeleted((void *)(&task.getTimer()));
478  }
479  else {
480  //It is ok to miss start timer, so don't throw exception.
481  }
482 }
483 
484 void Manager::cancelPreStartTimer(const std::string &reservationToken)
485 {
486  PreStartTimerCT::iterator it = preStartTimers.find(reservationToken);
487  if(it != preStartTimers.end()) {
488  ReservationPreStartTimerTask &task = it->second;
489  task.getTimer().cancel();
490  emit timerDeleted((void *)(&task.getTimer()));
491  }
492  else {
493  //It is ok to miss start timer, so don't throw exception.
494  }
495 }
496 
497 void Manager::cancelExpireTimer(const std::string &reservationToken)
498 {
499  ExpireTimerCT::iterator it = expireTimers.find(reservationToken);
500  if(it != expireTimers.end()) {
501  ReservationExpirationTimerTask &task = it->second;
502  task.getTimer().cancel();
503  emit timerDeleted((void *)(&task.getTimer()));
504  }
505  else {
506  Log() << "cancelExpireTimer cannot find timer for token " << reservationToken << std::endl;
507  throw ItemNotFoundException();
508  }
509 }
510 
511 void Manager::adjustExpireTimer(const std::string &reservationToken)
512 {
513  try {
514  TunerReservation &reservation = Manager::getInstance().getReservation(reservationToken);
515  ExpireTimerCT::iterator it = expireTimers.find(reservationToken);
516  if(it != expireTimers.end()) {
517  Log() << "adjustExpireTimer adjusting expire timer " << reservationToken << std::endl;
518  ReservationExpirationTimerTask &task = it->second;
519  task.getTimer().cancel();
520  task.getTimer().schedule(task, reservation.getExpirationTime());
521  }
522  else {
523  }
524  }
525  catch(...) {
526  Log() << "adjustExpireTimer cannot find timer or token, may expried already " << reservationToken << std::endl;
527  }
528 }
529 
530 void Manager::cancelPendingTimer(const std::string &reservationToken)
531 {
532  PedingRequestTimerCT::iterator it = pendingRequestTimers.find(reservationToken);
533  if(it != pendingRequestTimers.end()) {
534  PendingRequestTimeoutTimerTask &task = it->second;
535  task.getTimer().cancel();
536  //@TODO Timer may already have started.
537  delete (&task.getTimer());
538  }
539  else {
540  //It is ok to miss start timer, so don't throw exception.
541  }
542 }
543 
544 void Manager::prepareRecordHandover(const std::string &tunerId, const std::string &reservationToken)
545 {
546  /* If recording is about to start, and tuner is hybrid on a different
547  * channel, pre-sync need to cancelLive to yield tuner to
548  * recording. Upon syncHybrid, guide will be notified and tune LIVE
549  * to the recording channel.
550  */
551  if (getTuner(tunerId).getState().getState() == TunerState::kHybrid) {
552  /* First get the recording token */
553  std::string liveToken= "";
554  std::string recordToken= "";
555  std::string recordLocator="";
556  std::string liveLocator="";
557  std::string nextRecordLocator="";
558 
559  TunerReservation::TokenList tokens;
560  Manager::getInstance().getReservationTokens(tokens, tunerId);
561 
562  TunerReservation::TokenList::const_iterator it = tokens.begin();
563  while (it != tokens.end()) {
564  if (getReservation(*it).state == TunerReservation::ACTIVE) {
565  if (getReservation(*it).getActivity().getActivity() == Activity::kRecord) {
566  recordLocator = getReservation(*it).getServiceLocator();
567  recordToken = *it;
568  }
569  if (getReservation(*it).getActivity().getActivity() == Activity::kLive) {
570  liveLocator = getReservation(*it).getServiceLocator();
571  liveToken = *it;
572  }
573  }
574  it++;
575  }
576 
577  /* Since we are in hybrid mode, there must be 1 Record locator, and 1 live locator */
578  Assert(!recordLocator.empty());
579  Assert(!liveLocator.empty());
580  Assert(liveLocator.compare(recordLocator) == 0);
581 
582  nextRecordLocator = Manager::getInstance().getReservation(reservationToken).getServiceLocator();
583  Assert(Manager::getInstance().getReservation(reservationToken).getActivity() == Activity::kRecord);
584  Assert(!nextRecordLocator.empty());
585 
586  if (liveLocator.compare(nextRecordLocator) != 0) {
587  Log() << "Hybrid tuner is on : LIVE + RECORD [ " << liveLocator
588  << " ] and is about to switch to RECORD [" << nextRecordLocator << " ]\r\n";
589  try {
590  Log() << "Pre-Syncing...Target Tuner for recording is not yet on record channel now, need to cancel tune, so send a real a cancelLive" << std::endl;
591  CancelLive cancelLive(GenerateUUID(),
592  liveLocator,
593  liveToken);
594  std::vector<uint8_t> out;
595  SerializeMessage(cancelLive,Connection::kRecorderClientId, out);
596  ::serverInstance->getConnection(Connection::kRecorderClientId).sendAsync(out);
597 
598  }
599  catch (ConnectionNotFoundException) {
600  /* Connection may have lost. If so, don't send the message */
601  }
602 
603  }
604  }
605  else {
606  /* do nothing */
607  }
608 
609  Log() << "Tuner " << tunerId << " is pre-sync'd in " << (const char *) getTuner(tunerId).getState().getState() << " state \r\n";
610 }
611 
612 void Manager::syncHybrid(const std::string &tunerId, const std::string &reservationToken)
613 {
614  if (getTuner(tunerId).getState().getState() == TunerState::kHybrid) {
615  /* First get the recording token */
616  std::string recordLocator="";
617  TunerReservation::TokenList tokens;
618  Manager::getInstance().getReservationTokens(tokens, tunerId);
619 
620  TunerReservation::TokenList::const_iterator it = tokens.begin();
621  while (it != tokens.end()) {
622  if (getReservation(*it).state == TunerReservation::ACTIVE) {
623  if (getReservation(*it).getActivity().getActivity() == Activity::kRecord) {
624  recordLocator = getReservation(*it).getServiceLocator();
625  break;
626  }
627  }
628  it++;
629  }
630 
631  /* Since we are in hybrid mode, there must be 1 Record locator */
632  Assert(!recordLocator.empty());
633  /* Find active LIVE tokens and send notifyUpdate */
634  it = tokens.begin();
635  while (it != tokens.end()) {
636  if (getReservation(*it).state == TunerReservation::ACTIVE) {
637  if (getReservation(*it).getActivity().getActivity() == Activity::kLive) {
638  std::string liveLocator = getReservation(*it).getServiceLocator();
639  if (liveLocator.compare(recordLocator) != 0) {
640  Log() << "Synchronization is needed in hybrid mode : LIVE[ " << liveLocator
641  << " ] vs RECORD [" << recordLocator << " ]\r\n";
642  try {
643  getReservation(*it).setServiceLocator(recordLocator);
644  if (getReservation(*it).getCustomAttributes() != NULL) {
645  Log() << "Resetting custome attributes to NULL " << std::endl;
646  extern void delete_ReservationCustomAttributes(void *p);
647  delete_ReservationCustomAttributes((void *)getReservation(*it).getCustomAttributes());
648  getReservation(*it).setCustomAttributes(NULL);
649  }
650  std::vector<uint8_t> out;
651  SerializeMessage(NotifyTunerReservationUpdate(GenerateUUID(), getReservation(*it)), getReservationAttributes(*it).getClientId(), out);
652  Log() << "Sending the message:RL: " << std::endl;
653  ::serverInstance->getConnection(getReservationAttributes(*it).getClientId()).sendAsync(out);
654  emit reservationUpdated();
655  /* Message sent successfully */
656  }
657  catch (ConnectionNotFoundException) {
658  /* Connection may have lost. If so, don't send the message */
659  }
660 
661  }
662  }
663  }
664  it++;
665  }
666  }
667  else {
668  /* do nothing */
669  }
670 
671  Log() << "Tuner " << tunerId << " is sync'd in " << (const char *) getTuner(tunerId).getState().getState() << " state \r\n";
672 }
673 
674 void Manager::startReservation(const std::string &reservationToken)
675 {
676  /* Send Pretune */
677  TunerReservation &reservation = getReservation(reservationToken);
678 
679  if (reservation.getActivity() == Activity::kLive) {
680  /* Send Pretune */
681  Log() << "TRM Request PRETUNE " << reservation.getServiceLocator() << std::endl;
682  std::vector<uint8_t> out;
683  try {
684  if (reservation.getActivity().getDetail("ppv").compare("true") != 0) {
685  SerializeMessage(NotifyTunerPretune(GenerateUUID(), reservation.getServiceLocator()), Connection::kTunerAgentId, out);
686  ::serverInstance->getConnection(Connection::kTunerAgentId).sendAsync(out);
687  }
688  else
689  {
690  Log() << "Do not Pretune for PPV Channel " << reservation.getServiceLocator() << std::endl;
691  }
692  }
693  catch(ConnectionNotFoundException &e) {
694  Log() << "Tuner Agent is not connected " << std::endl;
695  }
696  }
697  emit reservationUpdated();
698 }
699 
700 NotifyTunerStatesUpdate Manager::getTunerStatesUpdate(void)
701 {
702  NotifyTunerStatesUpdate notifyTunerStatesUpdate(GenerateUUID());
703  Tuner::IdList tunerIds;
704  tunerIds.clear();
705  Manager::getInstance().getTunerIds(tunerIds);
706  Tuner::IdList::const_iterator tidIT = tunerIds.begin();
707  for (tidIT = tunerIds.begin(); tidIT != tunerIds.end(); tidIT++) {
708  DetailedTunerState detailedTunerState;
709  const Tuner &tuner = Manager::getInstance().getTuner(*tidIT);
710  Log() << "Adding detailedTunerState for Tuner "
711  << *tidIT << "State= "
712  << (const char *)tuner.getState().getState() << "locator=" << tuner.getServiceLocator() << std::endl;
713 
714  {
715  TunerReservation::TokenList tokens;
716  tokens.clear();
717  Manager::getInstance().getTuner(*tidIT).getReservationTokens(tokens);
718  TunerReservation::TokenList::const_iterator itt;
719  for (itt=tokens.begin(); itt != tokens.end(); itt++) {
720  const TunerReservation &reservation = Manager::getInstance().getReservation(*itt);
721  if (reservation.state == TunerReservation::ACTIVE) {
722  SafeAssert(reservation.getServiceLocator() == tuner.getServiceLocator(false));
723  detailedTunerState.addTunerOwner(((const char *)reservation.getActivity().getActivity()), reservation.getDevice());
724  Log() << "Tuner " << *tidIT << "has activity " << ((const char *)reservation.getActivity().getActivity())
725  << "owned by " << reservation.getDevice() << std::endl;
726  detailedTunerState.setState((const char *)tuner.getState().getState(), tuner.getServiceLocator());
727  }
728  }
729  }
730 
731  if (getLocalTuner().compare(*tidIT) == 0) {
732  Log() << "LocalTuner " << getLocalTuner() << "set reservedDeviceId" << std::endl;
733  detailedTunerState.setReservedDeviceId(GetDeviceId());
734  }
735  notifyTunerStatesUpdate.addTunerDetailedState(*tidIT, detailedTunerState);
736  }
737 
738  return notifyTunerStatesUpdate;
739 }
740 
741 void Manager::onCancelLiveResponse(const CancelLiveResponse response, const ReserveTuner request, const std::string parentId)
742 {
743  /* regardless cancellation success or failure, it is last change to grant record token */
744  Log() << "Manager::onCancelLiveResponse from client "
745  << " for activity " << (const char *) Activity::kLive
746  << " for serviceLocator " << response.getServiceLocator()
747  << " for UUID " << response.getUUID() << " for Tuner " << parentId << std::endl;
748  Executor<ReserveTuner> exec(request, Connection::kRecorderClientId);
749  Execute(exec, parentId);
750 }
751 
752 std::string Manager::getLocalTuner(void)
753 {
754  return localTuner;
755 }
756 
757 void Manager::setLocalTuner(const std::string &tunerId)
758 {
759  this->localTuner = tunerId;
760 }
761 
762 void Manager::onTimerDeleted(void *ptr)
763 {
764  delete ((Timer *)ptr);
765 }
766 
767 bool PendingCancelRecordingProcessor::timeout()
768 {
769  CancelRecordingResponse response(request.getUUID(), request.getReservationToken());
770  response.getStatus() += "Cancellation Timedout, assuming cancelled=false\r\n";
771  response.getStatus() = ResponseStatus::kOk;
772  response.setCanceled(false);
773 
774  std::vector<uint8_t> out;
775  SerializeMessage(response, clientId, out);
776  ::serverInstance->getConnection(clientId).sendAsync(out);
777 
778  return true;
779 }
780 
781 bool PendingReserveTunerConflictProcessor::timeout()
782 {
783  bool recordingCancelled = false;
784 
785  Assert(this == &Manager::getInstance().getPendingRequest(getUUID()));
786  Assert(request.getTunerReservation().getActivity().getActivity() == Activity::kRecord);
787  Assert(notification.getConflicts().size() == 1);
788 
789  TunerReservation &conflict = *notification.getConflicts().begin();
790 
791  Assert(conflict.getActivity().getActivity() == Activity::kRecord);
792  Assert(notification.getTunerReservation().getActivity().getActivity() == Activity::kLive);
793 
794  /* First cancelLive if the current LIVE is not recording channel, then start the recording timer */
795  {
796  TunerReservation::TokenList tokens;
797  tokens.clear();
798  Manager::getInstance().getReservationTokens(tokens, parentId);
799 
800  if ((tokens.size() == 1)) {
801  /* Force tune to the Recording channel if it is not EAS, and if user is not already on recording channel*/
802  if (Manager::getInstance().getReservation(*tokens.begin()).getActivity().getDetail("eas").compare("true") == 0) {
803  Log() << "The current Live channel " <<
804  Manager::getInstance().getReservation(*tokens.begin()).getServiceLocator() <<
805  " is EAS channel" << std::endl;
806  if (request.getTunerReservation().getServiceLocator().compare(Manager::getInstance().getReservation(*tokens.begin()).getServiceLocator()) != 0) {
807  Log() << "The recording channel " <<
808  request.getTunerReservation().getServiceLocator() <<
809  "is not EAS channel, cancel Recording " << std::endl;
810  ReserveTunerResponse response(request.getUUID());
811  response.getStatus() += "Cancel Recording For EAS\r\n";
812  response.getStatus() = ResponseStatus::kInsufficientResource;
813  {
814  std::vector<uint8_t> out;
815  SerializeMessage(response, Connection::kRecorderClientId, out);
816  ::serverInstance->getConnection(Connection::kRecorderClientId).sendAsync(out);
817  }
818  recordingCancelled = true;
819  }
820  else {
821  Log() << "The recording channel " <<
822  request.getTunerReservation().getServiceLocator() <<
823  "is EAS channel, allow Recording " << std::endl;
824 
825  }
826  }
827 
828  if (!recordingCancelled) {
829 
830  if ((Manager::getInstance().getReservation(*tokens.begin()).getActivity().getActivity() == Activity::kLive)) {
831  Log() << "PendingReserveTunerConflictProcessor " << getUUID() << " Timedout...Cancel LIVE first before grating Record " << std::endl;
832  Assert(notification.getConflicts().size() == 1);
833  try {
834  if (Manager::getInstance().getReservation(*tokens.begin()).getServiceLocator().compare(request.getTunerReservation().getServiceLocator()) != 0) {
835  Log() << "Target Tuner for recording is not on record channel now, so need to cancel tune, so send a real a cancel" << std::endl;
836  CancelLive cancelLive(GenerateUUID(),
837  Manager::getInstance().getReservation(*tokens.begin()).getServiceLocator(),
838  Manager::getInstance().getReservation(*tokens.begin()).getReservationToken());
839 
840  const int CANCEL_LIVE_TIMEOUT_MS = (10000);
841 
842  std::vector<uint8_t> out;
843  SerializeMessage(cancelLive,Connection::kRecorderClientId, out);
844  ::serverInstance->getConnection(Connection::kRecorderClientId).sendAsync(out);
845  /* Now add cancelLive to pending request */
846 
847  Manager::getInstance().addPendingRequest(new PendingCancelLiveProcessor(Connection::kTrmClientId, cancelLive, request, parentId), CANCEL_LIVE_TIMEOUT_MS);
848  }
849  else {
850 #if 0
851  /* no race condition */
852  Log() << "Target Tuner for recording is on record channel now, no need to cancel tune, so fake a cancel success and start Recording" << std::endl;
853  PendingCancelLiveProcessor fakeCancelProcessor(Connection::kTrmClientId, cancelLive, request, parentId);
854  fakeCancelProcessor.timeout();
855 #else
856  /* race condition */
857  CancelLive cancelLive(GenerateUUID(),
858  notification.getTunerReservation().getServiceLocator(),
859  notification.getTunerReservation().getReservationToken());
860  Log() << "Target Tuner for recording is on record channel now, or it is on its way to the recoridng chanel." << std::endl;
861  const int CANCEL_LIVE_TIMEOUT_MS = (10000);
862 
863  std::vector<uint8_t> out;
864  SerializeMessage(cancelLive,Connection::kRecorderClientId, out);
865  ::serverInstance->getConnection(Connection::kRecorderClientId).sendAsync(out);
866  /* Now add cancelLive to pending request */
867 
868  Manager::getInstance().addPendingRequest(new PendingCancelLiveProcessor(Connection::kTrmClientId, cancelLive, request, parentId), CANCEL_LIVE_TIMEOUT_MS);
869 
870 #endif
871  }
872  }
873  catch (ConnectionNotFoundException &e) {
874  Log() << "No Recorder alive, ignore " << std::endl;
875  }
876  }
877  else {
878  Log() << "Target Tuner for recording is already recording" << std::endl;
879  Assert(0);
880  }
881  }
882  }
883  else if (tokens.size() == 2) {
884  /* The tuner is already in H state. New recording will take over once the current R is completed */
885  /* Make sure current recording stop before next recording */
886  Assert(Manager::getInstance().getTuner(parentId).getState().getState() == TunerState::kHybrid);
887  Log() << "Target Tuner for recording is still recording , cannot cancel tune, so fake a cancel success and grant Recording" << std::endl;
888  CancelLive cancelLive(GenerateUUID(), Manager::getInstance().getReservation(*tokens.begin()).getServiceLocator(), Manager::getInstance().getReservation(*tokens.begin()).getReservationToken());
889  PendingCancelLiveProcessor fakeCancelProcessor(Connection::kTrmClientId, cancelLive, request, parentId);
890  fakeCancelProcessor.timeout();
891  }
892  else if (tokens.size() == 0) {
893  Log() << "Target Tuner for recording is free now, no need to cancel live, so fake a cancel success and grant Recording" << std::endl;
894  Assert(Manager::getInstance().getTuner(parentId).getState().getState() == TunerState::kFree);
895  CancelLive cancelLive(GenerateUUID(),
896  request.getTunerReservation().getServiceLocator(),
897  ""/* use empty token for the fake success*/);
898  PendingCancelLiveProcessor fakeCancelProcessor(Connection::kTrmClientId, cancelLive, request, parentId);
899  fakeCancelProcessor.timeout();
900  }
901  else {
902  Log() << "Incorrect token number " << tokens.size() << std::endl;
903  Assert(0);
904  }
905  }
906  return true;
907 
908 }
909 
910 bool PendingCancelLiveProcessor::timeout()
911 {
912  /* CancelLive timeout */
913  emit Manager::getInstance().cancelLiveResponse(CancelLiveResponse(
914  cancelLiveRequest.getUUID(),
915  ResponseStatus(ResponseStatus::kOk, "Assuming cancellation success upon timeout"),
916  cancelLiveRequest.getReservationToken(),
917  cancelLiveRequest.getServiceLocator(),
918  true), reserveRequest, parentId);
919  return true;
920 
921 }
922 
923 TRM_END_NAMESPACE
924 
925 
926 /** @} */
927 /** @} */
ReservationExpirationTimerTask
Definition: ReservationTimerTask.h:37
ReservationPreStartTimerTask
Definition: ReservationTimerTask.h:67
ReservationStartTimerTask
Definition: ReservationTimerTask.h:52
Executor
Definition: Executors.h:44
Timer
Definition: timer.h:42
TRM::Server
Definition: Server.h:42
PendingRequestTimeoutTimerTask
Definition: ReservationTimerTask.h:82
Tuner
Definition: Tuner.h:43