bc::duration<double> Scheduler::estimateExecutionTime(JobPtr j) {
  // TODO[mtottenh]:Add code to estimate a job finish time
  double milliseconds = (double)j->getReq()->predictedTimeMillis;
  bc::duration<double, boost::ratio<1, 1000> > milli_sec(milliseconds);
  auto micro_sec = bc::duration_cast<bc::microseconds>(milli_sec);
  // LOG(debug) << milli_sec.count() << "ms"
  //             << ", " << micro_sec.count() << "us";
  return milli_sec;
}
void Scheduler::runJob(JobResPairPtr j) {
  ResourceListPtr resourceList;
  JobTuplePtr jobTuplePtr;
  std::tie(jobTuplePtr, resourceList) = *j;
  JobPtr jobPtr = std::get<0>(*jobTuplePtr);
  // LOG(debug) << "- Scheduler::runJob(" << *jobPtr << ")";
  // LOG(debug) << "- Allocated[" << resourceList->size() << "]";
  char packed_rids = 0x0;

  std::stringstream ss;
  for (auto &r : *resourceList) {
    ss << r.getId() << ", ";
    switch (r.getId()) {

    case 1:
      packed_rids |= RID1;
      break;
    case 2:
      packed_rids |= RID2;
      break;
    case 3:
      packed_rids |= RID3;
      break;
    case 4:
      packed_rids |= RID4;
      break;
    }
  }
  // LOG(debug) << "\t* Rids: { " << ss.str()  <<  "}";
  const Resource& r = resourceList->front();
  const string &name = r.getName().c_str();
  int portNumber = r.getPort();
  msg_t *req = jobPtr->getReq();

  // LOG(debug) << "\t* Opening connection to: " << name << ":"
  //             << portNumber << "";

  Client c(portNumber, name);
  auto start = bc::system_clock::now();
  c.start();

  boost::this_thread::interruption_point();
  if (req != NULL) {
    req->rids = packed_rids;
    c.send(req);
  }

  int sizeBytes = sizeof(msg_t) + req->expDataSizeBytes;
  char *buff = (char *)calloc(sizeBytes, 1);

  if (buff == NULL) {
    // LOG(debug) << "\tUnable to allocate result buffer";
    c.stop();
    returnResources(resourceList);
    resourceList = nullptr;
  }

  msg_t *rsp = (msg_t *)buff;

  do {
    // LOG(debug) << "\t Reading reply, size: " << sizeBytes;
    c.read(buff, sizeBytes);
  } while (rsp->msgId != MSG_RESULT);
  // LOG(debug) << "\t* Got Result";
  c.stop();
  auto end = bc::system_clock::now();
  jobPtr->setMeasuredExecutionTime(end - start);
  jobPtr->setActualExecutionTime(bc::milliseconds(rsp->predictedTimeMillis));
  jobPtr->setRsp((msg_t *)buff);
  returnResources(resourceList);
  resourceList = nullptr;
  std::get<0>(*jobTuplePtr)->setFinishTime(bc::system_clock::now());
  finishedQ->push_front(jobTuplePtr);
  // LOG(debug) << "Removing job from runQ";
  removeJobFromRunQ(jobPtr->getId());
}