<|start_filename|>core/preprocess/hwvideoframe/include/resize_by_factor.h<|end_filename|>
// Copyright (c) 2020 PaddlePaddle Authors. 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.

#ifndef CORE_PREPROCESS_HWVIDEOFRAME_INCLUDE_RESIZE_BY_FACTOR_H_
#define CORE_PREPROCESS_HWVIDEOFRAME_INCLUDE_RESIZE_BY_FACTOR_H_

#include <npp.h>

#include <memory>
#include <vector>

#include "core/preprocess/hwvideoframe/include/op_context.h"

extern "C" cudaError_t resize_linear(const float *input,
                                     float *output,
                                     const int inputWidth,
                                     const int inputHeight,
                                     const int outputWidth,
                                     const int outputHeight,
                                     const int inputChannels,
                                     const bool use_fixed_point);

// Resize the input numpy array Image to a size multiple of factor which is
// usually required by a network
// only support linear interpolation
// only support RGB channels
class ResizeByFactor {
 public:
  // Resize factor. make width and height multiple factor of the value of
  // factor. Default is 32
  ResizeByFactor(int factor = 32,
                 int max_side_len = 2400,
                 bool use_fixed_point = false,
                 int interpolation = 0)
      : _factor(factor),
        _max_side_len(max_side_len),
        _use_fixed_point(use_fixed_point),
        _interpolation(interpolation) {}
  std::shared_ptr<OpContext> operator()(std::shared_ptr<OpContext> input);

 private:
  int _factor;  // target of smaller edge
  int _max_side_len;
  bool _use_fixed_point;
  int _interpolation;  // unused
};

#endif  // CORE_PREPROCESS_HWVIDEOFRAME_INCLUDE_RESIZE_BY_FACTOR_H_


<|start_filename|>core/predictor/mempool/mempool.h<|end_filename|>
// Copyright (c) 2019 PaddlePaddle Authors. 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.

#pragma once

#ifdef BCLOUD
#include <base/atomicops.h>
#include <base/logging.h>
#else
#include <butil/atomicops.h>
#include <butil/logging.h>
#endif

#include <execinfo.h>
#include <pthread.h>
#include <iostream>
#include <new>
#include <sstream>
#include <string>

namespace im {
namespace fugue {

#ifdef BCLOUD
namespace butil = base;
#endif

namespace lockfree {

/*
struct BigNode {
    BigNode* next;
    char data[0];
  };
*/
// template T is BigNode
// which is a node of variable length memory linked list
// _head is a BigNode* ptr, always points to the head node of the Stack.
// so PushOnlyStack is the head node of the Stack with some member function.
template <class T>
class PushOnlyStack {
 public:
  PushOnlyStack() { _head.store(NULL, butil::memory_order_relaxed); }

  void push(T* node) {
    T* head = _head.load(butil::memory_order_relaxed);
    node->next = head;
    while (
        !_head.compare_exchange_weak(head, node, butil::memory_order_relaxed)) {
      node->next = head;
    }
  }

  T* releaseAndGetHeadPtr() {
    return _head.exchange(NULL, butil::memory_order_relaxed);
  }

 private:
  butil::atomic<T*> _head;
};

// T can be class Block or class BlockReference
// class Block is 2M bytes memory
// class BlockReference is class Block* ptr.
// so the main member of FreeListNode is 2M bytes or class Block* ptr
// int 'id' is the index of itself in a FreeList.
// int 'next' is the index of next FreeListNode<T> in a FreeList.
template <class T>
struct FreeListNode {
  uint64_t id;
  uint64_t next;
  T data;
};

// T can be class Block or class BlockReference
// CAP means capicity
// the main member of FreeList is FreeListNode<T>* [CAP].
// FreeList doesn`t realse the block data, it`s only an array of
// FreeListNode<T>* ptr.
template <class T, int CAP>
class FreeList {
 public:
  typedef FreeListNode<T> Node;
  static const uint64_t EMPTY = 0xFFFFFFFFFFFFFFFF;

  // get the head Node`s member data ptr(T*)
  T* get() {
    uint64_t head = _head.load(butil::memory_order_acquire);
    if (head == EMPTY) {
      return new_node();
    }

    // _head is atomic<int>, which means the head index.
    // head is the tempValue of _head.
    // maybe _head is not equals head anymore.
    // cause other thread may change the _head.
    /*compare_exchange_weak
    When the current value is equal to the expected value, modify the current
    value to the set value and return true
    When the current value is not equal to the expected value, modify the
    expected value to the current value and return false
    */
    Node* node = address(head);
    while (!_head.compare_exchange_weak(
        head, node->next, butil::memory_order_acquire)) {
      if (head == EMPTY) {
        return new_node();
      }
      node = address(head);
    }
    return &node->data;
  }

  void put(T* value) {
    /*
    container_of
    according to the member(pointer type) of a Class
    to get the class Pointer
    for example
    T is the member of class Node, T data, 'data' is the name.
    T* value is the member(pointer type) of class Node
    so we can get the Node* by calling container_of(value, Node, data)
    */
    Node* node = container_of(value, Node, data);

    uint64_t head = _head.load(butil::memory_order_acquire);

    // node->id is int64. slot index is int32.
    // address(): slot = static_cast<uint32_t>(node->id)
    // will this be wrong?
    // add version? maybe this is different from new node?
    node->id += (1UL << 32);
    node->next = head;

    // NOTE: we MUST use a temp var *head* to call compare_exchange_weak
    // because Boost.Atomic will update the *expected* even success
    // std::atomic do not have this limitation
    while (!_head.compare_exchange_weak(
        head, node->id, butil::memory_order_release)) {
      node->next = head;
    }
  }

  // F is callable class, class PutBlockByReference.
  // actually, F is the function put.
  // this function put the reuse the used block or blockReference
  template <class F>
  void unsafe_foreach() {
    uint32_t used_blk_cnt = _slot_index.load(butil::memory_order_relaxed);
    for (uint32_t i = 0; i < used_blk_cnt; ++i) {
      F()(&_node[i]->data);
    }
  }

  uint32_t real_used_size() const {
    uint32_t used_blk_cnt = _slot_index.load(butil::memory_order_relaxed);
    uint64_t used_bytes = 0;
    for (uint32_t i = 0; i < used_blk_cnt; ++i) {
      used_bytes += _node[i]->data.offset;
    }
    // used_bytes/1024 = KB
    return used_bytes >> 10;
  }

  uint32_t get_number_of_allocate_blocks() const {
    return _slot_index.load(butil::memory_order_relaxed);
  }

  uint32_t get_number_of_free_blocks() const {
    uint64_t head = _head.load(butil::memory_order_relaxed);
    uint32_t size = 0;
    while (head != FreeList::EMPTY) {
      const Node* head_ptr = address(head);
      head = head_ptr->next;
      ++size;
    }
    return size;
  }

  void reset() {
    _head.store(FreeList::EMPTY, butil::memory_order_relaxed);
    _slot_index.store(0, butil::memory_order_relaxed);
  }

  FreeList() {
    for (int i = 0; i < CAP; ++i) {
      _node[i] = NULL;
    }
    reset();
  }

 private:
  uint32_t slot(uint64_t id) const { return static_cast<uint32_t>(id); }

  T* new_node() {
    uint32_t index = _slot_index.fetch_add(1, butil::memory_order_relaxed);
    if (index >= CAP) {
      return NULL;
    }

    if (_node[index] != NULL) {
      return &(_node[index]->data);
    }

    Node* node = reinterpret_cast<Node*>(malloc(sizeof(Node)));
    new (node) Node;

    node->id = index;
    _node[index] = node;

    return &node->data;
  }

  Node* address(uint64_t id) { return _node[slot(id)]; }

  const Node* address(uint64_t id) const { return _node[slot(id)]; }

  butil::atomic<uint64_t> _head;
  butil::atomic<uint32_t> _slot_index;
  Node* _node[CAP];
};
}  // namespace lockfree

namespace memory {

// Memory is 2M bytes
struct Block {
  static const int BLOCK_SIZE = 2 * 1024 * 1024;  // 2MB
  char data[BLOCK_SIZE];
};

// Block* and offset
struct BlockReference {
  BlockReference() : offset(0), block(NULL) {
    // do nothing
  }

  void reset() {
    offset = 0;
    block = NULL;
  }

  uint32_t offset;
  Block* block;
};

// This is a real singleton class FreeList<Block,MAX_BLOCK_COUNT>
// FreeList is always an array of FreeListNode<Block>* ptr.
// Block(2MB) is created when get() is called.

// because BlockFreeList is a threal-safe Singleton.
// so we don`t release Block, it is global memory.
// total number is 256*1024.
// the MAX_BLOCK_COUNT of Region(one thread one Region) is 1024.
// so BlockFreeList allow 256 Region(means 256 thread).
// the memory used by BlockFreeListType is sizeof(void*)*256*1024.
// Block(2MB) memory is created only when get() is called.
class BlockFreeList {
 public:
  static const int MAX_BLOCK_COUNT = 256 * 1024;
  typedef lockfree::FreeList<Block, MAX_BLOCK_COUNT> BlockFreeListType;
  static BlockFreeListType* instance() {
    static BlockFreeListType singleton;
    return &singleton;
  }
};

// _big_mem_capacity: a large memory is owned by Region.
// _bigNode_Stack: A list of bigNode(variable length memory)is owned by
// Region,the number is unlimit.
// _blockReference_FreeList: a FreeList of Block(2MB) is owned by singleton
// BlockFreeList, which is global.
// we can borrow 1024*Block from BlockFreeList.
class Region {
 public:
  struct PutBlockByReference {
    void operator()(BlockReference* block_ref) {
      if (block_ref->block != NULL) {
        BlockFreeList::instance()->put(block_ref->block);
      }
      block_ref->reset();
    }
  };

  // this is a variable length memory node.
  struct BigNode {
    BigNode* next;
    char data[0];
  };

  ~Region() {
    reset();
    delete[] _big_mem_start;
    _big_mem_start = NULL;
  }

  char const* debug_str() const {
    uint32_t alloc_blocks =
        _blockReference_FreeList.get_number_of_allocate_blocks();
    uint32_t free_blocks = _blockReference_FreeList.get_number_of_free_blocks();
    uint32_t used_mem_mb = _blockReference_FreeList.real_used_size();
    uint32_t big_buf_size = _big_mem_size.load(butil::memory_order_relaxed);
    uint32_t big_buf_count = _big_mem_count.load(butil::memory_order_relaxed);
    uint32_t mlc_mem_size =
        _total_bigNode_size.load(butil::memory_order_relaxed);
    uint32_t mlc_mem_count =
        _total_bigNode_count.load(butil::memory_order_relaxed);

    std::ostringstream oss;
    oss << "[alloc_blks:" << alloc_blocks << ",free_blks:" << free_blocks
        << ",used_mem_kb:" << used_mem_mb
        << ",big_mem_kb:" << (big_buf_size >> 10)
        << ",big_buf_cnt:" << big_buf_count
        << ",mlc_mem_kb:" << (mlc_mem_size >> 10)
        << ",mlc_cnt:" << mlc_mem_count << "]";

    return oss.str().c_str();
  }

  Region();

  void init();

  void reset();

  BlockReference* get();

  void* malloc(size_t size);

  void put(BlockReference* blockReference);

  static const int MAX_BLOCK_COUNT = 1024;  // each Block is 2MB
  static const int BIG_MEM_THRESHOLD =
      2 * 1024 *
      1024;  // 2MB,means when you need less than 2M, get memory from Block.

  // 128MB,means when you need less than 128MB, get memory from BigMemory
  // instead
  // of BigNode
  static const int BIGNODE_MEM_THRESHOLD = (128 * 1024 * 1024 + 1);
  static const int COUNTER_SIZE =
      BIGNODE_MEM_THRESHOLD / BIG_MEM_THRESHOLD + 1;  // this is not used

 private:
  lockfree::FreeList<BlockReference, MAX_BLOCK_COUNT> _blockReference_FreeList;

  // _total_bigNode_size is the total size of BigNodeStack.
  // _total_bigNode_count is the total count of BigNodeStack.
  // BigNode is variable length memory.
  lockfree::PushOnlyStack<BigNode> _bigNode_Stack;
  butil::atomic<uint32_t> _total_bigNode_size;
  butil::atomic<uint32_t> _total_bigNode_count;

  // '_big_mem_start' points to a single big memory belong to Region.
  // _big_mem_capacity is the size of single big memory.
  // _big_mem_size is the already used size.
  // _big_mem_count is the used count.
  char* _big_mem_start;
  uint32_t _big_mem_capacity;  // 32M
  butil::atomic<uint32_t> _big_mem_size;
  butil::atomic<uint32_t> _big_mem_count;
};
}  // namespace memory
}  // namespace fugue

class Mempool {
 public:
  void* malloc(size_t size) {
    size = _align(size);
    // It does not enter the if statement the first time.
    // The if statement may enter after the block is created.
    // If the block has not been used up, it will enter.
    if (size <= _free_size) {
      void* p = _free_cursor;
      _free_size -= size;
      _free_cursor += size;
      return p;
    }

    return malloc_from_region(size);
  }

  void free(void* p, size_t size) {
    // size>Block(2M)
    // other memory is managed by Region，no need to release here.
    if (size > fugue::memory::Region::BIG_MEM_THRESHOLD) {
      return;
    }

    // memory in _block，update the pointer.
    if (_free_cursor - size == static_cast<char*>(p)) {
      // for example, you need to release -(8+1)bytes
      // you can only release -8bytes，cause -(8+2)byte is used by other.
      size_t down_aligned = _down_align(size);
      _free_cursor -= down_aligned;
      _free_size += down_aligned;
    }
  }

  void* realloc(void* old_data, size_t old_size, size_t new_size) {
    // Return the pointer directly and reuse it without expansion.
    if (old_size >= new_size) {
      return old_data;
    }

    size_t required = new_size - old_size;
    if (_free_cursor == static_cast<char*>(old_data) + old_size) {
      if (_free_size >= required) {
        _free_cursor += required;
        _free_size -= required;
        return old_data;
      } else {
        // old_data will copy to other structure
        // so _free_cursor rollback，means the memory used by old_data can be
        // used.
        _free_cursor = static_cast<char*>(old_data);
        _free_size += old_size;
      }
    }

    // 可能返回的是单独Region中malloc的内存。
    // 也可能是Block，例如new_size=1M, old_data原本的指针头就在1.2M处
    // old_size = 0.5M
    // 此时,_free_size = 0.3M，new_size<2M,但是required = 1-0.5 >0.3
    // 分配出来的就是Block，但是该Block没有并很完美的利用完全。
    void* p = this->malloc_from_region(new_size);
    if (p != NULL) {
      memcpy(p, old_data, old_size);
      return p;
    }

    return NULL;
  }

  explicit Mempool(fugue::memory::Region* region)
      : _free_size(0), _free_cursor(NULL), _region(region) {
    _blockReference = NULL;
  }

  ~Mempool() { release_block(); }

  void release_block() {
    if (_blockReference) {
      _blockReference->offset = fugue::memory::Block::BLOCK_SIZE - _free_size;
      _region->put(_blockReference);
    }

    _free_size = 0;
    _free_cursor = NULL;
    _blockReference = NULL;
  }

 private:
  void* malloc_from_region(size_t size) {
    // if greater than BIG_MEM_THRESHOLD, _region->malloc
    // else get the memory from the Block.
    if (size > fugue::memory::Region::BIG_MEM_THRESHOLD) {
      return _region->malloc(size);
    }

    while (true) {
      fugue::memory::BlockReference* blockReference = _region->get();
      if (blockReference == NULL) {
        return NULL;
      }

      uint32_t free_size =
          fugue::memory::Block::BLOCK_SIZE - blockReference->offset;
      // 若未能满足要求，则while下一次循环，那么上次的block必然成为野值。
      if (size <= free_size) {
        // 试图更新该节点的offset，但是该结点已经变成了野值，无法被再次使用了，只有等待归还。
        // 应将该节点put进队列,进入该判断语句内，证明本来get已肯定可以return.
        // 此时，上次没用完的值，应该更新offset后，还回去，下次没准还能用，不至于浪费。
        if (_blockReference) {
          _blockReference->offset =
              fugue::memory::Block::BLOCK_SIZE - _free_size;
          _region->put(_blockReference);
        }

        char* p = blockReference->block->data + blockReference->offset;
        _free_size = free_size - size;
        _free_cursor = p + size;
        _blockReference = blockReference;
        return p;
      }
    }
    // It's not executed at all, for the sake of syntax.
    return _region->malloc(size);
  }

  static const int ALIGN_SIZE = sizeof(void*);

  // align to the 8bytes, if (8+1), it will be (8+8)bytes.
  inline size_t _align(size_t size) const {
    return (size + (ALIGN_SIZE - 1)) & ~(ALIGN_SIZE - 1);
  }

  // down_align to 8bytes, if (8+1), it will be (8+0)bytes.
  inline size_t _down_align(size_t size) const {
    return size & ~(ALIGN_SIZE - 1);
  }

  size_t _free_size;
  char* _free_cursor;

  fugue::memory::Region* _region;
  fugue::memory::BlockReference* _blockReference;
};

// use threal-local key instead of __thread.
// it`s not referenced.
/*
extern __thread Mempool* g_mempool;
*/

// class mempool is a Interface.
// it`s not necessary at all.
/*
class mempool {
 public:
  virtual void* malloc(size_t size) = 0;
  virtual void free(void* p, size_t size) = 0;
  inline virtual ~mempool() {}
};
*/

// GlobalMempool is a Singleton-RAII class.
// It`s propose is to manage the thread-local pointer 'g_mempool'(class
// Mempool*)
// It`s not referenced, so it`s useless.
/*
class GlobalMempool : public mempool {
 public:
  GlobalMempool() {
    // do nothing;
  }

  virtual ~GlobalMempool() {
    // do nothing;
  }

  static GlobalMempool* instance() {
    static GlobalMempool singleton;
    return &singleton;
  }

  void reset(Mempool* mempool) { g_mempool = mempool; }

  void* malloc(size_t size) { return g_mempool->malloc(size); }

  void* realloc(void* old_data, size_t old_size, size_t new_size) {
    return g_mempool->realloc(old_data, old_size, new_size);
  }

  void free(void* p, size_t s) { g_mempool->free(p, s); }

  void clear() { g_mempool->release_block(); }

  Mempool* get() { return g_mempool; }
};
*/

// MempoolGuard is a RAII class.
// It`s propose is to manage the thread-local pointer 'g_mempool'(class
// Mempool*)
// It`s not referenced, so it`s useless.
/*
class MempoolGuard {
 public:
  explicit MempoolGuard(fugue::memory::Region* region) : _mempool(region) {
    acquire();
  }

  void acquire() {
    _saved_mempool = g_mempool;
    g_mempool = &_mempool;
  }

  void release() {
    _mempool.release_block();
    g_mempool = _saved_mempool;
  }

  ~MempoolGuard() { release(); }

 private:
  Mempool _mempool;
  Mempool* _saved_mempool;
};
*/
inline std::string print_trace() {
  static const int BT_BUF_SIZE = 400;
  std::stringstream debug_stream;

  void* buffer[BT_BUF_SIZE];
  int nptrs = backtrace(buffer, BT_BUF_SIZE);
  char** strings = backtrace_symbols(buffer, nptrs);

  for (int j = 0; j < nptrs; j++) {
    debug_stream << strings[j] << "\t";
  }

  return debug_stream.str();
}
}  // namespace im


<|start_filename|>core/predictor/common/constant.cpp<|end_filename|>
// Copyright (c) 2019 PaddlePaddle Authors. 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.

#include "core/predictor/common/constant.h"

namespace baidu {
namespace paddle_serving {
namespace predictor {

DEFINE_bool(use_parallel_infer_service, false, "");
DEFINE_int32(el_log_level, 16, "");
DEFINE_int32(idle_timeout_s, 16, "");
DEFINE_int32(port, 8010, "");
DEFINE_string(workflow_path, "./conf", "");
DEFINE_string(workflow_file, "workflow.prototxt", "");
DEFINE_string(inferservice_path, "./conf", "");
DEFINE_string(inferservice_file, "infer_service.prototxt", "");
DEFINE_string(logger_path, "./conf", "");
DEFINE_string(logger_file, "log.conf", "");
DEFINE_string(resource_path, "./conf", "");
DEFINE_string(resource_file, "resource.prototxt", "");
DEFINE_int32(max_concurrency,
             0,
             "Limit of request processing in parallel, 0: unlimited");
DEFINE_int32(
    num_threads,
    0,
    "Number of pthreads that server runs on, not change if this value <= 0");
DEFINE_int32(reload_interval_s, 10, "");
DEFINE_bool(enable_model_toolkit, true, "enable model toolkit");
DEFINE_string(enable_protocol_list, "baidu_std", "set protocol list");
DEFINE_bool(enable_cube, false, "enable cube");
DEFINE_string(general_model_path, "./conf", "");
DEFINE_string(general_model_file, "general_model.prototxt", "");
DEFINE_bool(enable_general_model, true, "enable general model");

const char* START_OP_NAME = "startup_op";
}  // namespace predictor
}  // namespace paddle_serving
}  // namespace baidu

// Baidurpc
BAIDU_REGISTER_ERRNO(baidu::paddle_serving::predictor::ERR_INTERNAL_FAILURE,
                     "Paddle Serving Framework Internal Error.");
BAIDU_REGISTER_ERRNO(baidu::paddle_serving::predictor::ERR_MEM_ALLOC_FAILURE,
                     "Paddle Serving Memory Alloc Error.");
BAIDU_REGISTER_ERRNO(baidu::paddle_serving::predictor::ERR_OVERFLOW_FAILURE,
                     "Paddle Serving Array Overflow Error.");
BAIDU_REGISTER_ERRNO(baidu::paddle_serving::predictor::ERR_OP_INFER_FAILURE,
                     "Paddle Serving Op Inference Error.");


<|start_filename|>core/general-client/src/pybind_general_model.cpp<|end_filename|>
// Copyright (c) 2020 PaddlePaddle Authors. 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.

#include <Python.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <unordered_map>
#include "core/general-client/include/general_model.h"

namespace py = pybind11;

namespace baidu {
namespace paddle_serving {
namespace general_model {

PYBIND11_MODULE(serving_client, m) {
  m.doc() = R"pddoc(this is a practice
       )pddoc";

  py::class_<PredictorRes>(m, "PredictorRes", py::buffer_protocol())
      .def(py::init())
      .def("get_int64_by_name",
           [](PredictorRes &self, int model_idx, std::string &name) {
             // see more: https://github.com/pybind/pybind11/issues/1042
             std::vector<int64_t> *ptr = new std::vector<int64_t>(
                 std::move(self.get_int64_by_name_with_rv(model_idx, name)));
             auto capsule = py::capsule(ptr, [](void *p) {
               delete reinterpret_cast<std::vector<int64_t> *>(p);
             });
             return py::array(ptr->size(), ptr->data(), capsule);
           })
      .def("get_float_by_name",
           [](PredictorRes &self, int model_idx, std::string &name) {
             std::vector<float> *ptr = new std::vector<float>(
                 std::move(self.get_float_by_name_with_rv(model_idx, name)));
             auto capsule = py::capsule(ptr, [](void *p) {
               delete reinterpret_cast<std::vector<float> *>(p);
             });
             return py::array(ptr->size(), ptr->data(), capsule);
           })
      .def("get_int32_by_name",
           [](PredictorRes &self, int model_idx, std::string &name) {
             std::vector<int32_t> *ptr = new std::vector<int32_t>(
                 std::move(self.get_int32_by_name_with_rv(model_idx, name)));
             auto capsule = py::capsule(ptr, [](void *p) {
               delete reinterpret_cast<std::vector<int32_t> *>(p);
             });
             return py::array(ptr->size(), ptr->data(), capsule);
           })
      .def("get_string_by_name",
           [](PredictorRes &self, int model_idx, std::string &name) {
             return self.get_string_by_name_with_rv(model_idx, name);
           })
      .def("get_shape",
           [](PredictorRes &self, int model_idx, std::string &name) {
             std::vector<int> *ptr = new std::vector<int>(
                 std::move(self.get_shape_by_name_with_rv(model_idx, name)));
             auto capsule = py::capsule(ptr, [](void *p) {
               delete reinterpret_cast<std::vector<int> *>(p);
             });
             return py::array(ptr->size(), ptr->data(), capsule);
           })
      .def("get_lod",
           [](PredictorRes &self, int model_idx, std::string &name) {
             std::vector<int> *ptr = new std::vector<int>(
                 std::move(self.get_lod_by_name_with_rv(model_idx, name)));
             auto capsule = py::capsule(ptr, [](void *p) {
               delete reinterpret_cast<std::vector<int> *>(p);
             });
             return py::array(ptr->size(), ptr->data(), capsule);
           })
      .def("variant_tag", [](PredictorRes &self) { return self.variant_tag(); })
      .def("get_engine_names",
           [](PredictorRes &self) { return self.get_engine_names(); })
      .def("get_tensor_alias_names", [](PredictorRes &self, int model_idx) {
        return self.get_tensor_alias_names(model_idx);
      });

  py::class_<PredictorClient>(m, "PredictorClient", py::buffer_protocol())
      .def(py::init())
      .def("init_gflags",
           [](PredictorClient &self, std::vector<std::string> argv) {
             self.init_gflags(argv);
           })
      .def("init",
           [](PredictorClient &self, const std::vector<std::string> &conf) {
             return self.init(conf);
           })
      .def("set_predictor_conf",
           [](PredictorClient &self,
              const std::string &conf_path,
              const std::string &conf_file) {
             self.set_predictor_conf(conf_path, conf_file);
           })
      .def("create_predictor_by_desc",
           [](PredictorClient &self, const std::string &sdk_desc) {
             self.create_predictor_by_desc(sdk_desc);
           })
      .def("create_predictor",
           [](PredictorClient &self) { self.create_predictor(); })
      .def("destroy_predictor",
           [](PredictorClient &self) { self.destroy_predictor(); })
      .def("numpy_predict",
           [](PredictorClient &self,
              const std::vector<py::array_t<float>> &float_feed,
              const std::vector<std::string> &float_feed_name,
              const std::vector<std::vector<int>> &float_shape,
              const std::vector<std::vector<int>> &float_lod_slot_batch,
              const std::vector<py::array_t<int32_t>> &int32_feed,
              const std::vector<std::string> &int32_feed_name,
              const std::vector<std::vector<int>> &int32_shape,
              const std::vector<std::vector<int>> &int32_lod_slot_batch,
              const std::vector<py::array_t<int64_t>> &int64_feed,
              const std::vector<std::string> &int64_feed_name,
              const std::vector<std::vector<int>> &int64_shape,
              const std::vector<std::vector<int>> &int64_lod_slot_batch,
              const std::vector<std::string> &string_feed,
              const std::vector<std::string> &string_feed_name,
              const std::vector<std::vector<int>> &string_shape,
              const std::vector<std::vector<int>> &string_lod_slot_batch,
              const std::vector<std::string> &fetch_name,
              PredictorRes &predict_res_batch,
              const int &pid,
              const uint64_t log_id) {
             return self.numpy_predict(float_feed,
                                       float_feed_name,
                                       float_shape,
                                       float_lod_slot_batch,
                                       int32_feed,
                                       int32_feed_name,
                                       int32_shape,
                                       int32_lod_slot_batch,
                                       int64_feed,
                                       int64_feed_name,
                                       int64_shape,
                                       int64_lod_slot_batch,
                                       string_feed,
                                       string_feed_name,
                                       string_shape,
                                       string_lod_slot_batch,
                                       fetch_name,
                                       predict_res_batch,
                                       pid,
                                       log_id);
           },
           py::call_guard<py::gil_scoped_release>());
}

}  // namespace general_model
}  // namespace paddle_serving
}  // namespace baidu


<|start_filename|>core/general-server/op/general_detection_op.h<|end_filename|>
// Copyright (c) 2019 PaddlePaddle Authors. 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.

#pragma once
#include <string>
#include <vector>
#include <numeric>
#include "core/general-server/general_model_service.pb.h"
#include "core/general-server/op/general_infer_helper.h"
#include "core/predictor/tools/ocrtools/postprocess_op.h"
#include "core/predictor/tools/ocrtools/preprocess_op.h"
#include "paddle_inference_api.h"  // NOLINT

#include "opencv2/core.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"


namespace baidu {
namespace paddle_serving {
namespace serving {

class GeneralDetectionOp
    : public baidu::paddle_serving::predictor::OpWithChannel<GeneralBlob> {
  public:
    typedef std::vector<paddle::PaddleTensor> TensorVector;

    DECLARE_OP(GeneralDetectionOp);

    int inference();

  private:
    //config info
    bool use_gpu_ = false;
    int gpu_id_ = 0;
    int gpu_mem_ = 4000;
    int cpu_math_library_num_threads_ = 4;
    bool use_mkldnn_ = false;
    // pre-process
    PaddleOCR::ResizeImgType0 resize_op_;
    PaddleOCR::Normalize normalize_op_;
    PaddleOCR::Permute permute_op_;
    PaddleOCR::CrnnResizeImg resize_op_rec;

    bool use_tensorrt_ = false;
    bool use_fp16_ = false;
    // post-process
    PaddleOCR::PostProcessor post_processor_;

    //det config info
    int max_side_len_ = 960;

    double det_db_thresh_ = 0.3;
    double det_db_box_thresh_ = 0.5;
    double det_db_unclip_ratio_ = 1.5;

    std::vector<float> mean_det = {0.485f, 0.456f, 0.406f};
    std::vector<float> scale_det = {1 / 0.229f, 1 / 0.224f, 1 / 0.225f};
    bool is_scale_ = true;

    //rec config info
    std::vector<std::string> label_list_;
    std::vector<float> mean_rec = {0.5f, 0.5f, 0.5f};
    std::vector<float> scale_rec = {1 / 0.5f, 1 / 0.5f, 1 / 0.5f};
    cv::Mat GetRotateCropImage(const cv::Mat &srcimage,
                              std::vector<std::vector<int>> box);
    cv::Mat Base2Mat(std::string &base64_data);
    std::string base64Decode(const char* Data, int DataByte);
    std::vector<std::vector<std::vector<int>>> boxes;
};

}  // namespace serving
}  // namespace paddle_serving
}  // namespace baidu


<|start_filename|>core/preprocess/hwvideoframe/src/normalize.cpp<|end_filename|>
// Copyright (c) 2020 PaddlePaddle Authors. 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.

#include <npp.h>
#include <stdexcept>

#include "core/preprocess/hwvideoframe/include/normalize.h"
#include "core/preprocess/hwvideoframe/include/utils.h"

Normalize::Normalize(const std::vector<float> &mean,
                     const std::vector<float> &std,
                     bool channel_first) {
  if (mean.size() != CHANNEL_SIZE) {
    throw std::runtime_error("size of mean must be three");
  }
  if (std.size() != CHANNEL_SIZE) {
    throw std::runtime_error("size of std must be three");
  }
  for (size_t i = 0; i < CHANNEL_SIZE; i++) {
    _mean[i] = mean[i];
    _std[i] = std[i];
  }
  _channel_first = channel_first;
}

std::shared_ptr<OpContext> Normalize::operator()(
    std::shared_ptr<OpContext> input) {
  NppStatus ret = nppiSubC_32f_C3IR(
      _mean, input->p_frame(), input->step(), input->nppi_size());
  verify_npp_ret("nppiSubC_32f_C3IR", ret);
  ret = nppiDivC_32f_C3IR(
      _std, input->p_frame(), input->step(), input->nppi_size());
  verify_npp_ret("nppiDivC_32f_C3IR", ret);
  return input;
}


<|start_filename|>core/general-client/include/client.h<|end_filename|>
// Copyright (c) 2021 PaddlePaddle Authors. 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.
#pragma once

#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <memory>

namespace baidu {
namespace paddle_serving {
namespace predictor {
  namespace general_model {
    class Request;
    class Response;
  }
}
namespace client {

class PredictorInputs;
class PredictorOutputs;

class ServingClient {
 public:
  ServingClient() {};

  virtual ~ServingClient() = default;

  int init(const std::vector<std::string>& client_conf,
           const std::string server_port);

  int load_client_config(const std::vector<std::string>& client_conf);

  virtual int connect(const std::string server_port) = 0;

  virtual int predict(const PredictorInputs& inputs,
                      PredictorOutputs& outputs,
                      const std::vector<std::string>& fetch_name,
                      const uint64_t log_id) = 0;

 protected:
  std::map<std::string, int> _feed_name_to_idx;
  std::vector<std::string> _feed_name;
  std::map<std::string, int> _fetch_name_to_idx;
  std::map<std::string, std::string> _fetch_name_to_var_name;
  std::map<std::string, int> _fetch_name_to_type;
  std::vector<std::vector<int>> _shape;
  std::vector<int> _type;
  std::vector<int64_t> _last_request_ts;
};

class PredictorData {
 public:
  PredictorData() {};
  virtual ~PredictorData() {};

  void add_float_data(const std::vector<float>& data,
                      const std::string& name,
                      const std::vector<int>& shape,
                      const std::vector<int>& lod,
                      const int datatype = 1);

  void add_int64_data(const std::vector<int64_t>& data,
                      const std::string& name,
                      const std::vector<int>& shape,
                      const std::vector<int>& lod,
                      const int datatype = 0);

  void add_int32_data(const std::vector<int32_t>& data,
                      const std::string& name,
                      const std::vector<int>& shape,
                      const std::vector<int>& lod,
                      const int datatype = 2);

  void add_string_data(const std::string& data,
                       const std::string& name,
                       const std::vector<int>& shape,
                       const std::vector<int>& lod,
                       const int datatype = 20);

  const std::map<std::string, std::vector<float>>& float_data_map() const {
    return _float_data_map;
  };

  std::map<std::string, std::vector<float>>* mutable_float_data_map() {
    return &_float_data_map;
  };

  const std::map<std::string, std::vector<int64_t>>& int64_data_map() const {
    return _int64_data_map;
  };

  std::map<std::string, std::vector<int64_t>>* mutable_int64_data_map() {
    return &_int64_data_map;
  };

  const std::map<std::string, std::vector<int32_t>>& int_data_map() const {
    return _int32_data_map;
  };

  std::map<std::string, std::vector<int32_t>>* mutable_int_data_map() {
    return &_int32_data_map;
  };

  const std::map<std::string, std::string>& string_data_map() const {
    return _string_data_map;
  };

  std::map<std::string, std::string>* mutable_string_data_map() {
    return &_string_data_map;
  };

  const std::map<std::string, std::vector<int>>& shape_map() const {
    return _shape_map;
  };

  std::map<std::string, std::vector<int>>* mutable_shape_map() {
    return &_shape_map;
  };

  const std::map<std::string, std::vector<int>>& lod_map() const {
    return _lod_map;
  };

  std::map<std::string, std::vector<int>>* mutable_lod_map() {
    return &_lod_map;
  };

  int get_datatype(std::string name) const;

  void set_datatype(std::string name, int type);

  std::string print();

 private:
  // used to print vector data map e.g. _float_data_map
  template<typename T1, typename T2>
  std::string map2string(const std::map<T1, std::vector<T2>>& map) {
    std::ostringstream oss;
    oss.str("");
    oss.precision(6);
	  oss.setf(std::ios::fixed);
    std::string key_seg = ":";
    std::string val_seg = ",";
    std::string end_seg = "\n";
    typename std::map<T1, std::vector<T2>>::const_iterator it = map.begin();
    typename std::map<T1, std::vector<T2>>::const_iterator itEnd = map.end();
    for (; it != itEnd; it++) {
      oss << "{";
      oss << it->first << key_seg;
      const std::vector<T2>& v = it->second;
      oss << v.size() << key_seg;
      for (size_t i = 0; i < v.size(); ++i) {
        if (i != v.size() - 1) {
          oss << v[i] << val_seg;
        }
        else {
          oss << v[i];
        }
      }
      oss << "}";
    }
    return oss.str();
  };

  // used to print data map without vector e.g. _string_data_map
  template<typename T1, typename T2>
  std::string map2string(const std::map<T1, T2>& map) {
    std::ostringstream oss;
    oss.str("");
    std::string key_seg = ":";
    std::string val_seg = ",";
    std::string end_seg = "\n";
    typename std::map<T1, T2>::const_iterator it = map.begin();
    typename std::map<T1, T2>::const_iterator itEnd = map.end();
    for (; it != itEnd; it++) {
      oss << "{";
      oss << it->first << key_seg
          << "size=" << it->second.size() << key_seg
          << "type=" << this->get_datatype(it->first);
      oss << "}";
    }
    return oss.str();
  };

 protected:
  std::map<std::string, std::vector<float>> _float_data_map;
  std::map<std::string, std::vector<int64_t>> _int64_data_map;
  std::map<std::string, std::vector<int32_t>> _int32_data_map;
  std::map<std::string, std::string> _string_data_map;
  std::map<std::string, std::vector<int>> _shape_map;
  std::map<std::string, std::vector<int>> _lod_map;
  std::map<std::string, int> _datatype_map;
};

class PredictorInputs : public PredictorData {
 public:
  PredictorInputs() {};
  virtual ~PredictorInputs() {};

  // generate proto from inputs
  // feed_name_to_idx: mapping alias name to idx
  // feed_name: mapping idx to name
  static int GenProto(const PredictorInputs& inputs,
                      const std::map<std::string, int>& feed_name_to_idx,
                      const std::vector<std::string>& feed_name,
                      predictor::general_model::Request& req);
};

class PredictorOutputs {
 public:
  struct PredictorOutput {
    std::string engine_name;
    PredictorData data;
  };

  PredictorOutputs() {};
  virtual ~PredictorOutputs() {};

  const std::vector<std::shared_ptr<PredictorOutputs::PredictorOutput>>& datas() {
    return _datas;
  };

  std::vector<std::shared_ptr<PredictorOutputs::PredictorOutput>>* mutable_datas() {
    return &_datas;
  };

  void add_data(const std::shared_ptr<PredictorOutputs::PredictorOutput>& data) {
    _datas.push_back(data);
  };

  std::string print();

  void clear();

  // Parse proto to outputs
  // fetch_name: name of data to be output
  // fetch_name_to_type: mapping of fetch_name to datatype
  static int ParseProto(const predictor::general_model::Response& res,
                        const std::vector<std::string>& fetch_name,
                        std::map<std::string, int>& fetch_name_to_type,
                        PredictorOutputs& outputs);

 protected:
  std::vector<std::shared_ptr<PredictorOutputs::PredictorOutput>> _datas;
};

}  // namespace client
}  // namespace paddle_serving
}  // namespace baidu

<|start_filename|>core/preprocess/hwvideoframe/src/sub.cpp<|end_filename|>
// Copyright (c) 2020 PaddlePaddle Authors. 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.

#include <npp.h>
#include <stdexcept>

#include "core/preprocess/hwvideoframe/include/sub.h"
#include "core/preprocess/hwvideoframe/include/utils.h"

Sub::Sub(float subtractor) {
  for (size_t i = 0; i < CHANNEL_SIZE; i++) {
    _subtractors[i] = subtractor;
  }
}

Sub::Sub(const std::vector<float> &subtractors) {
  if (subtractors.size() != CHANNEL_SIZE) {
    throw std::runtime_error("size of subtractors must be three");
  }
  for (size_t i = 0; i < CHANNEL_SIZE; i++) {
    _subtractors[i] = subtractors[i];
  }
}

std::shared_ptr<OpContext> Sub::operator()(std::shared_ptr<OpContext> input) {
  NppStatus ret = nppiSubC_32f_C3IR(
      _subtractors, input->p_frame(), input->step(), input->nppi_size());
  verify_npp_ret("nppiSubC_32f_C3IR", ret);
  return input;
}


<|start_filename|>core/preprocess/hwvideoframe/include/rgb_swap.h<|end_filename|>
// Copyright (c) 2020 PaddlePaddle Authors. 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.

#ifndef CORE_PREPROCESS_HWVIDEOFRAME_INCLUDE_RGB_SWAP_H_
#define CORE_PREPROCESS_HWVIDEOFRAME_INCLUDE_RGB_SWAP_H_

#include <npp.h>
#include <memory>
#include "core/preprocess/hwvideoframe/include/op_context.h"

// swap channel 0 and channel 2 for every pixel
// both RGB2BGR and BGR2RGB use this operator
class SwapChannel {
 public:
  SwapChannel() {}
  std::shared_ptr<OpContext> operator()(std::shared_ptr<OpContext> input);

 private:
  static const int
      _ORDER[CHANNEL_SIZE];  // describing how channel values are permutated
};

class RGB2BGR : public SwapChannel {};
class BGR2RGB : public SwapChannel {};

#endif  // CORE_PREPROCESS_HWVIDEOFRAME_INCLUDE_RGB_SWAP_H_


<|start_filename|>core/predictor/framework/cache.h<|end_filename|>
// Copyright (c) 2019 PaddlePaddle Authors. 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.

#pragma once
#include <sys/types.h>
#include <numeric>
#include <string>
#include <unordered_map>
#include "core/cube/cube-api/include/cube_api.h"

namespace baidu {
namespace paddle_serving {
namespace predictor {

// Large models that use sparse parameters may use cube cache.
// When the cube cache exists, the model is required to be
// consistent with the version of the cube cache. Therefore,
// when the model is updated, the model and the cube cache are
// required to be reloaded at the same time.
// Load all cached data at once without updating, it's lock free
// switching two cube cache.
class CubeCache {
 public:
  CubeCache() {}

  ~CubeCache() { clear(); }

  // clear cache data.
  int clear();

  // get cache data by key
  rec::mcube::CubeValue* get_data(uint64_t key);

  // reload all cache files from cache_path
  int reload_data(const std::string& cache_path);

 private:
  // switching free lock, key type is uint64_t, value type is CubeValue*
  std::unordered_map<uint64_t, rec::mcube::CubeValue*> _map_cache;
};

}  // namespace predictor
}  // namespace paddle_serving
}  // namespace baidu


<|start_filename|>core/predictor/framework/resource.h<|end_filename|>
// Copyright (c) 2019 PaddlePaddle Authors. 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.

#pragma once
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "core/cube/cube-api/include/cube_api.h"
#include "core/predictor/common/inner_common.h"
#include "core/predictor/framework/infer.h"
#include "core/predictor/framework/memory.h"

namespace baidu {
namespace paddle_serving {
namespace predictor {

// Paddle general model configuration, read the model configuration information
// from the general_model_config.proto file
class PaddleGeneralModelConfig {
 public:
  PaddleGeneralModelConfig() {}

  ~PaddleGeneralModelConfig() {}

 public:
  // feed/fetch name and alias_name
  std::vector<std::string> _feed_name;
  std::vector<std::string> _feed_alias_name;
  std::vector<std::string> _fetch_name;
  std::vector<std::string> _fetch_alias_name;

  // Be consistent with model saving interface var type conversion
  // (python/paddle serving client/io/__init__)
  // int64 => 0;
  // float32 => 1;
  // int32 => 2;
  // float64 => 3;
  // int16 => 4;
  // float16 => 5;
  // bfloat16 => 6;
  // uint8 => 7;
  // int8 => 8;
  // bool => 9;
  // complex64 => 10,
  // complex128 => 11;
  std::vector<int> _feed_type;

  // whether a feed or fetch var is lod_tensor.
  std::vector<bool> _is_lod_feed;
  std::vector<bool> _is_lod_fetch;

  // capacity for each tensor
  std::vector<int> _capacity;

  // _feed_shape and _fetch_shape are used to represent the dimensional
  // information of tensor.
  // for examples, feed_shape_[i][j] represents the j(th) dim for i(th) input
  // tensor.
  // if is_lod_feed_[i] == False, feed_shape_[i][0] = -1
  std::vector<std::vector<int>> _feed_shape;
  std::vector<std::vector<int>> _fetch_shape;

  // fetch name -> index of fetch_name vector.
  std::map<std::string, int> _fetch_name_to_index;

  // fetch alias name -> index of fetch_alias_name vector.
  std::map<std::string, int> _fetch_alias_name_to_index;
};

class BaseRdDict;

class Resource {
 public:
  Resource() {
    // Reference InferManager::instance() explicitly, to make sure static
    // instance of InferManager is constructed before that of Resource, and
    // destruct after that of Resource
    // See https://stackoverflow.com/a/335746/1513460
    InferManager::instance();
  }

  ~Resource() { finalize(); }

  static Resource& instance() {
    static Resource ins;
    return ins;
  }

  // initialize resource
  int initialize(const std::string& path, const std::string& file);

  // loading all models configurations from prototxt
  int general_model_initialize(const std::string& path,
                               const std::string& file);

  // initialize thread local data
  int thread_initialize();

  // clear thread local data
  int thread_clear();

  // reload resources
  int reload();

  // finalize
  int finalize();

  // get all model configs
  std::vector<std::shared_ptr<PaddleGeneralModelConfig>>
  get_general_model_config();

  // print all configurations of all models
  void print_general_model_config(
      const std::shared_ptr<PaddleGeneralModelConfig>& config);

  // get cube quantity bit size
  size_t get_cube_quant_bits();

 private:
  int thread_finalize() { return 0; }

 private:
  // configuration infermation of all models, loading from prototxt files
  std::vector<std::shared_ptr<PaddleGeneralModelConfig>> _configs;

  // full path of cube configuration file.
  std::string _cube_config_fullpath;

  // cube quantify bit size, support 0/8. set 0 if no quant.
  size_t _cube_quant_bits;

  // bthread local key
  THREAD_KEY_T _tls_bspec_key;
};

}  // namespace predictor
}  // namespace paddle_serving
}  // namespace baidu


<|start_filename|>core/preprocess/hwvideoframe/src/image_io.cpp<|end_filename|>
// Copyright (c) 2020 PaddlePaddle Authors. 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.

#include <cuda_runtime.h>
#include <pybind11/numpy.h>

#include <stdexcept>

#include "core/preprocess/hwvideoframe/include/image_io.h"
#include "core/preprocess/hwvideoframe/include/utils.h"

std::shared_ptr<OpContext> Image2Gpubuffer::operator()(
    pybind11::array_t<float> input) {
  pybind11::buffer_info buf = input.request();
  if (buf.format != pybind11::format_descriptor<float>::format()) {
    throw std::runtime_error("Incompatible format: expected a float numpy!");
  }
  if (buf.ndim != 3) {
    throw std::runtime_error("Number of dimensions must be three");
  }
  if (buf.shape[2] != CHANNEL_SIZE) {
    throw std::runtime_error("Number of channels must be three");
  }
  auto result = std::make_shared<OpContext>(buf.shape[0], buf.shape[1]);
  auto ret = cudaMemcpy(result->p_frame(),
                        static_cast<float*>(buf.ptr),
                        result->size(),
                        cudaMemcpyHostToDevice);
  verify_cuda_ret("cudaMemcpy", ret);
  return result;
}

pybind11::array_t<float> Gpubuffer2Image::operator()(
    std::shared_ptr<OpContext> input) {
  auto result = pybind11::array_t<float>({input->nppi_size().height,
                                          input->nppi_size().width,
                                          static_cast<int>(CHANNEL_SIZE)});
  pybind11::buffer_info buf = result.request();
  auto ret = cudaMemcpy(static_cast<float*>(buf.ptr),
                        input->p_frame(),
                        input->size(),
                        cudaMemcpyDeviceToHost);
  verify_cuda_ret("cudaMemcpy", ret);
  return result;
}


<|start_filename|>core/predictor/framework/cache.cpp<|end_filename|>
// Copyright (c) 2019 PaddlePaddle Authors. 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

#include "core/predictor/framework/cache.h"
#include <dirent.h>
#include <sys/stat.h>
#include <fstream>
#include <string>
#include <utility>
#include "core/cube/cube-builder/include/cube-builder/seqfile_reader.h"

namespace baidu {
namespace paddle_serving {
namespace predictor {

int CubeCache::clear() {
  for (auto it = _map_cache.begin(); it != _map_cache.end(); ++it) {
    if (it->second) {
      delete (it->second);
      it->second = nullptr;
    }
  }
  _map_cache.clear();

  return 0;
}

rec::mcube::CubeValue* CubeCache::get_data(uint64_t key) {
  auto it = _map_cache.find(key);
  if (it != _map_cache.end()) {
    return it->second;
  }
  return nullptr;
}

int CubeCache::reload_data(const std::string& cache_path) {
  LOG(INFO) << "cube cache is loading data, path: " << cache_path;
  DIR* dp = nullptr;
  struct dirent* dirp = nullptr;
  struct stat st;

  // clear cache data
  clear();

  // loading data from cache files
  if (stat(cache_path.c_str(), &st) < 0 || !S_ISDIR(st.st_mode)) {
    LOG(ERROR) << "invalid cache path " << cache_path;
    return -1;
  }
  if ((dp = opendir(cache_path.c_str())) == nullptr) {
    LOG(ERROR) << "opendir " << cache_path << " fail.";
    return -1;
  }
  while ((dirp = readdir(dp)) != nullptr) {
    // filtering by file type.
    if (dirp->d_type != DT_REG) {
      continue;
    }
    // Filter upper-level directories and hidden files
    if ((!strncmp(dirp->d_name, ".", 1)) || (!strncmp(dirp->d_name, "..", 2))) {
      continue;
    }
    // Match the file whose name prefix is ​​'part-'
    if (std::string(dirp->d_name).find("part-") != std::string::npos) {
      SequenceFileRecordReader reader(cache_path + "/" + dirp->d_name);

      if (reader.open() != 0) {
        LOG(ERROR) << "open file failed! " << dirp->d_name;
        continue;
      }
      if (reader.read_header() != 0) {
        LOG(ERROR) << "read header error! " << dirp->d_name;
        reader.close();
        continue;
      }

      Record record(reader.get_header());
      while (reader.next(&record) == 0) {
        uint64_t key =
            *reinterpret_cast<uint64_t*>(const_cast<char*>(record.key.data()));

        auto it_find = _map_cache.find(key);
        if (it_find != _map_cache.end()) {
          // load dumplicate key
          LOG(WARNING) << "Load dumplicate key:" << key
                       << " from file:" << dirp->d_name;
          continue;
        }
        rec::mcube::CubeValue* new_value = new rec::mcube::CubeValue();
        new_value->error = 0;
        new_value->buff.swap(record.value);
        _map_cache.insert(std::make_pair(key, new_value));
      }

      LOG(WARNING) << "Load cube cache file " << dirp->d_name << " done.";
    }
    LOG(WARNING) << "Load all cube cache files done";
  }
  return 0;
}

}  // namespace predictor
}  // namespace paddle_serving
}  // namespace baidu


<|start_filename|>cmake/external/boost.cmake<|end_filename|>
# Copyright (c) 2016 PaddlePaddle Authors. 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.

include(ExternalProject)

set(BOOST_PROJECT       "extern_boost")
# To release PaddlePaddle as a pip package, we have to follow the
# manylinux1 standard, which features as old Linux kernels and
# compilers as possible and recommends CentOS 5. Indeed, the earliest
# CentOS version that works with NVIDIA CUDA is CentOS 6.  And a new
# version of boost, say, 1.66.0, doesn't build on CentOS 6.  We
# checked that the devtools package of CentOS 6 installs boost 1.41.0.
# So we use 1.41.0 here.

set(BOOST_VER           "1.74.0")
set(BOOST_TAR "boost_1_74_0" CACHE STRING "" FORCE)
set(BOOST_URL "http://paddlepaddledeps.bj.bcebos.com/${BOOST_TAR}.tar.gz" CACHE STRING "" FORCE)

MESSAGE(STATUS "BOOST_TAR: ${BOOST_TAR}, BOOST_URL: ${BOOST_URL}")

set(BOOST_SOURCES_DIR ${THIRD_PARTY_PATH}/boost)
set(BOOST_DOWNLOAD_DIR  "${BOOST_SOURCES_DIR}/src/${BOOST_PROJECT}")

set(BOOST_INCLUDE_DIR "${BOOST_DOWNLOAD_DIR}" CACHE PATH "boost include directory." FORCE)
set_directory_properties(PROPERTIES CLEAN_NO_CUSTOM 1)
include_directories(${BOOST_INCLUDE_DIR})

ExternalProject_Add(
    ${BOOST_PROJECT}
    ${EXTERNAL_PROJECT_LOG_ARGS}
    DOWNLOAD_DIR          ${BOOST_DOWNLOAD_DIR}
    URL      ${BOOST_URL}
    DOWNLOAD_NO_PROGRESS  1
    PREFIX                ${BOOST_SOURCES_DIR}
    CONFIGURE_COMMAND     ""
    BUILD_COMMAND         ""
    INSTALL_COMMAND       ""
    UPDATE_COMMAND        ""
    )

if (${CMAKE_VERSION} VERSION_LESS "3.3.0" OR NOT WIN32)
    set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/boost_dummy.c)
    file(WRITE ${dummyfile} "const char *dummy = \"${dummyfile}\";")
    add_library(boost STATIC ${dummyfile})
else()
    add_library(boost INTERFACE)
endif()

add_dependencies(boost ${BOOST_PROJECT})
list(APPEND external_project_dependencies boost)
set(Boost_INCLUDE_DIR ${BOOST_INCLUDE_DIR})


<|start_filename|>core/predictor/common/utils.h<|end_filename|>
// Copyright (c) 2019 PaddlePaddle Authors. 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.

#pragma once
#include <algorithm>
#include <cctype>
#include <fstream>
#include <string>
#include "core/predictor/common/inner_common.h"
#include "core/predictor/common/macros.h"

namespace baidu {
namespace paddle_serving {
namespace predictor {

#ifdef BCLOUD
namespace butil = base;
#endif

enum class Precision {
  kUnk = -1,     // unknown type
  kFloat32 = 0,  // fp32
  kInt8,         // int8
  kHalf,         // fp16
  kBfloat16,     // bf16
};

static std::string PrecisionTypeString(const Precision data_type) {
  switch (data_type) {
    case Precision::kFloat32:
      return "kFloat32";
    case Precision::kInt8:
      return "kInt8";
    case Precision::kHalf:
      return "kHalf";
    case Precision::kBfloat16:
      return "kBloat16";
    default:
      return "unUnk";
  }
}

static std::string ToLower(const std::string& data) {
  std::string result = data;
  std::transform(
      result.begin(), result.end(), result.begin(), [](unsigned char c) {
        return tolower(c);
      });
  return result;
}

class TimerFlow {
 public:
  static const int MAX_SIZE = 1024;

  TimerFlow() { init(); }

  void init() {
    _csize = 0;
    _name = NULL;
    _started = false;
    _auto = false;
  }

  explicit TimerFlow(const char* name) : _csize(0), _name(name) {
    _last = _start = butil::cpuwide_time_us();
    _auto = true;
    _started = true;
  }

  void set_name(const char* name) { _name = name; }

  void start() {
    _last = _start = butil::cpuwide_time_us();
    _started = true;
  }

  bool check(const char* tag) {
    if (!_started) {
      LOG(WARNING) << "Timer not started yet!";
      return false;
    }
    uint64_t now = butil::cpuwide_time_us();
    if (!appendf("%s:%lu|", tag, now - _last)) {
      LOG(WARNING) << "Failed check timer: " << _name << ", value = [" << tag
                   << ":" << (now - _last) << "]!";
      return false;
    }

    _last = now;
    return true;
  }

  std::string info() { return std::string(_buf); }

  void end() {
    uint64_t now = butil::cpuwide_time_us();
    if (!appendf("total:%lu", now - _start)) {
      LOG(WARNING) << "Failed dump time_info[" << _name << "]";
    }
    _started = false;
  }

  ~TimerFlow() {
    if (!_auto) {
      return;
    }
    uint64_t now = butil::cpuwide_time_us();
    if (appendf("total:%lu,%s", now - _start, _name)) {
      LOG(INFO) << " " << _name << "_tc=[" << _buf << "]";
    } else {
      LOG(WARNING) << "Failed dump time_info[" << _name << "]";
    }
  }

 private:
  bool appendf(const char* fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    try {
      int bytes = vsnprintf(_buf + _csize, MAX_SIZE - _csize, fmt, ap);
      if (bytes >= MAX_SIZE - _csize || bytes < 0) {
        LOG(WARNING) << "Overflow when appendf!";
        return false;
      }
      _csize += bytes;
    }
    CATCH_ANY_AND_RET(false);

    va_end(ap);
    return true;
  }

 private:
  char _buf[1024];
  int _csize;
  uint64_t _start;
  uint64_t _last;
  const char* _name;
  bool _started;
  bool _auto;
};

template <bool flag>
struct derived_from_message {};

template <typename T, typename TBase>
class TIsDerivedFromB {
 private:
  static uint8_t check(TBase*) { return 1; }

  static uint32_t check(void*) { return 0; }

 public:
  enum {
    // function call cannot apprear in a constant-expression
    RESULT = (sizeof(uint8_t) == sizeof(check(reinterpret_cast<T*>(NULL)))),
  };
};

template <typename TBase>
class IsDerivedFrom {
 private:
  static bool check(TBase*) { return true; }

  static bool check(void*) { return false; }

 public:
  template <typename T>
  static bool yes(T* x) {
    return check(x);
  }
};

static void ReadBinaryFile(const std::string& filename, std::string* contents) {
  std::ifstream fin(filename, std::ios::in | std::ios::binary);
  fin.seekg(0, std::ios::end);
  contents->clear();
  contents->resize(fin.tellg());
  fin.seekg(0, std::ios::beg);
  fin.read(&(contents->at(0)), contents->size());
  fin.close();
}

}  // namespace predictor
}  // namespace paddle_serving
}  // namespace baidu


<|start_filename|>core/preprocess/hwvideoframe/include/op_context.h<|end_filename|>
// Copyright (c) 2020 PaddlePaddle Authors. 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.

#ifndef CORE_PREPROCESS_HWVIDEOFRAME_INCLUDE_OP_CONTEXT_H_
#define CORE_PREPROCESS_HWVIDEOFRAME_INCLUDE_OP_CONTEXT_H_

#include <npp.h>

const size_t CHANNEL_SIZE = 3;

// The context as input/ouput of all operators
// contains pointer to raw data on gpu, frame size
class OpContext {
 public:
  OpContext() {
    _step = 0;
    _size = 0;
    _p_frame = nullptr;
  }
  // constructor to apply gpu memory of image raw data
  OpContext(int height, int width) {
    _step = sizeof(Npp32f) * width * CHANNEL_SIZE;
    _length = height * width * CHANNEL_SIZE;
    _size = _step * height;
    _nppi_size.height = height;
    _nppi_size.width = width;
    cudaMalloc(reinterpret_cast<void**>(&_p_frame), _size);
  }
  virtual ~OpContext() { free_memory(); }

 public:
  Npp32f* p_frame() const { return _p_frame; }
  int step() const { return _step; }
  int length() const { return _length; }
  int size() const { return _size; }
  NppiSize& nppi_size() { return _nppi_size; }
  void free_memory() {
    if (_p_frame != nullptr) {
      cudaFree(_p_frame);
      _p_frame = nullptr;
    }
    _nppi_size.height = 0;
    _nppi_size.width = 0;
    _step = 0;
    _size = 0;
  }

 private:
  Npp32f* _p_frame;     // pointer to raw data on gpu
  int _step;            // number of bytes in a row
  int _length;          // length of _p_frame, _size = _length * sizeof(Npp32f)
  int _size;            // number of bytes of the image
  NppiSize _nppi_size;  // contains height and width
};

#endif  // CORE_PREPROCESS_HWVIDEOFRAME_INCLUDE_OP_CONTEXT_H_


<|start_filename|>core/pdcodegen/src/pdcodegen.cpp<|end_filename|>
// Copyright (c) 2019 PaddlePaddle Authors. 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.

#include <list>
#include "boost/algorithm/string.hpp"
#include "boost/scoped_ptr.hpp"
#include "core/pdcodegen/pds_option.pb.h"
#include "core/pdcodegen/plugin/strutil.h"
#include "core/pdcodegen/plugin/substitute.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/compiler/plugin.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/io/printer.h"
#include "google/protobuf/io/zero_copy_stream.h"
using std::string;
using google::protobuf::Descriptor;
using google::protobuf::FileDescriptor;
using google::protobuf::FieldDescriptor;
using google::protobuf::MethodDescriptor;
using google::protobuf::ServiceDescriptor;
using google::protobuf::compiler::CodeGenerator;
using google::protobuf::compiler::GeneratorContext;
using google::protobuf::HasSuffixString;
using google::protobuf::StripSuffixString;
namespace google {
namespace protobuf {
string dots_to_colons(const string& name) {
  return StringReplace(name, ".", "::", true);
}
string full_class_name(const Descriptor* descriptor) {
  // Find "outer", the descriptor of the top-level message in which
  // "descriptor" is embedded.
  const Descriptor* outer = descriptor;
  while (outer->containing_type() != NULL) {
    outer = outer->containing_type();
  }
  return outer->full_name();
}
}  // namespace protobuf
}  // namespace google
string strip_proto(const string& filename) {
  if (HasSuffixString(filename, ".protolevel")) {
    return StripSuffixString(filename, ".protolevel");
  } else {
    return StripSuffixString(filename, ".proto");
  }
}
void string_format(std::string& source) {  // NOLINT
  size_t len = source.length();
  std::string sep = "_";
  for (int i = 0; i < len; i++) {
    if (source[i] >= 'A' && source[i] <= 'Z') {
      source[i] += 32;
      if (i == 0) {
        continue;
      }
      source.insert(i, sep);
      i++;
      len++;
    }
  }
}
bool valid_service_method(const std::vector<const MethodDescriptor*>& methods) {
  if (methods.size() != 2) {
    return false;
  }
  if (methods[0]->name() == "inference" && methods[1]->name() == "debug") {
    return true;
  }
  if (methods[1]->name() == "inference" && methods[0]->name() == "debug") {
    return true;
  }
  return false;
}

#ifdef BCLOUD
class PdsCodeGenerator : public CodeGenerator {
 public:
  virtual bool Generate(const FileDescriptor* file,
                        const string& parameter,
                        GeneratorContext* context,
                        std::string* error) const {
    const string header = strip_proto(file->name()) + ".pb.h";
    const string body = strip_proto(file->name()) + ".pb.cc";
    bool include_inserted = false;
    for (int i = 0; i < file->service_count(); ++i) {
      const ServiceDescriptor* descriptor = file->service(i);
      if (!descriptor) {
        *error = "get descriptor failed";
        return false;
      }
      pds::PaddleServiceOption options =
          descriptor->options().GetExtension(pds::options);
      bool generate_impl = options.generate_impl();
      bool generate_stub = options.generate_stub();
      if (!generate_impl && !generate_stub) {
        return true;
      }
      if (!include_inserted) {
        boost::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
            context->OpenForInsert(header, "includes"));
        google::protobuf::io::Printer printer(output.get(), '$');
        if (generate_impl) {
          printer.Print("#include \"core/predictor/common/inner_common.h\"\n");
          printer.Print("#include \"core/predictor/framework/service.h\"\n");
          printer.Print("#include \"core/predictor/framework/manager.h\"\n");
          printer.Print(
              "#include \"core/predictor/framework/service_manager.h\"\n");
        }
        if (generate_stub) {
          printer.Print("#include <baidu/rpc/parallel_channel.h>\n");
          printer.Print("#include \"core/sdk-cpp/include/factory.h\"\n");
          printer.Print("#include \"core/sdk-cpp/include/stub.h\"\n");
          printer.Print("#include \"core/sdk-cpp/include/stub_impl.h\"\n");
        }
        include_inserted = true;
      }
      const std::string& class_name = descriptor->name();
      const std::string& service_name = descriptor->name();
      // xxx.ph.h
      {
        if (generate_impl) {
          // service scope
          // namespace scope
          boost::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
              context->OpenForInsert(header, "namespace_scope"));
          google::protobuf::io::Printer printer(output.get(), '$');
          if (!generate_paddle_serving_head(
                  &printer, descriptor, error, service_name, class_name)) {
            return false;
          }
        }
        if (generate_stub) {
          // service class scope

          // namespace scope
          {
            boost::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream>
                output(context->OpenForInsert(header, "namespace_scope"));
            google::protobuf::io::Printer printer(output.get(), '$');
            if (!generate_paddle_serving_stub_head(
                    &printer, descriptor, error, service_name, class_name)) {
              return false;
            }
          }
        }
      }
      // xxx.pb.cc
      {
        if (generate_impl) {
          // service scope
          // namespace scope
          boost::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
              context->OpenForInsert(body, "namespace_scope"));
          google::protobuf::io::Printer printer(output.get(), '$');
          if (!generate_paddle_serving_body(
                  &printer, descriptor, error, service_name, class_name)) {
            return false;
          }
        }
        if (generate_stub) {
          // service class scope
          {}  // namespace scope
          {
            boost::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream>
                output(context->OpenForInsert(body, "namespace_scope"));
            google::protobuf::io::Printer printer(output.get(), '$');
            if (!generate_paddle_serving_stub_body(
                    &printer, descriptor, error, service_name, class_name)) {
              return false;
            }
          }
        }
      }
    }
    return true;
  }

 private:
  bool generate_paddle_serving_head(google::protobuf::io::Printer* printer,
                                    const ServiceDescriptor* descriptor,
                                    string* error,
                                    const std::string& service_name,
                                    const std::string& class_name) const {
    std::vector<const MethodDescriptor*> methods;
    for (int i = 0; i < descriptor->method_count(); ++i) {
      methods.push_back(descriptor->method(i));
    }
    if (!valid_service_method(methods)) {
      *error = "Service can only contains two methods: inferend, debug";
      return false;
    }
    std::string variable_name = class_name;
    string_format(variable_name);
    printer->Print(
        "class $name$Impl : public $name$ {\n"
        "public:\n"
        "  virtual ~$name$Impl() {}\n"
        "  static $name$Impl& instance() {\n"
        "    return _s_$variable_name$_impl;\n"
        "  }\n\n"
        "  $name$Impl(const std::string& service_name) {\n"
        "    REGIST_FORMAT_SERVICE(\n"
        "            service_name, &$name$Impl::instance());\n"
        "  }\n\n",
        "name",
        class_name,
        "variable_name",
        variable_name);
    for (int i = 0; i < methods.size(); i++) {
      const MethodDescriptor* m = methods[i];
      printer->Print(
          "  virtual void $name$(google::protobuf::RpcController* cntl_base,\n"
          "          const $input_name$* request,\n"
          "          $output_name$* response,\n"
          "          google::protobuf::Closure* done);\n\n",
          "name",
          m->name(),
          "input_name",
          google::protobuf::dots_to_colons(m->input_type()->full_name()),
          "output_name",
          google::protobuf::dots_to_colons(m->output_type()->full_name()));
    }
    printer->Print(
        "  static $name$Impl _s_$variable_name$_impl;\n"
        "};",
        "name",
        class_name,
        "variable_name",
        variable_name);
    return true;
  }
  bool generate_paddle_serving_body(google::protobuf::io::Printer* printer,
                                    const ServiceDescriptor* descriptor,
                                    string* error,
                                    const std::string& service_name,
                                    const std::string& class_name) const {
    std::vector<const MethodDescriptor*> methods;
    for (int i = 0; i < descriptor->method_count(); ++i) {
      methods.push_back(descriptor->method(i));
    }
    if (!valid_service_method(methods)) {
      *error = "Service can only contains two methods: inferend, debug";
      return false;
    }
    std::string variable_name = class_name;
    string_format(variable_name);
    for (int i = 0; i < methods.size(); i++) {
      const MethodDescriptor* m = methods[i];
      printer->Print("void $name$Impl::$method$(\n",
                     "name",
                     class_name,
                     "method",
                     m->name());
      printer->Print(
          "        google::protobuf::RpcController* cntl_base,\n"
          "        const $input_name$* request,\n"
          "        $output_name$* response,\n"
          "        google::protobuf::Closure* done) {\n"
          "   struct timeval tv;\n"
          "   gettimeofday(&tv, NULL);"
          "   long start = tv.tv_sec * 1000000 + tv.tv_usec;",
          "input_name",
          google::protobuf::dots_to_colons(m->input_type()->full_name()),
          "output_name",
          google::protobuf::dots_to_colons(m->output_type()->full_name()));
      if (m->name() == "inference") {
        std::string inference_body = "";
        inference_body += "  brpc::ClosureGuard done_guard(done);\n";
        inference_body += "  brpc::Controller* cntl = \n";
        inference_body += "        static_cast<brpc::Controller*>(cntl_base);\n";
        inference_body += "  cntl->set_response_compress_type(brpc::COMPRESS_TYPE_GZIP);\n";
        inference_body += "  uint64_t log_id = request->log_id();\n";
        inference_body += "  cntl->set_log_id(log_id);\n";
        inference_body += "  ::baidu::paddle_serving::predictor::InferService* svr = \n";
        inference_body += "       ";
        inference_body += "::baidu::paddle_serving::predictor::InferServiceManager::instance(";
        inference_body += ").item(\"$service$\");\n";
        inference_body += "  if (svr == NULL) {\n";
        inference_body += "    LOG(ERROR) << \"(logid=\" << log_id << \") Not found service: ";
        inference_body += "$service$\";\n";
        inference_body += "    cntl->SetFailed(404, \"Not found service: $service$\");\n";
        inference_body += "    return ;\n";
        inference_body += "  }\n";
        inference_body += "  LOG(INFO) << \"(logid=\" << log_id << \") ";
        inference_body += "remote_side=\[\" << cntl->remote_side() << ";  // NOLINT
        inference_body += "\"\]\";\n";
        inference_body += "  LOG(INFO) << \"(logid=\" << log_id << \") ";
        inference_body += "local_side=\[\" << cntl->local_side() << ";  // NOLINT
        inference_body += "\"\]\";\n";
        inference_body += "  LOG(INFO) << \"(logid=\" << log_id << \") ";
        inference_body += "service_name=\[\" << \"$name$\" << \"\]\";\n";  // NOLINT
        inference_body += "  int err_code = svr->inference(request, response, log_id);\n";
        inference_body += "  if (err_code != 0) {\n";
        inference_body += "    LOG(WARNING)\n";
        inference_body += "        << \"(logid=\" << log_id << \") Failed call ";
        inference_body += "inferservice[$name$], name[$service$]\"\n";
        inference_body += "        << \", error_code: \" << err_code;\n";
        inference_body += "    cntl->SetFailed(err_code, \"InferService inference ";
        inference_body += "failed!\");\n";
        inference_body += "  }\n";
        inference_body += "  gettimeofday(&tv, NULL);\n";
        inference_body += "  long end = tv.tv_sec * 1000000 + tv.tv_usec;\n";
        if (service_name == "GeneralModelService") {
          inference_body += "  std::ostringstream oss;\n";
          inference_body += "  oss << \"[serving]\"\n";
          inference_body += "      << \"logid=\" << log_id << \",\";\n";
          inference_body += "  int op_num = response->profile_time_size() / 2;\n";
          inference_body += "  for (int i = 0; i < op_num; ++i) {\n";
          inference_body += "    double t = (response->profile_time(i * 2 + 1)\n";
          inference_body += "                - response->profile_time(i * 2)) / 1000.0;\n";
          inference_body += "    oss << \"op\" << i << \"=\" << t << \"ms,\";\n";
          inference_body += "  }\n";
          inference_body += "  double total_time = (end - start) / 1000.0;\n";
          inference_body += "  oss << \"cost=\" << total_time << \"ms.\";\n";
          inference_body += "  // flush notice log\n";
          inference_body += "  LOG(INFO) << oss.str();\n";
          inference_body += "  response->add_profile_time(start);\n";
          inference_body += "  response->add_profile_time(end);\n";
        } else {
          inference_body += "  // flush notice log\n";
          inference_body += "  LOG(INFO) << \"(logid=\" << log_id << \") tc=\[\" << (end - ";  // NOLINT
          inference_body += "start) << \"\]\";\n";
        }
        printer->Print(
            inference_body.c_str(),
            "name",
            class_name,
            "service",
            service_name);
      }
      if (m->name() == "debug") {
        printer->Print(
            "  baidu::rpc::ClosureGuard done_guard(done);\n"
            "  baidu::rpc::Controller* cntl = \n"
            "        static_cast<baidu::rpc::Controller*>(cntl_base);\n"
            "  cntl->set_response_compress_type(brpc::COMPRESS_TYPE_GZIP);\n"
            "  uint64_t log_id = equest->log_id();\n"
            "  cntl->set_log_id(log_id);\n"
            "  ::baidu::paddle_serving::predictor::InferService* svr = \n"
            "       "
            "::baidu::paddle_serving::predictor::InferServiceManager::instance("
            ").item(\"$service$\");\n"
            "  if (svr == NULL) {\n"
            "    LOG(ERROR) << \"(logid=\" << log_id << \") Not found service: "
            "$service$\";\n"
            "    cntl->SetFailed(404, \"Not found service: $service$\");\n"
            "    return ;\n"
            "  }\n"
            "  LOG(INFO) << \"(logid=\" << log_id << \") remote_side=\[\" "  // NOLINT
            "<< cntl->remote_side() << \"\]\";\n"
            "  LOG(INFO) << \"(logid=\" << log_id << \") local_side=\[\" "  // NOLINT
            "<< cntl->local_side() << \"\]\";\n"
            "  LOG(INFO) << \"(logid=\" << log_id << \") service_name=\[\" "  // NOLINT
            "<< \"$name$\" << \"\]\";\n"
            "  butil::IOBufBuilder debug_os;\n"
            "  int err_code = svr->inference(request, response, log_id, "
            "&debug_os);\n"
            "  if (err_code != 0) {\n"
            "    LOG(WARNING)\n"
            "        << \"(logid=\" << log_id << \") Failed call "
            "inferservice[$name$], name[$service$]\"\n"
            "        << \", error_code: \" << err_code;\n"
            "    cntl->SetFailed(err_code, \"InferService inference "
            "failed!\");\n"
            "  }\n"
            "  debug_os.move_to(cntl->response_attachment());\n"
            "  gettimeofday(&tv, NULL);\n"
            "  long end = tv.tv_sec * 1000000 + tv.tv_usec;\n"
            "  // flush notice log\n"
            "  LOG(INFO) << \"(logid=\" << log_id << \") tc=\[\" << (end - "  // NOLINT
            "start) << \"\]\";\n"
            "  LOG(INFO)\n"
            "      << \"(logid=\" << log_id << \") TC=[\" << (end - start) << "
            "\"] Received debug "
            "request[log_id=\" << cntl->log_id()\n"
            "      << \"] from \" << cntl->remote_side()\n"
            "      << \" to \" << cntl->local_side();\n",
            "name",
            class_name,
            "service",
            service_name);
      }
      printer->Print("}\n");
    }
    printer->Print(
        "$name$Impl $name$Impl::_s_$variable_name$_impl(\"$service$\");\n",
        "name",
        class_name,
        "variable_name",
        variable_name,
        "service",
        service_name);
    return true;
  }
  bool generate_paddle_serving_stub_head(google::protobuf::io::Printer* printer,
                                         const ServiceDescriptor* descriptor,
                                         string* error,
                                         const std::string& service_name,
                                         const std::string& class_name) const {
    printer->Print(
        "class $name$_StubCallMapper : public baidu::rpc::CallMapper {\n"
        "private:\n"
        "   uint32_t _package_size;\n"
        "   baidu::paddle_serving::sdk_cpp::Stub* _stub_handler;\n"
        "public:\n",
        "name",
        class_name);
    printer->Indent();
    printer->Print(
        "$name$_StubCallMapper(uint32_t package_size, "
        "baidu::paddle_serving::sdk_cpp::Stub* stub) {\n"
        "   _package_size = package_size;\n"
        "   _stub_handler = stub;\n"
        "}\n",
        "name",
        class_name);

    printer->Print(
        "baidu::rpc::SubCall default_map(\n"
        "        int channel_index,\n"
        "        const google::protobuf::MethodDescriptor* method,\n"
        "        const google::protobuf::Message* request,\n"
        "        google::protobuf::Message* response) {\n"
        "   baidu::paddle_serving::sdk_cpp::TracePackScope "
        "scope(\"default_map\", channel_index);",
        "name",
        class_name);
    printer->Indent();

    if (!generate_paddle_serving_stub_default_map(
            printer, descriptor, error, service_name, class_name)) {
      return false;
    }

    printer->Outdent();
    printer->Print("}\n");

    printer->Print(
        "baidu::rpc::SubCall sub_package_map(\n"
        "        int channel_index,\n"
        "        const google::protobuf::MethodDescriptor* method,\n"
        "        const google::protobuf::Message* request,\n"
        "        google::protobuf::Message* response) {\n"
        "   baidu::paddle_serving::sdk_cpp::TracePackScope scope(\"sub_map\", "
        "channel_index);",
        "name",
        class_name);
    printer->Indent();

    std::vector<const FieldDescriptor*> in_shared_fields;
    std::vector<const FieldDescriptor*> in_item_fields;
    const MethodDescriptor* md = descriptor->FindMethodByName("inference");
    if (!md) {
      *error = "not found inference method!";
      return false;
    }
    for (int i = 0; i < md->input_type()->field_count(); ++i) {
      const FieldDescriptor* fd = md->input_type()->field(i);
      if (!fd) {
        *error = "invalid fd at: " + i;
        return false;
      }
      bool pack_on = fd->options().GetExtension(pds::pack_on);
      if (pack_on && !fd->is_repeated()) {
        *error = "Pack fields must be repeated, field: " + fd->name();
        return false;
      }
      if (pack_on) {
        in_item_fields.push_back(fd);
      } else {
        in_shared_fields.push_back(fd);
      }
    }

    if (!generate_paddle_serving_stub_package_map(printer,
                                                  descriptor,
                                                  error,
                                                  service_name,
                                                  class_name,
                                                  in_shared_fields,
                                                  in_item_fields)) {
      return false;
    }
    printer->Outdent();
    printer->Print("}\n");

    printer->Print(
        "baidu::rpc::SubCall Map(\n"
        "        int channel_index,\n"
        "        const google::protobuf::MethodDescriptor* method,\n"
        "        const google::protobuf::Message* request,\n"
        "        google::protobuf::Message* response) {\n",
        "name",
        class_name);
    printer->Indent();

    if (in_item_fields.size() <= 0) {
      printer->Print(
          "// No packed items found in proto file, use default map method\n"
          "return default_map(channel_index, method, request, response);\n");
    } else {
      printer->Print(
          "butil::Timer tt(butil::Timer::STARTED);\n"
          "baidu::rpc::SubCall ret;\n"
          "if (_package_size == 0) {\n"
          "   ret = default_map(channel_index, method, request, response);\n"
          "} else {\n"
          "   ret = sub_package_map(channel_index, method, request, "
          "response);\n"
          "}\n"
          "tt.stop();\n"
          "if (ret.flags != baidu::rpc::SKIP_SUB_CHANNEL && ret.method != "
          "NULL) {\n"
          "   _stub_handler->update_latency(tt.u_elapsed(), \"pack_map\");\n"
          "}\n"
          "return ret;\n");
    }

    printer->Outdent();
    printer->Print("}\n");

    printer->Outdent();
    printer->Print("};\n");

    ////////////////////////////////////////////////////////////////
    printer->Print(
        "class $name$_StubResponseMerger : public baidu::rpc::ResponseMerger "
        "{\n"
        "private:\n"
        "   uint32_t _package_size;\n"
        "   baidu::paddle_serving::sdk_cpp::Stub* _stub_handler;\n"
        "public:\n",
        "name",
        class_name);
    printer->Indent();
    printer->Print(
        "$name$_StubResponseMerger(uint32_t package_size, "
        "baidu::paddle_serving::sdk_cpp::Stub* stub) {\n"
        "   _package_size = package_size;\n"
        "   _stub_handler = stub;\n"
        "}\n",
        "name",
        class_name);

    printer->Print(
        "baidu::rpc::ResponseMerger::Result default_merge(\n"
        "        google::protobuf::Message* response,\n"
        "        const google::protobuf::Message* sub_response) {\n"
        "   baidu::paddle_serving::sdk_cpp::TracePackScope "
        "scope(\"default_merge\");",
        "name",
        class_name);
    printer->Indent();
    if (!generate_paddle_serving_stub_default_merger(
            printer, descriptor, error, service_name, class_name)) {
      return false;
    }
    printer->Outdent();
    printer->Print("}\n");

    printer->Print(
        "baidu::rpc::ResponseMerger::Result sub_package_merge(\n"
        "        google::protobuf::Message* response,\n"
        "        const google::protobuf::Message* sub_response) {\n"
        "   baidu::paddle_serving::sdk_cpp::TracePackScope "
        "scope(\"sub_merge\");",
        "name",
        class_name);
    printer->Indent();
    if (!generate_paddle_serving_stub_package_merger(
            printer, descriptor, error, service_name, class_name)) {
      return false;
    }
    printer->Outdent();
    printer->Print("}\n");

    printer->Print(
        "baidu::rpc::ResponseMerger::Result Merge(\n"
        "        google::protobuf::Message* response,\n"
        "        const google::protobuf::Message* sub_response) {\n",
        "name",
        class_name);
    printer->Indent();
    printer->Print(
        "butil::Timer tt(butil::Timer::STARTED);\n"
        "baidu::rpc::ResponseMerger::Result ret;"
        "if (_package_size <= 0) {\n"
        "    ret = default_merge(response, sub_response);\n"
        "} else {\n"
        "    ret = sub_package_merge(response, sub_response);\n"
        "}\n"
        "tt.stop();\n"
        "if (ret != baidu::rpc::ResponseMerger::FAIL) {\n"
        "   _stub_handler->update_latency(tt.u_elapsed(), \"pack_merge\");\n"
        "}\n"
        "return ret;\n");
    printer->Outdent();
    printer->Print("}\n");

    printer->Outdent();
    printer->Print("};\n");
    return true;
  }
  bool generate_paddle_serving_stub_default_map(
      google::protobuf::io::Printer* printer,
      const ServiceDescriptor* descriptor,
      string* error,
      const std::string& service_name,
      const std::string& class_name) const {
    printer->Print(
        "if (channel_index > 0) { \n"
        "   return baidu::rpc::SubCall::Skip();\n"
        "}\n");
    printer->Print(
        "google::protobuf::Message* cur_res = "
        "_stub_handler->fetch_response();\n"
        "if (cur_res == NULL) {\n"
        "   LOG(INFO) << \"Failed fetch response from stub handler, new it\";\n"
        "   cur_res = response->New();\n"
        "   if (cur_res == NULL) {\n"
        "       LOG(ERROR) << \"Failed new response item!\";\n"
        "       _stub_handler->update_average(1, \"pack_fail\");\n"
        "       return baidu::rpc::SubCall::Bad();\n"
        "   }\n"
        "   return baidu::rpc::SubCall(method, request, cur_res, "
        "baidu::rpc::DELETE_RESPONSE);\n"
        "}\n");
    "LOG(INFO) \n"
    "   << \"[default] Succ map, channel_index: \" << channel_index;\n";
    printer->Print(
        "return baidu::rpc::SubCall(method, request, cur_res, 0);\n");
    return true;
  }
  bool generate_paddle_serving_stub_default_merger(
      google::protobuf::io::Printer* printer,
      const ServiceDescriptor* descriptor,
      string* error,
      const std::string& service_name,
      const std::string& class_name) const {
    printer->Print(
        "try {\n"
        "   response->MergeFrom(*sub_response);\n"
        "   return baidu::rpc::ResponseMerger::MERGED;\n"
        "} catch (const std::exception& e) {\n"
        "   LOG(ERROR) << \"Merge failed.\";\n"
        "   _stub_handler->update_average(1, \"pack_fail\");\n"
        "   return baidu::rpc::ResponseMerger::FAIL;\n"
        "}\n");
    return true;
  }
  bool generate_paddle_serving_stub_package_map(
      google::protobuf::io::Printer* printer,
      const ServiceDescriptor* descriptor,
      string* error,
      const std::string& service_name,
      const std::string& class_name,
      std::vector<const FieldDescriptor*>& in_shared_fields,        // NOLINT
      std::vector<const FieldDescriptor*>& in_item_fields) const {  // NOLINT
    const MethodDescriptor* md = descriptor->FindMethodByName("inference");
    if (!md) {
      *error = "not found inference method!";
      return false;
    }

    printer->Print(
        "const $req_type$* req \n"
        "       = dynamic_cast<const $req_type$*>(request);\n"
        "$req_type$* sub_req = NULL;",
        "req_type",
        google::protobuf::dots_to_colons(md->input_type()->full_name()));

    // 1. pack fields 逐字段计算index范围，并从req copy值sub_req
    printer->Print("\n// 1. 样本字段(必须为repeated类型)按指定下标复制\n");
    for (uint32_t ii = 0; ii < in_item_fields.size(); ii++) {
      const FieldDescriptor* fd = in_item_fields[ii];
      std::string field_name = fd->name();
      printer->Print("\n/////$field_name$\n", "field_name", field_name);
      if (ii == 0) {
        printer->Print(
            "uint32_t total_size = req->$field_name$_size();\n"
            "if (channel_index == 0) {\n"
            "   _stub_handler->update_average(total_size, \"item_size\");\n"
            "}\n",
            "field_name",
            field_name);

        printer->Print(
            "int start = _package_size * channel_index;\n"
            "if (start >= total_size) {\n"
            "   return baidu::rpc::SubCall::Skip();\n"
            "}\n"
            "int end = _package_size * (channel_index + 1);\n"
            "if (end > total_size) {\n"
            "   end = total_size;\n"
            "}\n");

        printer->Print(
            "sub_req = "
            "dynamic_cast<$req_type$*>(_stub_handler->fetch_request());\n"
            "if (sub_req == NULL) {\n"
            "    LOG(ERROR) << \"failed fetch sub_req from stub.\";\n"
            "    _stub_handler->update_average(1, \"pack_fail\");\n"
            "    return baidu::rpc::SubCall::Bad();\n"
            "}\n",
            "name",
            class_name,
            "req_type",
            google::protobuf::dots_to_colons(md->input_type()->full_name()));

      } else {
        printer->Print(
            "if (req->$field_name$_size() != total_size) {\n"
            "    LOG(ERROR) << \"pack field size not consistency: \"\n"
            "               << total_size << \"!=\" << "
            "req->$field_name$_size()\n"
            "               << \", field: $field_name$.\";\n"
            "    _stub_handler->update_average(1, \"pack_fail\");\n"
            "    return baidu::rpc::SubCall::Bad();\n"
            "}\n",
            "field_name",
            field_name);
      }

      printer->Print("for (uint32_t i = start; i < end; ++i) {\n");
      printer->Indent();
      if (fd->cpp_type() ==
          google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
        printer->Print(
            "sub_req->add_$field_name$()->CopyFrom(req->$field_name$(i));\n",
            "field_name",
            field_name);
      } else {
        printer->Print("sub_req->add_$field_name$(req->$field_name$(i));\n",
                       "field_name",
                       field_name);
      }
      printer->Outdent();
      printer->Print("}\n");
    }

    // 2. shared fields逐字段从req copy至sub_req
    printer->Print("\n// 2. 共享字段，从req逐个复制到sub_req\n");
    if (in_item_fields.size() == 0) {
      printer->Print(
          "if (sub_req == NULL) { // no packed items\n"
          "   sub_req = "
          "dynamic_cast<$req_type$*>(_stub_handler->fetch_request());\n"
          "   if (!sub_req) {\n"
          "       LOG(ERROR) << \"failed fetch sub_req from stub handler.\";\n"
          "       _stub_handler->update_average(1, \"pack_fail\");\n"
          "       return baidu::rpc::SubCall::Bad();\n"
          "   }\n"
          "}\n",
          "req_type",
          google::protobuf::dots_to_colons(md->input_type()->full_name()));
    }
    for (uint32_t si = 0; si < in_shared_fields.size(); si++) {
      const FieldDescriptor* fd = in_shared_fields[si];
      std::string field_name = fd->name();
      printer->Print("\n/////$field_name$\n", "field_name", field_name);
      if (fd->is_optional()) {
        printer->Print(
            "if (req->has_$field_name$()) {\n", "field_name", field_name);
        printer->Indent();
      }
      if (fd->cpp_type() ==
              google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE ||
          fd->is_repeated()) {
        printer->Print(
            "sub_req->mutable_$field_name$()->CopyFrom(req->$field_name$());\n",
            "field_name",
            field_name);
      } else {
        printer->Print("sub_req->set_$field_name$(req->$field_name$());\n",
                       "field_name",
                       field_name);
      }
      if (fd->is_optional()) {
        printer->Outdent();
        printer->Print("}\n");
      }
    }

    printer->Print(
        "LOG(INFO)\n"
        "   << \"[pack] Succ map req at: \"\n"
        "   << channel_index;\n");
    printer->Print(
        "google::protobuf::Message* sub_res = "
        "_stub_handler->fetch_response();\n"
        "if (sub_res == NULL) {\n"
        "    LOG(ERROR) << \"failed create sub_res from res.\";\n"
        "    _stub_handler->update_average(1, \"pack_fail\");\n"
        "    return baidu::rpc::SubCall::Bad();\n"
        "}\n"
        "return baidu::rpc::SubCall(method, sub_req, sub_res, 0);\n");
    return true;
  }
  bool generate_paddle_serving_stub_package_merger(
      google::protobuf::io::Printer* printer,
      const ServiceDescriptor* descriptor,
      string* error,
      const std::string& service_name,
      const std::string& class_name) const {
    return generate_paddle_serving_stub_default_merger(
        printer, descriptor, error, service_name, class_name);
  }
  bool generate_paddle_serving_stub_body(google::protobuf::io::Printer* printer,
                                         const ServiceDescriptor* descriptor,
                                         string* error,
                                         const std::string& service_name,
                                         const std::string& class_name) const {
    std::vector<const MethodDescriptor*> methods;
    for (int i = 0; i < descriptor->method_count(); ++i) {
      methods.push_back(descriptor->method(i));
    }
    if (!valid_service_method(methods)) {
      *error = "Service can only contains two methods: inferend, debug";
      return false;
    }

    const MethodDescriptor* md = methods[0];
    std::map<string, string> variables;
    variables["name"] = class_name;
    variables["req_type"] =
        google::protobuf::dots_to_colons(md->input_type()->full_name());
    variables["res_type"] =
        google::protobuf::dots_to_colons(md->output_type()->full_name());
    variables["fullname"] = descriptor->full_name();
    printer->Print(variables,
                   "REGIST_STUB_OBJECT_WITH_TAG(\n"
                   "       $name$_Stub,\n"
                   "       $name$_StubCallMapper,\n"
                   "       $name$_StubResponseMerger,\n"
                   "       $req_type$,\n"
                   "       $res_type$,\n"
                   "       \"$fullname$\");\n");
    variables.clear();
    return true;
  }
};
#else   // #ifdef BCLOUD
class PdsCodeGenerator : public CodeGenerator {
 public:
  virtual bool Generate(const FileDescriptor* file,
                        const string& parameter,
                        GeneratorContext* context,
                        std::string* error) const {
    const string header = strip_proto(file->name()) + ".pb.h";
    const string body = strip_proto(file->name()) + ".pb.cc";
    bool include_inserted = false;
    for (int i = 0; i < file->service_count(); ++i) {
      const ServiceDescriptor* descriptor = file->service(i);
      if (!descriptor) {
        *error = "get descriptor failed";
        return false;
      }
      pds::PaddleServiceOption options =
          descriptor->options().GetExtension(pds::options);
      bool generate_impl = options.generate_impl();
      bool generate_stub = options.generate_stub();
      if (!generate_impl && !generate_stub) {
        return true;
      }
      if (!include_inserted) {
        boost::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
            context->OpenForInsert(header, "includes"));
        google::protobuf::io::Printer printer(output.get(), '$');
        if (generate_impl) {
          printer.Print("#include \"core/predictor/common/inner_common.h\"\n");
          printer.Print("#include \"core/predictor/framework/service.h\"\n");
          printer.Print("#include \"core/predictor/framework/manager.h\"\n");
          printer.Print(
              "#include \"core/predictor/framework/service_manager.h\"\n");
        }
        if (generate_stub) {
          printer.Print("#include <brpc/parallel_channel.h>\n");
          printer.Print("#include \"core/sdk-cpp/include/factory.h\"\n");
          printer.Print("#include \"core/sdk-cpp/include/stub.h\"\n");
          printer.Print("#include \"core/sdk-cpp/include/stub_impl.h\"\n");
        }
        include_inserted = true;
      }
      const std::string& class_name = descriptor->name();
      const std::string& service_name = descriptor->name();
      // xxx.ph.h
      {
        if (generate_impl) {
          // service scope
          // namespace scope
          boost::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
              context->OpenForInsert(header, "namespace_scope"));
          google::protobuf::io::Printer printer(output.get(), '$');
          if (!generate_paddle_serving_head(
                  &printer, descriptor, error, service_name, class_name)) {
            return false;
          }
        }
        if (generate_stub) {
          // service class scope

          // namespace scope
          {
            boost::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream>
                output(context->OpenForInsert(header, "namespace_scope"));
            google::protobuf::io::Printer printer(output.get(), '$');
            if (!generate_paddle_serving_stub_head(
                    &printer, descriptor, error, service_name, class_name)) {
              return false;
            }
          }
        }
      }
      // xxx.pb.cc
      {
        if (generate_impl) {
          // service scope
          // namespace scope
          boost::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
              context->OpenForInsert(body, "namespace_scope"));
          google::protobuf::io::Printer printer(output.get(), '$');
          if (!generate_paddle_serving_body(
                  &printer, descriptor, error, service_name, class_name)) {
            return false;
          }
        }
        if (generate_stub) {
          // service class scope
          {}  // namespace scope
          {
            boost::scoped_ptr<google::protobuf::io::ZeroCopyOutputStream>
                output(context->OpenForInsert(body, "namespace_scope"));
            google::protobuf::io::Printer printer(output.get(), '$');
            if (!generate_paddle_serving_stub_body(
                    &printer, descriptor, error, service_name, class_name)) {
              return false;
            }
          }
        }
      }
    }
    return true;
  }

 private:
  bool generate_paddle_serving_head(google::protobuf::io::Printer* printer,
                                    const ServiceDescriptor* descriptor,
                                    string* error,
                                    const std::string& service_name,
                                    const std::string& class_name) const {
    std::vector<const MethodDescriptor*> methods;
    for (int i = 0; i < descriptor->method_count(); ++i) {
      methods.push_back(descriptor->method(i));
    }
    if (!valid_service_method(methods)) {
      *error = "Service can only contains two methods: inferend, debug";
      return false;
    }
    std::string variable_name = class_name;
    string_format(variable_name);
    printer->Print(
        "class $name$Impl : public $name$ {\n"
        "public:\n"
        "  virtual ~$name$Impl() {}\n"
        "  static $name$Impl& instance() {\n"
        "    return _s_$variable_name$_impl;\n"
        "  }\n\n"
        "  $name$Impl(const std::string& service_name) {\n"
        "    REGIST_FORMAT_SERVICE(\n"
        "            service_name, &$name$Impl::instance());\n"
        "  }\n\n",
        "name",
        class_name,
        "variable_name",
        variable_name);
    for (int i = 0; i < methods.size(); i++) {
      const MethodDescriptor* m = methods[i];
      printer->Print(
          "  virtual void $name$(google::protobuf::RpcController* cntl_base,\n"
          "          const $input_name$* request,\n"
          "          $output_name$* response,\n"
          "          google::protobuf::Closure* done);\n\n",
          "name",
          m->name(),
          "input_name",
          google::protobuf::dots_to_colons(m->input_type()->full_name()),
          "output_name",
          google::protobuf::dots_to_colons(m->output_type()->full_name()));
    }
    printer->Print(
        "  static $name$Impl _s_$variable_name$_impl;\n"
        "};",
        "name",
        class_name,
        "variable_name",
        variable_name);
    return true;
  }
  bool generate_paddle_serving_body(google::protobuf::io::Printer* printer,
                                    const ServiceDescriptor* descriptor,
                                    string* error,
                                    const std::string& service_name,
                                    const std::string& class_name) const {
    std::vector<const MethodDescriptor*> methods;
    for (int i = 0; i < descriptor->method_count(); ++i) {
      methods.push_back(descriptor->method(i));
    }
    if (!valid_service_method(methods)) {
      *error = "Service can only contains two methods: inferend, debug";
      return false;
    }
    std::string variable_name = class_name;
    string_format(variable_name);
    for (int i = 0; i < methods.size(); i++) {
      const MethodDescriptor* m = methods[i];
      printer->Print("void $name$Impl::$method$(\n",
                     "name",
                     class_name,
                     "method",
                     m->name());
      printer->Print(
          "        google::protobuf::RpcController* cntl_base,\n"
          "        const $input_name$* request,\n"
          "        $output_name$* response,\n"
          "        google::protobuf::Closure* done) {\n"
          "   struct timeval tv;\n"
          "   gettimeofday(&tv, NULL);"
          "   long start = tv.tv_sec * 1000000 + tv.tv_usec;",
          "input_name",
          google::protobuf::dots_to_colons(m->input_type()->full_name()),
          "output_name",
          google::protobuf::dots_to_colons(m->output_type()->full_name()));
      if (m->name() == "inference") {
        std::string inference_body = "";
        inference_body += "  brpc::ClosureGuard done_guard(done);\n";
        inference_body += "  brpc::Controller* cntl = \n";
        inference_body += "        static_cast<brpc::Controller*>(cntl_base);\n";
        inference_body += "  cntl->set_response_compress_type(brpc::COMPRESS_TYPE_GZIP);\n";
        inference_body += "  uint64_t log_id = request->log_id();\n";
        inference_body += "  cntl->set_log_id(log_id);\n";
        inference_body += "  ::baidu::paddle_serving::predictor::InferService* svr = \n";
        inference_body += "       ";
        inference_body += "::baidu::paddle_serving::predictor::InferServiceManager::instance(";
        inference_body += ").item(\"$service$\");\n";
        inference_body += "  if (svr == NULL) {\n";
        inference_body += "    LOG(ERROR) << \"(logid=\" << log_id << \") Not found service: ";
        inference_body += "$service$\";\n";
        inference_body += "    cntl->SetFailed(404, \"Not found service: $service$\");\n";
        inference_body += "    return ;\n";
        inference_body += "  }\n";
        inference_body += "  LOG(INFO) << \"(logid=\" << log_id << \") ";
        inference_body += "remote_side=\[\" << cntl->remote_side() << ";  // NOLINT
        inference_body += "\"\]\";\n";
        inference_body += "  LOG(INFO) << \"(logid=\" << log_id << \") ";
        inference_body += "local_side=\[\" << cntl->local_side() << ";  // NOLINT
        inference_body += "\"\]\";\n";
        inference_body += "  LOG(INFO) << \"(logid=\" << log_id << \") ";
        inference_body += "service_name=\[\" << \"$name$\" << \"\]\";\n";  // NOLINT
        inference_body += "  int err_code = svr->inference(request, response, log_id);\n";
        inference_body += "  if (err_code != 0) {\n";
        inference_body += "    LOG(WARNING)\n";
        inference_body += "        << \"(logid=\" << log_id << \") Failed call ";
        inference_body += "inferservice[$name$], name[$service$]\"\n";
        inference_body += "        << \", error_code: \" << err_code;\n";
        inference_body += "    cntl->SetFailed(err_code, \"InferService inference ";
        inference_body += "failed!\");\n";
        inference_body += "  }\n";
        inference_body += "  gettimeofday(&tv, NULL);\n";
        inference_body += "  long end = tv.tv_sec * 1000000 + tv.tv_usec;\n";
        if (service_name == "GeneralModelService") {
          inference_body += "  std::ostringstream oss;\n";
          inference_body += "  oss << \"[serving]\"\n";
          inference_body += "      << \"logid=\" << log_id << \",\";\n";
          inference_body += "  int op_num = response->profile_time_size() / 2;\n";
          inference_body += "  for (int i = 0; i < op_num; ++i) {\n";
          inference_body += "    double t = (response->profile_time(i * 2 + 1)\n";
          inference_body += "                - response->profile_time(i * 2)) / 1000.0;\n";
          inference_body += "    oss << \"op\" << i << \"=\" << t << \"ms,\";\n";
          inference_body += "  }\n";
          inference_body += "  double total_time = (end - start) / 1000.0;\n";
          inference_body += "  oss << \"cost=\" << total_time << \"ms.\";\n";
          inference_body += "  // flush notice log\n";
          inference_body += "  LOG(INFO) << oss.str();\n";
          inference_body += "  response->add_profile_time(start);\n";
          inference_body += "  response->add_profile_time(end);\n";
        } else {
          inference_body += "  // flush notice log\n";
          inference_body += "  LOG(INFO) << \"(logid=\" << log_id << \") tc=\[\" << (end - ";  // NOLINT
          inference_body += "start) << \"\]\";\n";
        }
        printer->Print(
            inference_body.c_str(),
            "name",
            class_name,
            "service",
            service_name);
      }
      if (m->name() == "debug") {
        printer->Print(
            "  brpc::ClosureGuard done_guard(done);\n"
            "  brpc::Controller* cntl = \n"
            "        static_cast<brpc::Controller*>(cntl_base);\n"
            "  cntl->set_response_compress_type(brpc::COMPRESS_TYPE_GZIP);\n"
            "  uint64_t log_id = request->log_id();\n"
            "  cntl->set_log_id(log_id);\n"
            "  ::baidu::paddle_serving::predictor::InferService* svr = \n"
            "       "
            "::baidu::paddle_serving::predictor::InferServiceManager::instance("
            ").item(\"$service$\");\n"
            "  if (svr == NULL) {\n"
            "    LOG(ERROR) << \"(logid=\" << log_id << \") Not found service: "
            "$service$\";\n"
            "    cntl->SetFailed(404, \"Not found service: $service$\");\n"
            "    return ;\n"
            "  }\n"
            "  LOG(INFO) << \"(logid=\" << log_id << \") remote_side=\[\" "  // NOLINT
            " << cntl->remote_side() << \"\]\";\n"
            "  LOG(INFO) << \"(logid=\" << log_id << \") local_side=\[\" "  // NOLINT
            "<< cntl->local_side() << \"\]\";\n"
            "  LOG(INFO) << \"(logid=\" << log_id << \") service_name=\[\" "  // NOLINT
            "<< \"$name$\" << \"\]\";\n"
            "  butil::IOBufBuilder debug_os;\n"
            "  int err_code = svr->inference(request, response, log_id, "
            "&debug_os);\n"
            "  if (err_code != 0) {\n"
            "    LOG(WARNING)\n"
            "        << \"(logid=\" << log_id << \") Failed call "
            "inferservice[$name$], name[$service$]\"\n"
            "        << \", error_code: \" << err_code;\n"
            "    cntl->SetFailed(err_code, \"InferService inference "
            "failed!\");\n"
            "  }\n"
            "  debug_os.move_to(cntl->response_attachment());\n"
            "  gettimeofday(&tv, NULL);\n"
            "  long end = tv.tv_sec * 1000000 + tv.tv_usec;\n"
            "  // flush notice log\n"
            "  LOG(INFO) << \"(logid=\" << log_id << \") tc=\[\" << (end - "  // NOLINT
            "start) << \"\]\";\n"  // NOLINT
            "  LOG(INFO)\n"
            "      << \"(logid=\" << log_id << \") TC=[\" << (end - start) << "
            "\"] Received debug "
            "request[log_id=\" << cntl->log_id()\n"
            "      << \"] from \" << cntl->remote_side()\n"
            "      << \" to \" << cntl->local_side();\n",
            "name",
            class_name,
            "service",
            service_name);
      }
      printer->Print("}\n");
    }
    printer->Print(
        "$name$Impl $name$Impl::_s_$variable_name$_impl(\"$service$\");\n",
        "name",
        class_name,
        "variable_name",
        variable_name,
        "service",
        service_name);
    return true;
  }
  bool generate_paddle_serving_stub_head(google::protobuf::io::Printer* printer,
                                         const ServiceDescriptor* descriptor,
                                         string* error,
                                         const std::string& service_name,
                                         const std::string& class_name) const {
    printer->Print(
        "class $name$_StubCallMapper : public brpc::CallMapper {\n"
        "private:\n"
        "   uint32_t _package_size;\n"
        "   baidu::paddle_serving::sdk_cpp::Stub* _stub_handler;\n"
        "public:\n",
        "name",
        class_name);
    printer->Indent();
    printer->Print(
        "$name$_StubCallMapper(uint32_t package_size, "
        "baidu::paddle_serving::sdk_cpp::Stub* stub) {\n"
        "   _package_size = package_size;\n"
        "   _stub_handler = stub;\n"
        "}\n",
        "name",
        class_name);

    printer->Print(
        "brpc::SubCall default_map(\n"
        "        int channel_index,\n"
        "        const google::protobuf::MethodDescriptor* method,\n"
        "        const google::protobuf::Message* request,\n"
        "        google::protobuf::Message* response) {\n"
        "   baidu::paddle_serving::sdk_cpp::TracePackScope "
        "scope(\"default_map\", channel_index);",
        "name",
        class_name);
    printer->Indent();

    if (!generate_paddle_serving_stub_default_map(
            printer, descriptor, error, service_name, class_name)) {
      return false;
    }

    printer->Outdent();
    printer->Print("}\n");

    printer->Print(
        "brpc::SubCall sub_package_map(\n"
        "        int channel_index,\n"
        "        const google::protobuf::MethodDescriptor* method,\n"
        "        const google::protobuf::Message* request,\n"
        "        google::protobuf::Message* response) {\n"
        "   baidu::paddle_serving::sdk_cpp::TracePackScope scope(\"sub_map\", "
        "channel_index);",
        "name",
        class_name);
    printer->Indent();

    std::vector<const FieldDescriptor*> in_shared_fields;
    std::vector<const FieldDescriptor*> in_item_fields;
    const MethodDescriptor* md = descriptor->FindMethodByName("inference");
    if (!md) {
      *error = "not found inference method!";
      return false;
    }
    for (int i = 0; i < md->input_type()->field_count(); ++i) {
      const FieldDescriptor* fd = md->input_type()->field(i);
      if (!fd) {
        *error = "invalid fd at: " + i;
        return false;
      }
      bool pack_on = fd->options().GetExtension(pds::pack_on);
      if (pack_on && !fd->is_repeated()) {
        *error = "Pack fields must be repeated, field: " + fd->name();
        return false;
      }
      if (pack_on) {
        in_item_fields.push_back(fd);
      } else {
        in_shared_fields.push_back(fd);
      }
    }

    if (!generate_paddle_serving_stub_package_map(printer,
                                                  descriptor,
                                                  error,
                                                  service_name,
                                                  class_name,
                                                  in_shared_fields,
                                                  in_item_fields)) {
      return false;
    }
    printer->Outdent();
    printer->Print("}\n");

    printer->Print(
        "brpc::SubCall Map(\n"
        "        int channel_index,\n"
        "        const google::protobuf::MethodDescriptor* method,\n"
        "        const google::protobuf::Message* request,\n"
        "        google::protobuf::Message* response) {\n",
        "name",
        class_name);
    printer->Indent();

    if (in_item_fields.size() <= 0) {
      printer->Print(
          "// No packed items found in proto file, use default map method\n"
          "return default_map(channel_index, method, request, response);\n");
    } else {
      printer->Print(
          "butil::Timer tt(butil::Timer::STARTED);\n"
          "brpc::SubCall ret;\n"
          "if (_package_size == 0) {\n"
          "   ret = default_map(channel_index, method, request, response);\n"
          "} else {\n"
          "   ret = sub_package_map(channel_index, method, request, "
          "response);\n"
          "}\n"
          "tt.stop();\n"
          "if (ret.flags != brpc::SKIP_SUB_CHANNEL && ret.method != NULL) {\n"
          "   _stub_handler->update_latency(tt.u_elapsed(), \"pack_map\");\n"
          "}\n"
          "return ret;\n");
    }

    printer->Outdent();
    printer->Print("}\n");

    printer->Outdent();
    printer->Print("};\n");

    ////////////////////////////////////////////////////////////////
    printer->Print(
        "class $name$_StubResponseMerger : public brpc::ResponseMerger {\n"
        "private:\n"
        "   uint32_t _package_size;\n"
        "   baidu::paddle_serving::sdk_cpp::Stub* _stub_handler;\n"
        "public:\n",
        "name",
        class_name);
    printer->Indent();
    printer->Print(
        "$name$_StubResponseMerger(uint32_t package_size, "
        "baidu::paddle_serving::sdk_cpp::Stub* stub) {\n"
        "   _package_size = package_size;\n"
        "   _stub_handler = stub;\n"
        "}\n",
        "name",
        class_name);

    printer->Print(
        "brpc::ResponseMerger::Result default_merge(\n"
        "        google::protobuf::Message* response,\n"
        "        const google::protobuf::Message* sub_response) {\n"
        "   baidu::paddle_serving::sdk_cpp::TracePackScope "
        "scope(\"default_merge\");",
        "name",
        class_name);
    printer->Indent();
    if (!generate_paddle_serving_stub_default_merger(
            printer, descriptor, error, service_name, class_name)) {
      return false;
    }
    printer->Outdent();
    printer->Print("}\n");

    printer->Print(
        "brpc::ResponseMerger::Result sub_package_merge(\n"
        "        google::protobuf::Message* response,\n"
        "        const google::protobuf::Message* sub_response) {\n"
        "   baidu::paddle_serving::sdk_cpp::TracePackScope "
        "scope(\"sub_merge\");",
        "name",
        class_name);
    printer->Indent();
    if (!generate_paddle_serving_stub_package_merger(
            printer, descriptor, error, service_name, class_name)) {
      return false;
    }
    printer->Outdent();
    printer->Print("}\n");

    printer->Print(
        "brpc::ResponseMerger::Result Merge(\n"
        "        google::protobuf::Message* response,\n"
        "        const google::protobuf::Message* sub_response) {\n",
        "name",
        class_name);
    printer->Indent();
    printer->Print(
        "butil::Timer tt(butil::Timer::STARTED);\n"
        "brpc::ResponseMerger::Result ret;"
        "if (_package_size <= 0) {\n"
        "    ret = default_merge(response, sub_response);\n"
        "} else {\n"
        "    ret = sub_package_merge(response, sub_response);\n"
        "}\n"
        "tt.stop();\n"
        "if (ret != brpc::ResponseMerger::FAIL) {\n"
        "   _stub_handler->update_latency(tt.u_elapsed(), \"pack_merge\");\n"
        "}\n"
        "return ret;\n");
    printer->Outdent();
    printer->Print("}\n");

    printer->Outdent();
    printer->Print("};\n");
    return true;
  }
  bool generate_paddle_serving_stub_default_map(
      google::protobuf::io::Printer* printer,
      const ServiceDescriptor* descriptor,
      string* error,
      const std::string& service_name,
      const std::string& class_name) const {
    printer->Print(
        "if (channel_index > 0) { \n"
        "   return brpc::SubCall::Skip();\n"
        "}\n");
    printer->Print(
        "google::protobuf::Message* cur_res = "
        "_stub_handler->fetch_response();\n"
        "if (cur_res == NULL) {\n"
        "   LOG(INFO) << \"Failed fetch response from stub handler, new it\";\n"
        "   cur_res = response->New();\n"
        "   if (cur_res == NULL) {\n"
        "       LOG(ERROR) << \"Failed new response item!\";\n"
        "       _stub_handler->update_average(1, \"pack_fail\");\n"
        "       return brpc::SubCall::Bad();\n"
        "   }\n"
        "   return brpc::SubCall(method, request, cur_res, "
        "brpc::DELETE_RESPONSE);\n"
        "}\n");
    "LOG(INFO) \n"
    "   << \"[default] Succ map, channel_index: \" << channel_index;\n";
    printer->Print("return brpc::SubCall(method, request, cur_res, 0);\n");
    return true;
  }
  bool generate_paddle_serving_stub_default_merger(
      google::protobuf::io::Printer* printer,
      const ServiceDescriptor* descriptor,
      string* error,
      const std::string& service_name,
      const std::string& class_name) const {
    printer->Print(
        "try {\n"
        "   response->MergeFrom(*sub_response);\n"
        "   return brpc::ResponseMerger::MERGED;\n"
        "} catch (const std::exception& e) {\n"
        "   LOG(ERROR) << \"Merge failed.\";\n"
        "   _stub_handler->update_average(1, \"pack_fail\");\n"
        "   return brpc::ResponseMerger::FAIL;\n"
        "}\n");
    return true;
  }
  bool generate_paddle_serving_stub_package_map(
      google::protobuf::io::Printer* printer,
      const ServiceDescriptor* descriptor,
      string* error,
      const std::string& service_name,
      const std::string& class_name,
      std::vector<const FieldDescriptor*>& in_shared_fields,        // NOLINT
      std::vector<const FieldDescriptor*>& in_item_fields) const {  // NOLINT
    const MethodDescriptor* md = descriptor->FindMethodByName("inference");
    if (!md) {
      *error = "not found inference method!";
      return false;
    }

    printer->Print(
        "const $req_type$* req \n"
        "       = dynamic_cast<const $req_type$*>(request);\n"
        "$req_type$* sub_req = NULL;",
        "req_type",
        google::protobuf::dots_to_colons(md->input_type()->full_name()));

    // 1. pack fields 逐字段计算index范围，并从req copy值sub_req
    printer->Print("\n// 1. 样本字段(必须为repeated类型)按指定下标复制\n");
    for (uint32_t ii = 0; ii < in_item_fields.size(); ii++) {
      const FieldDescriptor* fd = in_item_fields[ii];
      std::string field_name = fd->name();
      printer->Print("\n/////$field_name$\n", "field_name", field_name);
      if (ii == 0) {
        printer->Print(
            "uint32_t total_size = req->$field_name$_size();\n"
            "if (channel_index == 0) {\n"
            "   _stub_handler->update_average(total_size, \"item_size\");\n"
            "}\n",
            "field_name",
            field_name);

        printer->Print(
            "int start = _package_size * channel_index;\n"
            "if (start >= total_size) {\n"
            "   return brpc::SubCall::Skip();\n"
            "}\n"
            "int end = _package_size * (channel_index + 1);\n"
            "if (end > total_size) {\n"
            "   end = total_size;\n"
            "}\n");

        printer->Print(
            "sub_req = "
            "dynamic_cast<$req_type$*>(_stub_handler->fetch_request());\n"
            "if (sub_req == NULL) {\n"
            "    LOG(ERROR) << \"failed fetch sub_req from stub.\";\n"
            "    _stub_handler->update_average(1, \"pack_fail\");\n"
            "    return brpc::SubCall::Bad();\n"
            "}\n",
            "name",
            class_name,
            "req_type",
            google::protobuf::dots_to_colons(md->input_type()->full_name()));

      } else {
        printer->Print(
            "if (req->$field_name$_size() != total_size) {\n"
            "    LOG(ERROR) << \"pack field size not consistency: \"\n"
            "               << total_size << \"!=\" << "
            "req->$field_name$_size()\n"
            "               << \", field: $field_name$.\";\n"
            "    _stub_handler->update_average(1, \"pack_fail\");\n"
            "    return brpc::SubCall::Bad();\n"
            "}\n",
            "field_name",
            field_name);
      }

      printer->Print("for (uint32_t i = start; i < end; ++i) {\n");
      printer->Indent();
      if (fd->cpp_type() ==
          google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
        printer->Print(
            "sub_req->add_$field_name$()->CopyFrom(req->$field_name$(i));\n",
            "field_name",
            field_name);
      } else {
        printer->Print("sub_req->add_$field_name$(req->$field_name$(i));\n",
                       "field_name",
                       field_name);
      }
      printer->Outdent();
      printer->Print("}\n");
    }

    // 2. shared fields逐字段从req copy至sub_req
    printer->Print("\n// 2. 共享字段，从req逐个复制到sub_req\n");
    if (in_item_fields.size() == 0) {
      printer->Print(
          "if (sub_req == NULL) { // no packed items\n"
          "   sub_req = "
          "dynamic_cast<$req_type$*>(_stub_handler->fetch_request());\n"
          "   if (!sub_req) {\n"
          "       LOG(ERROR) << \"failed fetch sub_req from stub handler.\";\n"
          "       _stub_handler->update_average(1, \"pack_fail\");\n"
          "       return brpc::SubCall::Bad();\n"
          "   }\n"
          "}\n",
          "req_type",
          google::protobuf::dots_to_colons(md->input_type()->full_name()));
    }
    for (uint32_t si = 0; si < in_shared_fields.size(); si++) {
      const FieldDescriptor* fd = in_shared_fields[si];
      std::string field_name = fd->name();
      printer->Print("\n/////$field_name$\n", "field_name", field_name);
      if (fd->cpp_type() ==
              google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE ||
          fd->is_repeated()) {
        printer->Print(
            "sub_req->mutable_$field_name$()->CopyFrom(req->$field_name$());\n",
            "field_name",
            field_name);
      } else {
        printer->Print("sub_req->set_$field_name$(req->$field_name$());\n",
                       "field_name",
                       field_name);
      }
    }

    printer->Print(
        "LOG(INFO)\n"
        "   << \"[pack] Succ map req at: \"\n"
        "   << channel_index;\n");
    printer->Print(
        "google::protobuf::Message* sub_res = "
        "_stub_handler->fetch_response();\n"
        "if (sub_res == NULL) {\n"
        "    LOG(ERROR) << \"failed create sub_res from res.\";\n"
        "    _stub_handler->update_average(1, \"pack_fail\");\n"
        "    return brpc::SubCall::Bad();\n"
        "}\n"
        "return brpc::SubCall(method, sub_req, sub_res, 0);\n");
    return true;
  }
  bool generate_paddle_serving_stub_package_merger(
      google::protobuf::io::Printer* printer,
      const ServiceDescriptor* descriptor,
      string* error,
      const std::string& service_name,
      const std::string& class_name) const {
    return generate_paddle_serving_stub_default_merger(
        printer, descriptor, error, service_name, class_name);
  }
  bool generate_paddle_serving_stub_body(google::protobuf::io::Printer* printer,
                                         const ServiceDescriptor* descriptor,
                                         string* error,
                                         const std::string& service_name,
                                         const std::string& class_name) const {
    std::vector<const MethodDescriptor*> methods;
    for (int i = 0; i < descriptor->method_count(); ++i) {
      methods.push_back(descriptor->method(i));
    }
    if (!valid_service_method(methods)) {
      *error = "Service can only contains two methods: inferend, debug";
      return false;
    }

    const MethodDescriptor* md = methods[0];
    std::map<string, string> variables;
    variables["name"] = class_name;
    variables["req_type"] =
        google::protobuf::dots_to_colons(md->input_type()->full_name());
    variables["res_type"] =
        google::protobuf::dots_to_colons(md->output_type()->full_name());
    variables["fullname"] = descriptor->full_name();
    printer->Print(variables,
                   "REGIST_STUB_OBJECT_WITH_TAG(\n"
                   "       $name$_Stub,\n"
                   "       $name$_StubCallMapper,\n"
                   "       $name$_StubResponseMerger,\n"
                   "       $req_type$,\n"
                   "       $res_type$,\n"
                   "       \"$fullname$\");\n");
    variables.clear();
    return true;
  }
};
#endif  // #ifdef BCLOUD

int main(int argc, char** argv) {
  PdsCodeGenerator generator;
  return google::protobuf::compiler::PluginMain(argc, argv, &generator);
}


<|start_filename|>core/general-client/include/brpc_client.h<|end_filename|>
// Copyright (c) 2021 PaddlePaddle Authors. 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.
#pragma once

#include "core/general-client/include/client.h"
#include "core/sdk-cpp/include/predictor_sdk.h"
using baidu::paddle_serving::sdk_cpp::Predictor;
using baidu::paddle_serving::sdk_cpp::PredictorApi;

namespace baidu {
namespace paddle_serving {
namespace client {

class ServingBrpcClient : public ServingClient {
 public:

  ServingBrpcClient() {};

  ~ServingBrpcClient() {};

  virtual int connect(const std::string server_port);

  int predict(const PredictorInputs& inputs,
              PredictorOutputs& outputs,
              const std::vector<std::string>& fetch_name,
              const uint64_t log_id);

 private:
  // generate default SDKConf
  std::string gen_desc(const std::string server_port);

 private:
  PredictorApi _api;
  Predictor* _predictor;
};

}  // namespace client
}  // namespace paddle_serving
}  // namespace baidu

<|start_filename|>core/preprocess/hwvideoframe/src/center_crop.cpp<|end_filename|>
// Copyright (c) 2020 PaddlePaddle Authors. 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.

#include <npp.h>

#include <algorithm>

#include "core/preprocess/hwvideoframe/include/center_crop.h"
#include "core/preprocess/hwvideoframe/include/utils.h"

std::shared_ptr<OpContext> CenterCrop::operator()(
    std::shared_ptr<OpContext> input) {
  int new_width = std::min(_size, input->nppi_size().width);
  int new_height = std::min(_size, input->nppi_size().height);
  auto output = std::make_shared<OpContext>(new_height, new_width);
  int x_start = (input->nppi_size().width - new_width) / 2;
  int y_start = (input->nppi_size().height - new_height) / 2;
  Npp32f* p_src = input->p_frame() +
                  y_start * input->nppi_size().width * CHANNEL_SIZE +
                  x_start * CHANNEL_SIZE;
  NppStatus ret = nppiCopy_32f_C3R(p_src,
                                   input->step(),
                                   output->p_frame(),
                                   output->step(),
                                   output->nppi_size());
  verify_npp_ret("nppiCopy_32f_C3R", ret);
  return output;
}


<|start_filename|>core/cube/cube-api/go-api/server.go<|end_filename|>
package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

type Input struct {
	Keys []uint64 `json:"keys"`
}

type SingleValue struct {
	Status uint32 `json:"status"`
	Value  string `json:"value"`
}
type Output struct {
	Values []SingleValue `json:"values"`
}

type ServerNode struct {
	Ip   string `json:"ip"`
	Port uint64 `json:"port"`
}

type CubeServer struct {
	Name  string       `json:"dict_name"`
	Shard uint64       `json:"shard"`
	Nodes []ServerNode `json:"nodes"`
}

func (server *CubeServer) SplitKeys(keys []uint64) (splited_keys map[uint64]Input, offset map[uint64][]uint64) {
	splited_keys = make(map[uint64]Input)

	offset = make(map[uint64][]uint64)
	for i, key := range keys {
		shard_id := key % server.Shard
		temp_split, _ := splited_keys[shard_id]
		temp_split.Keys = append(temp_split.Keys, key)
		splited_keys[shard_id] = temp_split

		temp_offset, _ := offset[shard_id]
		temp_offset = append(temp_offset, uint64(i))
		offset[shard_id] = temp_offset
	}

	return splited_keys, offset
}

func (server *CubeServer) Seek(input string, output_path string) (err error) {
	file, err := os.Open(input)
	if err != nil {
		return err
	}
	defer file.Close()

	buf := bufio.NewReader(file)

	for {
		line, err := buf.ReadBytes('\n')
		//line = strings.TrimSpace(line)
		if err != nil || io.EOF == err {
			break
		}
		var temp_input Input
		json.Unmarshal(line, &temp_input)
		key_nums := len(temp_input.Keys)
		var output Output
		output.Values = make([]SingleValue, key_nums+1)
		splited_keys, offset := server.SplitKeys(temp_input.Keys)
		for shard_id, keys := range splited_keys {
			cur_output, _ := server.Post(shard_id, keys)
			for index, single_value := range cur_output.Values {
				output.Values[offset[shard_id][index]] = single_value
			}
		}
		json_str, _ := json.Marshal(output)
		fp, err := os.OpenFile(output_path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0755)
		if err != nil {
			log.Fatal(err)
		}
		defer fp.Close()
		_, err = fp.Write(json_str)
	}
	return err
}

func (server *CubeServer) Post(shard_id uint64, input Input) (output Output, err error) {
	if shard_id >= uint64(len(server.Nodes)) {
		err = fmt.Errorf("have no shard:%v", shard_id)
		return output, err
	}
	json_str, _ := json.Marshal(input)
	URL := fmt.Sprintf("http://%s:%v/DictService/seek", server.Nodes[shard_id].Ip, server.Nodes[shard_id].Port)
	req, err := http.NewRequest("POST", URL, bytes.NewBuffer(json_str))
	if err != nil {
		return output, err
	}
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return output, err
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return output, err
	}
	err = json.Unmarshal(body, &output)
	return output, err
}


<|start_filename|>core/predictor/framework/resource.cpp<|end_filename|>
// Copyright (c) 2019 PaddlePaddle Authors. 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.

#include "core/predictor/framework/resource.h"
#include <sstream>
#include <string>
#include "core/predictor/common/inner_common.h"
#include "core/predictor/framework/kv_manager.h"
#ifdef BCLOUD
#include "aipe_sec_client.h"  // NOLINT
#endif
namespace baidu {
namespace paddle_serving {
namespace predictor {

using configure::ResourceConf;
using configure::GeneralModelConfig;
using rec::mcube::CubeAPI;

std::vector<std::shared_ptr<PaddleGeneralModelConfig>>
Resource::get_general_model_config() {
  return _configs;
}

void Resource::print_general_model_config(
    const std::shared_ptr<PaddleGeneralModelConfig>& config) {
  if (config == nullptr) {
    LOG(INFO) << "paddle general model config is not set";
    return;
  }
  LOG(INFO) << "Number of Feed Tensor: " << config->_feed_name.size();
  std::ostringstream oss;
  LOG(INFO) << "Feed Name Info";
  for (auto& feed_name : config->_feed_name) {
    oss << feed_name << " ";
  }
  LOG(INFO) << oss.str();
  oss.clear();
  oss.str("");
  LOG(INFO) << "Feed Type Info";
  for (auto& feed_type : config->_feed_type) {
    oss << feed_type << " ";
  }
  LOG(INFO) << oss.str();
  oss.clear();
  oss.str("");
  LOG(INFO) << "Lod Type Info";

  for (auto is_lod : config->_is_lod_feed) {
    oss << is_lod << " ";
  }

  LOG(INFO) << oss.str();
  oss.clear();
  oss.str("");
  LOG(INFO) << "Capacity Info";
  for (auto& cap : config->_capacity) {
    oss << cap << " ";
  }
  LOG(INFO) << oss.str();
  oss.clear();
  oss.str("");
  LOG(INFO) << "Feed Shape Info";
  int tensor_idx = 0;
  for (auto& shape : config->_feed_shape) {
    for (auto& dim : shape) {
      oss << dim << " ";
    }
    LOG(INFO) << "Tensor[" << tensor_idx++ << "].shape: " << oss.str();
    oss.clear();
    oss.str("");
  }
}

int Resource::initialize(const std::string& path, const std::string& file) {
  ResourceConf resource_conf;
  if (configure::read_proto_conf(path, file, &resource_conf) != 0) {
    LOG(ERROR) << "Failed initialize resource from: " << path << "/" << file;
    return -1;
  }

  // mempool
  if (MempoolWrapper::instance().initialize() != 0) {
    LOG(ERROR) << "Failed proc initialized mempool wrapper";
    return -1;
  }
  LOG(WARNING) << "Successfully proc initialized mempool wrapper";

#ifdef WITH_AUTH
  std::string product_name_str = resource_conf.auth_product_name();
  std::string container_id_str = resource_conf.auth_container_id();

  char* product_name = new char[product_name_str.size() + 1];
  snprintf(product_name,
           product_name_str.size() + 1,
           "%s",
           product_name_str.c_str());
  char* container_id = new char[container_id_str.size() + 1];
  snprintf(container_id,
           container_id_str.size() + 1,
           "%s",
           container_id_str.c_str());

  aipe_auth_request request;
  request.product_name = product_name;
  request.container_id = container_id;
  request.request_ts = (int64_t)time(NULL);

  LOG(INFO) << "\nEasypack info"
            << "\nproduct name: " << request.product_name
            << "\ncontainer_id: " << request.container_id
            << "\nrequest time stamp: " << request.request_ts;

  aipe_auth_response response;
  response = check_auth(request);

  if (response.result == 0) {
    LOG(INFO) << "Authentication succeed.";
  } else {
    LOG(ERROR) << "Authentication failed. Error code: " << response.result;
    return -1;
  }
#endif

  if (FLAGS_enable_model_toolkit) {
    size_t model_toolkit_num = resource_conf.model_toolkit_path_size();
    // 此处暂时认为，每个model_toolkit仅包含一个engine
    // 故认为 model_toolkit_num == engine总数
    // 若以后出现model_toolkit仅包含多个engine
    // 则应先for循环统计engine总数,再set_taskexecutor_num
    // 切不可动态im::bsf::TaskExecutorVector<TaskT>::instance().resize
    // TaskExecutor是线程池，内含锁，在engine进程初始化时已开始work加锁循环运行了
    // 之后再resize内存搬运，会导致work使用原锁，而搬运后的TaskExecutor的锁内存已改变
    if (InferManager::instance().set_taskexecutor_num(model_toolkit_num) != 0) {
      LOG(ERROR) << "failed set_taskexecutor_num";
      return -1;
    }
    std::shared_ptr<int> engine_index_ptr(new int(0));
    for (size_t mi = 0; mi < model_toolkit_num; ++mi) {
      std::string model_toolkit_path = resource_conf.model_toolkit_path(mi);
      std::string model_toolkit_file = resource_conf.model_toolkit_file(mi);

      if (InferManager::instance().proc_initialize(model_toolkit_path.c_str(),
                                                   model_toolkit_file.c_str(),
                                                   engine_index_ptr) != 0) {
        LOG(ERROR) << "failed proc initialize modeltoolkit, config: "
                   << model_toolkit_path << "/" << model_toolkit_file;
        return -1;
      }

      if (KVManager::instance().proc_initialize(
              model_toolkit_path.c_str(), model_toolkit_file.c_str()) != 0) {
        LOG(ERROR) << "Failed proc initialize kvmanager, config: "
                   << model_toolkit_path << "/" << model_toolkit_file;
      }
    }
  }

  // init rocksDB or cube instance
  if (resource_conf.has_cube_config_file() &&
      resource_conf.has_cube_config_path()) {
    LOG(INFO) << "init cube client, path[ " << resource_conf.cube_config_path()
              << " ], config file [ " << resource_conf.cube_config_file()
              << " ].";
    rec::mcube::CubeAPI* cube = rec::mcube::CubeAPI::instance();
    std::string cube_config_fullpath = "./" + resource_conf.cube_config_path() +
                                       "/" + resource_conf.cube_config_file();
    this->_cube_config_fullpath = cube_config_fullpath;
    this->_cube_quant_bits = resource_conf.has_cube_quant_bits()
                                 ? resource_conf.cube_quant_bits()
                                 : 0;
    if (this->_cube_quant_bits != 0 && this->_cube_quant_bits != 8) {
      LOG(ERROR) << "Cube quant bits illegal! should be 0 or 8.";
      return -1;
    }
    if (this->_cube_quant_bits == 0) {
      LOG(INFO) << "cube quant mode OFF";
    } else {
      LOG(INFO) << "cube quant mode ON, quant bits: " << this->_cube_quant_bits;
    }
  }

  THREAD_SETSPECIFIC(_tls_bspec_key, NULL);
  return 0;
}

// model config
int Resource::general_model_initialize(const std::string& path,
                                       const std::string& file) {
  if (this->_cube_config_fullpath.size() != 0) {
    LOG(INFO) << "init cube by config file : " << this->_cube_config_fullpath;
    rec::mcube::CubeAPI* cube = rec::mcube::CubeAPI::instance();
    int ret = cube->init(this->_cube_config_fullpath.c_str());
    if (ret != 0) {
      LOG(ERROR) << "cube init error";
      return -1;
    }
  }
  VLOG(2) << "general model path: " << path;
  VLOG(2) << "general model file: " << file;
  if (!FLAGS_enable_general_model) {
    LOG(ERROR) << "general model is not enabled";
    return -1;
  }
  ResourceConf resource_conf;
  if (configure::read_proto_conf(path, file, &resource_conf) != 0) {
    LOG(ERROR) << "Failed initialize resource from: " << path << "/" << file;
    return -1;
  }
  size_t general_model_num = resource_conf.general_model_path_size();
  for (size_t gi = 0; gi < general_model_num; ++gi) {
    std::string general_model_path = resource_conf.general_model_path(gi);
    std::string general_model_file = resource_conf.general_model_file(gi);

    GeneralModelConfig model_config;
    if (configure::read_proto_conf(general_model_path.c_str(),
                                   general_model_file.c_str(),
                                   &model_config) != 0) {
      LOG(ERROR) << "Failed initialize model config from: "
                 << general_model_path << "/" << general_model_file;
      return -1;
    }
    auto _config = std::make_shared<PaddleGeneralModelConfig>();
    int feed_var_num = model_config.feed_var_size();
    VLOG(2) << "load general model config";
    VLOG(2) << "feed var num: " << feed_var_num;
    _config->_feed_name.resize(feed_var_num);
    _config->_feed_alias_name.resize(feed_var_num);
    _config->_feed_type.resize(feed_var_num);
    _config->_is_lod_feed.resize(feed_var_num);
    _config->_capacity.resize(feed_var_num);
    _config->_feed_shape.resize(feed_var_num);
    for (int i = 0; i < feed_var_num; ++i) {
      _config->_feed_name[i] = model_config.feed_var(i).name();
      _config->_feed_alias_name[i] = model_config.feed_var(i).alias_name();
      VLOG(2) << "feed var[" << i << "]: " << _config->_feed_name[i];
      VLOG(2) << "feed var[" << i << "]: " << _config->_feed_alias_name[i];
      _config->_feed_type[i] = model_config.feed_var(i).feed_type();
      VLOG(2) << "feed type[" << i << "]: " << _config->_feed_type[i];

      if (model_config.feed_var(i).is_lod_tensor()) {
        VLOG(2) << "var[" << i << "] is lod tensor";
        _config->_feed_shape[i] = {-1};
        _config->_is_lod_feed[i] = true;
      } else {
        VLOG(2) << "var[" << i << "] is tensor";
        _config->_capacity[i] = 1;
        _config->_is_lod_feed[i] = false;
        for (int j = 0; j < model_config.feed_var(i).shape_size(); ++j) {
          int32_t dim = model_config.feed_var(i).shape(j);
          VLOG(2) << "var[" << i << "].shape[" << i << "]: " << dim;
          _config->_feed_shape[i].push_back(dim);
          _config->_capacity[i] *= dim;
        }
      }
    }

    int fetch_var_num = model_config.fetch_var_size();
    _config->_is_lod_fetch.resize(fetch_var_num);
    _config->_fetch_name.resize(fetch_var_num);
    _config->_fetch_alias_name.resize(fetch_var_num);
    _config->_fetch_shape.resize(fetch_var_num);
    for (int i = 0; i < fetch_var_num; ++i) {
      _config->_fetch_name[i] = model_config.fetch_var(i).name();
      _config->_fetch_alias_name[i] = model_config.fetch_var(i).alias_name();
      _config->_fetch_name_to_index[_config->_fetch_name[i]] = i;
      _config->_fetch_alias_name_to_index[_config->_fetch_alias_name[i]] = i;
      if (model_config.fetch_var(i).is_lod_tensor()) {
        VLOG(2) << "fetch var[" << i << "] is lod tensor";
        _config->_fetch_shape[i] = {-1};
        _config->_is_lod_fetch[i] = true;
      } else {
        _config->_is_lod_fetch[i] = false;
        for (int j = 0; j < model_config.fetch_var(i).shape_size(); ++j) {
          int dim = model_config.fetch_var(i).shape(j);
          _config->_fetch_shape[i].push_back(dim);
        }
      }
    }
    _configs.push_back(std::move(_config));
  }
  return 0;
}

int Resource::thread_initialize() {
  // mempool
  if (MempoolWrapper::instance().thread_initialize() != 0) {
    LOG(ERROR) << "Failed thread initialized mempool wrapper";
    return -1;
  }
  LOG(WARNING) << "Successfully thread initialized mempool wrapper";

  // infer manager
  if (FLAGS_enable_model_toolkit &&
      InferManager::instance().thrd_initialize() != 0) {
    LOG(ERROR) << "Failed thrd initialized infer manager";
    return -1;
  }

  return 0;
}

int Resource::thread_clear() {
  // mempool
  if (MempoolWrapper::instance().thread_clear() != 0) {
    LOG(ERROR) << "Failed thread clear mempool wrapper";
    return -1;
  }

  // infer manager
  if (FLAGS_enable_model_toolkit &&
      InferManager::instance().thrd_clear() != 0) {
    LOG(ERROR) << "Failed thrd clear infer manager";
    return -1;
  }
  return 0;
}
size_t Resource::get_cube_quant_bits() { return this->_cube_quant_bits; }

int Resource::reload() {
  if (FLAGS_enable_model_toolkit && InferManager::instance().reload() != 0) {
    LOG(ERROR) << "Failed reload infer manager";
    return -1;
  }

  // other resource reload here...
  return 0;
}

int Resource::finalize() {
  if (FLAGS_enable_model_toolkit &&
      InferManager::instance().proc_finalize() != 0) {
    LOG(ERROR) << "Failed proc finalize infer manager";
    return -1;
  }
  if (CubeAPI::instance()->destroy() != 0) {
    LOG(ERROR) << "Destory cube api failed ";
    return -1;
  }
  THREAD_KEY_DELETE(_tls_bspec_key);

  return 0;
}

}  // namespace predictor
}  // namespace paddle_serving
}  // namespace baidu


<|start_filename|>core/cube/cube-transfer/src/transfer/transfer.go<|end_filename|>
// Copyright (c) 2019 PaddlePaddle Authors. 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.

package transfer

import (
	"fmt"
	"github.com/Badangel/logex"
	"transfer/dict"
)

func Start() {

	BackupTransfer()
}

func BackupTransfer() {
	//trigger
	version, err := TriggerStart(Dict.DonefileAddress)
	if err != nil {
		logex.Fatalf("[trigger err]trigger err:%v ", err)
		fmt.Printf("[error]trigger err:%v \n", err)
		fmt.Print("transfer over!")
        	logex.Noticef("[transfer]status machine exit!")
                return
	}
	logex.Noticef("[trigger] get version:%v \n", version)
        Dict.WaitVersionInfo = version
	logex.Noticef("[trigger finish] WaitVersionInfo version:%v \n", Dict.WaitVersionInfo)
	WriteWaitVersionInfoToFile()
        
	//builder
	Dict.WaitVersionInfo.Status = dict.Dict_Status_Building
	Dict.WaitVersionInfo.MetaInfos = make(map[int]string)
	WriteWaitVersionInfoToFile()
	if err = BuilderStart(Dict.WaitVersionInfo); err != nil {
		logex.Fatalf("builder err:%v \n", err)
	}

	if Dict.WaitVersionInfo.Mode == dict.BASE {
		var newCurrentVersion []dict.DictVersionInfo
		Dict.CurrentVersionInfo = newCurrentVersion
		WriteCurrentVersionInfoToFile()
	}
        if Dict.WaitVersionInfo.Mode == dict.DELTA {
                var newCurrentVersion []dict.DictVersionInfo
                Dict.CurrentVersionInfo = newCurrentVersion
                WriteCurrentVersionInfoToFile()
        }
	logex.Noticef("[builder finish] WaitVersionInfo version:%v \n", Dict.WaitVersionInfo)

	//deployer
	Dict.WaitVersionInfo.Status = dict.Dict_Status_Deploying
	WriteWaitVersionInfoToFile()
	if err = DeployStart(Dict.WaitVersionInfo); err != nil {
		logex.Fatalf("deploy err:%v \n", err)
	}
        logex.Noticef("[deploy finish]current version: %v\n",Dict.CurrentVersionInfo)
	fmt.Print("transfer over!")
	logex.Noticef("[transfer]status machine exit!")
}


<|start_filename|>core/general-client/example/simple_client.cpp<|end_filename|>
// Copyright (c) 2021 PaddlePaddle Authors. 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.

#include <fstream>
#include <vector>

#include "core/general-client/include/brpc_client.h"

using baidu::paddle_serving::client::ServingClient;
using baidu::paddle_serving::client::ServingBrpcClient;
using baidu::paddle_serving::client::PredictorInputs;
using baidu::paddle_serving::client::PredictorOutputs;

DEFINE_string(server_port, "127.0.0.1:9292", "ip:port");
DEFINE_string(client_conf, "serving_client_conf.prototxt", "Path of client conf");
DEFINE_string(test_type, "brpc", "brpc");
// fit_a_line, bert
DEFINE_string(sample_type, "fit_a_line", "List: fit_a_line, bert");

namespace {
int prepare_fit_a_line(PredictorInputs& input, std::vector<std::string>& fetch_name) {
  std::vector<float> float_feed = {0.0137f, -0.1136f, 0.2553f, -0.0692f,
            0.0582f, -0.0727f, -0.1583f, -0.0584f,
            0.6283f, 0.4919f, 0.1856f, 0.0795f, -0.0332f};
  std::vector<int> float_shape = {1, 13};
  std::string feed_name = "x";
  fetch_name = {"price"};
  std::vector<int> lod;
  input.add_float_data(float_feed, feed_name, float_shape, lod);
  return 0;
}

int prepare_bert(PredictorInputs& input, std::vector<std::string>& fetch_name) {
  {
    std::vector<float> float_feed(128, 0.0f);
    float_feed[0] = 1.0f;
    std::vector<int> float_shape = {1, 128, 1};
    std::string feed_name = "input_mask";
    std::vector<int> lod;
    input.add_float_data(float_feed, feed_name, float_shape, lod);
  }
  {
    std::vector<int64_t> feed(128, 0);
    std::vector<int> shape = {1, 128, 1};
    std::string feed_name = "position_ids";
    std::vector<int> lod;
    input.add_int64_data(feed, feed_name, shape, lod);
  }
  {
    std::vector<int64_t> feed(128, 0);
    feed[0] = 101;
    std::vector<int> shape = {1, 128, 1};
    std::string feed_name = "input_ids";
    std::vector<int> lod;
    input.add_int64_data(feed, feed_name, shape, lod);
  }
  {
    std::vector<int64_t> feed(128, 0);
    std::vector<int> shape = {1, 128, 1};
    std::string feed_name = "segment_ids";
    std::vector<int> lod;
    input.add_int64_data(feed, feed_name, shape, lod);
  }
  
  fetch_name = {"pooled_output"};
  return 0;
}
} // namespace

int main(int argc, char* argv[]) {

  google::ParseCommandLineFlags(&argc, &argv, true);
  std::string url = FLAGS_server_port;
  std::string conf = FLAGS_client_conf;
  std::string test_type = FLAGS_test_type;
  std::string sample_type = FLAGS_sample_type;
  LOG(INFO) << "url = " << url << ";"
            << "client_conf = " << conf << ";"
            << "test_type = " << test_type
            << "sample_type = " << sample_type;
  std::unique_ptr<ServingClient> client;
  // default type is brpc
  // will add grpc&http in the future
  if (test_type == "brpc") {
    client.reset(new ServingBrpcClient());
  } else {
    client.reset(new ServingBrpcClient());
  }
  std::vector<std::string> confs;
  confs.push_back(conf);
  if (client->init(confs, url) != 0) {
    LOG(ERROR) << "Failed to init client!";
    return 0;
  }

  PredictorInputs input;
  PredictorOutputs output;
  std::vector<std::string> fetch_name;

  if (sample_type == "fit_a_line") {
    prepare_fit_a_line(input, fetch_name);
  }
  else if (sample_type == "bert") {
    prepare_bert(input, fetch_name);
  }
  else {
    prepare_fit_a_line(input, fetch_name);
  }

  if (client->predict(input, output, fetch_name, 0) != 0) {
    LOG(ERROR) << "Failed to predict!";
  }
  else {
    LOG(INFO) << output.print();
  }
  
  return 0;
}


<|start_filename|>core/predictor/tools/seq_reader.cpp<|end_filename|>
// Copyright (c) 2020 PaddlePaddle Authors. 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.

#include <sys/time.h>
#include <limits.h> 
#include <fstream>
#include <iostream>
#include <memory>
#include <thread>
#include "core/cube/cube-builder/include/cube-builder/seqfile_reader.h"
std::string string_to_hex(const std::string& input) {
  static const char* const lut = "0123456789ABCDEF";
  size_t len = input.length();

  std::string output;
  output.reserve(2 * len);
  for (size_t i = 0; i < len; ++i) {
    const unsigned char c = input[i];
    output.push_back(lut[c >> 4]);
    output.push_back(lut[c & 15]);
  }
  return output;
}

void printSeq(std::string file, int limit) {
  SequenceFileRecordReader reader(file.c_str());

  if (reader.open() != 0) {
    std::cerr << "open file failed! " << file;
    return;
  }
  if (reader.read_header() != 0) {
    std::cerr << "read header error! " << file;
    reader.close();
    return;
  }

  Record record(reader.get_header());
  int total_count = 0;

  while (reader.next(&record) == 0) {
    uint64_t key =
        *reinterpret_cast<uint64_t *>(const_cast<char *>(record.key.data()));

    total_count++;
    int64_t value_length = record.record_len - record.key_len;
    std::cout << "key: " << key << " , value: " << string_to_hex(record.value.c_str()) << std::endl; 
    if (total_count >= limit) {
        break;
    }
  }

  if (reader.close() != 0) {
    std::cerr << "close file failed! " << file;
    return;
  }
}

int main(int argc, char **argv) {
    if (argc != 3 && argc != 2) {
        std::cout << "Seq Reader Usage:" << std::endl;
        std::cout << "get all keys: ./seq_reader $FILENAME " << std::endl;
        std::cout << "get some keys: ./seq_reader $FILENAME $KEY_NUM" << std::endl;
        return -1; 
    }
    if (argc == 3 || argc == 2) {
        const char* filename_str = argv[1];
        std::cout << "cstr filename is " << filename_str << std::endl;
        std::string filename = filename_str;
        std::cout << "filename is " << filename << std::endl;
        if (argc == 3) {
          const char* key_num_str = argv[2];
          int key_limit = std::stoi(key_num_str);
          printSeq(filename, key_limit);
        } else {
          printSeq(filename, INT_MAX);
        }
    }
    return 0;
}


<|start_filename|>core/cube/cube-api/go-api/meta.go<|end_filename|>
package main

import "fmt"

type Meta struct {
	Servers []CubeServer `json:"servers,omitempty"`
}

func (meta *Meta) Seek(dict_name string, input string, output string) (err error) {
	var server CubeServer

	for _, s := range meta.Servers {
		if s.Name == dict_name {
			server = s
			break
		}
	}
	if server.Name != dict_name {
		err = fmt.Errorf("%s server not exist", dict_name)
		return err
	}
	err = server.Seek(input, output)
	return err
}


<|start_filename|>core/cube/cube-api/go-api/demo.go<|end_filename|>
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
)

func main() {
	dict_name := flag.String("n", "test", "cube name")
	conf_path := flag.String("c", "./conf/cube.conf", "cube conf path")
	input_path := flag.String("i", "./input.json", "keys to seek")
	output_path := flag.String("o", "./output.json", "result to save")
	flag.Parse()
	bytes, err := ioutil.ReadFile(*conf_path)
	if err != nil {
		fmt.Println("读取配置文件失败", err)
		return
	}
	var meta Meta
	err = json.Unmarshal(bytes, &meta.Servers)
	if err != nil {
		fmt.Println("解析数据失败", err)
		return
	}

	err = meta.Seek(*dict_name, *input_path, *output_path)
	if err != nil {
		fmt.Println(err)
	}
	return
}
