RDK Documentation (Open Sourced RDK Components)
Tuner.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 * @defgroup trm
23 * @{
24 * @defgroup common
25 * @{
26 **/
27 
28 
29 #include "trm/TRM.h"
30 #include "trm/TunerReservation.h"
31 #include "trm/Activity.h"
32 #include "trm/TunerState.h"
33 
34 #include "ReservationCustomAttributes.h"
35 #include "Util.h"
36 #include "Tuner.h"
37 
38 
39 TRM_BEGIN_NAMESPACE
40 
41 static bool isOverlap(uint64_t start1, uint64_t dur1, uint64_t start2, uint64_t dur2)
42 {
43  bool overlap = true;
44  if (((start1 + dur1) <= start2)|| ((start2 + dur2) <= start1)) {
45  overlap = false;
46  }
47 
48  return overlap;
49 }
50 
51 Tuner::Tuner(const std::string & internalId)
52 : internalId(internalId)
53 {
54  Assert(reservations.size() == 0);
55 }
56 
57 TunerReservation::TokenList & Tuner::getReservationTokens(TunerReservation::TokenList & tokens) const
58 {
59  ReservationCT::const_iterator it;
60  for (it = reservations.begin(); it != reservations.end(); it++) {
61  tokens.push_back(it->first);
62  }
63  Assert(reservations.size() <= tokens.size());
64 
65  return tokens;
66 }
67 
68 const TunerReservation& Tuner::getReservation(const std::string &reservationToken) const
69 {
70  ReservationCT::const_iterator it;
71  it = reservations.find(reservationToken);
72  if (it == reservations.end()) {
73  //@TODO: Throw Exception.
74  Assert(0);
75  }
76 
77  return it->second;
78 }
79 
80 TunerReservation& Tuner::getReservation(const std::string &reservationToken)
81 {
82  ReservationCT::iterator it;
83  it = reservations.find(reservationToken);
84  if (it == reservations.end()) {
85  //@TODO: Throw Exception.
86  Assert(0);
87  }
88 
89  return it->second;
90 }
91 
92 const TunerReservation & Tuner::getReservation(const Activity &activity, int reservationState, const std::string &serviceLocator) const
93 {
94  /*
95  * Construct state based on ACTIVE reservations.
96  */
97  ReservationCT::const_iterator it = reservations.begin();
98  while(it != reservations.end()) {
99  if (it->second.state == reservationState) {
100  if (it->second.getActivity() == activity) {
101  if (serviceLocator.empty() || (serviceLocator.compare(it->second.getServiceLocator()) == 0)) {
102  break;
103  }
104  }
105  }
106  it++;
107  }
108 
109  if (it == reservations.end()) {
110  throw ItemNotFoundException();
111  }
112 
113  return it->second;
114 }
115 
116 
117 const TunerState Tuner::getState(void) const
118 {
119  /*
120  * Construct state based on ACTIVE reservations.
121  */
122  TunerState state = TunerState::kFree;
123  ReservationCT::const_iterator it = reservations.begin();
124  while(it != reservations.end()) {
125  if (it->second.state == TunerReservation::ACTIVE) {
126  if (it->second.getStartTime() > GetCurrentEpoch()) {
127  std::cout << "WARN::" << it->second.getReservationToken()
128  << " has start Time " << it->second.getStartTime()
129  << "vs current " << GetCurrentEpoch() << std::endl;
130  }
131 
132  if ((it->second.getStartTime() + it->second.getDuration()) < GetCurrentEpoch()) {
133  std::cout << "WARN:: " << it->second.getReservationToken()
134  << " has end Time " << (it->second.getStartTime() + it->second.getDuration())
135  << "vs current " << GetCurrentEpoch() << std::endl;
136  }
137 
138 // SafeAssert(it->second.getStartTime() <= GetCurrentEpoch());
139 // SafeAssert((it->second.getStartTime() + it->second.getDuration()) >= GetCurrentEpoch());
140 
141  if (it->second.getActivity() == Activity::kLive) {
142  state = state + Activity::kLive;
143  }
144  else if (it->second.getActivity() == Activity::kRecord) {
145  state = state + Activity::kRecord;
146  }
147  }
148  it++;
149  }
150 
151  std::cout << "Tuner::getState() returning " << (const char *) (state.getState()) << std::endl;
152  return state;
153 }
154 
155 void Tuner::setState(const TunerState &state)
156 {
157 // this->state = state;
158 }
159 
160 const std::string Tuner::getServiceLocator(bool considerFutureToken) const
161 {
162  /* Return the active token's locator, which are guaranteed to match,
163  * or return the nearest pending token's locator.
164  */
165  std::string serviceLocator = "";
166 
167  if (serviceLocator.empty()){
168  /* First look for active locator */
169  ReservationCT::const_iterator it = reservations.begin();
170  while(it != reservations.end()) {
171  if (it->second.state == TunerReservation::ACTIVE) {
172  serviceLocator = it->second.getServiceLocator();
173  break;
174  }
175  it++;
176  }
177  }
178 
179  if (serviceLocator.empty() && considerFutureToken){
180  Assert(getState().getState() == TunerState::kFree);
181  /* Then look for nearest token's locator */
182  ReservationCT::const_iterator it = reservations.begin();
183  uint64_t startTime = std::numeric_limits<uint64_t>::max();
184  while(it != reservations.end()) {
185  if (it->second.getStartTime() < startTime) {
186  startTime = it->second.getStartTime();
187  serviceLocator = it->second.getServiceLocator();
188  }
189  it++;
190  }
191  }
192 
193  return serviceLocator;
194 }
195 
196 uint64_t Tuner::getEndTime(const Activity &activity) const
197 {
198  /* Return last token's expiration time.
199  */
200  uint64_t endTime = 0;
201 
202  /* First look for active locator */
203  ReservationCT::const_iterator it = reservations.begin();
204  while(it != reservations.end() && it->second.getActivity() == activity ) {
205  if ((it->second.getStartTime() + it->second.getDuration()) > endTime) {
206  endTime = it->second.getStartTime() + it->second.getDuration();
207  }
208  it++;
209  }
210 
211 
212  return endTime;
213 }
214 
215 const std::string &Tuner::getId(void) const {
216  return internalId;
217 }
218 
219 void Tuner::addReservation(const TunerReservation & reservation)
220 {
221  std::cout << "Enter addReservation" << std::endl;
222 
223  /*
224  * TunerReservation::EXPIRED is only transicent token state when duration expires.
225  */
226  SafeAssert(assertTunerState(TunerReservation::EXPIRED, 0, 0));
227 
228  /* Reservations of same tuner must have same service locator */
229  if (getState() == TunerState::kFree) {
230  SafeAssert(assertTunerState(TunerReservation::ACTIVE, 0, 0));
231  }
232  else if (getState() == TunerState::kHybrid) {
233  }
234  else {
235  //When 1st recording expires at the same time the 2nd recording starts, the
236  //Timer Start and Timer Stop may be in random order. In case that Timer start
237  //Arrives before Expiration, the tuner may have two active reservations.
238  SafeAssert(assertTunerState(TunerReservation::ACTIVE, 1, 2));
239  }
240 
241  /* First Make sure that the reservation does not yet exist */
242  ReservationCT::const_iterator it = reservations.find(reservation.getReservationToken());
243  if (it != reservations.end()) {
244  std::cout << "Tuner Reservation " << reservation.getReservationToken() << " Already Exist!" << std::endl;
245  }
246 
247  if (getState() != TunerState::kFree) {
248  Assert(reservations.size() > 0);
249  ReservationCT::const_iterator it = reservations.begin();
250  /* if two reservations overlap, they should have same source id */
251  while(it != reservations.end()) {
252  if (isOverlap(it->second.getStartTime(), it->second.getDuration(), reservation.getStartTime(), reservation.getDuration())) {
253  std::cout << "one locator is " << it->second.getServiceLocator() << std::endl;
254  std::cout << "other locator is " << reservation.getServiceLocator() << std::endl;
255  /* Use SafeAssert to issue warning. Different Locator is allowed between L and R
256  * L will be force tunen to R when hybrid mode starts.
257  */
258  if (it->second.getActivity() == reservation.getActivity()) {
259  Assert(it->second.getServiceLocator().compare(reservation.getServiceLocator()) == 0);
260  }
261  else {
262  /* A tuner may temporary holding tow different locator, one for record, one for live.
263  * but they will be sync'd upon record start.
264  */
265  }
266  }
267  it++;
268  }
269  }
270 
271  std::cout << "Reservation to Add is new" << std::endl;
272 
273  std::cout << " Current Tuner State is " << (const char *) getState().getState()
274  << " Activity requested is " << (const char *) reservation.getActivity().getActivity() << std::endl;
275 
276 #if 1
277  /* Schedule to update the tuner state at reservation start time. */
278 #else
279  /* else do the state now... wont work if we allow future reservations */
280  state = state + reservation.getActivity().getActivity();
281  std::cout << "New Tuner State is " << (const char *) state.getState() << std::endl;
282 #endif
283  reservations[reservation.getReservationToken()] = reservation;
284 
285  {
286 
287  int count = 0;
288  ReservationCT::const_iterator it = reservations.begin();
289  while(it != reservations.end()) {
290  if (it->second.state == TunerReservation::ACTIVE) {
291  count++;
292  }
293  it++;
294  }
295  Assert(count <= 2);
296  }
297 
298  std::cout << " Reservation Added Successfully : " << reservation.getReservationToken() << std::endl;
299 }
300 
301 void Tuner::releaseReservation(const std::string & reservationToken)
302 {
303  std::cout << "Enter releaseReservation" << std::endl;
304 
305  /* First Make sure that the reservation does not yet exist */
306  ReservationCT::iterator it = reservations.find(reservationToken);
307  if (it != reservations.end()) {
308  TunerReservation & removedReservation = it->second;
309  printf("Releasing Reservation %p\r\n", &removedReservation);
310 
311  /* Reservations of same tuner must have same service locator */
312  if (getState() == TunerState::kFree) {
313  SafeAssert(assertTunerState(TunerReservation::ACTIVE, 0, 0));
314  SafeAssert(assertTunerState(TunerReservation::EXPIRED, 0, 1));
315  }
316  else if (getState() == TunerState::kHybrid) {
317  }
318  else {
319  //When 1st recording expires at the same time the 2nd recording starts, the
320  //Timer Start and Timer Stop may be in random order. In case that Timer start
321  //Arrives before Expiration, the tuner may have two active reservations.
322  SafeAssert(assertTunerState(TunerReservation::ACTIVE, 1, 2));
323  SafeAssert(assertTunerState(TunerReservation::EXPIRED, 0, 1));
324  }
325 
326  Assert((removedReservation).getReservationToken().compare(reservationToken) == 0);
327  extern void delete_ReservationCustomAttributes(void *p);
328  delete_ReservationCustomAttributes((void *)removedReservation.getCustomAttributes());
329 
330 #if 0
331  if (removedReservation.state == TunerReservation::IDLE) {
332  std::cout << "Removing Future Reservation " << std::endl;
333  } else if (removedReservation.state == TunerReservation::ACTIVE) {
334  std::cout << "Removing Current Reservation " << std::endl;
335  state = state - removedReservation.getActivity().getActivity();
336  }
337  else {
338  std::cout << " Removing Expired Reservation " << std::endl;
339  state = state - removedReservation.getActivity().getActivity();
340  }
341 #endif
342  reservations.erase(it);
343 
344  }
345 }
346 
347 bool Tuner::assertTunerState(int state, int lowMark, int highMark)
348 {
349  int count = 0;
350  bool ok = false;
351  ReservationCT::const_iterator it = reservations.begin();
352  while(it != reservations.end()) {
353  if (it->second.state == state) {
354  count++;
355  }
356  it++;
357  }
358  if (count >= lowMark && count <= highMark) {
359  ok = true;
360  }
361  else {
362  std::cout << "TUner has " << count << " reservations in state " << state << " vs " << lowMark << ", " << highMark << std::endl;
363  ok = false;
364  }
365  return(ok);
366 }
367 
368 
369 TRM_END_NAMESPACE
370 
371 
372 /** @} */
373 /** @} */