text:
/*
 * Copyright 2021 Huawei Technologies Co., Ltd. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include "FairmotMindsporePost.h"

#include <dirent.h>
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <memory>
#include <string>
#include <boost/property_tree/json_parser.hpp>
#include <opencv2/core/hal/hal.hpp>
#include <opencv2/opencv.hpp>

#include "MxBase/CV/ObjectDetection/Nms/Nms.h"
#include "acl/acl.h"

namespace {
// Output Tensor
const int OUTPUT_TENSOR_SIZE = 2;
const int OUTPUT_ID_FEATURE_INDEX = 0;
const int OUTPUT_DETS_INDEX = 1;

const int OUTPUT_ID_FEATURE_SIZE = 2;
const int OUTPUT_DETS_SIZE = 3;
const float CONF_THRES = 0.3;
const int TRACK_BUFFER = 30;
const int K = 500;
const int TrackState_New = 0;
const int TrackState_Tracked = 1;
const int TrackState_Lost = 2;
const int TrackState_Removed = 3;
const int MIN_BOX_AREA = 100;
}  // namespace

namespace MxBase {
BaseTrack basetrack;
KalmanFilter kalmanfilter;
void FairmotMindsporePost::get_result(int *collist, int cols, cost *d, cost min,
                                      int rows, int &endofpath, row *colsol,
                                      cost **assigncost, cost *v, int *pred) {
  col low = 0, up = 0;  // columns in 0..low-1 are ready, now none.
  int k, j, i, j1;
  cost h, v2;
  boolean unassignedfound = FALSE;
  do {
    if (up == low) {
      min = d[collist[up++]];
      for (k = up; k < cols; k++) {
        j = collist[k];
        h = d[j];
        if (h <= min) {
          if (h < min) {
            up = low;  // restart list at index low.
            min = h;
          }
          collist[k] = collist[up];
          collist[up++] = j;
        }
      }
      for (k = low; k < up; k++)
        if (colsol[collist[k]] < 0) {
          endofpath = collist[k];
          unassignedfound = TRUE;
          break;
        }
    }
    if (!unassignedfound) {
      j1 = collist[low];
      low++;
      i = colsol[j1];
      if (i > rows) {
        i = 0;
      }
      h = assigncost[i][j1] - v[j1] - min;
      for (k = up; k < cols; k++) {
        j = collist[k];
        v2 = assigncost[i][j] - v[j] - h;
        if (v2 < d[j]) {
          pred[j] = i;
          if (v2 == min) {
            if (colsol[j] < 0) {
              endofpath = j;
              unassignedfound = TRUE;
              break;
            } else {
              collist[k] = collist[up];
              collist[up++] = j;
            }
          }
          d[j] = v2;
        }
      }
    }
  } while (!unassignedfound);
}
void FairmotMindsporePost::func(int &numfree, int *free, cost **assigncost,
                                row *colsol, cost *v, col *rowsol, int cols) {
  int j2, loopcnt = 0;  // do-loop to be done twice.
  do {
    loopcnt++;
    int k = 0;
    row prvnumfree;
    prvnumfree = numfree;
    numfree = 0;
    while (k < prvnumfree) {
      int i = free[k++];
      int umin = assigncost[i][0] - v[0];
      int j1 = 0;
      int usubmin = BIG;
      for (int j = 1; j < cols; j++) {
        int h = assigncost[i][j] - v[j];
        if (h < usubmin) {
          if (h >= umin) {
            usubmin = h;
            j2 = j;
          } else {
            usubmin = umin;
            umin = h;
            j2 = j1;
            j1 = j;
          }
        }
      }
      int i0 = colsol[j1];
      if (umin < usubmin) {
        v[j1] = v[j1] - (usubmin - umin);
      } else {
        if (i0 > -1) {
          j1 = j2;
          i0 = colsol[j2];
        }
      }
      rowsol[i] = j1;
      colsol[j1] = i;
      if (i0 > -1) {
        if (umin < usubmin) {
          free[--k] = i0;
        } else {
          free[numfree++] = i0;
        }
      }
    }
  } while (loopcnt < 2);  // repeat once.
}

void FairmotMindsporePost::lap(cost **assigncost, col *rowsol, row *colsol,
                               cost *u, cost *v, int rows, int cols) {
  int i, numfree = 0, f, *pred = new row[rows], *free = new row[rows], j, j1,
         endofpath, *collist = new col[cols], *matches = new col[cols];
  cost min, *d = new cost[rows];
  for (i = 0; i < rows; i++) matches[i] = 0;
  for (j = cols; j--;) {  // reverse order gives better results.
    row imin = 0;
    min = assigncost[0][j];
    for (i = 1; i < rows; i++)
      if (assigncost[i][j] < min) {
        min = assigncost[i][j];
        imin = i;
      }
    v[j] = min;
    if (++matches[imin] == 1) {
      rowsol[imin] = j;
      colsol[j] = imin;
    } else if (v[j] < v[rowsol[imin]]) {
      int j_1 = rowsol[imin];
      rowsol[imin] = j;
      colsol[j] = imin;
      colsol[j_1] = -1;
    } else {
      colsol[j] = -1;
    }
  }
  for (i = 0; i < rows; i++)
    if (matches[i] == 0) {
      free[numfree++] = i;
    } else if (matches[i] == 1) {
      j1 = rowsol[i];
      min = BIG;
      for (j = 0; j < cols; j++)
        if (j != j1)
          if (assigncost[i][j] - v[j] < min) min = assigncost[i][j] - v[j];
      v[j1] = v[j1] - min;
    }
  func(numfree, free, assigncost, colsol, v, rowsol, cols);
  for (f = 0; f < numfree; f++) {
    row freerow;
    freerow = free[f];  // start row of augmenting path.
    for (j = cols; j--;) {
      d[j] = assigncost[freerow][j] - v[j];
      pred[j] = freerow;
      collist[j] = j;  // init column list.
    }
    get_result(collist, cols, d, min, rows, endofpath, colsol, assigncost, v,
               pred);
    do {
      i = pred[endofpath];
      colsol[endofpath] = i;
      j1 = endofpath;
      endofpath = rowsol[i];
      rowsol[i] = j1;
    } while (i != freerow);
  }
  delete[] matches;
}

int BaseTrack::next_id() {
  this->count += 1;
  return this->count;
}

Results::Results(uint32_t frame_id, const std::vector<cv::Mat> &online_tlwhs,
                 const std::vector<int> &online_ids) {
  this->frame_id = frame_id;
  this->online_tlwhs = online_tlwhs;
  this->online_ids = online_ids;
}

JDETracker::JDETracker(uint32_t frame_rate) {
  this->det_thresh = CONF_THRES;
  this->buffer_size = static_cast<int>(frame_rate / 30.0 * TRACK_BUFFER);
  this->max_time_lost = this->buffer_size;
  this->max_per_image = K;
  KalmanFilter kalman_filter;
  this->kalman_filter = kalman_filter;
}
STack::STack() {}
STack::STack(cv::Mat tlwh, float score, cv::Mat temp_feat,
             uint32_t buffer_size) {
  tlwh.convertTo(this->tlwh, CV_64FC1);
  this->is_activated = false;
  this->score = score;
  this->tracklet_len = 0;
  this->update_features(temp_feat);
  this->alpha = 0.9;
}
cv::Mat STack::gettlwh() {
  if (this->mean.rows == 0) {
    return this->tlwh.clone();
  } else {
    cv::Mat ret =
        this->mean(cv::Range(0, this->mean.rows), cv::Range(0, 4)).clone();
    ret.at<double>(0, 2) *= ret.at<double>(0, 3);
    for (size_t i = 0; i < 2; i++) {
      ret.at<double>(0, i) -= ret.at<double>(0, i + 2) / 2;
    }
    return ret;
  }
}
cv::Mat STack::tlbr() {
  cv::Mat ret = this->gettlwh();
  for (size_t i = 0; i < 2; i++) {
    ret.at<double>(0, i + 2) += ret.at<double>(0, i);
  }
  return ret;
}
cv::Mat STack::tlwh_to_xyah(cv::Mat tlwh) {
  cv::Mat ret = tlwh;
  for (size_t i = 0; i < 2; i++) {
    ret.at<double>(0, i) += ret.at<double>(0, i + 2) / 2;
  }
  ret.at<double>(0, 2) /= ret.at<double>(0, 3);
  return ret;
}
void STack::activate(const KalmanFilter &kalman_filter, uint32_t frame_id) {
  this->kalman_filter = kalman_filter;
  this->track_id = basetrack.next_id();
  this->kalman_filter.initiate(this->tlwh_to_xyah(this->tlwh), this->mean,
                               this->covariance);
  this->tracklet_len = 0;
  this->state = TrackState_Tracked;
  this->is_activated = false;
  if (frame_id == 1) {
    this->is_activated = true;
  }
  this->frame_id = frame_id;
  this->start_frame = frame_id;
}
void STack::update_features(cv::Mat temp_feat) {
  cv::Mat feat;
  cv::normalize(temp_feat, feat);
  this->curr_feat = feat;
  if (this->smooth_feat.empty()) {
    this->smooth_feat = feat;
  } else {
    this->smooth_feat =
        this->alpha * this->smooth_feat + (1 - this->alpha) * feat;
  }
  this->features.push_back(feat);
  cv::normalize(this->smooth_feat, this->smooth_feat);
}

void STack::update(STack new_track, int frame_id, bool update_feature) {
  this->frame_id = frame_id;
  this->tracklet_len += 1;
  cv::Mat new_tlwh = new_track.gettlwh();
  this->kalman_filter.update(this->mean, this->covariance,
                             this->tlwh_to_xyah(new_tlwh));
  this->state = TrackState_Tracked;
  this->is_activated = true;
  this->score = new_track.score;
  if (update_feature == true) {
    this->update_features(new_track.curr_feat);
  }
}

void STack::re_activate(STack new_track, int frame_id, bool new_id) {
  this->kalman_filter.update(this->mean, this->covariance,
                             this->tlwh_to_xyah(new_track.gettlwh()));
  this->update_features(new_track.curr_feat);
  this->tracklet_len = 0;
  this->state = TrackState_Tracked;
  this->is_activated = true;
  this->frame_id = frame_id;
  if (new_id) {
    this->track_id = basetrack.next_id();
  }
}

void KalmanFilter::initiate(cv::Mat measurement, cv::Mat &mean,
                            cv::Mat &covariance) {
  cv::Mat mean_pos = measurement;
  cv::Mat mean_vel = cv::Mat::zeros(mean_pos.rows, mean_pos.cols, CV_64FC1);
  hconcat(mean_pos, mean_vel, mean);
  double tmp[1][8] = {
      2 * this->std_weight_position * measurement.at<double>(0, 3),
      2 * this->std_weight_position * measurement.at<double>(0, 3),
      1e-2,
      2 * this->std_weight_position * measurement.at<double>(0, 3),
      10 * this->std_weight_velocity * measurement.at<double>(0, 3),
      10 * this->std_weight_velocity * measurement.at<double>(0, 3),
      1e-5,
      10 * this->std_weight_velocity * measurement.at<double>(0, 3)};
  cv::Mat std = cv::Mat(1, 8, CV_64FC1, tmp);
  std = std.mul(std);
  covariance = cv::Mat::eye(std.cols, std.cols, CV_64FC1);
  for (size_t i = 0; i < std.cols; i++)
    covariance.at<double>(i, i) = std.at<double>(0, i);
}
void KalmanFilter::multi_predict(cv::Mat &mean,
                                 std::vector<cv::Mat> &covariance) {
  cv::Mat std_pos(4, mean.rows, CV_64FC1);
  cv::Mat std_vel(4, mean.rows, CV_64FC1);
  for (size_t i = 0; i < 4; i++)
    for (size_t j = 0; j < mean.rows; j++)
      if (i == 2) {
        std_pos.at<double>(i, j) = 1e-2;
        std_vel.at<double>(i, j) = 1e-5;
      } else {
        std_pos.at<double>(i, j) =
            this->std_weight_position * mean.at<double>(j, 3);
        std_vel.at<double>(i, j) =
            this->std_weight_velocity * mean.at<double>(j, 3);
      }
  cv::Mat sqr;
  vconcat(std_pos, std_vel, sqr);
  sqr = sqr.mul(sqr).t();
  std::vector<cv::Mat> motion_cov;
  for (size_t i = 0; i < mean.rows; i++) {
    cv::Mat diag = cv::Mat::eye(sqr.cols, sqr.cols, CV_64FC1);
    for (size_t j = 0; j < sqr.cols; j++) {
      diag.at<double>(j, j) = sqr.at<double>(i, j);
    }
    motion_cov.push_back(diag);
  }
  mean = mean * this->motion_mat.t();
  std::vector<cv::Mat> left;
  for (size_t i = 0; i < covariance.size(); i++) {
    left.push_back(this->motion_mat * covariance[i]);
  }
  for (size_t i = 0; i < covariance.size(); i++) {
    covariance[i] = left[i] * this->motion_mat.t() + motion_cov[i];
  }
}
KalmanFilter::KalmanFilter() {
  this->ndim = 4;
  this->dt = 1.0;
  this->motion_mat = cv::Mat::eye(2 * (this->ndim), 2 * (this->ndim), CV_64FC1);
  for (size_t i = 0; i < this->ndim; ++i) {
    this->motion_mat.at<double>(i, this->ndim + i) = this->dt;
  }
  this->update_mat = cv::Mat::eye(this->ndim, 2 * (this->ndim), CV_64FC1);
  this->std_weight_position = 1.0 / 20;
  this->std_weight_velocity = 1.0 / 160;
}
cv::Mat KalmanFilter::GatingDistance(cv::Mat mean, cv::Mat covariance,
                                     cv::Mat measurements, bool only_position,
                                     const std::string &metric) {
  this->project(mean, covariance);
  cv::Mat d(measurements.rows, measurements.cols, CV_64FC1);
  for (size_t i = 0; i < measurements.rows; i++) {
    d.row(i) = measurements.row(i) - mean;
  }
  cv::Mat cholesky_factor = cv::Mat::zeros(covariance.size(), CV_64F);
  for (int i = 0; i < covariance.rows; ++i) {
    int j;
    double sum;
    for (j = 0; j < i; ++j) {
      sum = 0;
      for (int k = 0; k < j; ++k) {
        sum +=
            cholesky_factor.at<double>(i, k) * cholesky_factor.at<double>(j, k);
      }
      cholesky_factor.at<double>(i, j) = (covariance.at<double>(i, j) - sum) /
                                         cholesky_factor.at<double>(j, j);
    }
    sum = 0;
    assert(i == j);
    for (int k = 0; k < j; ++k) {
      sum +=
          cholesky_factor.at<double>(j, k) * cholesky_factor.at<double>(j, k);
    }
    cholesky_factor.at<double>(j, j) = sqrt(covariance.at<double>(j, j) - sum);
  }
  cv::Mat z;
  cv::solve(cholesky_factor, d.t(), z);
  z = z.mul(z);
  cv::Mat squared_maha(1, z.cols, CV_64FC1);
  for (size_t i = 0; i < z.cols; i++) {
    double sum = 0;
    for (size_t t = 0; t < z.rows; t++) {
      sum += z.at<double>(t, i);
    }
    squared_maha.at<double>(0, i) = sum;
  }
  return squared_maha;
}

void KalmanFilter::project(cv::Mat &mean, cv::Mat &covariance) {
  cv::Mat std(1, 4, CV_64FC1);
  for (size_t i = 0; i < 4; i++)
    if (i == 2)
      std.at<double>(0, i) = 1e-1;
    else
      std.at<double>(0, i) = this->std_weight_position * mean.at<double>(0, 3);
  std = std.mul(std);
  cv::Mat innovation_cov = cv::Mat::eye(std.cols, std.cols, CV_64FC1);
  for (size_t j = 0; j < std.cols; j++) {
    innovation_cov.at<double>(j, j) = std.at<double>(0, j);
  }
  cv::Mat tmp(mean.rows, this->update_mat.rows, CV_64FC1);
  for (size_t i = 0; i < this->update_mat.rows; i++) {
    tmp.at<double>(0, i) = this->update_mat.row(i).dot(mean);
  }
  mean = tmp;
  covariance =
      this->update_mat * covariance * this->update_mat.t() + innovation_cov;
}

void KalmanFilter::update(cv::Mat &mean, cv::Mat &covariance,
                          cv::Mat measurement) {
  cv::Mat projected_mean = mean.clone();
  cv::Mat projected_cov = covariance.clone();
  this->project(projected_mean, projected_cov);
  cv::Mat chol_factor;
  this->cholesky_decomposition(projected_cov, chol_factor);
  cv::Mat b = covariance * this->update_mat.t();
  b = b.t();
  cv::Mat kalman_gain(chol_factor.rows, b.cols, CV_64FC1);
  for (size_t i = 0; i < b.cols; i++) {
    f64_vec_t x = {0, 0, 0, 0};
    f64_vec_t *f_x = &x;
    cv::Mat mat_b(b.rows, 1, CV_64FC1);
    mat_b = b.col(i);
    this->chol_subtitute(chol_factor, mat_b, f_x, chol_factor.rows);
    for (size_t j = 0; j < chol_factor.rows; j++) {
      if ((*f_x)[j] < 0.001)
        kalman_gain.at<double>(j, i) = 0;
      else
        kalman_gain.at<double>(j, i) = (*f_x)[j];
    }
  }
  kalman_gain = kalman_gain.t();
  cv::Mat innovation = measurement - projected_mean;
  mean += innovation * kalman_gain.t();
  covariance -= kalman_gain * projected_cov * kalman_gain.t();
}

void KalmanFilter::chol_subtitute(cv::Mat chol_factor, cv::Mat mat_b,
                                  f64_vec_t *f_x, int n) {
  f64_mat_t L;
  f64_vec_t b;
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < n; ++j) L[i][j] = chol_factor.at<double>(i, j);
  for (int i = 0; i < n; ++i) b[i] = mat_b.at<double>(i, 0);
  f64_mat_t *f_L = &L;
  f64_vec_t *f_b = &b;
  int i, j;
  double f_sum;

  double *pX;
  double *pXj;
  const double *pL;
  const double *pB;
  /** @llr - This function shall solve the unknown vector f_x given a matrix f_L
   * and a vector f_b with the relation f_L*fL'*f_x = f_b.*/

  pX = &(*f_x)[0];
  pB = &(*f_b)[0];
  /* Copy f_b into f_x */
  for (i = 0u; i < n; i++) {
    (*pX) = (*pB);
    pX++;
    pB++;
  }
  /* Solve Ly = b  for y */
  pXj = &(*f_x)[0];
  for (i = 0u; i < n; i++) {
    double *pXi;
    double fLii;
    f_sum = (*f_x)[i];
    fLii = (*f_L)[i][i];
    pXi = &(*f_x)[0];
    pL = &(*f_L)[i][0];

    for (j = 0u; j < i; j++) {
      f_sum -= (*pL) * (*pXi);
      pL++;
      pXi++;
    }
    (*pXj) = f_sum / fLii;
    pXj++;
  }
  /* Solve L'x = y for x */
  for (i = 1u; i <= n; i++) {
    f_sum = (*f_x)[n - i];
    pXj = &(*f_x)[n - i + 1u];
    pL = &(*f_L)[n - i + 1u][n - i];
    for (j = n - i + 1u; j < n; j++) {
      f_sum -= (*pL) * (*pXj);
      pXj++;
      pL += n; /* PRQA S 0488 */
    }
    (*f_x)[n - i] = f_sum / (*f_L)[n - i][n - i];
  }
}

void KalmanFilter::cholesky_decomposition(const cv::Mat &A, cv::Mat &L) {
  L = cv::Mat::zeros(A.size(), CV_64F);
  int rows = A.rows;

  for (int i = 0; i < rows; ++i) {
    int j;
    float sum;

    for (j = 0; j < i; ++j) {
      sum = 0;
      for (int k = 0; k < j; ++k) {
        sum += L.at<double>(i, k) * L.at<double>(j, k);
      }
      L.at<double>(i, j) = (A.at<double>(i, j) - sum) / L.at<double>(j, j);
    }
    sum = 0;
    assert(i == j);
    for (int k = 0; k < j; ++k) {
      sum += L.at<double>(j, k) * L.at<double>(j, k);
    }
    L.at<double>(j, j) = sqrt(A.at<double>(j, j) - sum);
  }
}

FairmotMindsporePost &FairmotMindsporePost::operator=(
    const FairmotMindsporePost &other) {
  if (this == &other) {
    return *this;
  }
  PostProcessBase::operator=(other);
  return *this;
}

APP_ERROR FairmotMindsporePost::Init(
    const std::map<std::string, std::shared_ptr<void>> &postConfig) {
  LogInfo << "Begin to initialize FairmotMindsporePost.";
  APP_ERROR ret = PostProcessBase::Init(postConfig);
  if (ret != APP_ERR_OK) {
    LogError << GetError(ret) << "Fail to superinit  in PostProcessBase.";
    return ret;
  }

  LogInfo << "End to initialize FairmotMindsporePost.";
  return APP_ERR_OK;
}

APP_ERROR FairmotMindsporePost::DeInit() {
  LogInfo << "Begin to deinitialize FairmotMindsporePost.";
  LogInfo << "End to deinitialize FairmotMindsporePost.";
  return APP_ERR_OK;
}

bool FairmotMindsporePost::IsValidTensors(
    const std::vector<TensorBase> &tensors) const {
  if (tensors.size() < OUTPUT_TENSOR_SIZE) {
    LogError << "The number of tensor (" << tensors.size()
             << ") is less than required (" << OUTPUT_TENSOR_SIZE << ")";
    return false;
  }

  auto idFeatureShape = tensors[OUTPUT_ID_FEATURE_INDEX].GetShape();
  if (idFeatureShape.size() != OUTPUT_ID_FEATURE_SIZE) {
    LogError << "The number of tensor[" << OUTPUT_ID_FEATURE_INDEX
             << "] dimensions (" << idFeatureShape.size()
             << ") is not equal to (" << OUTPUT_ID_FEATURE_SIZE << ")";
    return false;
  }

  auto detsShape = tensors[OUTPUT_DETS_INDEX].GetShape();
  if (detsShape.size() != OUTPUT_DETS_SIZE) {
    LogError << "The number of tensor[" << OUTPUT_DETS_INDEX << "] dimensions ("
             << detsShape.size() << ") is not equal to ("
             << OUTPUT_ID_FEATURE_SIZE << ")";
    return false;
  }

  return true;
}

void FairmotMindsporePost::TransformPreds(const cv::Mat &coords,
                                          MxBase::JDETracker tracker,
                                          cv::Mat &target_coords) {
  target_coords = cv::Mat::zeros(coords.rows, coords.cols, CV_32FC1);
  float scale = tracker.s;
  uint32_t h = tracker.out_height;
  uint32_t w = tracker.out_width;
  float scale_value[1][2] = {scale, scale};
  cv::Mat scale_tmp = cv::Mat(1, 2, CV_32FC1, scale_value);
  float src_w = scale_tmp.at<float>(0, 0);
  uint32_t dst_w = w;
  uint32_t dst_h = h;
  float sn = 0.0;
  float cs = 1.0;
  uint32_t src_point_0 = 0;
  float src_point_1 = src_w * (-0.5);
  float src_dir_value[1][2] = {src_point_0 * cs - src_point_1 * sn,
                               src_point_0 * sn + src_point_1 * cs};
  cv::Mat src_dir = cv::Mat(1, 2, CV_32FC1, src_dir_value);
  float dst_dir_value[1][2] = {0, static_cast<float>(dst_w * (-0.5))};
  cv::Mat dst_dir = cv::Mat(1, 2, CV_32FC1, dst_dir_value);
  cv::Mat src = cv::Mat::zeros(3, 2, CV_32FC1);
  cv::Mat dst = cv::Mat::zeros(3, 2, CV_32FC1);
  float center_value[1][2] = {tracker.c[0], tracker.c[1]};
  cv::Mat center = cv::Mat(1, 2, CV_32FC1, center_value);
  cv::Mat shift = cv::Mat::zeros(1, 2, CV_32FC1);
  cv::Mat src_0 = scale_tmp.mul(shift) + center;
  cv::Mat src_1 = scale_tmp.mul(shift) + center + src_dir;
  cv::Mat direct = src_0 - src_1;
  float direct_tmp_value[1][2] = {-direct.at<float>(0, 1),
                                  direct.at<float>(0, 0)};
  cv::Mat direct_tmp = cv::Mat(1, 2, CV_32FC1, direct_tmp_value);
  cv::Mat src_2 = src_1 + direct_tmp;
  float dst_0_value[1][2] = {static_cast<float>(dst_w * (0.5)),
                             static_cast<float>(dst_h * (0.5))};
  cv::Mat dst_0 = cv::Mat(1, 2, CV_32FC1, dst_0_value);
  float dst_1_value[1][2] = {
      static_cast<float>(dst_w * (0.5)) + dst_dir.at<float>(0, 0),
      static_cast<float>(dst_h * (0.5)) + dst_dir.at<float>(0, 1)};
  cv::Mat dst_1 = cv::Mat(1, 2, CV_32FC1, dst_1_value);
  direct = dst_0 - dst_1;
  float direct_value[1][2] = {-direct.at<float>(0, 1), direct.at<float>(0, 0)};
  direct_tmp = cv::Mat(1, 2, CV_32FC1, direct_value);
  cv::Mat dst_2 = dst_1 + direct_tmp;
  for (size_t y = 0; y < src.cols; ++y) {
    src.at<float>(0, y) = src_0.at<float>(0, y);
    src.at<float>(1, y) = src_1.at<float>(0, y);
    src.at<float>(2, y) = src_2.at<float>(0, y);
    dst.at<float>(0, y) = dst_0.at<float>(0, y);
    dst.at<float>(1, y) = dst_1.at<float>(0, y);
    dst.at<float>(2, y) = dst_2.at<float>(0, y);
  }
  cv::Mat trans(2, 3, CV_32FC1);
  trans = cv::getAffineTransform(dst, src);
  trans.convertTo(trans, CV_32F);
  for (size_t x = 0; x < coords.rows; ++x) {
    float pt_value[3][1] = {coords.at<float>(x, 0), coords.at<float>(x, 1),
                            1.0};
    cv::Mat pt = cv::Mat(3, 1, CV_32FC1, pt_value);
    for (size_t y = 0; y < 2; ++y) {
      cv::Mat new_pt = trans * pt;
      target_coords.at<float>(x, y) = new_pt.at<float>(y);
    }
  }
}

void FairmotMindsporePost::PostProcess(cv::Mat &det,
                                       const MxBase::JDETracker &tracker) {
  cv::Mat coords_0 = det(cv::Range(0, det.rows), cv::Range(0, 2));
  cv::Mat coords_1 = det(cv::Range(0, det.rows), cv::Range(2, 4));
  cv::Mat target_coords_0;
  cv::Mat target_coords_1;
  TransformPreds(coords_0, tracker, target_coords_0);
  TransformPreds(coords_1, tracker, target_coords_1);
  for (size_t x = 0; x < det.rows; ++x) {
    for (size_t y = 0; y < 4; ++y) {
      if (y < 2) {
        det.at<float>(x, y) = target_coords_0.at<float>(x, y);
      } else {
        det.at<float>(x, y) = target_coords_1.at<float>(x, y - 2);
      }
    }
  }
  det = det(cv::Range(0, det.rows), cv::Range(0, 5));
}
void FairmotMindsporePost::TensorBaseToCVMat(cv::Mat &imageMat,
                                             const MxBase::TensorBase &tensor) {
  TensorBase Data = tensor;
  uint32_t outputModelWidth;
  uint32_t outputModelHeight;
  auto shape = Data.GetShape();
  if (shape.size() == 2) {
    outputModelWidth = shape[0];
    outputModelHeight = shape[1];
  } else {
    outputModelWidth = shape[1];
    outputModelHeight = shape[2];
  }
  auto *data = reinterpret_cast<float *>(GetBuffer(Data, 0));
  cv::Mat dataMat(outputModelWidth, outputModelHeight, CV_32FC1);
  for (size_t x = 0; x < outputModelWidth; ++x) {
    for (size_t y = 0; y < outputModelHeight; ++y) {
      dataMat.at<float>(x, y) = data[x * outputModelHeight + y];
    }
  }
  imageMat = dataMat.clone();
}

std::vector<cv::Mat> FairmotMindsporePost::get_lap(cost **assigncost,
                                                   col *rowsol, row *colsol,
                                                   cost *u, cost *v, int row,
                                                   int col, int dim) {
  std::vector<cv::Mat> results;
  lap(assigncost, rowsol, colsol, u, v, dim, dim);
  cv::Mat x(1, row, CV_32FC1), y(1, col, CV_32FC1);
  for (int i = 0; i < row; i++)
    x.at<float>(0, i) = rowsol[i] > (col - 1) ? (-1) : rowsol[i];
  for (int j = 0; j < col; j++)
    y.at<float>(0, j) = colsol[j] > (row - 1) ? (-1) : colsol[j];
  cv::Mat matches(0, 2, CV_32FC1);
  for (size_t i = 0; i < x.cols; i++) {
    if (x.at<float>(0, i) >= 0) {
      cv::Mat tmp(1, 2, CV_32FC1);
      tmp.at<float>(0, 0) = i;
      tmp.at<float>(0, 1) = x.at<float>(0, i);
      matches.push_back(tmp);
    }
  }
  std::vector<int> a, b;
  for (size_t i = 0; i < x.cols; i++)
    if (x.at<float>(0, i) < 0) a.push_back(i);
  for (size_t i = 0; i < y.cols; i++)
    if (y.at<float>(0, i) < 0) b.push_back(i);
  cv::Mat unmatched_a(1, a.size(), CV_32FC1),
      unmatched_b(1, b.size(), CV_32FC1);
  for (size_t i = 0; i < a.size(); i++) unmatched_a.at<float>(0, i) = a[i];
  for (size_t i = 0; i < b.size(); i++) unmatched_b.at<float>(0, i) = b[i];
  results.push_back(matches);
  results.push_back(unmatched_a);
  results.push_back(unmatched_b);
  return results;
}

std::vector<cv::Mat> FairmotMindsporePost::LinearAssignment(cv::Mat cost_matrix,
                                                            float thresh) {
  if (cost_matrix.rows == 0) {
    std::vector<cv::Mat> results;
    cv::Mat matches(0, 2, CV_32FC1), u_track,
        u_detection(1, cost_matrix.cols, CV_32FC1);
    for (size_t i = 0; i < cost_matrix.cols; ++i)
      u_detection.at<float>(0, i) = i;
    results.push_back(matches);
    results.push_back(u_track);
    results.push_back(u_detection);
    return results;
  } else {
    int row = cost_matrix.rows, col = cost_matrix.cols;
    int N = row > col ? row : col;
    cv::Mat cost_c_extended = cv::Mat::ones(2 * N, 2 * N, CV_64FC1);
    cost_c_extended *= thresh;
    if (row != col) {
      double min = 0, max = 0;
      double *minp = &min, *maxp = &max;
      cv::minMaxIdx(cost_matrix, minp, maxp);
      for (size_t i = 0; i < N; i++)
        for (size_t j = 0; j < N; j++)
          cost_c_extended.at<double>(i, j) = (*maxp) + thresh + 1;
    }
    for (size_t i = 0; i < row; i++)
      for (size_t j = 0; j < col; j++)
        cost_c_extended.at<double>(i, j) = cost_matrix.at<double>(i, j);
    cost_matrix = cost_c_extended;
    int dim = 2 * N, *rowsol = new int[dim], *colsol = new int[dim];
    double **costMatrix = new double *[dim], *u = new double[dim],
           *v = new double[dim];
    for (int i = 0; i < dim; i++) costMatrix[i] = new double[dim];
    for (int i = 0; i < dim; ++i)
      for (int j = 0; j < dim; ++j)
        costMatrix[i][j] = cost_matrix.at<double>(i, j);
    return get_lap(costMatrix, rowsol, colsol, u, v, row, col, dim);
  }
}

void FairmotMindsporePost::FuseMotion(MxBase::KalmanFilter &kf,
                                      cv::Mat &cost_matrix,
                                      std::vector<STack *> tracks,
                                      std::vector<STack *> detections,
                                      bool only_position, float lambda_) {
  if (cost_matrix.rows != 0) {
    int gating_dim;
    if (only_position = false)
      gating_dim = 2;
    else
      gating_dim = 4;
    float gating_threshold = kalmanfilter.chi2inv95[gating_dim];
    cv::Mat measurements(detections.size(), 4, CV_64FC1);
    for (size_t i = 0; i < detections.size(); i++)
      measurements.row(i) =
          (*detections[i]).tlwh_to_xyah((*detections[i]).gettlwh()) + 0;
    for (size_t i = 0; i < tracks.size(); i++) {
      cv::Mat gating_distance =
          kf.GatingDistance((*tracks[i]).mean, (*tracks[i]).covariance,
                            measurements, only_position);
      for (size_t t = 0; t < gating_distance.cols; t++)
        if (gating_distance.at<double>(0, t) > gating_threshold)
          cost_matrix.at<double>(i, t) = DBL_MAX;
      cost_matrix.row(i) =
          lambda_ * cost_matrix.row(i) + (1 - lambda_) * gating_distance;
    }
  }
}
std::vector<STack *> FairmotMindsporePost::JointStracks(
    std::vector<STack *> tlista, std::vector<STack *> tlistb) {
  std::vector<STack *> res;
  std::map<int, int> exists;
  for (size_t t = 0; t < tlista.size(); t++) {
    exists[(*tlista[t]).track_id] = 1;
    res.push_back(tlista[t]);
  }
  for (size_t t = 0; t < tlistb.size(); t++) {
    int tid = (*tlistb[t]).track_id;
    if (exists[tid] == 0) {
      exists[tid] = 1;
      res.push_back(tlistb[t]);
    }
  }
  return res;
}
void FairmotMindsporePost::RemoveDuplicateStracks(
    std::vector<STack *> &stracksa, std::vector<STack *> &stracksb) {
  cv::Mat pdist = IouDistance(stracksa, stracksb);
  std::vector<size_t> p, q, dupa, dupb;
  std::vector<STack *> resa;
  std::vector<STack *> resb;
  for (size_t i = 0; i < pdist.rows; i++)
    for (size_t j = 0; j < pdist.cols; j++)
      if (pdist.at<double>(i, j) < 0.15) {
        p.push_back(i);
        q.push_back(j);
      }
  for (size_t i = 0; i < p.size(); i++) {
    int timep = (*stracksa[p[i]]).frame_id - (*stracksa[p[i]]).start_frame;
    int timeq = (*stracksb[q[i]]).frame_id - (*stracksb[q[i]]).start_frame;
    if (timep > timeq) {
      dupb.push_back(q[i]);
    } else {
      dupa.push_back(p[i]);
    }
  }
  for (size_t i = 0; i < stracksa.size(); i++) {
    if (std::find(dupa.begin(), dupa.end(), i) == dupa.end()) {
      resa.push_back(stracksa[i]);
    }
  }
  for (size_t i = 0; i < stracksb.size(); i++) {
    if (std::find(dupb.begin(), dupb.end(), i) == dupb.end()) {
      resb.push_back(stracksb[i]);
    }
  }
  stracksa = resa;
  stracksb = resb;
}
std::vector<STack *> FairmotMindsporePost::SubStracks(
    std::vector<STack *> tlista, std::vector<STack *> tlistb) {
  std::vector<STack *> res;
  std::map<size_t, STack *> stracks;
  std::map<size_t, STack *>::iterator it;
  std::vector<size_t> key;
  std::vector<size_t> del_key;
  for (size_t t = 0; t < tlista.size(); t++) {
    key.push_back((*tlista[t]).track_id);
    stracks[(*tlista[t]).track_id] = tlista[t];
  }
  for (size_t t = 0; t < tlistb.size(); t++) {
    int tid = (*tlistb[t]).track_id;
    it = stracks.find(tid);
    if (it != stracks.end()) {
      del_key.push_back(tid);
      stracks.erase(it);
    }
  }
  for (size_t i = 0; i < key.size(); i++) {
    bool flag = false;
    for (size_t j = 0; j < del_key.size(); j++) {
      if (del_key[j] == key[i]) {
        flag = true;
      }
      if (flag == true) {
        break;
      }
    }
    if (flag == false) {
      res.push_back(stracks[key[i]]);
    }
  }
  return res;
}
cv::Mat FairmotMindsporePost::BboxOverlaps(std::vector<cv::Mat> boxes,
                                           std::vector<cv::Mat> query_boxes) {
  int N = boxes.size();
  int K = query_boxes.size();
  cv::Mat overlaps = cv::Mat::zeros(N, K, CV_64FC1);
  for (size_t k = 0; k < K; k++) {
    double box_area =
        (query_boxes[k].at<double>(0, 2) - query_boxes[k].at<double>(0, 0) +
         1) *
        (query_boxes[k].at<double>(0, 3) - query_boxes[k].at<double>(0, 1) + 1);
    for (size_t n = 0; n < N; n++) {
      double iw =
          std::min(boxes[n].at<double>(0, 2), query_boxes[k].at<double>(0, 2)) -
          std::max(boxes[n].at<double>(0, 0), query_boxes[k].at<double>(0, 0)) +
          1;
      if (iw > 0) {
        double ih = std::min(boxes[n].at<double>(0, 3),
                             query_boxes[k].at<double>(0, 3)) -
                    std::max(boxes[n].at<double>(0, 1),
                             query_boxes[k].at<double>(0, 1)) +
                    1;
        if (ih > 0) {
          double ua = static_cast<double>(
              (boxes[n].at<double>(0, 2) - boxes[n].at<double>(0, 0) + 1) *
                  (boxes[n].at<double>(0, 3) - boxes[n].at<double>(0, 1) + 1) +
              box_area - iw * ih);
          overlaps.at<double>(n, k) = iw * ih / ua;
        }
      }
    }
  }
  return overlaps;
}
cv::Mat FairmotMindsporePost::IouDistance(std::vector<STack *> atracks,
                                          std::vector<STack *> btracks) {
  std::vector<cv::Mat> atlbrs;
  std::vector<cv::Mat> btlbrs;
  cv::Mat cost_matrix;
  for (size_t i = 0; i < atracks.size(); i++) {
    atlbrs.push_back((*atracks[i]).tlbr());
  }
  for (size_t i = 0; i < btracks.size(); i++) {
    btlbrs.push_back((*btracks[i]).tlbr());
  }
  cv::Mat ious = cv::Mat::zeros(atlbrs.size(), btlbrs.size(), CV_64FC1);
  if (!ious.empty()) {
    ious = BboxOverlaps(atlbrs, btlbrs);
    cost_matrix = 1 - ious;
  } else {
    cost_matrix = cv::Mat::zeros(atlbrs.size(), btlbrs.size(), CV_64FC1);
  }
  return cost_matrix;
}
void FairmotMindsporePost::MultiPredict(std::vector<STack *> &stracks) {
  if (stracks.size() > 0) {
    cv::Mat multi_mean(stracks.size(), (*stracks[0]).mean.cols, CV_64FC1);
    std::vector<cv::Mat> multi_covariance;
    for (size_t i = 0; i < stracks.size(); i++) {
      multi_mean.row(i) = (*stracks[i]).mean.clone() + 0;
      multi_covariance.push_back((*stracks[i]).covariance);
    }
    for (size_t i = 0; i < stracks.size(); i++) {
      if ((*stracks[i]).state != TrackState_Tracked) {
        multi_mean.at<double>(i, 7) = 0;
      }
    }
    kalmanfilter.multi_predict(multi_mean, multi_covariance);
    for (size_t i = 0; i < multi_covariance.size(); i++) {
      (*stracks[i]).mean = multi_mean.row(i);
      (*stracks[i]).covariance = multi_covariance[i];
    }
  }
}

std::vector<STack *> FairmotMindsporePost::Get_output_stracks(
    MxBase::JDETracker &tracker, const std::vector<STack *> &activated_starcks,
    const std::vector<STack *> &refind_stracks,
    std::vector<STack *> lost_stracks, std::vector<STack *> removed_stracks) {
  std::vector<STack *> det_tmp;
  for (size_t i = 0; i < tracker.tracked_stracks.size(); i++) {
    if ((*tracker.tracked_stracks[i]).state == TrackState_Tracked) {
      det_tmp.push_back(tracker.tracked_stracks[i]);
    }
  }
  std::vector<STack *>().swap(tracker.tracked_stracks);
  tracker.tracked_stracks = det_tmp;
  std::vector<STack *>().swap(det_tmp);
  tracker.tracked_stracks =
      JointStracks(tracker.tracked_stracks, activated_starcks);
  tracker.tracked_stracks =
      JointStracks(tracker.tracked_stracks, refind_stracks);
  tracker.lost_stracks =
      SubStracks(tracker.lost_stracks, tracker.tracked_stracks);
  for (size_t i = 0; i < lost_stracks.size(); i++) {
    tracker.lost_stracks.push_back(lost_stracks[i]);
  }
  tracker.lost_stracks =
      SubStracks(tracker.lost_stracks, tracker.removed_stracks);
  for (size_t i = 0; i < removed_stracks.size(); i++) {
    tracker.removed_stracks.push_back(removed_stracks[i]);
  }
  std::vector<STack *> output_stracks;
  RemoveDuplicateStracks(tracker.tracked_stracks, tracker.lost_stracks);
  // get scores of lost tracks
  for (size_t i = 0; i < tracker.tracked_stracks.size(); i++) {
    if ((*tracker.tracked_stracks[i]).is_activated) {
      output_stracks.push_back(tracker.tracked_stracks[i]);
    }
  }
  return output_stracks;
}

void FairmotMindsporePost::Get_detections(cv::Mat det,
                                          std::vector<STack *> &detections,
                                          cv::Mat id_feature) {
  if (det.rows > 0) {
    cv::Mat det_tmp = det(cv::Range(0, det.rows), cv::Range(0, 5)).clone();
    for (size_t x = 0; x < det.rows; ++x) {
      cv::Mat tlbrs = det_tmp.row(x);
      cv::Mat f = id_feature.row(x);
      cv::Mat ret = tlbrs(cv::Range(0, tlbrs.rows), cv::Range(0, 4));
      for (size_t y = 0; y < 2; ++y) {
        ret.at<float>(0, y + 2) -= ret.at<float>(0, y);
      }
      STack *stack = new STack(ret, tlbrs.at<float>(0, 4), f, 30);
      detections.push_back(stack);
    }
  }
}

void FairmotMindsporePost::Get_dists(cv::Mat &dists,
                                     std::vector<STack *> &detections,
                                     std::vector<STack *> &strack_pool) {
  if (dists.rows != 0) {
    cv::Mat det_features(detections.size(), (*detections[0]).curr_feat.cols,
                         CV_32FC1);
    cv::Mat track_features(strack_pool.size(),
                           (*strack_pool[0]).smooth_feat.cols, CV_32FC1);
    for (size_t i = 0; i < detections.size(); i++)
      det_features.row(i) = (*detections[i]).curr_feat + 0;
    det_features.convertTo(det_features, CV_64F);
    for (size_t i = 0; i < strack_pool.size(); i++)
      track_features.row(i) = (*strack_pool[i]).smooth_feat + 0;
    track_features.convertTo(track_features, CV_64F);
    // cv::Mat cdist(track_features.rows, det_features.rows, CV_64FC1);
    for (size_t i = 0; i < dists.rows; i++)
      for (size_t j = 0; j < dists.cols; j++) {
        cv::normalize(det_features.row(j), det_features.row(j));
        cv::normalize(track_features.row(i), track_features.row(i));
        dists.at<double>(i, j) =
            1 - track_features.row(i).dot(det_features.row(j));
      }
  }
}

void FairmotMindsporePost::Update_Starcks(
    const std::vector<STack *> &strack_pool, std::vector<STack *> &detections,
    const cv::Mat &matches, std::vector<STack *> &activated_starcks,
    std::vector<STack *> &refind_stracks, const MxBase::JDETracker &tracker) {
  for (size_t i = 0; i < matches.rows; i++) {
    STack *track = strack_pool[matches.at<float>(i, 0)];
    STack *dets = detections[matches.at<float>(i, 1)];
    if ((*track).state == TrackState_Tracked) {
      (*track).update((*detections[matches.at<float>(i, 1)]), tracker.frame_id);
      activated_starcks.push_back(track);
    } else {
      (*track).re_activate(*dets, tracker.frame_id, false);
      refind_stracks.push_back(track);
    }
  }
}

std::vector<STack *> FairmotMindsporePost::ObjectDetectionOutput(
    const std::vector<TensorBase> &tensors, MxBase::JDETracker &tracker) {
  tracker.frame_id += 1;
  cv::Mat id_feature, det, matches, u_track, u_detection, u_unconfirmed, dists;
  std::vector<STack *> activated_starcks, refind_stracks, lost_stracks,
      removed_stracks, detections, unconfirmed, tracked_stracks, det_tmp,
      r_tracked_stracks, output_stracks, strack_pool;
  TensorBaseToCVMat(det, tensors[1]);
  TensorBaseToCVMat(id_feature, tensors[0]);
  PostProcess(det, tracker);
  cv::Mat scores = det(cv::Range(0, det.rows), cv::Range(4, 5));
  cv::Mat new_det(0, det.cols, CV_32FC1), new_id(0, id_feature.cols, CV_32FC1);
  for (size_t x = 0; x < det.rows; ++x) {
    if (det.at<float>(x, 4) > CONF_THRES) {
      new_det.push_back(det.row(x));
      new_id.push_back(id_feature.row(x));
    }
  }
  det = new_det;
  id_feature = new_id;
  Get_detections(det, detections, id_feature);
  for (size_t i = 0; i < tracker.tracked_stracks.size(); i++)
    if (!(*tracker.tracked_stracks[i]).is_activated)
      unconfirmed.push_back(tracker.tracked_stracks[i]);
    else
      tracked_stracks.push_back(tracker.tracked_stracks[i]);
  strack_pool = JointStracks(tracked_stracks, tracker.lost_stracks);
  MultiPredict(strack_pool);
  dists = cv::Mat::zeros(strack_pool.size(), detections.size(), CV_64FC1);
  Get_dists(dists, detections, strack_pool);
  FuseMotion(tracker.kalman_filter, dists, strack_pool, detections);
  std::vector<cv::Mat> results;
  results = LinearAssignment(dists, 0.4);
  matches = results[0];
  u_track = results[1];
  u_detection = results[2];
  Update_Starcks(strack_pool, detections, matches, activated_starcks,
                 refind_stracks, tracker);
  for (size_t i = 0; i < u_detection.cols; ++i)
    det_tmp.push_back(
        detections[static_cast<int>(u_detection.at<float>(0, i))]);
  detections = det_tmp;
  std::vector<STack *>().swap(det_tmp);
  for (size_t i = 0; i < u_track.cols; ++i)
    if ((*strack_pool[u_track.at<float>(0, i)]).state == TrackState_Tracked)
      r_tracked_stracks.push_back(strack_pool[u_track.at<float>(0, i)]);
  dists = IouDistance(r_tracked_stracks, detections);
  results = LinearAssignment(dists, 0.5);
  matches = results[0];
  u_track = results[1];
  u_detection = results[2];
  Update_Starcks(r_tracked_stracks, detections, matches, activated_starcks,
                 refind_stracks, tracker);
  for (size_t i = 0; i < u_track.cols; i++) {
    STack *track = r_tracked_stracks[u_track.at<float>(0, i)];
    if ((*track).state != TrackState_Lost) {
      (*track).state = TrackState_Lost;
      lost_stracks.push_back(track);
    }
  }
  for (size_t i = 0; i < u_detection.cols; ++i)
    det_tmp.push_back(
        detections[static_cast<int>(u_detection.at<float>(0, i))]);
  detections = det_tmp;
  std::vector<STack *>().swap(det_tmp);
  dists = IouDistance(unconfirmed, detections);
  results = LinearAssignment(dists, 0.7);
  matches = results[0];
  u_unconfirmed = results[1];
  u_detection = results[2];
  for (size_t i = 0; i < matches.rows; i++) {
    (*unconfirmed[matches.at<float>(i, 0)])
        .update((*detections[matches.at<float>(i, 1)]), tracker.frame_id);
    activated_starcks.push_back(unconfirmed[matches.at<float>(i, 0)]);
  }
  for (size_t i = 0; i < u_unconfirmed.cols; i++) {
    STack *track = unconfirmed[u_unconfirmed.at<float>(0, i)];
    (*track).state = TrackState_Removed;
    removed_stracks.push_back(track);
  }
  for (int j = 0; j < u_detection.cols; j++) {
    auto inew = u_detection.at<float>(0, j);
    STack *track = detections[inew];
    if ((*track).score < tracker.det_thresh) continue;
    (*track).activate(tracker.kalman_filter, tracker.frame_id);
    activated_starcks.push_back(track);
  }
  for (size_t i = 0; i < tracker.lost_stracks.size(); i++) {
    if (tracker.frame_id - (*tracker.lost_stracks[i]).frame_id >
        tracker.max_time_lost) {
      (*tracker.lost_stracks[i]).state = TrackState_Removed;
      removed_stracks.push_back(tracker.lost_stracks[i]);
    }
  }
  output_stracks =
      Get_output_stracks(tracker, activated_starcks, refind_stracks,
                         lost_stracks, removed_stracks);
  return output_stracks;
}

APP_ERROR FairmotMindsporePost::Process(const std::vector<TensorBase> &tensors,
                                        MxBase::JDETracker &tracker,
                                        MxBase::Files &file) {
  LogDebug << "Begin to process FairmotMindsporePost.";
  auto inputs = tensors;
  APP_ERROR ret = CheckAndMoveTensors(inputs);
  if (ret != APP_ERR_OK) {
    LogError << "CheckAndMoveTensors failed, ret=" << ret;
    return ret;
  }
  std::vector<STack *> online_targets;
  online_targets = ObjectDetectionOutput(inputs, tracker);
  std::vector<cv::Mat> online_tlwhs;
  std::vector<int> online_ids;
  for (size_t i = 0; i < online_targets.size(); i++) {
    cv::Mat tlwh = (*online_targets[i]).gettlwh();
    int tid = (*online_targets[i]).track_id;
    double tmp = tlwh.at<double>(0, 2) / tlwh.at<double>(0, 3);
    bool vertical = false;
    if (tmp > 1.6) {
      vertical = true;
    }
    if ((tlwh.at<double>(0, 2) * tlwh.at<double>(0, 3) > MIN_BOX_AREA) &&
        vertical == false) {
      online_tlwhs.push_back(tlwh);
      online_ids.push_back(tid);
    }
  }
  Results *result = new Results(file.frame_id + 1, online_tlwhs, online_ids);
  file.results.push_back(result);
  file.frame_id += 1;
  LogInfo << "End to process FairmotMindsporePost.";
  return APP_ERR_OK;
}

extern "C" {
std::shared_ptr<MxBase::FairmotMindsporePost> GetObjectInstance() {
  LogInfo << "Begin to get FairmotMindsporePost instance.";
  auto instance = std::make_shared<FairmotMindsporePost>();
  LogInfo << "End to get FairmotMindsporePost Instance";
  return instance;
}
}

}  // namespace MxBase

max_stars_repo_name: leelige/mindspore

max_issues_repo_name: leelige/mindspore

max_forks_repo_name: leelige/mindspore


text:
#ifdef WIN32
#pragma warning( disable : 4786)
#endif

#ifndef _WIN32
    #include <stdio.h>
#endif

#include "../common/RDMUtils.h"
#include "../common/RDMDict.h"
#include "OMMInteractiveProvider.h"

#include <boost/lexical_cast.hpp>

#define DICT_ID    1
#define FIELD_LIST_ID 3

OMMInteractiveProvider::OMMInteractiveProvider(rfa::sessionLayer::OMMProvider* pOMMProvider,
                                               const std::string& vendorName,
                                               const std::string& serviceName,
                                               rfa::common::RFA_String fieldDictionaryFilename,
                                               rfa::common::RFA_String enumTypeFilename,
                                               const RDMFieldDict* dict,
                                               rfa::logger::ComponentLogger& componentLogger):
    _pOMMProvider(pOMMProvider),
    _vendorName(vendorName.c_str()),
    _serviceName(serviceName.c_str()),
    _serviceState(1),
    _debug(false),
    _pLoginToken(0),
    _pDirectoryToken(0),
    _rRDMFieldDictionary(rfa::rdm::RDMFieldDictionary::create()),
    _bDictionaryDataRead(false),
    _pDict(dict),
    _componentLogger(componentLogger)
{
    if(_bDictionaryDataRead == false)
	{
		_rRDMFieldDictionary.readRDMFieldDictionary(fieldDictionaryFilename);
		_rRDMFieldDictionary.readRDMEnumTypeDef(enumTypeFilename);
		_rRDMFieldDictionary.setDictId(1);
		_bDictionaryDataRead = true;
	}
}

OMMInteractiveProvider::~OMMInteractiveProvider()
{
    cleanup();
}

void OMMInteractiveProvider::processPostMsg(const rfa::sessionLayer::OMMSolicitedItemEvent& event) {
    const rfa::message::PostMsg& postMsg = static_cast<const rfa::message::PostMsg&>(event.getMsg());
	rfa::sessionLayer::RequestToken& rToken = event.getRequestToken();
	rfa::common::Handle* pCSH = event.getHandle();
	UInt8 hintMask = postMsg.getHintMask();
	UInt8 indicationMask = postMsg.getIndicationMask();

	//RFA_String text( "<- Received PostMsg ", 0, false);
    _log = "[OMMInteractiveProvider::processPostMsg] Received PostMsg";

	// Get Visible Publisher Identity that sent the post message:
	const PrincipalIdentity& ppi = postMsg.getPrincipalIdentity();
	if ( ppi.getIdentityType() == PublisherPrincipalIdentityEnum )
	{
		const PublisherPrincipalIdentity& ppId = static_cast<const PublisherPrincipalIdentity&>(ppi);
		UInt32 userAddress = ppId.getUserAddress();
		UInt32 userID = ppId.getUserID();
		_log += " with publisher [user ID: ";
		_log.append(userID);
		_log.append("] at [user address: " );
		_log.append( userAddress );
		_log.append( "] " );
	}
	//text += "from Client Session Handle:";
	//AppUtil::log(__LINE__, AppUtil::TRACE, "%s %p", text.c_str(), pCSH);

	ClientWatchList* cwl = _providerWatchList.getClientWatchList(pCSH);
	ClientWatchList::TokenInfo* pTS = cwl->getTokenInfo(&rToken);

	//Populate attribInfo of the response message according to the following rule:
	//1) If this is off-stream post message (matches login request token),
	//   then get attribInfo from the post message; it MUST be there!
	//2) If this is on-stream post message (matches item request token),
	//   then get it from the TokenInfo which contains attribInfo received
	//   with this items request; attribInfo may or may not be on the post message
	//   since it is not needed (it may be optimized out by consumer app)
	rfa::message::AttribInfo ai;

	if(pTS->bItemRequest)
	{
		ai = pTS->attribInfo;
	}
	else
	{
		assert(hintMask & PostMsg::AttribInfoFlag);
		ai = postMsg.getAttribInfo();
	}

	// If the hint mask on the PostMsg has PostMsg::PermissionDataFlag set,
	// then the permission data included in the PostMsg is obtained by PostMsg::getPermissionData() method
	// which is used to permission the user that is posting the information.

	UInt32 postID = 0;
	bool bPostIdSet = false;
	if(hintMask & PostMsg::PostIdFlag)
	{
		bPostIdSet = true;
		postID = postMsg.getPostID();
	}

	UInt32 sequenceNum = 0;
	bool bSequenceNumSet = false;
	if(hintMask & PostMsg::SeqFlag)
	{
		bSequenceNumSet = true;
		sequenceNum = postMsg.getSeqNum();
	}

	bool bWantAck = (indicationMask & PostMsg::WantAckFlag) ? true : false;
	if(bWantAck)
	{
		rfa::common::RFA_String text;
		//if(_cfgVars.bIgnoreNackCode)
        text.append("Positive AckMsg");
		//else
		//	text.append("AccessDenied");

		submitAckMsg(&rToken, pCSH, bPostIdSet, postID, bSequenceNumSet, sequenceNum,
		             false, AckMsg::AccessDenied, text, postMsg.getMsgModelType());
	}

	//Re-send this post to all clients that subscribed to this item
	//But only if the postMsg's payload is a response message
	if(hintMask & PostMsg::PayloadFlag)
	{
		const Data& payload = postMsg.getPayload();
		if(MsgEnum == payload.getDataType())
		{
			UInt8 msgMMT = postMsg.getMsgModelType();
			const Msg& msg = static_cast<const Msg&>(payload);
			UInt8 payloadMMT = msg.getMsgModelType();
			if(RespMsgEnum == msg.getMsgType() && msgMMT == payloadMMT)
			{
				const RespMsg& respMsg = static_cast<const RespMsg&>(msg);
				RespMsg& ncRespMsg = const_cast<RespMsg&>(respMsg);

				ProviderWatchList::TOKENS requestTokens;
				ProviderWatchList::CLIENT_SESSIONS clientSessions;

				_providerWatchList.findTokens(ai.getName(), msgMMT, requestTokens, clientSessions);
				submitPostedData(ncRespMsg, ppi, ai.getServiceName(), requestTokens, clientSessions);
			}
		}
		//_pDecoder->decodeData(payload);
	}
}

void OMMInteractiveProvider::submitAckMsg(rfa::sessionLayer::RequestToken* pRT,
                                          Handle* pCSH,
                                          bool postIdSet,
                                          UInt32 ackID,
                                          bool sequenceNumSet,
                                          UInt32 sequenceNum,
                                          bool nackCodeSet,
                                          rfa::message::AckMsg::NackCode nackCode,
                                          const RFA_String& text, UInt8 msgModelType)
{
	rfa::message::AckMsg ackMsg;
	ackMsg.setAckID(ackID);

	//Client app is required to set msg Model type of the posted  message.
	ackMsg.setMsgModelType(msgModelType);
	if(sequenceNumSet) ackMsg.setSeqNum(sequenceNum);
	if(nackCodeSet)    ackMsg.setNackCode(nackCode);
	if(!text.empty())  ackMsg.setText(text);

	ackMsg.setAssociatedMetaInfo(*pCSH);

	rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
	itemCmd.setMsg(ackMsg);
	itemCmd.setRequestToken(*pRT);
	_pOMMProvider->submit(&itemCmd);
}

void OMMInteractiveProvider::submitPostedData(RespMsg& respMsg,
                                              const PrincipalIdentity& ppi,
                                              const RFA_String& serviceName,
                                              ProviderWatchList::TOKENS& requestTokens,
                                              ProviderWatchList::CLIENT_SESSIONS& clientSessions)
{
	//This code "trusts" the consumer that encoded this respMsg in its post message
	//the only things that need to be done are:
	//1) addition of the "missing serviceName on respMsg's attribInfo
	//2) addition of the publisherPrincipalIdentity received on PostMsg
	//   overwrites any publisherPrincipalIdentity that was there on the respMsg.
	//3) versioning information
	if(respMsg.getHintMask() & RespMsg::AttribInfoFlag)
	{
		AttribInfo& ai = const_cast<AttribInfo&>(respMsg.getAttribInfo());
		ai.setServiceName(serviceName);
	}
	respMsg.setPrincipalIdentity(ppi);

	//Now loop thru all the request tokens opened for this item and submit this message
	rfa::sessionLayer::OMMSolicitedItemCmd cmd;
	cmd.setMsg(respMsg);
	for(unsigned int pos = 0; pos < requestTokens.size(); pos++)
	{
		//Versioning for each connection
		respMsg.setAssociatedMetaInfo(*clientSessions[pos]);
		cmd.setRequestToken(*requestTokens[pos]);
		_pOMMProvider->submit(&cmd);
	}
}

void OMMInteractiveProvider::processReqMsg(const rfa::sessionLayer::OMMSolicitedItemEvent& event, boost::python::tuple& out) {
    const rfa::message::ReqMsg& msg = static_cast<const rfa::message::ReqMsg&>(event.getMsg());
	if(!(msg.getInteractionType() & rfa::message::ReqMsg::InitialImageFlag) && !(msg.getInteractionType() & rfa::message::ReqMsg::InterestAfterRefreshFlag)) {
		_log = "[OMMInteractiveProvider::processReqMsg] Received close item request (";
        processCloseReq(event, out);
        _log += ")";
        if (_debug) {
            _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());
            printClientWatchlists();
        }
		return;
	}
    _log = "[OMMInteractiveProvider::processReqMsg] Received ";
	switch(msg.getMsgModelType())
	{
        case rfa::rdm::MMT_LOGIN:
            _log += "MMT_LOGIN request (";
            _log += msg.getAttribInfo().getName();
            _log += ")";
			processLoginReq(event, out);
			break;
        case rfa::rdm::MMT_DIRECTORY:
            _log += "MMT_DIRECTORY request";
			processDirectoryReq(event);
			break;
        case rfa::rdm::MMT_DICTIONARY:
            _log += "MMT_DICTIONARY request (";
            _log += msg.getAttribInfo().getName();
            _log += ")";
			processDictionaryReq(event);
			break;
        case rfa::rdm::MMT_MARKET_PRICE:
            _log += "MMT_MARKET_PRICE request (";
            _log += msg.getAttribInfo().getName();
            _log += ")";
            processMarketPriceReq(event, out);
			break;
		default:
            _log += "request with unknown msgModelType ";
            _log.append(msg.getMsgModelType());
			break;
	}
    if (_debug) {
        _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());
        printClientWatchlists();
    }
}

//This application may choose to deny a login request by sending a Status RespMsg with the RespState.StreamState of Closed.
//This application may force a logoff at any time by sending a Status RespMsg with a Closed StreamState.
void OMMInteractiveProvider::processLoginReq(const rfa::sessionLayer::OMMSolicitedItemEvent& event, boost::python::tuple& out) {
    dict d;
    const rfa::message::ReqMsg& reqMsg = static_cast<const rfa::message::ReqMsg&>(event.getMsg());
	_pLoginToken = &event.getRequestToken();
	rfa::common::Handle* pCSH = event.getHandle();
	//AppUtil::log(__LINE__, AppUtil::INFO, "<- Received MMT_LOGIN Request token: %p handle: %p", _pLoginToken, pCSH);

	_providerWatchListLock.lock();
	ClientWatchList* cwl = _providerWatchList.getClientWatchList(pCSH);
	cwl->addToken(_pLoginToken, reqMsg, false);
	_providerWatchListLock.unlock();
	//if ( _cfgVars.bDisplayTables ) displayTables();

	//Login request message must contain attribInfo
	assert( reqMsg.getHintMask() & ReqMsg::AttribInfoFlag );

	//Decode and print AttribInfo Attribs for the login request
	//This section can be elaborated to extract credentials and authenticate as desired before continuing.
	//For now, just print what is in the attrib and accept login.
	//if(reqMsg.getAttribInfo().getHintMask() & AttribInfo::AttribFlag)
	//{
	//	const Data& data = reqMsg.getAttribInfo().getAttrib();
	//	_pDecoder->decodeData(data);
	//}

    rfa::message::RespMsg respMsg;
	rfa::common::RespStatus rStatus;
	rStatus.setStreamState(RespStatus::OpenEnum);
	rStatus.setDataState(RespStatus::OkEnum);
	rStatus.setStatusCode(RespStatus::NoneEnum);
	rfa::common::RFA_String text("Refresh Completed", 0, false);
	rStatus.setStatusText(text);

	const rfa::message::AttribInfo& reqAI = reqMsg.getAttribInfo();
	rfa::message::AttribInfo respAI;
	rfa::data::ElementList reencodedAttrInfo;
	_encoder.reencodeAttribs( reqAI.getAttrib(), reencodedAttrInfo, Encoder::SUPPORT_POST_FLAG );
	respAI.setAttrib( reencodedAttrInfo );

	if ( reqAI.getHintMask() & AttribInfo::NameFlag )
		respAI.setName( reqAI.getName() );

	if ( reqAI.getHintMask() & AttribInfo::NameTypeFlag )
		respAI.setNameType( reqAI.getNameType() );

    _encoder.encodeLoginMsg( &respMsg, respAI, rStatus );

	rfa::sessionLayer::OMMSolicitedItemCmd loginCmd;
	loginCmd.setMsg(respMsg);

	//This request token generally should be saved for future possible logouts
	loginCmd.setRequestToken(*_pLoginToken);
	//submitCmd(&loginCmd, 0, "MMT_LOGIN Refresh");
    _pOMMProvider->submit(&loginCmd);

    d["MTYPE"] = "LOGIN";
    d["USERNAME"] = reqAI.getName().c_str();
    d["SERVICE"] = _serviceName.c_str();
    d["SESSIONID"] = boost::lexical_cast<std::string>(reinterpret_cast<unsigned long>(pCSH));
    out += boost::python::make_tuple(d);
}

void OMMInteractiveProvider::processDirectoryReq(const rfa::sessionLayer::OMMSolicitedItemEvent& event) {
    const rfa::message::ReqMsg& reqMsg = static_cast<const rfa::message::ReqMsg&>(event.getMsg());
	//rfa::sessionLayer::RequestToken& rToken = event.getRequestToken();
	//const rfa::common::Handle* pCSH = rToken.getHandle();
    _pDirectoryToken = &event.getRequestToken();
	rfa::common::Handle* pCSH = event.getHandle();

	//The DataMask in the AttribInfo could be checked here to find out if there was a specific part of the directory that is requested.
	//(SERVICE_INFO_FILTER, SERVICE_STATE_FILTER, etc...)
	//For this example this is disregarded and the whole directory will be sent.
	//rfa::common::UInt8 requestedDataMask =  reqMsg.getAttribInfo().getDataMask();

	//The serviceName from the AttribInfo could be checked here to see if the consumer is requesting a particular servicname for the directory.
	//For this example this is disregarded and the whole directory will be sent.
	//RFA_String requestedServiceName = reqMsg.getAttribInfo().getServiceName();

	rfa::common::RespStatus rStatus;
	rStatus.setStreamState(RespStatus::OpenEnum);
	rStatus.setDataState(RespStatus::OkEnum);
	rStatus.setStatusCode(RespStatus::NoneEnum);
	rfa::common::RFA_String text("Refresh Completed");
	rStatus.setStatusText(text);

    //Add capability
    _encoder.setDomainModelType(6); //MMT_MARKET_PRICE

	rfa::message::RespMsg respMsg;
	_encoder.encodeDirectoryMsg(&respMsg, reqMsg.getAttribInfo(), rStatus);

	Map dataBody;
	QualityOfService QoS;
	QoS.setRate(QualityOfService::tickByTick);
	QoS.setTimeliness(QualityOfService::realTime);
	if(pCSH)
		dataBody.setAssociatedMetaInfo(*pCSH);
	_encoder.encodeDirectoryDataBody(&dataBody, _serviceName, _vendorName, _serviceState, &QoS);
	respMsg.setPayload(dataBody);

	rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
	itemCmd.setMsg(static_cast<rfa::common::Msg&>(respMsg));

	//This request token generally should be saved for future possible logouts
	//itemCmd.setRequestToken(rToken);
    itemCmd.setRequestToken(*_pDirectoryToken);
	//submitCmd(&itemCmd, 0, "MMT_DIRECTORY Refresh");
    _pOMMProvider->submit(&itemCmd);
}

void OMMInteractiveProvider::processDictionaryReq(const rfa::sessionLayer::OMMSolicitedItemEvent& event) {
    const rfa::message::ReqMsg& reqMsg = static_cast<const rfa::message::ReqMsg&>(event.getMsg());
	rfa::sessionLayer::RequestToken& rToken = event.getRequestToken();
	//const rfa::common::Handle* pCSH = rToken.getHandle();

	UInt8 verbosity = rfa::rdm::DICTIONARY_NORMAL;
	if((reqMsg.getAttribInfo().getHintMask() & AttribInfo::DataMaskFlag))
		verbosity = reqMsg.getAttribInfo().getDataMask();

	const rfa::common::Handle* handle = event.getRequestToken().getHandle();

	rfa::common::UInt8 indicationMask = 0;
	bool complete = false;

	if(reqMsg.getAttribInfo().getName()== "RWFFld")
	{
		do {

			rfa::message::RespMsg respMsg;
			Series dictionaryBody;
			rfa::common::RespStatus rStatus;
			rStatus.setStreamState(RespStatus::OpenEnum);
			rStatus.setDataState(RespStatus::OkEnum);
			rStatus.setStatusCode(RespStatus::NoneEnum);

			if(handle)
				dictionaryBody.setAssociatedMetaInfo(*handle);
			complete = _rRDMFieldDictionary.encodeRDMFieldDictionary(dictionaryBody, verbosity, false);
			if(complete)
			{
				indicationMask = respMsg.getIndicationMask() | RespMsg::RefreshCompleteFlag;
				rStatus.setStatusText(RFA_String("Refresh Completed", 0, false));
			}
			else
			{
				indicationMask = respMsg.getIndicationMask();
				rStatus.setStatusText(RFA_String("", 0, false));
			}
			_encoder.encodeDictionaryMsg(&respMsg, reqMsg.getAttribInfo(), rStatus, indicationMask);
			respMsg.setPayload(dictionaryBody);

			rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
			itemCmd.setMsg(static_cast<rfa::common::Msg&>(respMsg));
			itemCmd.setRequestToken(rToken);
			//submitCmd(&itemCmd, 0, "MMT_DICTIONARY Refresh");
            _pOMMProvider->submit(&itemCmd);
		} while(!complete);
	}
	else if(reqMsg.getAttribInfo().getName()== "RWFEnum")
	{
		//int numFrag = 0;
		do {

			rfa::message::RespMsg respMsg;
			Series dictionaryBody;
			rfa::common::RespStatus rStatus;
			rStatus.setStreamState(RespStatus::OpenEnum);
			rStatus.setDataState(RespStatus::OkEnum);
			rStatus.setStatusCode(RespStatus::NoneEnum);

			if(handle)
				dictionaryBody.setAssociatedMetaInfo(*handle);
			complete = _rRDMFieldDictionary.encodeRDMEnumDictionary(dictionaryBody, verbosity, false);
			if(complete)
			{
				indicationMask = respMsg.getIndicationMask() | RespMsg::RefreshCompleteFlag;
				rStatus.setStatusText(RFA_String("Refresh Completed", 0, false));
			}
			else
			{
				indicationMask = respMsg.getIndicationMask();
				rStatus.setStatusText(RFA_String("", 0, false));
			}
			_encoder.encodeDictionaryMsg(&respMsg, reqMsg.getAttribInfo(), rStatus, indicationMask);
			respMsg.setPayload(dictionaryBody);

			rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
			itemCmd.setMsg(static_cast<rfa::common::Msg&>(respMsg));
			itemCmd.setRequestToken(rToken);

			//submitCmd(&itemCmd, 0, "MMT_DICTIONARY Refresh");
            _pOMMProvider->submit(&itemCmd);
		} while(!complete);
	}
}

void OMMInteractiveProvider::processMarketPriceReq(const rfa::sessionLayer::OMMSolicitedItemEvent& event, boost::python::tuple& out) {
    dict d;
    const rfa::message::ReqMsg& reqMsg = static_cast<const rfa::message::ReqMsg&>(event.getMsg());
	rfa::sessionLayer::RequestToken& rToken = event.getRequestToken();
	const rfa::common::Handle* pCSH = rToken.getHandle();

	rfa::sessionLayer::OMMSolicitedItemCmd solItemCmd;
    _respMsg.clear();
	if ( reqMsg.getInteractionType() == (rfa::message::ReqMsg::InitialImageFlag | rfa::message::ReqMsg::InterestAfterRefreshFlag) )
	{
		_providerWatchListLock.lock();

		ClientWatchList* cwl = _providerWatchList.getClientWatchList(pCSH);

		if ( !cwl )
		{
			_providerWatchListLock.unlock();
			return;
		}

		ClientWatchList::TokenInfo* pTS = cwl->getTokenInfo(&rToken);
		if ( !pTS )
		{
			//A new streaming request, delegate submit to the timer by adding it to the watch list
			pTS = cwl->addToken(&rToken, reqMsg, true);
		}
		else
		{
			//A re-request of an already watched streaming request, submit on demand
            rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;

            _respStatus.clear();
            _respStatus.setStreamState(RespStatus::OpenEnum);
            _respStatus.setDataState(RespStatus::OkEnum);
            _respStatus.setStatusCode(RespStatus::NoneEnum);
            _respStatus.setStatusText(RFA_String("Refresh Completed", 0, false));

            _qos.setRate(QualityOfService::tickByTick);
            _qos.setTimeliness(QualityOfService::realTime);

            _encoder.encodeMarketPriceMsg(&_respMsg, RespMsg::RefreshEnum, pTS->attribInfo,  _respStatus, &_qos, true, true);

            itemCmd.setMsg(static_cast<rfa::common::Msg&>(_respMsg));
            itemCmd.setRequestToken(*pTS->pToken);

            _pOMMProvider->submit(&itemCmd);
		}
		_providerWatchListLock.unlock();

        d["MTYPE"] = "REQUEST";
        d["RIC"] = reqMsg.getAttribInfo().getName().c_str();
        d["USERNAME"] = cwl->first()->attribInfo.getName().c_str();
        d["SERVICE"] = _serviceName.c_str();
        d["SESSIONID"] = boost::lexical_cast<std::string>(reinterpret_cast<unsigned long>(pCSH));
        out += boost::python::make_tuple(d);
	}
	else if ( reqMsg.getInteractionType() & ReqMsg::InitialImageFlag )
	{
		//A snapshot request, we don't watch snapshot requests, submit on demand
        rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;

        _respStatus.clear();
        _respStatus.setStreamState(RespStatus::NonStreamingEnum);
        _respStatus.setDataState(RespStatus::OkEnum);
        _respStatus.setStatusCode(RespStatus::NoneEnum);
        _respStatus.setStatusText(RFA_String("Refresh Completed", 0, false));

        _qos.setRate(QualityOfService::tickByTick);
        _qos.setTimeliness(QualityOfService::realTime);

        _encoder.encodeMarketPriceMsg(&_respMsg, RespMsg::RefreshEnum, reqMsg.getAttribInfo(),  _respStatus, &_qos, true, true);

        itemCmd.setMsg(static_cast<rfa::common::Msg&>(_respMsg));
        itemCmd.setRequestToken(rToken);

        _pOMMProvider->submit(&itemCmd);
	}
}

void OMMInteractiveProvider::processCloseReq(const rfa::sessionLayer::OMMSolicitedItemEvent& event, boost::python::tuple& out) {
    dict d;
	rfa::sessionLayer::RequestToken& rToken = event.getRequestToken();
	rfa::common::Handle* pCSH = event.getHandle();
	ClientWatchList* cwl = _providerWatchList.getClientWatchList( pCSH );

	// make sure that the client watch list still is there
	if ( !cwl ) return;

	// make sure that token info was found
	ClientWatchList::TokenInfo* tokenInfoPtr = cwl->getTokenInfo( &rToken );

	if ( !tokenInfoPtr ) return;

	if ( tokenInfoPtr->bItemRequest )
	{
		// this is item token, just remove this token and its info from the watchlist
        _log += tokenInfoPtr->attribInfo.getName();
        d["MTYPE"] = "CLOSE";
        d["RIC"] = tokenInfoPtr->attribInfo.getName().c_str();
        d["USERNAME"] = cwl->first()->attribInfo.getName().c_str();
        d["SERVICE"] = _serviceName.c_str();
        d["SESSIONID"] = boost::lexical_cast<std::string>(reinterpret_cast<unsigned long>(pCSH));
        out += boost::python::make_tuple(d);
		cwl->removeToken( &rToken );
	}
	else
	{
		// this is login token, need to remove all item tokens associated with
		// this client session
        _log += tokenInfoPtr->attribInfo.getName();
        // remove all token in removeClientWatchList when session disconnection
		//cwl->cleanup();
	}
}

void OMMInteractiveProvider::cleanup()
{
    ProviderWatchList::CLIENT_SESSIONS clientSessions;
	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); pos++ )
	{
		_pOMMProvider->unregisterClient(const_cast<rfa::common::Handle*>(clientSessions[pos]));
	}

	_providerWatchListLock.unlock();
	_providerWatchList.cleanup();
    _rRDMFieldDictionary.destroy();
}

void OMMInteractiveProvider::directorySubmit(const UInt8 &domainType, rfa::common::RFA_String& serviceName)
{
}

void OMMInteractiveProvider::clearPublishedItemList() {
}

void OMMInteractiveProvider::submitData(const rfa::common::RFA_String& item, const rfa::common::RFA_Vector<rfa::common::RFA_String>& fieldList, int domainType, const std::string& msgType, rfa::common::RFA_String& serviceName, const std::string& session, const std::string& mapAction, const std::string& mapKey)
{
    rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
	ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
		const rfa::common::Handle* pCSH = clientSessions[pos];
        if((boost::lexical_cast<std::string>(reinterpret_cast<unsigned long>(pCSH)) != session) && session.length())
            continue;

		ClientWatchList* cwl = _providerWatchList.getClientWatchList( pCSH );

		if(!cwl || !cwl->first()) continue;

		ClientWatchList::TokenInfo* pTS = cwl->first();
		while(pTS)
		{
			if(pTS->bItemRequest && (pTS->attribInfo.getName() == item))//Need to skip login request token
			{
				//rfa::common::RFA_String reason("Solicited");
				//reason += " MMT_MARKET_PRICE ";
				//rfa::common::RespStatus status;
                _respMsg.clear();
				if(!pTS->bSubmitted || msgType == "image")
				{
                    _respStatus.clear();
                    _respStatus.setStreamState(RespStatus::OpenEnum);
                    _respStatus.setDataState(RespStatus::OkEnum);
                    _respStatus.setStatusCode(RespStatus::NoneEnum);
                    _respStatus.setStatusText(RFA_String("Refresh Completed", 0, false));

                    _qos.setRate(QualityOfService::tickByTick);
                    _qos.setTimeliness(QualityOfService::realTime);

                    _encoder.encodeMarketPriceMsg(&_respMsg, RespMsg::RefreshEnum, pTS->attribInfo,  _respStatus, &_qos, true, true);
                    _encoder.encodeMarketPriceDataBody(&_fieldList, RespMsg::RefreshEnum, fieldList, _pDict);
                    _respMsg.setPayload(_fieldList);

                    itemCmd.setMsg(static_cast<rfa::common::Msg&>(_respMsg));
					itemCmd.setRequestToken(*pTS->pToken);

                    _pOMMProvider->submit(&itemCmd);
					pTS->bSubmitted = true;
                    break;
				}
				else
				{
                    _encoder.encodeMarketPriceMsg(&_respMsg, RespMsg::UpdateEnum, pTS->attribInfo,  _respStatus, &_qos, pTS->bAttribInfoInUpdates, true);
                    _encoder.encodeMarketPriceDataBody(&_fieldList, RespMsg::RefreshEnum, fieldList, _pDict);
                    _respMsg.setPayload(_fieldList);
					itemCmd.setMsg(static_cast<rfa::common::Msg&>(_respMsg));
					itemCmd.setRequestToken(*pTS->pToken);
                    _pOMMProvider->submit(&itemCmd);
                    break;
				}
			}
			pTS = cwl->next(pTS->pToken);
		}
	}

	_providerWatchListLock.unlock();
}

void OMMInteractiveProvider::closeSubmit(const rfa::common::RFA_String& item, const std::string& session) {
    rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
	ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
		const rfa::common::Handle* pCSH = clientSessions[pos];
        if((boost::lexical_cast<std::string>(reinterpret_cast<unsigned long>(pCSH)) != session) && session.length())
            continue;

		ClientWatchList* cwl = _providerWatchList.getClientWatchList( pCSH );

		if(!cwl || !cwl->first()) continue;

		ClientWatchList::TokenInfo* pTS = cwl->first();
		while(pTS)
		{
			if(pTS->bItemRequest && (pTS->attribInfo.getName() == item))//Need to skip login request token
			{
                _respMsg.clear();
                _respStatus.clear();
                _respStatus.setStreamState(RespStatus::ClosedEnum);
                _respStatus.setStatusText(RFA_String("Item Closed", 0, false));

                _encoder.encodeMarketPriceMsg(&_respMsg, RespMsg::StatusEnum, pTS->attribInfo,  _respStatus, NULL, true, true);

                itemCmd.setMsg(static_cast<rfa::common::Msg&>(_respMsg));
                itemCmd.setRequestToken(*pTS->pToken);

                _pOMMProvider->submit(&itemCmd);

                cwl->removeToken(pTS->pToken);
                break;
			}
			pTS = cwl->next(pTS->pToken);
		}
	}

	_providerWatchListLock.unlock();
    if (_debug) {
        _log = "[OMMInteractiveProvider::closeSubmit]";
        _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());
        printClientWatchlists();
    }
}

void OMMInteractiveProvider::closeAllSubmit() {
    rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
	ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
		const rfa::common::Handle* pCSH = clientSessions[pos];
		ClientWatchList* cwl = _providerWatchList.getClientWatchList( pCSH );

		if(!cwl || !cwl->first()) continue;

		ClientWatchList::TokenInfo* pTS = cwl->first();
		while(pTS)
		{
			if(pTS->bItemRequest)//Need to skip login request token
			{
                _respMsg.clear();
                _respStatus.clear();
                _respStatus.setStreamState(RespStatus::ClosedEnum);
                _respStatus.setStatusText(RFA_String("Item Closed", 0, false));

                _encoder.encodeMarketPriceMsg(&_respMsg, RespMsg::StatusEnum, pTS->attribInfo,  _respStatus, NULL, true, true);

                itemCmd.setMsg(static_cast<rfa::common::Msg&>(_respMsg));
                itemCmd.setRequestToken(*pTS->pToken);

                _pOMMProvider->submit(&itemCmd);
                cwl->removeToken(pTS->pToken);
                pTS = cwl->first();
			}
			pTS = cwl->next(pTS->pToken);
		}
	}

	_providerWatchListLock.unlock();
    if (_debug) {
        _log = "[OMMInteractiveProvider::closeAllSubmit]";
        _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());
        printClientWatchlists();
    }
}

void OMMInteractiveProvider::staleSubmit(const rfa::common::RFA_String& item, const std::string& session) {
    rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
	ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
		const rfa::common::Handle* pCSH = clientSessions[pos];
        if((boost::lexical_cast<std::string>(reinterpret_cast<unsigned long>(pCSH)) != session) && session.length())
            continue;

		ClientWatchList* cwl = _providerWatchList.getClientWatchList( pCSH );

		if(!cwl || !cwl->first()) continue;

		ClientWatchList::TokenInfo* pTS = cwl->first();
		while(pTS)
		{
			if(pTS->bItemRequest && (pTS->attribInfo.getName() == item))//Need to skip login request token
			{
                _respMsg.clear();
                _respStatus.clear();
                _respStatus.setStreamState(RespStatus::OpenEnum);
                _respStatus.setDataState(RespStatus::SuspectEnum);
                _respStatus.setStatusText(RFA_String("Item Stale", 0, false));

                _encoder.encodeMarketPriceMsg(&_respMsg, RespMsg::StatusEnum, pTS->attribInfo,  _respStatus, NULL, true, true);

                itemCmd.setMsg(static_cast<rfa::common::Msg&>(_respMsg));
                itemCmd.setRequestToken(*pTS->pToken);

                _pOMMProvider->submit(&itemCmd);

                //cwl->removeToken(pTS->pToken);
                break;
			}
			pTS = cwl->next(pTS->pToken);
		}
	}

	_providerWatchListLock.unlock();
    if (_debug) {
        _log = "[OMMInteractiveProvider::staleSubmit]";
        _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());
        printClientWatchlists();
    }
}

void OMMInteractiveProvider::staleAllSubmit() {
    rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
	ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
		const rfa::common::Handle* pCSH = clientSessions[pos];
		ClientWatchList* cwl = _providerWatchList.getClientWatchList( pCSH );

		if(!cwl || !cwl->first()) continue;

		ClientWatchList::TokenInfo* pTS = cwl->first();
		while(pTS)
		{
			if(pTS->bItemRequest)//Need to skip login request token
			{
                _respMsg.clear();
                _respStatus.clear();
                _respStatus.setStreamState(RespStatus::OpenEnum);
                _respStatus.setDataState(RespStatus::SuspectEnum);
                _respStatus.setStatusText(RFA_String("Item Stale", 0, false));

                _encoder.encodeMarketPriceMsg(&_respMsg, RespMsg::StatusEnum, pTS->attribInfo,  _respStatus, NULL, true, true);

                itemCmd.setMsg(static_cast<rfa::common::Msg&>(_respMsg));
                itemCmd.setRequestToken(*pTS->pToken);

                _pOMMProvider->submit(&itemCmd);
                //cwl->removeToken(pTS->pToken);
                //pTS = cwl->first();
			}
			pTS = cwl->next(pTS->pToken);
		}
	}

	_providerWatchListLock.unlock();
    if (_debug) {
        _log = "[OMMInteractiveProvider::staleAllSubmit]";
        _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());
        printClientWatchlists();
    }
}

void OMMInteractiveProvider::serviceStateSubmit(int serviceState, rfa::common::RFA_String& serviceName) {
    _respMsg.clear();
    _map.clear();
    if ( _pDirectoryToken )
        _map.setAssociatedMetaInfo(*_pDirectoryToken->getHandle());

    //const UInt8 domainType = rfa::rdm::MMT_DIRECTORY;

    // Encode msg header
    _attribInfo.clear();
    _attribInfo.setDataMask(SERVICE_INFO_FILTER | SERVICE_STATE_FILTER);

    /*if(_itemMap.empty()) {
        // directory refresh
        ItemInfo *itemInfo = new ItemInfo();
        itemInfo->name = serviceName;
        itemInfo->srvName = serviceName;
        itemInfo->token = &(_pOMMProvider->generateItemToken());
        _itemMap.push_back(itemInfo);
    }*/
    // Set RespTypeNum
    _respStatus.clear();
    _respStatus.setStreamState(RespStatus::OpenEnum);
    _respStatus.setDataState(RespStatus::SuspectEnum);
    _respStatus.setStatusCode(RespStatus::NoneEnum);
    RFA_String  tmpStr("Service state updated");
    _respStatus.setStatusText(tmpStr);

    _encoder.encodeDirectoryMsg(&_respMsg, _attribInfo, _respStatus, false);

    // Reset respTypeNum to unsolicited refresh
    //_respMsg.setRespTypeNum(rfa::rdm::REFRESH_UNSOLICITED);

    // Encode Data Body
    _qos.setRate(QualityOfService::realTime);
    _qos.setTimeliness(QualityOfService::tickByTick);

    _encoder.encodeDirectoryDataBody(&_map,serviceName,_vendorName, serviceState, &_qos);
    _respMsg.setPayload(_map);

    _log = "[OMMInteractiveProvider::serviceStateSubmit] Updating directory with service state: ";
    _log.append(serviceState);
    _log.append(" for service ");
    _log.append(serviceName);
    _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());

    rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
    itemCmd.setMsg(static_cast<rfa::common::Msg&>(_respMsg));
    //itemCmd.setItemToken(_itemMap[0]->token);

    itemCmd.setRequestToken(*_pDirectoryToken);
    _pOMMProvider->submit(&itemCmd);
}

void OMMInteractiveProvider::logoutSubmit(const std::string& session) {
    rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
	ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
		rfa::common::Handle* pCSH = const_cast<rfa::common::Handle*>(clientSessions[pos]);
		ClientWatchList* cwl = _providerWatchList.getClientWatchList( pCSH );

		if(!cwl || !cwl->first()) continue;

		ClientWatchList::TokenInfo* pTS = cwl->first();
		if(!pTS->bItemRequest && (boost::lexical_cast<std::string>(reinterpret_cast<unsigned long>(pCSH)) == session))
        {
            // Logging out a client session
            _respMsg.clear();
            _respStatus.clear();
            _respStatus.setStreamState(RespStatus::ClosedEnum);
            _respStatus.setDataState(RespStatus::SuspectEnum);
            _respStatus.setStatusText(RFA_String("Provider logout", 0, false));
            _respMsg.setRespStatus(_respStatus);
            _respMsg.setAttribInfo(pTS->attribInfo);
            _respMsg.setMsgModelType(rfa::rdm::MMT_LOGIN);
            _respMsg.setRespType(RespMsg::StatusEnum);
            itemCmd.setMsg(static_cast<rfa::common::Msg&>(_respMsg));
            itemCmd.setRequestToken(*pTS->pToken);
            _pOMMProvider->submit(&itemCmd);
            break;
        }
	}

	_providerWatchListLock.unlock();
    if (_debug) {
        _log = "[OMMInteractiveProvider::logoutSubmit]";
        _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());
        printClientWatchlists();
    }
}

void OMMInteractiveProvider::logoutAllSubmit() {
    rfa::sessionLayer::OMMSolicitedItemCmd itemCmd;
	ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
		rfa::common::Handle* pCSH = const_cast<rfa::common::Handle*>(clientSessions[pos]);
		ClientWatchList* cwl = _providerWatchList.getClientWatchList( pCSH );

		if(!cwl || !cwl->first()) continue;

		ClientWatchList::TokenInfo* pTS = cwl->first();
		if(!pTS->bItemRequest)
        {
            // Logging out a client session
            _respMsg.clear();
            _respStatus.clear();
            _respStatus.setStreamState(RespStatus::ClosedEnum);
            _respStatus.setDataState(RespStatus::SuspectEnum);
            _respStatus.setStatusText(RFA_String("Provider logout", 0, false));
            _respMsg.setRespStatus(_respStatus);
            _respMsg.setAttribInfo(pTS->attribInfo);
            _respMsg.setMsgModelType(rfa::rdm::MMT_LOGIN);
            _respMsg.setRespType(RespMsg::StatusEnum);
            itemCmd.setMsg(static_cast<rfa::common::Msg&>(_respMsg));
            itemCmd.setRequestToken(*pTS->pToken);
            _pOMMProvider->submit(&itemCmd);
        }
	}

	_providerWatchListLock.unlock();
    if (_debug) {
        _log = "[OMMInteractiveProvider::logoutAllSubmit]";
        _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());
        printClientWatchlists();
    }
}

void OMMInteractiveProvider::rejectSessionSubmit(const std::string& session) {
    rfa::sessionLayer::OMMClientSessionCmd clientSessionCmd;
    rfa::sessionLayer::ClientSessionStatus clientSessionStatus;
	ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
		rfa::common::Handle* pCSH = const_cast<rfa::common::Handle*>(clientSessions[pos]);

		if(boost::lexical_cast<std::string>(reinterpret_cast<unsigned long>(pCSH)) == session)
        {
            // Reject the client session
            clientSessionCmd.setClientSessionHandle(pCSH);
            clientSessionStatus.setState(rfa::sessionLayer::ClientSessionStatus::Inactive);
            clientSessionStatus.setStatusCode(rfa::sessionLayer::ClientSessionStatus::Reject);
            clientSessionCmd.setStatus(clientSessionStatus);
            _pOMMProvider->submit(&clientSessionCmd);

            // Unregister client
            //_pOMMProvider->unregisterClient(pCSH);

            // Must remove as inactive clien event not invoked
            _providerWatchList.removeClientWatchList(pCSH);
            break;
        }
	}

	_providerWatchListLock.unlock();
    if (_debug) {
        _log = "[OMMInteractiveProvider::rejectSessionSubmit]";
        _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());
        printClientWatchlists();
    }
}

void OMMInteractiveProvider::rejectSessionAllSubmit() {
    rfa::sessionLayer::OMMClientSessionCmd clientSessionCmd;
    rfa::sessionLayer::ClientSessionStatus clientSessionStatus;
	ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
		rfa::common::Handle* pCSH = const_cast<rfa::common::Handle*>(clientSessions[pos]);

        // Reject the client session
        clientSessionCmd.setClientSessionHandle(pCSH);
        clientSessionStatus.setState(rfa::sessionLayer::ClientSessionStatus::Inactive);
        clientSessionStatus.setStatusCode(rfa::sessionLayer::ClientSessionStatus::Reject);
        clientSessionCmd.setStatus(clientSessionStatus);
        _pOMMProvider->submit(&clientSessionCmd);

        // Unregister client
        //_pOMMProvider->unregisterClient(pCSH);

        // Must remove as inactive clien event not invoked
        _providerWatchList.removeClientWatchList(pCSH);
	}

	_providerWatchListLock.unlock();
    if (_debug) {
        _log = "[OMMInteractiveProvider::rejectSessionAllSubmit]";
        _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());
        printClientWatchlists();
    }
}

void OMMInteractiveProvider::setDebugMode(const bool &debug) {
    _debug = debug;
    _encoder.setDebugMode(_debug);
}

bool OMMInteractiveProvider::addClientWatchList(const rfa::common::Handle* pCSH) {
    bool result = false;
    _providerWatchListLock.lock();
    result = _providerWatchList.addClientWatchList(pCSH);
    _providerWatchListLock.unlock();
    return result;
}

bool OMMInteractiveProvider::removeClientWatchList(const rfa::common::Handle* pCSH, boost::python::tuple& out) {
    dict d;
    bool result = false;
    _providerWatchListLock.lock();
    ClientWatchList* cwl = _providerWatchList.getClientWatchList( pCSH );

    if(!cwl || !cwl->first()) return result;

    d["MTYPE"] = "LOGOUT";
    d["USERNAME"] = cwl->first()->attribInfo.getName().c_str();
    d["SERVICE"] = _serviceName.c_str();
    d["SESSIONID"] = boost::lexical_cast<std::string>(reinterpret_cast<unsigned long>(pCSH));
    out += boost::python::make_tuple(d);
    cwl->cleanup();

    result = _providerWatchList.removeClientWatchList(pCSH);
    _providerWatchListLock.unlock();
    return result;
}

void OMMInteractiveProvider::printClientWatchlists() {
	ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
        _log = "[OMMInteractiveProvider::printClientWatchlists] ";
		const rfa::common::Handle* pCSH = clientSessions[pos];
		ClientWatchList* cwl = _providerWatchList.getClientWatchList( pCSH );

		if(!cwl || !cwl->first()) continue;

		ClientWatchList::TokenInfo* pTS = cwl->first();
		while(pTS)
		{
            _log += pTS->attribInfo.getName();
            _log += " ";
			pTS = cwl->next(pTS->pToken);
		}
        _componentLogger.log(LM_GENERIC_ONE,rfa::common::Information,_log.c_str());
	}

	_providerWatchListLock.unlock();
}

std::string OMMInteractiveProvider::getClientSessions() {
    std::string sessions;
    ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
		const rfa::common::Handle* pCSH = clientSessions[pos];
        sessions.append(boost::lexical_cast<std::string>(reinterpret_cast<unsigned long>(pCSH)));
        sessions.append(" ");
	}
	_providerWatchListLock.unlock();
    return sessions;
}

std::string OMMInteractiveProvider::getClientWatchList(const std::string& session) {
    std::string watchlist;
    ProviderWatchList::CLIENT_SESSIONS clientSessions;

	_providerWatchListLock.lock();
	_providerWatchList.getClientSessions( clientSessions );

	for ( unsigned int pos = 0; pos < clientSessions.size(); ++pos )
	{
		const rfa::common::Handle* pCSH = clientSessions[pos];
        if(boost::lexical_cast<std::string>(reinterpret_cast<unsigned long>(pCSH)) == session) {
            ClientWatchList* cwl = _providerWatchList.getClientWatchList( pCSH );

            if(!cwl || !cwl->first()) continue;

            ClientWatchList::TokenInfo* pTS = cwl->first();
            while(pTS)
            {
                if(pTS->bItemRequest) {//skip login token
                    watchlist.append(pTS->attribInfo.getName().c_str());
                    watchlist.append(" ");
                }
                pTS = cwl->next(pTS->pToken);
            }
            break;
        }
	}
	_providerWatchListLock.unlock();
    return watchlist;
}

///////////////////////////////////////////////////////////////////////////////
// ClientWatchList implementation
///////////////////////////////////////////////////////////////////////////////

ClientWatchList::ClientWatchList( const Handle* clientSessionHandle ) :
 _clientSessionHandle( clientSessionHandle )
{
}

ClientWatchList::~ClientWatchList()
{
	cleanup();
}

void ClientWatchList::cleanup()
{
	for(TokenInfoMap::iterator iter = _watchlist.begin(); iter != _watchlist.end(); iter++)
		delete iter->second;
	_watchlist.clear();
}

ClientWatchList::TokenInfo* ClientWatchList::addToken(rfa::sessionLayer::RequestToken* pT, const rfa::message::ReqMsg& reqMsg, bool isItemReq)
{
	TokenInfoMap::iterator iter = _watchlist.find(pT);

	if(iter != _watchlist.end())
		return 0;

	TokenInfo* sub = new TokenInfo();
	sub->pToken = pT;
	sub->attribInfo = reqMsg.getAttribInfo();
	sub->bAttribInfoInUpdates = (reqMsg.getIndicationMask() & rfa::message::ReqMsg::AttribInfoInUpdatesFlag) ? true : false;
	sub->bSubmitted = false;
	sub->bItemRequest = isItemReq;
	sub->msgModelType = reqMsg.getMsgModelType();
	_watchlist.insert(std::pair<rfa::sessionLayer::RequestToken*, TokenInfo*>(pT, sub));
	return sub;
}

ClientWatchList::TokenInfo* ClientWatchList::getTokenInfo(rfa::sessionLayer::RequestToken* pT)
{
	TokenInfoMap::iterator iter = _watchlist.find(pT);
	if(iter == _watchlist.end())
		return 0;
	return iter->second;
}

bool ClientWatchList::removeToken(rfa::sessionLayer::RequestToken* pT)
{
	TokenInfoMap::iterator iter = _watchlist.find(pT);
	if(iter == _watchlist.end())
		return false;
	delete iter->second;
	_watchlist.erase(iter);
	return true;
}

ClientWatchList::TokenInfo* ClientWatchList::first()
{
	ClientWatchList::TokenInfoMap::iterator iter = _watchlist.begin();
	if(iter == _watchlist.end())
		return 0;
	return iter->second;
}

ClientWatchList::TokenInfo* ClientWatchList::next(rfa::sessionLayer::RequestToken* pT)
{
	ClientWatchList::TokenInfoMap::iterator iter = _watchlist.find(pT);
	if(iter == _watchlist.end()) return 0;
	if(++iter == _watchlist.end()) return 0;
	return iter->second;
}

ProviderWatchList::ProviderWatchList()
{
}

ProviderWatchList::~ProviderWatchList()
{
	_watchList.clear();
}

bool ProviderWatchList::addClientWatchList( const Handle* pCSH )
{
	CSH_MAP::iterator iter = _watchList.find( pCSH );

	if ( iter != _watchList.end() ) return false;

	ClientWatchList* cwl = new ClientWatchList( pCSH );
	_watchList.insert( std::pair< const Handle*, ClientWatchList*>( pCSH, cwl ) );

	return true;
}

bool ProviderWatchList::removeClientWatchList( const Handle* pCSH )
{
	CSH_MAP::iterator iter = _watchList.find( pCSH );

	if ( iter == _watchList.end() ) return false;

	delete iter->second;
	_watchList.erase(iter);

	return true;
}

ClientWatchList* ProviderWatchList::getClientWatchList( const Handle* pCSH )
{
	CSH_MAP::iterator iter = _watchList.find( pCSH );

	if ( iter == _watchList.end() ) return 0;

	return iter->second;
}

bool ProviderWatchList::cleanup()
{
	for(CSH_MAP::iterator iter = _watchList.begin(); iter != _watchList.end(); ++iter)
	{
		iter->second->cleanup();
		delete iter->second;
	}
	return true;
}

void ProviderWatchList::getClientSessions(CLIENT_SESSIONS& sessions)
{
	sessions.clear();
	for(CSH_MAP::iterator iter = _watchList.begin(); iter != _watchList.end(); ++iter)
		sessions.push_back(iter->first);
}

void ProviderWatchList::findTokens(const RFA_String& itemName, UInt8 msgModelType, TOKENS& tokens, CLIENT_SESSIONS& cshs)
{
	tokens.clear();
	CLIENT_SESSIONS clientSessions;
	getClientSessions(clientSessions);
	for(unsigned int pos = 0; pos < clientSessions.size(); pos++)
	{
		ClientWatchList* cwl = getClientWatchList(clientSessions[pos]);
		if(!cwl || !cwl->first()) continue;
		ClientWatchList::TokenInfo* pTS = cwl->first();
		while(pTS)
		{
			if(pTS->attribInfo.getName() == itemName && pTS->msgModelType == msgModelType)
			{
				tokens.push_back(pTS->pToken);
				cshs.push_back(clientSessions[pos]);
			}
			pTS = cwl->next(pTS->pToken);
		}
	}
}

ext: cpp

max_forks_repo_name: devcartel/thomsonreuters


text:
//
// stream_descriptor.cpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

// Disable autolinking for unit tests.
#if !defined(BOOST_ALL_NO_LIB)
#define BOOST_ALL_NO_LIB 1
#endif // !defined(BOOST_ALL_NO_LIB)

// Test that header file is self-contained.
#include <boost/asio/posix/stream_descriptor.hpp>

#include <boost/asio/io_service.hpp>
#include "../unit_test.hpp"

//------------------------------------------------------------------------------

// posix_stream_descriptor_compile test
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The following test checks that all public member functions on the class
// posix::stream_descriptor compile and link correctly. Runtime failures are
// ignored.

namespace posix_stream_descriptor_compile {

void write_some_handler(const boost::system::error_code&, std::size_t)
{
}

void read_some_handler(const boost::system::error_code&, std::size_t)
{
}

void test()
{
#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
  using namespace boost::asio;
  namespace posix = boost::asio::posix;

  try
  {
    io_service ios;
    char mutable_char_buffer[128] = "";
    const char const_char_buffer[128] = "";
    posix::descriptor_base::bytes_readable io_control_command;
    boost::system::error_code ec;

    // basic_stream_descriptor constructors.

    posix::stream_descriptor descriptor1(ios);
    int native_descriptor1 = -1;
    posix::stream_descriptor descriptor2(ios, native_descriptor1);

#if defined(BOOST_ASIO_HAS_MOVE)
    posix::stream_descriptor descriptor3(std::move(descriptor3));
#endif // defined(BOOST_ASIO_HAS_MOVE)

    // basic_stream_descriptor operators.

#if defined(BOOST_ASIO_HAS_MOVE)
    descriptor1 = posix::stream_descriptor(ios);
    descriptor1 = std::move(descriptor2);
#endif // defined(BOOST_ASIO_HAS_MOVE)

    // basic_io_object functions.

    io_service& ios_ref = descriptor1.get_io_service();
    (void)ios_ref;

    // basic_descriptor functions.

    posix::stream_descriptor::lowest_layer_type& lowest_layer
      = descriptor1.lowest_layer();
    (void)lowest_layer;

    const posix::stream_descriptor& descriptor4 = descriptor1;
    const posix::stream_descriptor::lowest_layer_type& lowest_layer2
      = descriptor4.lowest_layer();
    (void)lowest_layer2;

    int native_descriptor2 = -1;
    descriptor1.assign(native_descriptor2);

    bool is_open = descriptor1.is_open();
    (void)is_open;

    descriptor1.close();
    descriptor1.close(ec);

    posix::stream_descriptor::native_type native_descriptor3
      = descriptor1.native();
    (void)native_descriptor3;

    posix::stream_descriptor::native_handle_type native_descriptor4
      = descriptor1.native_handle();
    (void)native_descriptor4;

    posix::stream_descriptor::native_handle_type native_descriptor5
      = descriptor1.release();
    (void)native_descriptor5;

    descriptor1.cancel();
    descriptor1.cancel(ec);

    descriptor1.io_control(io_control_command);
    descriptor1.io_control(io_control_command, ec);

    bool non_blocking1 = descriptor1.non_blocking();
    (void)non_blocking1;
    descriptor1.non_blocking(true);
    descriptor1.non_blocking(false, ec);

    bool non_blocking2 = descriptor1.native_non_blocking();
    (void)non_blocking2;
    descriptor1.native_non_blocking(true);
    descriptor1.native_non_blocking(false, ec);

    // basic_stream_descriptor functions.

    descriptor1.write_some(buffer(mutable_char_buffer));
    descriptor1.write_some(buffer(const_char_buffer));
    descriptor1.write_some(null_buffers());
    descriptor1.write_some(buffer(mutable_char_buffer), ec);
    descriptor1.write_some(buffer(const_char_buffer), ec);
    descriptor1.write_some(null_buffers(), ec);

    descriptor1.async_write_some(buffer(mutable_char_buffer),
        write_some_handler);
    descriptor1.async_write_some(buffer(const_char_buffer),
        write_some_handler);
    descriptor1.async_write_some(null_buffers(),
        write_some_handler);

    descriptor1.read_some(buffer(mutable_char_buffer));
    descriptor1.read_some(buffer(mutable_char_buffer), ec);
    descriptor1.read_some(null_buffers(), ec);

    descriptor1.async_read_some(buffer(mutable_char_buffer), read_some_handler);
    descriptor1.async_read_some(null_buffers(), read_some_handler);
  }
  catch (std::exception&)
  {
  }
#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
}

} // namespace posix_stream_descriptor_compile

//------------------------------------------------------------------------------
test_suite* init_unit_test_suite(int, char*[])
{
  test_suite* test = BOOST_TEST_SUITE("posix/stream_descriptor");
  test->add(BOOST_TEST_CASE(&posix_stream_descriptor_compile::test));
  return test;
}

max_stars_repo_name: olegshnitko/libboost

max_issues_repo_name: olegshnitko/libboost

max_forks_repo_name: olegshnitko/libboost