[ML] Added binary communication in getTensorRawData()
[platform/core/api/webapi-plugins.git] / src / ml / ml_instance.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 #include "ml_instance.h"
18 #include "ml_utils.h"
19
20 #include "common/converter.h"
21 #include "common/logger.h"
22 #include "common/picojson.h"
23 #include "common/platform_result.h"
24 #include "common/tools.h"
25
26 static_assert(ML_TENSOR_RANK_LIMIT == 4,
27               "This implementation requires different ML_TENSOR_RANK_LIMIT. Please fix the code.");
28
29 namespace extension {
30 namespace ml {
31
32 namespace {
33 const int kCustomFilterSuccess = 0;
34 const int kNoId = -1;
35 const std::string kAsync = "async";
36 const std::string kBOOLEAN = "BOOLEAN";
37 const std::string kBuffer = "buffer";
38 const std::string kCallbackId = "callbackId";
39 const std::string kDataId = "dataId";
40 const std::string kDefinition = "definition";
41 const std::string kDimensions = "dimensions";
42 const std::string kFwType = "fwType";
43 const std::string kGetInputMode = "getInputMode";
44 const std::string kHw = "hw";
45 const std::string kHwType = "hwType";
46 const std::string kId = "id";
47 const std::string kIndex = "index";
48 const std::string kInputTensorsInfoId = "inputTensorsInfoId";
49 const std::string kInTensorsInfo = "inTensorsInfo";
50 const std::string kIsDynamicMode = "isDynamicMode";
51 const std::string kListenerName = "listenerName";
52 const std::string kLocation = "location";
53 const std::string kModelPath = "modelPath";
54 const std::string kName = "name";
55 const std::string kNnfw = "nnfw";
56 const std::string kNodeName = "nodeName";
57 const std::string kOpen = "open";
58 const std::string kOtherId = "otherId";
59 const std::string kOutputTensorsInfoId = "outputTensorsInfoId";
60 const std::string kOutTensorsInfo = "outTensorsInfo";
61 const std::string kPadName = "padName";
62 const std::string kPipelineStateChangeListenerName = "listenerName";
63 const std::string kProperty = "property";
64 const std::string kRequestId = "requestId";
65 const std::string kShape = "shape";
66 const std::string kSize = "size";
67 const std::string kStatus = "status";
68 const std::string kSTRING = "STRING";
69 const std::string kTensorsDataId = "tensorsDataId";
70 const std::string kTensorsInfoId = "tensorsInfoId";
71 const std::string kTimeout = "timeout";
72 const std::string kType = "type";
73 const std::string kValue = "value";
74 }  //  namespace
75
76 using namespace common;
77
78 #define CHECK_EXIST(args, name, out)                                            \
79   if (!args.contains(name)) {                                                   \
80     std::string msg = std::string(name) + " is required argument";              \
81     LogAndReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, msg), &out); \
82     return;                                                                     \
83   }
84
85 // CHECK_TYPE will throw AbortError by default, but it can be changed by providing
86 // additional parameter to the macro, i.e.:
87 // CHECK_TYPE(args, "name", std::string, out, ErrorCode::TYPE_MISMATCH_ERR)
88 #define CHECK_TYPE(...) CHECK_TYPE_X(__VA_ARGS__, CHECK_TYPE_5, CHECK_TYPE_4)(__VA_ARGS__)
89 #define CHECK_TYPE_X(_1, _2, _3, _4, _5, EXC_TYPE, ...) EXC_TYPE
90 #define CHECK_TYPE_5(args, name, type, out, error_type)        \
91   if (!args.get(name).is<type>()) {                            \
92     std::string msg = std::string(name) + " has invalid type"; \
93     LogAndReportError(PlatformResult(error_type, msg), &out);  \
94     return;                                                    \
95   }
96 #define CHECK_TYPE_4(args, name, type, out) \
97   CHECK_TYPE_5(args, name, type, out, ErrorCode::ABORT_ERR)
98
99 #define CHECK_ARGS(args, name, type, out) \
100   CHECK_EXIST(args, name, out)            \
101   CHECK_TYPE(args, name, type, out)
102
103 MlInstance::MlInstance()
104     : tensors_info_manager_{&tensors_data_manager_},
105       single_manager_{&tensors_info_manager_},
106       pipeline_manager_{this, &tensors_info_manager_, &tensors_data_manager_} {
107   ScopeLogger();
108   using namespace std::placeholders;
109
110 #define REGISTER_METHOD(M) RegisterSyncHandler(#M, std::bind(&MlInstance::M, this, _1, _2))
111 #define REGISTER_BINARY_METHOD(M) RegisterBinaryHandler(std::bind(&MlInstance::M, this, _1, _2, _3))
112 #define REGISTER_METHOD_WITH_BINARY_ANWSER(M) \
113   RegisterSyncHandlerWithBinaryAnswer(#M, std::bind(&MlInstance::M, this, _1, _2))
114
115   REGISTER_METHOD(MLCheckNNFWAvailability);
116   REGISTER_METHOD(MLTensorsInfoCountGetter);
117   REGISTER_METHOD(MLTensorsInfoAddTensorInfo);
118   REGISTER_METHOD(MLTensorsInfoCreate);
119   REGISTER_METHOD(MLTensorsInfoGetDimensions);
120   REGISTER_METHOD(MLTensorsInfoSetDimensions);
121   REGISTER_METHOD(MLTensorsInfoGetTensorName);
122   REGISTER_METHOD(MLTensorsInfoSetTensorName);
123   REGISTER_METHOD(MLTensorsInfoGetTensorSize);
124   REGISTER_METHOD(MLTensorsInfoGetTensorType);
125   REGISTER_METHOD(MLTensorsInfoSetTensorType);
126   REGISTER_METHOD(MLTensorsInfoGetTensorsData);
127   REGISTER_METHOD(MLTensorsInfoClone);
128   REGISTER_METHOD(MLTensorsInfoEquals);
129   REGISTER_METHOD(MLTensorsInfoDispose);
130   REGISTER_METHOD(MLPipelineValveSetOpen);
131   REGISTER_METHOD(MLPipelineValveIsOpen);
132
133   REGISTER_METHOD(MLTensorsDataDispose);
134   REGISTER_METHOD(MLTensorsDataGetTensorRawData);
135   REGISTER_METHOD_WITH_BINARY_ANWSER(MLTensorsDataGetTensorRawDataBinary);
136   REGISTER_METHOD(MLTensorsDataGetTensorType);
137   REGISTER_METHOD(MLTensorsDataSetTensorRawData);
138   REGISTER_BINARY_METHOD(MLTensorsDataSetTensorRawDataBinary);
139
140   REGISTER_METHOD(MLSingleManagerOpenModel);
141   REGISTER_METHOD(MLSingleShotGetTensorsInfo);
142   REGISTER_METHOD(MLSingleShotSetInputInfo);
143   REGISTER_METHOD(MLSingleShotInvoke);
144   REGISTER_METHOD(MLSingleShotGetValue);
145   REGISTER_METHOD(MLSingleShotSetValue);
146   REGISTER_METHOD(MLSingleShotSetTimeout);
147   REGISTER_METHOD(MLSingleShotClose);
148
149   REGISTER_METHOD(MLPipelineManagerCreatePipeline);
150   REGISTER_METHOD(MLPipelineGetState);
151   REGISTER_METHOD(MLPipelineDispose);
152   REGISTER_METHOD(MLPipelineStart);
153   REGISTER_METHOD(MLPipelineStop);
154   REGISTER_METHOD(MLPipelineGetNodeInfo);
155   REGISTER_METHOD(MLPipelineGetSwitch);
156   REGISTER_METHOD(MLPipelineSwitchGetPadList);
157   REGISTER_METHOD(MLPipelineSwitchSelect);
158   REGISTER_METHOD(MLPipelineGetValve);
159   REGISTER_METHOD(MLPipelineNodeInfoGetProperty);
160   REGISTER_METHOD(MLPipelineNodeInfoSetProperty);
161   REGISTER_METHOD(MLPipelineGetSource);
162   REGISTER_METHOD(MLPipelineGetInputTensorsInfo);
163   REGISTER_METHOD(MLPipelineSourceInputData);
164   REGISTER_METHOD(MLPipelineRegisterSinkListener);
165   REGISTER_METHOD(MLPipelineUnregisterSinkListener);
166   REGISTER_METHOD(MLPipelineManagerRegisterCustomFilter);
167   REGISTER_METHOD(MLPipelineManagerCustomFilterOutput);
168   REGISTER_METHOD(MLPipelineManagerUnregisterCustomFilter);
169
170 #undef REGISTER_METHOD
171 }
172
173 MlInstance::~MlInstance() {
174   ScopeLogger();
175   worker_.stop();
176 }
177
178 TensorsInfoManager& MlInstance::GetTensorsInfoManager() {
179   return tensors_info_manager_;
180 }
181
182 TensorsDataManager& MlInstance::GetTensorsDataManager() {
183   return tensors_data_manager_;
184 }
185
186 void MlInstance::MLCheckNNFWAvailability(const picojson::value& args, picojson::object& out) {
187   ScopeLogger("args: %s", args.serialize().c_str());
188   CHECK_EXIST(args, kNnfw, out)
189   CHECK_EXIST(args, kHw, out)
190
191   std::string nnfw = args.get(kNnfw).get<std::string>();
192   std::string hw = args.get(kHw).get<std::string>();
193   bool availability_val = util::CheckNNFWAvailability(nnfw, hw);
194
195   picojson::value available = picojson::value{availability_val};
196   ReportSuccess(available, out);
197 }
198
199 void MlInstance::MLTensorsInfoCreate(const picojson::value& args, picojson::object& out) {
200   ScopeLogger("args: %s", args.serialize().c_str());
201
202   TensorsInfo* tensorsInfo = GetTensorsInfoManager().CreateTensorsInfo();
203   if (nullptr == tensorsInfo) {
204     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
205                       ("Could not create new TensorsInfo handle"));
206     return;
207   }
208   out[kId] = picojson::value(static_cast<double>(tensorsInfo->Id()));
209   ReportSuccess(out);
210 }
211
212 void MlInstance::MLTensorsInfoCountGetter(const picojson::value& args, picojson::object& out) {
213   ScopeLogger("args: %s", args.serialize().c_str());
214   CHECK_ARGS(args, kTensorsInfoId, double, out);
215
216   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
217   TensorsInfo* tensorsInfo = GetTensorsInfoManager().GetTensorsInfo(tensorsInfoId);
218   if (nullptr == tensorsInfo) {
219     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
220                       ("Could not find TensorsInfo handle with given id: %d", tensorsInfoId));
221     return;
222   }
223   unsigned int count = 0;
224   PlatformResult result = tensorsInfo->NativeGetCount(&count);
225   if (!result) {
226     ReportError(result, &out);
227     return;
228   }
229   picojson::value val = picojson::value{static_cast<double>(count)};
230   ReportSuccess(val, out);
231 }
232
233 void MlInstance::MLTensorsInfoAddTensorInfo(const picojson::value& args, picojson::object& out) {
234   ScopeLogger("args: %s", args.serialize().c_str());
235   CHECK_ARGS(args, kTensorsInfoId, double, out);
236   CHECK_ARGS(args, kType, std::string, out);
237   // kName is nullable
238   CHECK_EXIST(args, kName, out);
239   CHECK_ARGS(args, kDimensions, picojson::array, out);
240
241   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
242   TensorsInfo* tensorsInfo = GetTensorsInfoManager().GetTensorsInfo(tensorsInfoId);
243   if (nullptr == tensorsInfo) {
244     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
245                       ("Could not find TensorsInfo handle with given id: %d", tensorsInfoId));
246     return;
247   }
248
249   const std::string& tensorType = args.get(kType).get<std::string>();
250   ml_tensor_type_e tensorTypeEnum = ML_TENSOR_TYPE_UNKNOWN;
251   PlatformResult result = types::TensorTypeEnum.getValue(tensorType, &tensorTypeEnum);
252   if (!result) {
253     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Error getting value of TensorType"),
254                       &out,
255                       ("TensorTypeEnum.getValue() failed, error: %s", result.message().c_str()));
256     return;
257   }
258
259   std::string name;
260   if (args.get(kName).is<std::string>()) {
261     name = args.get(kName).get<std::string>();
262     LoggerD("name: %s", name.c_str());
263   }
264
265   unsigned int dimensions[ML_TENSOR_RANK_LIMIT] = {};
266   auto dim = args.get(kDimensions).get<picojson::array>();
267   result = util::GetDimensionsFromJsonArray(dim, dimensions);
268   if (!result) {
269     LogAndReportError(result, &out);
270     return;
271   }
272
273   result = tensorsInfo->AddTensorInfo(name, tensorTypeEnum, dimensions);
274   if (!result) {
275     LogAndReportError(result, &out);
276     return;
277   }
278
279   int count = tensorsInfo->Count() - 1;
280
281   picojson::value val = picojson::value{static_cast<double>(count)};
282   ReportSuccess(val, out);
283 }
284
285 void MlInstance::MLTensorsInfoGetDimensions(const picojson::value& args, picojson::object& out) {
286   ScopeLogger("args: %s", args.serialize().c_str());
287   CHECK_ARGS(args, kTensorsInfoId, double, out);
288   CHECK_ARGS(args, kIndex, double, out);
289
290   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
291   TensorsInfo* tensorsInfo = GetTensorsInfoManager().GetTensorsInfo(tensorsInfoId);
292   if (nullptr == tensorsInfo) {
293     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
294                       ("Could not find TensorsInfo handle with given id: %d", tensorsInfoId));
295     return;
296   }
297   int index = static_cast<int>(args.get(kIndex).get<double>());
298   unsigned int dim[ML_TENSOR_RANK_LIMIT];
299   PlatformResult result = tensorsInfo->NativeGetTensorDimensions(index, dim);
300   if (!result) {
301     LogAndReportError(result, &out);
302     return;
303   }
304   picojson::array array = picojson::array{};
305   for (int i = 0; i < ML_TENSOR_RANK_LIMIT; i++) {
306     if (0 == dim[i]) {
307       break;
308     }
309     array.push_back(picojson::value{static_cast<double>(dim[i])});
310   }
311   picojson::value val = picojson::value{array};
312   ReportSuccess(val, out);
313 }
314
315 void MlInstance::MLTensorsInfoSetDimensions(const picojson::value& args, picojson::object& out) {
316   ScopeLogger("args: %s", args.serialize().c_str());
317   CHECK_ARGS(args, kTensorsInfoId, double, out);
318   CHECK_ARGS(args, kIndex, double, out);
319   CHECK_ARGS(args, kDimensions, picojson::array, out);
320
321   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
322   TensorsInfo* tensorsInfo = GetTensorsInfoManager().GetTensorsInfo(tensorsInfoId);
323   if (nullptr == tensorsInfo) {
324     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
325                       ("Could not find TensorsInfo handle with given id: %d", tensorsInfoId));
326     return;
327   }
328
329   unsigned int dimensions[ML_TENSOR_RANK_LIMIT] = {};
330   auto dim = args.get(kDimensions).get<picojson::array>();
331   PlatformResult result = util::GetDimensionsFromJsonArray(dim, dimensions);
332   if (!result) {
333     LogAndReportError(result, &out);
334     return;
335   }
336
337   int index = static_cast<int>(args.get(kIndex).get<double>());
338   result = tensorsInfo->NativeSetTensorDimensions(index, dimensions);
339   if (!result) {
340     LogAndReportError(result, &out);
341     return;
342   }
343   ReportSuccess(out);
344 }
345
346 void MlInstance::MLTensorsInfoGetTensorName(const picojson::value& args, picojson::object& out) {
347   ScopeLogger("args: %s", args.serialize().c_str());
348   CHECK_ARGS(args, kTensorsInfoId, double, out);
349   CHECK_ARGS(args, kIndex, double, out);
350
351   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
352   TensorsInfo* tensorsInfo = GetTensorsInfoManager().GetTensorsInfo(tensorsInfoId);
353   if (nullptr == tensorsInfo) {
354     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
355                       ("Could not find TensorsInfo handle with given id: %d", tensorsInfoId));
356     return;
357   }
358   int index = static_cast<int>(args.get(kIndex).get<double>());
359   std::string name;
360   PlatformResult result = tensorsInfo->NativeGetTensorName(index, &name);
361   if (!result) {
362     LogAndReportError(result, &out);
363     return;
364   }
365   picojson::value val = picojson::value{name};
366   ReportSuccess(val, out);
367 }
368
369 void MlInstance::MLTensorsInfoSetTensorName(const picojson::value& args, picojson::object& out) {
370   ScopeLogger("args: %s", args.serialize().c_str());
371   CHECK_ARGS(args, kTensorsInfoId, double, out);
372   CHECK_ARGS(args, kIndex, double, out);
373   CHECK_ARGS(args, kName, std::string, out);
374
375   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
376   TensorsInfo* tensorsInfo = GetTensorsInfoManager().GetTensorsInfo(tensorsInfoId);
377   if (nullptr == tensorsInfo) {
378     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
379                       ("Could not find TensorsInfo handle with given id: %d", tensorsInfoId));
380     return;
381   }
382
383   int index = static_cast<int>(args.get(kIndex).get<double>());
384   const std::string& name = args.get(kName).get<std::string>();
385   PlatformResult result = tensorsInfo->NativeSetTensorName(index, name);
386   if (!result) {
387     LogAndReportError(result, &out);
388     return;
389   }
390   ReportSuccess(out);
391 }
392
393 void MlInstance::MLTensorsInfoGetTensorSize(const picojson::value& args, picojson::object& out) {
394   ScopeLogger("args: %s", args.serialize().c_str());
395   CHECK_ARGS(args, kTensorsInfoId, double, out);
396   CHECK_ARGS(args, kIndex, double, out);
397
398   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
399   TensorsInfo* tensorsInfo = GetTensorsInfoManager().GetTensorsInfo(tensorsInfoId);
400   if (nullptr == tensorsInfo) {
401     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
402                       ("Could not find TensorsInfo handle with given id: %d", tensorsInfoId));
403     return;
404   }
405   int index = static_cast<int>(args.get(kIndex).get<double>());
406   size_t size;
407   PlatformResult result = tensorsInfo->NativeGetTensorSize(index, &size);
408   if (!result) {
409     LogAndReportError(result, &out);
410     return;
411   }
412
413   picojson::value val = picojson::value{static_cast<double>(size)};
414   ReportSuccess(val, out);
415 }
416
417 void MlInstance::MLTensorsInfoGetTensorType(const picojson::value& args, picojson::object& out) {
418   ScopeLogger("args: %s", args.serialize().c_str());
419   CHECK_ARGS(args, kTensorsInfoId, double, out);
420   CHECK_ARGS(args, kIndex, double, out);
421
422   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
423   TensorsInfo* tensorsInfo = GetTensorsInfoManager().GetTensorsInfo(tensorsInfoId);
424   if (nullptr == tensorsInfo) {
425     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
426                       ("Could not find TensorsInfo handle with given id: %d", tensorsInfoId));
427     return;
428   }
429
430   int index = static_cast<int>(args.get(kIndex).get<double>());
431   ml_tensor_type_e tensorTypeEnum = ML_TENSOR_TYPE_UNKNOWN;
432   PlatformResult result = tensorsInfo->NativeGetTensorType(index, &tensorTypeEnum);
433   if (!result) {
434     LogAndReportError(result, &out);
435     return;
436   }
437   std::string tensorTypeString;
438   result = types::TensorTypeEnum.getName(tensorTypeEnum, &tensorTypeString);
439   if (!result) {
440     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Error getting name of TensorType"),
441                       &out,
442                       ("TensorTypeEnum.getName() failed, error: %s", result.message().c_str()));
443     return;
444   }
445
446   picojson::value val = picojson::value{tensorTypeString};
447   ReportSuccess(val, out);
448 }
449
450 void MlInstance::MLTensorsInfoSetTensorType(const picojson::value& args, picojson::object& out) {
451   ScopeLogger("args: %s", args.serialize().c_str());
452   CHECK_ARGS(args, kTensorsInfoId, double, out);
453   CHECK_ARGS(args, kIndex, double, out);
454   CHECK_ARGS(args, kType, std::string, out);
455
456   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
457   TensorsInfo* tensorsInfo = GetTensorsInfoManager().GetTensorsInfo(tensorsInfoId);
458   if (nullptr == tensorsInfo) {
459     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
460                       ("Could not find TensorsInfo handle with given id: %d", tensorsInfoId));
461     return;
462   }
463
464   const std::string& tensorType = args.get(kType).get<std::string>();
465   ml_tensor_type_e tensorTypeEnum = ML_TENSOR_TYPE_UNKNOWN;
466   PlatformResult result = types::TensorTypeEnum.getValue(tensorType, &tensorTypeEnum);
467   if (!result) {
468     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Error getting value of TensorType"),
469                       &out,
470                       ("TensorTypeEnum.getValue() failed, error: %s", result.message().c_str()));
471     return;
472   }
473
474   int index = static_cast<int>(args.get(kIndex).get<double>());
475   result = tensorsInfo->NativeSetTensorType(index, tensorTypeEnum);
476   if (!result) {
477     LogAndReportError(result, &out);
478     return;
479   }
480   ReportSuccess(out);
481 }
482
483 void MlInstance::MLTensorsInfoGetTensorsData(const picojson::value& args, picojson::object& out) {
484   ScopeLogger("args: %s", args.serialize().c_str());
485   CHECK_ARGS(args, kTensorsInfoId, double, out);
486
487   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
488   TensorsInfo* tensorsInfo = GetTensorsInfoManager().GetTensorsInfo(tensorsInfoId);
489   if (nullptr == tensorsInfo) {
490     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
491                       ("Could not find TensorsInfo handle with given id: %d", tensorsInfoId));
492     return;
493   }
494
495   TensorsData* tensorsData = GetTensorsInfoManager().CreateTensorsData(tensorsInfo);
496   if (!tensorsData) {
497     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
498                       ("Could not create TensorsData"));
499     return;
500   }
501
502   out[kTensorsDataId] = picojson::value(static_cast<double>(tensorsData->Id()));
503   out[kTensorsInfoId] = picojson::value(static_cast<double>(tensorsData->TensorsInfoId()));
504   ReportSuccess(out);
505 }
506
507 void MlInstance::MLTensorsInfoClone(const picojson::value& args, picojson::object& out) {
508   ScopeLogger("args: %s", args.serialize().c_str());
509   CHECK_ARGS(args, kTensorsInfoId, double, out);
510
511   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
512   TensorsInfo* tensorsInfo = GetTensorsInfoManager().GetTensorsInfo(tensorsInfoId);
513   if (nullptr == tensorsInfo) {
514     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
515                       ("Could not find TensorsInfo handle with given id: %d", tensorsInfoId));
516     return;
517   }
518
519   TensorsInfo* cloned = GetTensorsInfoManager().CloneTensorsInfo(tensorsInfo);
520   if (nullptr == cloned) {
521     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
522                       ("Could not clone TensorsInfo with given id: %d", tensorsInfoId));
523     return;
524   }
525
526   out["id"] = picojson::value(static_cast<double>(cloned->Id()));
527   ReportSuccess(out);
528 }
529
530 void MlInstance::MLTensorsInfoEquals(const picojson::value& args, picojson::object& out) {
531   ScopeLogger("args: %s", args.serialize().c_str());
532   CHECK_ARGS(args, kTensorsInfoId, double, out);
533   CHECK_ARGS(args, kOtherId, double, out);
534
535   int firstId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
536   int secondId = static_cast<int>(args.get(kOtherId).get<double>());
537
538   TensorsInfo* first = GetTensorsInfoManager().GetTensorsInfo(firstId);
539   if (nullptr == first) {
540     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
541                       ("Could not find TensorsInfo handle with given id: %d", firstId));
542     return;
543   }
544
545   TensorsInfo* second = GetTensorsInfoManager().GetTensorsInfo(secondId);
546   if (nullptr == second) {
547     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
548                       ("Could not find TensorsInfo handle with given id: %d", secondId));
549     return;
550   }
551
552   bool equals = first->Equals(second);
553   picojson::value val = picojson::value{equals};
554   ReportSuccess(val, out);
555 }
556
557 void MlInstance::MLTensorsInfoDispose(const picojson::value& args, picojson::object& out) {
558   ScopeLogger("args: %s", args.serialize().c_str());
559   CHECK_ARGS(args, kTensorsInfoId, double, out);
560   int tensorsInfoId = static_cast<int>(args.get(kTensorsInfoId).get<double>());
561
562   PlatformResult result = GetTensorsInfoManager().DisposeTensorsInfo(tensorsInfoId);
563   if (!result) {
564     LogAndReportError(result, &out);
565   }
566   ReportSuccess(out);
567 }
568
569 void MlInstance::MLTensorsDataDispose(const picojson::value& args, picojson::object& out) {
570   ScopeLogger("args: %s", args.serialize().c_str());
571   CHECK_ARGS(args, kTensorsDataId, double, out);
572   int tensors_data_id = static_cast<int>(args.get(kTensorsDataId).get<double>());
573
574   TensorsData* tensors_data = GetTensorsDataManager().GetTensorsData(tensors_data_id);
575   if (nullptr == tensors_data) {
576     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsData error"), &out,
577                       ("Could not find TensorsData handle with given id: %d", tensors_data_id));
578     return;
579   }
580
581   if (!tensors_data->DisposableFromJS()) {
582     ReportSuccess(out);
583     return;
584   }
585
586   // Dispose underlying tensorsInfo
587   PlatformResult result = GetTensorsInfoManager().DisposeTensorsInfo(tensors_data->TensorsInfoId());
588   if (!result) {
589     LogAndReportError(result, &out);
590     return;
591   }
592
593   result = GetTensorsDataManager().DisposeTensorsData(tensors_data_id);
594   if (!result) {
595     LogAndReportError(result, &out);
596     return;
597   }
598   ReportSuccess(out);
599 }
600
601 void MlInstance::MLTensorsDataGetTensorRawData(const picojson::value& args, picojson::object& out) {
602   ScopeLogger("args: %s", args.serialize().c_str());
603   CHECK_ARGS(args, kTensorsDataId, double, out);
604   CHECK_ARGS(args, kIndex, double, out);
605   CHECK_ARGS(args, kLocation, picojson::array, out);
606   CHECK_ARGS(args, kSize, picojson::array, out);
607
608   int tensor_data_id = static_cast<int>(args.get(kTensorsDataId).get<double>());
609   int index = static_cast<int>(args.get(kIndex).get<double>());
610
611   TensorsData* tensors_data = GetTensorsDataManager().GetTensorsData(tensor_data_id);
612   if (nullptr == tensors_data) {
613     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsData error"), &out,
614                       ("Could not find TensorsData handle with given id: %d", tensor_data_id));
615     return;
616   }
617
618   unsigned int location[ML_TENSOR_RANK_LIMIT] = {};
619   PlatformResult result =
620       util::GetLocationFromJsonArray(args.get(kLocation).get<picojson::array>(), location);
621   if (!result) {
622     LogAndReportError(result, &out);
623     return;
624   }
625
626   unsigned int dimensions[ML_TENSOR_RANK_LIMIT] = {};
627   result = tensors_data->GetTensorsInfo()->NativeGetTensorDimensions(index, dimensions);
628   if (!result) {
629     LogAndReportError(result, &out);
630     return;
631   }
632
633   unsigned int size[ML_TENSOR_RANK_LIMIT] = {};
634   result = util::GetSizeFromJsonArray(args.get(kSize).get<picojson::array>(), location, dimensions,
635                                       size);
636   if (!result) {
637     LogAndReportError(result, &out);
638     return;
639   }
640
641   TensorRawData raw_data;
642   result = tensors_data->GetTensorRawData(index, location, size, &raw_data);
643   if (!result) {
644     LogAndReportError(result, &out);
645     return;
646   }
647
648   std::vector<std::uint8_t> out_data{raw_data.data, raw_data.data + raw_data.size_in_bytes};
649   out[kBuffer] = picojson::value(picojson::string_type, true);
650   common::encode_binary_in_string(out_data, out[kBuffer].get<std::string>());
651
652   out[kType] = picojson::value(raw_data.type_str);
653   picojson::array shape = picojson::array{};
654   for (int i = 0; i < ML_TENSOR_RANK_LIMIT; i++) {
655     shape.push_back(picojson::value{static_cast<double>(raw_data.shape[i])});
656   }
657   out[kShape] = picojson::value{shape};
658
659   ReportSuccess(out);
660 }
661
662 void MlInstance::MLTensorsDataGetTensorRawDataBinary(const picojson::value& args,
663                                                      std::vector<uint8_t>* out) {
664   ScopeLogger("args: %s", args.serialize().c_str());
665   // TODO handle errors to out
666   // CHECK_ARGS(args, kTensorsDataId, double, out);
667   // CHECK_ARGS(args, kIndex, double, out);
668   // CHECK_ARGS(args, kLocation, picojson::array, out);
669   // CHECK_ARGS(args, kSize, picojson::array, out);
670
671   int tensor_data_id = static_cast<int>(args.get(kTensorsDataId).get<double>());
672   int index = static_cast<int>(args.get(kIndex).get<double>());
673
674   TensorsData* tensors_data = GetTensorsDataManager().GetTensorsData(tensor_data_id);
675   if (nullptr == tensors_data) {
676     LoggerE("Could not find TensorsData handle with given id: %d", tensor_data_id);
677     tools::ReportErrorToBinary(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsData error"),
678                                out);
679     return;
680   }
681
682   unsigned int location[ML_TENSOR_RANK_LIMIT] = {};
683   PlatformResult result =
684       util::GetLocationFromJsonArray(args.get(kLocation).get<picojson::array>(), location);
685   if (!result) {
686     LoggerE("Reporting error.");
687     tools::ReportErrorToBinary(result, out);
688     return;
689   }
690
691   unsigned int dimensions[ML_TENSOR_RANK_LIMIT] = {};
692   result = tensors_data->GetTensorsInfo()->NativeGetTensorDimensions(index, dimensions);
693   if (!result) {
694     LoggerE("Reporting error.");
695     tools::ReportErrorToBinary(result, out);
696     return;
697   }
698
699   unsigned int size[ML_TENSOR_RANK_LIMIT] = {};
700   result = util::GetSizeFromJsonArray(args.get(kSize).get<picojson::array>(), location, dimensions,
701                                       size);
702   if (!result) {
703     LoggerE("Reporting error.");
704     tools::ReportErrorToBinary(result, out);
705     return;
706   }
707
708   TensorRawData raw_data;
709   result = tensors_data->GetTensorRawData(index, location, size, &raw_data);
710   if (!result) {
711     LoggerE("Reporting error.");
712     tools::ReportErrorToBinary(result, out);
713     return;
714   }
715
716   picojson::value result_json = picojson::value(picojson::object());
717   auto& out_json = result_json.get<picojson::object>();
718
719   out_json[kType] = picojson::value(raw_data.type_str);
720   picojson::array shape = picojson::array{};
721   for (int i = 0; i < ML_TENSOR_RANK_LIMIT; i++) {
722     shape.push_back(picojson::value{static_cast<double>(raw_data.shape[i])});
723   }
724   out_json[kShape] = picojson::value{shape};
725
726   std::vector<std::uint8_t> out_data{raw_data.data, raw_data.data + raw_data.size_in_bytes};
727
728   // FORMAT:
729   // 4 byte    === JSON lenght (N)
730   // N bytest  === JSON data
731   tools::ReportSuccessToBinary(result_json, out);
732   // 4 byte    === buffer length (M)
733   // M bytes   === buffer data
734   tools::ReportDataToBinary(out_data, out);
735 }
736
737 void MlInstance::MLTensorsDataGetTensorType(const picojson::value& args, picojson::object& out) {
738   ScopeLogger("args: %s", args.serialize().c_str());
739   CHECK_ARGS(args, kTensorsDataId, double, out);
740   CHECK_ARGS(args, kIndex, double, out);
741
742   int tensors_data_id = static_cast<int>(args.get(kTensorsDataId).get<double>());
743   int index = static_cast<int>(args.get(kIndex).get<double>());
744
745   TensorsData* tensors_data = GetTensorsDataManager().GetTensorsData(tensors_data_id);
746   if (nullptr == tensors_data) {
747     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsData error"), &out,
748                       ("Could not find TensorsData handle with given id: %d", tensors_data_id));
749     return;
750   }
751
752   std::string tensor_type_string;
753   PlatformResult result =
754       types::TensorTypeEnum.getName(tensors_data->GetTensorType(index), &tensor_type_string);
755   if (!result) {
756     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Error getting name of TensorType"),
757                       &out,
758                       ("TensorTypeEnum.getName() failed, error: %s", result.message().c_str()));
759     return;
760   }
761
762   picojson::value val = picojson::value{tensor_type_string};
763   ReportSuccess(val, out);
764 }
765
766 void MlInstance::MLTensorsDataSetTensorRawData(const picojson::value& args, picojson::object& out) {
767   ScopeLogger();
768   CHECK_ARGS(args, kTensorsDataId, double, out);
769   CHECK_ARGS(args, kIndex, double, out);
770   CHECK_ARGS(args, kBuffer, std::string, out);
771   CHECK_ARGS(args, kLocation, picojson::array, out);
772   CHECK_ARGS(args, kSize, picojson::array, out);
773   LoggerD("%s, %s", kTensorsDataId.c_str(), args.get(kTensorsDataId).serialize().c_str());
774   LoggerD("%s, %s", kIndex.c_str(), args.get(kIndex).serialize().c_str());
775   LoggerD("%s, %s", kLocation.c_str(), args.get(kLocation).serialize().c_str());
776   LoggerD("%s, %s", kSize.c_str(), args.get(kSize).serialize().c_str());
777
778   int tensors_data_id = static_cast<int>(args.get(kTensorsDataId).get<double>());
779   int index = static_cast<int>(args.get(kIndex).get<double>());
780
781   TensorsData* tensors_data = GetTensorsDataManager().GetTensorsData(tensors_data_id);
782   if (nullptr == tensors_data) {
783     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsData error"), &out,
784                       ("Could not find TensorsData handle with given id: %d", tensors_data_id));
785     return;
786   }
787
788   unsigned int location[ML_TENSOR_RANK_LIMIT] = {};
789   PlatformResult result =
790       util::GetLocationFromJsonArray(args.get(kLocation).get<picojson::array>(), location);
791   if (!result) {
792     LogAndReportError(result, &out);
793     return;
794   }
795
796   unsigned int dimensions[ML_TENSOR_RANK_LIMIT] = {};
797   result = tensors_data->GetTensorsInfo()->NativeGetTensorDimensions(index, dimensions);
798   if (!result) {
799     LogAndReportError(result, &out);
800     return;
801   }
802
803   unsigned int size[ML_TENSOR_RANK_LIMIT] = {};
804   result = util::GetSizeFromJsonArray(args.get(kSize).get<picojson::array>(), location, dimensions,
805                                       size);
806   if (!result) {
807     LogAndReportError(result, &out);
808     return;
809   }
810   const std::string& str_buffer = args.get(kBuffer).get<std::string>();
811   std::vector<std::uint8_t> buffer;
812   common::decode_binary_from_string(str_buffer, buffer);
813
814   TensorRawData raw_data{buffer.data(), buffer.size()};
815   result = tensors_data->SetTensorRawData(index, location, size, raw_data);
816   if (!result) {
817     LogAndReportError(result, &out);
818     return;
819   }
820
821   ReportSuccess(out);
822 }
823
824 void MlInstance::MLTensorsDataSetTensorRawDataBinary(const char* data, size_t data_size,
825                                                      picojson::object& out) {
826   ScopeLogger();
827   /*
828   METHOD_ID WAS ALREADY REMOVED during message handling
829   other data packed with following format:
830     // FORMAT:
831     // 1 byte    === methodIndex   /// already parsed
832     // 4 byte    === JSON lenght (N)
833     // 4 byte    === buffer length (M)
834     // N bytest  === JSON data
835     // M bytes   === buffer data
836   */
837   unsigned int call_args_len_begin = 0;
838   unsigned int call_args_len = static_cast<unsigned int>(
839       (data[call_args_len_begin] << 24) + (data[call_args_len_begin + 1] << 16) +
840       (data[call_args_len_begin + 2] << 8) + (data[call_args_len_begin + 3]));
841
842   unsigned int buffer_len_begin = call_args_len_begin + 4;
843   unsigned int buffer_len = static_cast<unsigned int>(
844       (data[buffer_len_begin] << 24) + (data[buffer_len_begin + 1] << 16) +
845       (data[buffer_len_begin + 2] << 8) + (data[buffer_len_begin + 3]));
846
847   unsigned int call_args_begin = buffer_len_begin + 4;
848   std::string call_args(data + call_args_begin, call_args_len);
849
850   picojson::value args;
851   picojson::parse(args, call_args);
852
853   unsigned int buffer_begin = call_args_begin + call_args_len;
854
855   CHECK_ARGS(args, kTensorsDataId, double, out);
856   CHECK_ARGS(args, kIndex, double, out);
857   CHECK_ARGS(args, kLocation, picojson::array, out);
858   CHECK_ARGS(args, kSize, picojson::array, out);
859   LoggerD("%s, %s", kTensorsDataId.c_str(), args.get(kTensorsDataId).serialize().c_str());
860   LoggerD("%s, %s", kIndex.c_str(), args.get(kIndex).serialize().c_str());
861   LoggerD("%s, %s", kLocation.c_str(), args.get(kLocation).serialize().c_str());
862   LoggerD("%s, %s", kSize.c_str(), args.get(kSize).serialize().c_str());
863
864   int tensors_data_id = static_cast<int>(args.get(kTensorsDataId).get<double>());
865   int index = static_cast<int>(args.get(kIndex).get<double>());
866
867   TensorsData* tensors_data = GetTensorsDataManager().GetTensorsData(tensors_data_id);
868   if (nullptr == tensors_data) {
869     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsData error"), &out,
870                       ("Could not find TensorsData handle with given id: %d", tensors_data_id));
871     return;
872   }
873
874   unsigned int location[ML_TENSOR_RANK_LIMIT] = {};
875   PlatformResult result =
876       util::GetLocationFromJsonArray(args.get(kLocation).get<picojson::array>(), location);
877   if (!result) {
878     LogAndReportError(result, &out);
879     return;
880   }
881
882   unsigned int dimensions[ML_TENSOR_RANK_LIMIT] = {};
883   result = tensors_data->GetTensorsInfo()->NativeGetTensorDimensions(index, dimensions);
884   if (!result) {
885     LogAndReportError(result, &out);
886     return;
887   }
888
889   unsigned int size[ML_TENSOR_RANK_LIMIT] = {};
890   result = util::GetSizeFromJsonArray(args.get(kSize).get<picojson::array>(), location, dimensions,
891                                       size);
892   if (!result) {
893     LogAndReportError(result, &out);
894     return;
895   }
896
897   TensorRawData raw_data{reinterpret_cast<uint8_t*>(const_cast<char*>(data + buffer_begin)),
898                          buffer_len};
899   result = tensors_data->SetTensorRawData(index, location, size, raw_data);
900   if (!result) {
901     LogAndReportError(result, &out);
902     return;
903   }
904
905   ReportSuccess(out);
906 }
907
908 void MlInstance::MLSingleManagerOpenModel(const picojson::value& args, picojson::object& out) {
909   ScopeLogger("args: %s", args.serialize().c_str());
910   CHECK_ARGS(args, kModelPath, std::string, out);
911   CHECK_ARGS(args, kInTensorsInfo, double, out);
912   CHECK_ARGS(args, kOutTensorsInfo, double, out);
913   CHECK_ARGS(args, kFwType, std::string, out);
914   CHECK_ARGS(args, kHwType, std::string, out);
915   CHECK_ARGS(args, kIsDynamicMode, bool, out);
916
917   const auto& model_path = common::tools::ConvertUriToPath(args.get(kModelPath).get<std::string>());
918   CHECK_STORAGE_ACCESS(model_path, &out);
919
920   TensorsInfo* in_tensors_info = nullptr;
921   auto inTensorId = static_cast<int>(args.get(kInTensorsInfo).get<double>());
922   if (kNoId != inTensorId) {
923     in_tensors_info = GetTensorsInfoManager().GetTensorsInfo(inTensorId);
924     if (nullptr == in_tensors_info) {
925       LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
926                         ("Could not find TensorsInfo handle with given id: %d", inTensorId));
927       return;
928     }
929   }
930
931   TensorsInfo* out_tensors_info = nullptr;
932   auto outTensorId = static_cast<int>(args.get(kOutTensorsInfo).get<double>());
933   if (kNoId != outTensorId) {
934     out_tensors_info = GetTensorsInfoManager().GetTensorsInfo(outTensorId);
935     if (nullptr == out_tensors_info) {
936       LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
937                         ("Could not find TensorsInfo handle with given id: %d", outTensorId));
938       return;
939     }
940   }
941
942   ml_nnfw_type_e nnfw_e = ML_NNFW_TYPE_ANY;
943   PlatformResult result =
944       types::NNFWTypeEnum.getValue(args.get(kFwType).get<std::string>(), &nnfw_e);
945   if (!result) {
946     LogAndReportError(result, &out);
947     return;
948   }
949
950   ml_nnfw_hw_e hw_e = ML_NNFW_HW_ANY;
951   result = types::HWTypeEnum.getValue(args.get(kHwType).get<std::string>(), &hw_e);
952   if (!result) {
953     LogAndReportError(result, &out);
954     return;
955   }
956
957   auto is_dynamic_mode = args.get(kIsDynamicMode).get<bool>();
958
959   auto logic = [this, model_path, in_tensors_info, out_tensors_info, nnfw_e, hw_e,
960                 is_dynamic_mode](decltype(out) out) {
961     PlatformResult result = common::tools::CheckFileAvailability(model_path);
962     if (!result) {
963       LogAndReportError(
964           PlatformResult(ErrorCode::NOT_FOUND_ERR, "File does not exist or is not accessible"),
965           &out, ("File does not exist or is not accessible: %s", model_path.c_str()));
966       return;
967     }
968
969     int res_id = -1;
970     result = single_manager_.OpenModel(model_path, in_tensors_info, out_tensors_info, nnfw_e, hw_e,
971                                        is_dynamic_mode, &res_id);
972     if (!result) {
973       ReportError(result, &out);
974       return;
975     }
976
977     out[kId] = picojson::value(static_cast<double>(res_id));
978     ReportSuccess(out);
979   };
980
981   bool async =
982       (args.contains(kAsync) && args.get(kAsync).is<bool>()) ? args.get(kAsync).get<bool>() : false;
983
984   if (!async) {
985     logic(out);
986   } else {
987     // Async logic
988     CHECK_ARGS(args, kCallbackId, double, out);
989     double callback_id = args.get(kCallbackId).get<double>();
990     this->worker_.add_job([this, callback_id, logic] {
991       picojson::value response = picojson::value(picojson::object());
992       picojson::object& async_out = response.get<picojson::object>();
993       async_out[kCallbackId] = picojson::value(callback_id);
994       logic(async_out);
995       this->PostMessage(response.serialize().c_str());
996     });
997
998     // Sync return
999     ReportSuccess(out);
1000   }
1001 }
1002
1003 void MlInstance::MLSingleShotGetTensorsInfo(const picojson::value& args, picojson::object& out) {
1004   ScopeLogger("args: %s", args.serialize().c_str());
1005   CHECK_ARGS(args, kId, double, out);
1006   CHECK_ARGS(args, kGetInputMode, bool, out);
1007
1008   auto id = static_cast<int>(args.get(kId).get<double>());
1009   // true means gathering input data; false means gathering output data
1010   auto get_input_mode = static_cast<int>(args.get(kGetInputMode).get<bool>());
1011
1012   int res_id = -1;
1013   auto ret = single_manager_.GetNativeTensorsInfo(id, get_input_mode, &res_id);
1014   if (!ret) {
1015     ReportError(ret, &out);
1016     return;
1017   }
1018
1019   out[kId] = picojson::value(static_cast<double>(res_id));
1020   ReportSuccess(out);
1021 }
1022
1023 void MlInstance::MLSingleShotSetInputInfo(const picojson::value& args, picojson::object& out) {
1024   ScopeLogger("args: %s", args.serialize().c_str());
1025   CHECK_ARGS(args, kId, double, out);
1026   CHECK_ARGS(args, kInTensorsInfo, double, out);
1027
1028   auto id = static_cast<int>(args.get(kId).get<double>());
1029   auto inTensorId = static_cast<int>(args.get(kInTensorsInfo).get<double>());
1030
1031   TensorsInfo* in_tensors_info = GetTensorsInfoManager().GetTensorsInfo(inTensorId);
1032   if (nullptr == in_tensors_info) {
1033     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
1034                       ("Could not find TensorsInfo handle with given id: %d", inTensorId));
1035     return;
1036   }
1037
1038   TensorsInfo* clone = GetTensorsInfoManager().CloneTensorsInfo(in_tensors_info);
1039
1040   auto ret = single_manager_.SetNativeInputInfo(id, in_tensors_info);
1041   if (!ret) {
1042     ReportError(ret, &out);
1043     return;
1044   }
1045
1046   out[kId] = picojson::value(static_cast<double>(clone->Id()));
1047   ReportSuccess(out);
1048 }
1049
1050 void MlInstance::MLSingleShotInvoke(const picojson::value& args, picojson::object& out) {
1051   ScopeLogger("args: %s", args.serialize().c_str());
1052   CHECK_ARGS(args, kId, double, out);
1053   CHECK_ARGS(args, kTensorsDataId, double, out);
1054
1055   int id = static_cast<int>(args.get(kId).get<double>());
1056   int tensors_data_id = static_cast<int>(args.get(kTensorsDataId).get<double>());
1057   bool async =
1058       (args.contains(kAsync) && args.get(kAsync).is<bool>()) ? args.get(kAsync).get<bool>() : false;
1059
1060   TensorsData* in_tensors_data = GetTensorsDataManager().GetTensorsData(tensors_data_id);
1061   if (async && in_tensors_data) {
1062     // in case of async flow need to prevent destroying entry data during invoke
1063     // from JS, creation of a copy
1064     in_tensors_data = GetTensorsInfoManager().CloneNativeTensorWithData(
1065         in_tensors_data->GetTensorsInfo()->Handle(), in_tensors_data->Handle());
1066   }
1067   if (nullptr == in_tensors_data) {
1068     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsData error"), &out,
1069                       ("Could not find TensorsData handle with given id: %d", tensors_data_id));
1070     return;
1071   }
1072
1073   auto logic = [this, id, tensors_data_id, in_tensors_data, async](decltype(out) out) {
1074     TensorsData* out_tensors_data = nullptr;
1075     auto ret = single_manager_.Invoke(id, in_tensors_data, &out_tensors_data);
1076     if (async) {
1077       // in case of async flow, the in_tensor_data with underlying TensorsInfo
1078       // was copied, thus need to be released here
1079       GetTensorsInfoManager().DisposeTensorsInfo(in_tensors_data->GetTensorsInfo());
1080       GetTensorsDataManager().DisposeTensorsData(in_tensors_data);
1081     }
1082     if (!ret) {
1083       ReportError(ret, &out);
1084       return;
1085     }
1086
1087     out[kTensorsDataId] = picojson::value(static_cast<double>(out_tensors_data->Id()));
1088     out[kTensorsInfoId] = picojson::value(static_cast<double>(out_tensors_data->TensorsInfoId()));
1089     ReportSuccess(out);
1090   };
1091
1092   if (!async) {
1093     logic(out);
1094   } else {
1095     CHECK_ARGS(args, kCallbackId, double, out);
1096     double callback_id = args.get(kCallbackId).get<double>();
1097     this->worker_.add_job([this, callback_id, logic] {
1098       picojson::value response = picojson::value(picojson::object());
1099       picojson::object& async_out = response.get<picojson::object>();
1100       async_out[kCallbackId] = picojson::value(callback_id);
1101       logic(async_out);
1102       this->PostMessage(response.serialize().c_str());
1103     });
1104
1105     // Sync return
1106     ReportSuccess(out);
1107   }
1108 }
1109
1110 void MlInstance::MLSingleShotGetValue(const picojson::value& args, picojson::object& out) {
1111   ScopeLogger("args: %s", args.serialize().c_str());
1112   CHECK_ARGS(args, kId, double, out);
1113   CHECK_ARGS(args, kName, std::string, out);
1114
1115   auto id = static_cast<int>(args.get(kId).get<double>());
1116   const auto& name = args.get(kName).get<std::string>();
1117   std::string value;
1118   auto ret = single_manager_.GetValue(id, name, value);
1119   if (!ret) {
1120     ReportError(ret, &out);
1121     return;
1122   }
1123
1124   picojson::value val = picojson::value{value};
1125   ReportSuccess(val, out);
1126 }
1127
1128 void MlInstance::MLSingleShotSetValue(const picojson::value& args, picojson::object& out) {
1129   ScopeLogger("args: %s", args.serialize().c_str());
1130   CHECK_ARGS(args, kId, double, out);
1131   CHECK_ARGS(args, kName, std::string, out);
1132   CHECK_ARGS(args, kValue, std::string, out);
1133
1134   auto id = static_cast<int>(args.get(kId).get<double>());
1135   const auto& name = args.get(kName).get<std::string>();
1136   const auto& value = args.get(kValue).get<std::string>();
1137
1138   auto ret = single_manager_.SetValue(id, name, value);
1139   if (!ret) {
1140     ReportError(ret, &out);
1141     return;
1142   }
1143
1144   ReportSuccess(out);
1145 }
1146
1147 void MlInstance::MLSingleShotSetTimeout(const picojson::value& args, picojson::object& out) {
1148   ScopeLogger("args: %s", args.serialize().c_str());
1149   CHECK_ARGS(args, kId, double, out);
1150   CHECK_ARGS(args, kTimeout, double, out);
1151
1152   auto id = static_cast<int>(args.get(kId).get<double>());
1153   auto timeout = static_cast<unsigned long>(args.get(kTimeout).get<double>());
1154
1155   auto ret = single_manager_.SetTimeout(id, timeout);
1156   if (!ret) {
1157     ReportError(ret, &out);
1158     return;
1159   }
1160
1161   ReportSuccess(out);
1162 }
1163
1164 void MlInstance::MLSingleShotClose(const picojson::value& args, picojson::object& out) {
1165   ScopeLogger("args: %s", args.serialize().c_str());
1166   CHECK_ARGS(args, kId, double, out);
1167
1168   auto id = static_cast<int>(args.get(kId).get<double>());
1169
1170   auto ret = single_manager_.Close(id);
1171   if (!ret) {
1172     ReportError(ret, &out);
1173     return;
1174   }
1175
1176   ReportSuccess(out);
1177 }
1178
1179 namespace {
1180
1181 bool CreatePipelineArgumentsAreInvalid(const picojson::value& args) {
1182   ScopeLogger();
1183
1184   auto arguments_valid = args.get(kId).is<double>();
1185   arguments_valid &= args.get(kDefinition).is<std::string>();
1186   arguments_valid &= (args.get(kPipelineStateChangeListenerName).is<std::string>() ||
1187                       args.get(kPipelineStateChangeListenerName).is<picojson::null>());
1188   LoggerD("CreatePipeline arguments are %s", arguments_valid ? "valid" : "invalid");
1189
1190   return !arguments_valid;
1191 }
1192
1193 };  // namespace
1194
1195 void MlInstance::MLPipelineManagerCreatePipeline(const picojson::value& args,
1196                                                  picojson::object& out) {
1197   ScopeLogger("args: %s", args.serialize().c_str());
1198
1199   if (CreatePipelineArgumentsAreInvalid(args)) {
1200     ReportError(PlatformResult{ErrorCode::ABORT_ERR, "Could not create pipeline"}, &out);
1201     return;
1202   }
1203
1204   auto id = static_cast<int>(args.get(kId).get<double>());
1205   auto definition = args.get(kDefinition).get<std::string>();
1206   auto state_change_listener_name =
1207       args.get(kPipelineStateChangeListenerName).is<std::string>()
1208           ? args.get(kPipelineStateChangeListenerName).get<std::string>()
1209           : "";
1210
1211   auto ret = pipeline_manager_.CreatePipeline(id, definition, state_change_listener_name);
1212
1213   if (!ret) {
1214     ReportError(ret, &out);
1215     return;
1216   }
1217
1218   ReportSuccess(out);
1219 }
1220
1221 void MlInstance::MLPipelineGetState(const picojson::value& args, picojson::object& out) {
1222   ScopeLogger("args: %s", args.serialize().c_str());
1223
1224   if (!args.get(kId).is<double>()) {
1225     LoggerD("id is not a number");
1226     ReportError(PlatformResult{ErrorCode::ABORT_ERR, "Invalid pipeline"}, &out);
1227     return;
1228   }
1229   auto id = static_cast<int>(args.get(kId).get<double>());
1230
1231   picojson::value state_value{std::string{}};
1232   std::string* state_ptr = &state_value.get<std::string>();
1233   auto ret = pipeline_manager_.GetPipelineState(id, state_ptr);
1234   if (!ret) {
1235     ReportError(ret, &out);
1236     return;
1237   }
1238
1239   ReportSuccess(state_value, out);
1240 }
1241
1242 void MlInstance::MLPipelineStart(const picojson::value& args, picojson::object& out) {
1243   ScopeLogger("args: %s", args.serialize().c_str());
1244
1245   CHECK_ARGS(args, kId, double, out);
1246
1247   auto id = static_cast<int>(args.get(kId).get<double>());
1248
1249   PlatformResult result = pipeline_manager_.Start(id);
1250
1251   if (!result) {
1252     ReportError(result, &out);
1253     return;
1254   }
1255
1256   ReportSuccess(out);
1257 }
1258
1259 void MlInstance::MLPipelineStop(const picojson::value& args, picojson::object& out) {
1260   ScopeLogger("args: %s", args.serialize().c_str());
1261
1262   CHECK_ARGS(args, kId, double, out);
1263
1264   auto id = static_cast<int>(args.get(kId).get<double>());
1265
1266   PlatformResult result = pipeline_manager_.Stop(id);
1267
1268   if (!result) {
1269     LogAndReportError(result, &out);
1270     return;
1271   }
1272
1273   ReportSuccess(out);
1274 }
1275
1276 void MlInstance::MLPipelineDispose(const picojson::value& args, picojson::object& out) {
1277   ScopeLogger("args: %s", args.serialize().c_str());
1278
1279   if (!args.get(kId).is<double>()) {
1280     LoggerD("id is not a number");
1281     ReportError(PlatformResult{ErrorCode::ABORT_ERR, "Invalid pipeline"}, &out);
1282     return;
1283   }
1284
1285   auto id = static_cast<int>(args.get(kId).get<double>());
1286   auto ret = pipeline_manager_.DisposePipeline(id);
1287
1288   if (!ret) {
1289     ReportError(ret, &out);
1290     return;
1291   }
1292
1293   ReportSuccess(out);
1294 }
1295
1296 void MlInstance::MLPipelineGetNodeInfo(const picojson::value& args, picojson::object& out) {
1297   ScopeLogger("args: %s", args.serialize().c_str());
1298
1299   CHECK_ARGS(args, kId, double, out);
1300   CHECK_ARGS(args, kName, std::string, out);
1301
1302   auto name = args.get(kName).get<std::string>();
1303   auto id = static_cast<int>(args.get(kId).get<double>());
1304
1305   PlatformResult result = pipeline_manager_.GetNodeInfo(id, name);
1306
1307   if (!result) {
1308     LogAndReportError(result, &out);
1309     return;
1310   }
1311
1312   ReportSuccess(out);
1313 }
1314
1315 void MlInstance::MLPipelineGetSource(const picojson::value& args, picojson::object& out) {
1316   ScopeLogger("args: %s", args.serialize().c_str());
1317
1318   CHECK_ARGS(args, kId, double, out);
1319   CHECK_ARGS(args, kName, std::string, out);
1320
1321   auto name = args.get(kName).get<std::string>();
1322   auto id = static_cast<int>(args.get(kId).get<double>());
1323
1324   PlatformResult result = pipeline_manager_.GetSource(id, name);
1325
1326   if (!result) {
1327     LogAndReportError(result, &out);
1328     return;
1329   }
1330
1331   ReportSuccess(out);
1332 }
1333
1334 void MlInstance::MLPipelineGetSwitch(const picojson::value& args, picojson::object& out) {
1335   ScopeLogger("args: %s", args.serialize().c_str());
1336
1337   if (!args.get(kId).is<double>()) {
1338     LoggerD("id is not a number");
1339     ReportError(PlatformResult{ErrorCode::ABORT_ERR, "Invalid pipeline"}, &out);
1340     return;
1341   }
1342
1343   if (!args.get(kName).is<std::string>()) {
1344     LoggerD("name is not a string");
1345     ReportError(PlatformResult{ErrorCode::ABORT_ERR, "Invalid name"}, &out);
1346     return;
1347   }
1348
1349   auto name = args.get(kName).get<std::string>();
1350   auto pipeline_id = static_cast<int>(args.get(kId).get<double>());
1351   std::string type;
1352
1353   auto ret = pipeline_manager_.GetSwitch(name, pipeline_id, &type);
1354   if (!ret) {
1355     LogAndReportError(ret, &out);
1356     return;
1357   }
1358
1359   out["type"] = picojson::value{type};
1360   ReportSuccess(out);
1361 }
1362
1363 void MlInstance::MLPipelineGetValve(const picojson::value& args, picojson::object& out) {
1364   ScopeLogger("args: %s", args.serialize().c_str());
1365
1366   CHECK_ARGS(args, kId, double, out);
1367   CHECK_ARGS(args, kName, std::string, out);
1368
1369   auto name = args.get(kName).get<std::string>();
1370   auto pipeline_id = args.get(kId).get<double>();
1371
1372   auto ret = pipeline_manager_.GetValve(name, pipeline_id);
1373   if (!ret) {
1374     LogAndReportError(ret, &out);
1375     return;
1376   }
1377
1378   ReportSuccess(out);
1379 }
1380
1381 void MlInstance::MLPipelineRegisterSinkListener(const picojson::value& args,
1382                                                 picojson::object& out) {
1383   ScopeLogger("args: %s", args.serialize().c_str());
1384
1385   CHECK_ARGS(args, kId, double, out);
1386   CHECK_ARGS(args, kName, std::string, out);
1387   CHECK_ARGS(args, kListenerName, std::string, out);
1388
1389   auto pipeline_id = static_cast<int>(args.get(kId).get<double>());
1390   auto sink_name = args.get(kName).get<std::string>();
1391   auto listener_name = args.get(kListenerName).get<std::string>();
1392
1393   auto ret = pipeline_manager_.RegisterSinkListener(sink_name, pipeline_id, listener_name);
1394   if (!ret) {
1395     LogAndReportError(ret, &out);
1396     return;
1397   }
1398
1399   ReportSuccess(out);
1400 }
1401
1402 void MlInstance::MLPipelineUnregisterSinkListener(const picojson::value& args,
1403                                                   picojson::object& out) {
1404   ScopeLogger("args: %s", args.serialize().c_str());
1405
1406   CHECK_ARGS(args, kId, double, out);
1407   CHECK_ARGS(args, kName, std::string, out);
1408
1409   auto pipeline_id = static_cast<int>(args.get(kId).get<double>());
1410   auto sink_name = args.get(kName).get<std::string>();
1411
1412   auto ret = pipeline_manager_.UnregisterSinkListener(sink_name, pipeline_id);
1413   if (!ret) {
1414     LogAndReportError(ret, &out);
1415     return;
1416   }
1417
1418   ReportSuccess(out);
1419 }
1420
1421 void MlInstance::MLPipelineManagerRegisterCustomFilter(const picojson::value& args,
1422                                                        picojson::object& out) {
1423   ScopeLogger("args: %s", args.serialize().c_str());
1424
1425   CHECK_ARGS(args, kName, std::string, out);
1426   CHECK_ARGS(args, kListenerName, std::string, out);
1427   CHECK_ARGS(args, kInputTensorsInfoId, double, out);
1428   CHECK_ARGS(args, kOutputTensorsInfoId, double, out);
1429
1430   const auto& custom_filter_name = args.get(kName).get<std::string>();
1431   const auto& listener_name = args.get(kListenerName).get<std::string>();
1432   auto input_tensors_info_id = static_cast<int>(args.get(kInputTensorsInfoId).get<double>());
1433   auto output_tensors_info_id = static_cast<int>(args.get(kOutputTensorsInfoId).get<double>());
1434
1435   TensorsInfo* input_tensors_info_ptr =
1436       GetTensorsInfoManager().GetTensorsInfo(input_tensors_info_id);
1437   if (!input_tensors_info_ptr) {
1438     LogAndReportError(
1439         PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
1440         ("Could not find TensorsInfo handle with given id: %d", input_tensors_info_id));
1441     return;
1442   }
1443
1444   TensorsInfo* output_tensors_info_ptr =
1445       GetTensorsInfoManager().GetTensorsInfo(output_tensors_info_id);
1446   if (!output_tensors_info_ptr) {
1447     LogAndReportError(
1448         PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out,
1449         ("Could not find TensorsInfo handle with given id: %d", output_tensors_info_id));
1450     return;
1451   }
1452
1453   auto ret = pipeline_manager_.RegisterCustomFilter(
1454       custom_filter_name, listener_name, input_tensors_info_ptr, output_tensors_info_ptr);
1455   if (!ret) {
1456     LogAndReportError(ret, &out);
1457     return;
1458   }
1459
1460   ReportSuccess(out);
1461 }
1462
1463 void MlInstance::MLPipelineManagerCustomFilterOutput(const picojson::value& args,
1464                                                      picojson::object& out) {
1465   ScopeLogger("args: %s", args.serialize().c_str());
1466
1467   CHECK_ARGS(args, kName, std::string, out);
1468   CHECK_ARGS(args, kStatus, double, out);
1469   CHECK_ARGS(args, kRequestId, double, out);
1470
1471   const auto& custom_filter_name = args.get(kName).get<std::string>();
1472   auto status = static_cast<int>(args.get(kStatus).get<double>());
1473   auto request_id = static_cast<int>(args.get(kRequestId).get<double>());
1474
1475   auto ret = pipeline_manager_.CustomFilterOutput(custom_filter_name, request_id, status);
1476   if (!ret) {
1477     LogAndReportError(ret, &out);
1478     return;
1479   }
1480
1481   ReportSuccess(out);
1482 }
1483
1484 void MlInstance::MLPipelineManagerUnregisterCustomFilter(const picojson::value& args,
1485                                                          picojson::object& out) {
1486   ScopeLogger("args: %s", args.serialize().c_str());
1487
1488   CHECK_ARGS(args, kName, std::string, out);
1489
1490   const auto& custom_filter_name = args.get(kName).get<std::string>();
1491
1492   auto ret = pipeline_manager_.UnregisterCustomFilter(custom_filter_name);
1493   if (!ret) {
1494     LogAndReportError(ret, &out);
1495     return;
1496   }
1497
1498   ReportSuccess(out);
1499 }
1500
1501 void MlInstance::MLPipelineNodeInfoGetProperty(const picojson::value& args, picojson::object& out) {
1502   ScopeLogger("args: %s", args.serialize().c_str());
1503
1504   CHECK_ARGS(args, kId, double, out);
1505   CHECK_ARGS(args, kNodeName, std::string, out);
1506   CHECK_ARGS(args, kName, std::string, out);
1507   CHECK_ARGS(args, kType, std::string, out);
1508
1509   auto id = static_cast<int>(args.get(kId).get<double>());
1510   const auto& name = args.get(kName).get<std::string>();
1511   const auto& node_name = args.get(kNodeName).get<std::string>();
1512   const auto& type = args.get(kType).get<std::string>();
1513
1514   PlatformResult result = pipeline_manager_.getProperty(id, node_name, name, type, &out);
1515
1516   if (!result) {
1517     LogAndReportError(result, &out);
1518     return;
1519   }
1520
1521   ReportSuccess(out);
1522 }
1523
1524 void MlInstance::MLPipelineNodeInfoSetProperty(const picojson::value& args, picojson::object& out) {
1525   ScopeLogger("args: %s", args.serialize().c_str());
1526
1527   CHECK_ARGS(args, kId, double, out);
1528   CHECK_ARGS(args, kNodeName, std::string, out);
1529   CHECK_ARGS(args, kName, std::string, out);
1530   CHECK_ARGS(args, kType, std::string, out);
1531
1532   auto id = static_cast<int>(args.get(kId).get<double>());
1533   const auto& name = args.get(kName).get<std::string>();
1534   const auto& node_name = args.get(kNodeName).get<std::string>();
1535   const auto& type = args.get(kType).get<std::string>();
1536
1537   CHECK_EXIST(args, kProperty, out);
1538   if (kBOOLEAN == type) {
1539     CHECK_TYPE(args, kProperty, bool, out, ErrorCode::TYPE_MISMATCH_ERR);
1540   } else if (kSTRING == type) {
1541     CHECK_TYPE(args, kProperty, std::string, out, ErrorCode::TYPE_MISMATCH_ERR);
1542   } else {
1543     CHECK_TYPE(args, kProperty, double, out, ErrorCode::TYPE_MISMATCH_ERR);
1544   }
1545   const picojson::value& property = args.get(kProperty);
1546
1547   PlatformResult result = pipeline_manager_.setProperty(id, node_name, name, type, property);
1548   if (!result) {
1549     LogAndReportError(result, &out);
1550     return;
1551   }
1552
1553   ReportSuccess(out);
1554 }
1555
1556 void MlInstance::MLPipelineGetInputTensorsInfo(const picojson::value& args, picojson::object& out) {
1557   ScopeLogger("args: [%s]", args.serialize().c_str());
1558
1559   CHECK_ARGS(args, kId, double, out);
1560   CHECK_ARGS(args, kName, std::string, out);
1561
1562   auto id = static_cast<int>(args.get(kId).get<double>());
1563   const auto& name = args.get(kName).get<std::string>();
1564
1565   int res_id = -1;
1566   PlatformResult result = pipeline_manager_.getInputTensorsInfo(id, name, &res_id);
1567   if (!result) {
1568     LogAndReportError(result, &out);
1569     return;
1570   }
1571
1572   ReportSuccess(out);
1573 }
1574
1575 void MlInstance::MLPipelineSourceInputData(const picojson::value& args, picojson::object& out) {
1576   ScopeLogger("args: [%s]", args.serialize().c_str());
1577
1578   CHECK_ARGS(args, kId, double, out);
1579   CHECK_ARGS(args, kName, std::string, out);
1580   CHECK_ARGS(args, kTensorsDataId, double, out);
1581
1582   auto pipeline_id = static_cast<int>(args.get(kId).get<double>());
1583   auto& source_name = args.get(kName).get<std::string>();
1584   auto tensor_data_id = static_cast<int>(args.get(kTensorsDataId).get<double>());
1585
1586   TensorsData* tensors_data = GetTensorsDataManager().GetTensorsData(tensor_data_id);
1587
1588   if (nullptr == tensors_data) {
1589     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal Source error"), &out,
1590                       ("Could not get TensorData handle with given id: %d", tensor_data_id));
1591     return;
1592   }
1593
1594   auto ret = pipeline_manager_.SourceInputData(pipeline_id, source_name, tensors_data);
1595   if (!ret) {
1596     LogAndReportError(ret, &out);
1597     return;
1598   }
1599
1600   ReportSuccess(out);
1601 }
1602
1603 void MlInstance::MLPipelineSwitchGetPadList(const picojson::value& args, picojson::object& out) {
1604   ScopeLogger("args: [%s]", args.serialize().c_str());
1605
1606   CHECK_ARGS(args, kId, double, out);
1607   CHECK_ARGS(args, kName, std::string, out);
1608
1609   auto pipeline_id = static_cast<int>(args.get(kId).get<double>());
1610   auto& switch_name = args.get(kName).get<std::string>();
1611
1612   picojson::array pad_list;
1613   auto ret = pipeline_manager_.SwitchGetPadList(pipeline_id, switch_name, &pad_list);
1614   if (!ret) {
1615     LogAndReportError(ret, &out);
1616     return;
1617   }
1618
1619   ReportSuccess(picojson::value{std::move(pad_list)}, out);
1620 }
1621
1622 void MlInstance::MLPipelineSwitchSelect(const picojson::value& args, picojson::object& out) {
1623   ScopeLogger("args: [%s]", args.serialize().c_str());
1624
1625   CHECK_ARGS(args, kId, double, out);
1626   CHECK_ARGS(args, kName, std::string, out);
1627   CHECK_ARGS(args, kPadName, std::string, out);
1628
1629   auto pipeline_id = args.get(kId).get<double>();
1630   auto& switch_name = args.get(kName).get<std::string>();
1631   auto& pad_name = args.get(kPadName).get<std::string>();
1632
1633   auto ret = pipeline_manager_.SwitchSelect(pipeline_id, switch_name, pad_name);
1634   if (!ret) {
1635     LogAndReportError(ret, &out);
1636     return;
1637   }
1638
1639   ReportSuccess(out);
1640 }
1641
1642 void MlInstance::MLPipelineValveSetOpen(const picojson::value& args, picojson::object& out) {
1643   ScopeLogger("args: %s", args.serialize().c_str());
1644
1645   CHECK_ARGS(args, kId, double, out);
1646   CHECK_ARGS(args, kName, std::string, out);
1647   CHECK_ARGS(args, kOpen, bool, out);
1648
1649   auto name = args.get(kName).get<std::string>();
1650   auto pipeline_id = args.get(kId).get<double>();
1651   auto open = args.get(kOpen).get<bool>();
1652
1653   auto ret = pipeline_manager_.ValveSetOpen(pipeline_id, name, open);
1654   if (!ret) {
1655     LogAndReportError(ret, &out);
1656     return;
1657   }
1658
1659   ReportSuccess(out);
1660 }
1661
1662 void MlInstance::MLPipelineValveIsOpen(const picojson::value& args, picojson::object& out) {
1663   ScopeLogger("args: %s", args.serialize().c_str());
1664
1665   CHECK_ARGS(args, kId, double, out);
1666   CHECK_ARGS(args, kName, std::string, out);
1667
1668   auto name = args.get(kName).get<std::string>();
1669   auto pipeline_id = args.get(kId).get<double>();
1670   auto open = true;
1671
1672   auto ret = pipeline_manager_.ValveIsOpen(pipeline_id, name, &open);
1673   if (!ret) {
1674     LogAndReportError(ret, &out);
1675     return;
1676   }
1677
1678   ReportSuccess(picojson::value{open}, out);
1679 }
1680
1681 #undef CHECK_EXIST
1682 #undef CHECK_TYPE
1683 #undef CHECK_TYPE_X
1684 #undef CHECK_TYPE_4
1685 #undef CHECK_TYPE_5
1686 #undef CHECK_ARGS
1687
1688 }  // namespace ml
1689 }  // namespace extension