| 448 | } |
| 449 | |
| 450 | bool lgraph::SingleLanguagePluginManager::LoadPluginFromCode( |
| 451 | const std::string& user, const std::string& name_, |
| 452 | const std::vector<std::string>& code, |
| 453 | const std::vector<std::string>& filename, |
| 454 | plugin::CodeType code_type, const std::string& desc, bool read_only, |
| 455 | const std::string& version) { |
| 456 | // check input |
| 457 | bool empty_code = code.empty(); |
| 458 | for (auto& c : code) { |
| 459 | if (c.empty()) { |
| 460 | empty_code = true; |
| 461 | break; |
| 462 | } |
| 463 | } |
| 464 | if (empty_code) THROW_CODE(InputError, "Code cannot be empty."); |
| 465 | if (!IsValidPluginName(name_)) throw InvalidPluginNameException(name_); |
| 466 | if (version != plugin::PLUGIN_VERSION_1 && version != plugin::PLUGIN_VERSION_2) { |
| 467 | throw InvalidPluginVersionException(version); |
| 468 | } |
| 469 | |
| 470 | std::string name = ToInternalName(name_); |
| 471 | // check if plugin already exist, remove if overwrite |
| 472 | int tid = GetMyThreadId(); |
| 473 | AutoReadLock rlock(lock_, tid); |
| 474 | auto it = procedures_.find(name); |
| 475 | if (it != procedures_.end()) return false; |
| 476 | |
| 477 | // undo the changes if there is any problem |
| 478 | AutoCleanupAction rollback([&]() { |
| 479 | auto it = procedures_.find(name); |
| 480 | if (it != procedures_.end()) { |
| 481 | // unload plugin |
| 482 | try { |
| 483 | impl_->UnloadPlugin(user, name, it->second); |
| 484 | } catch (...) { |
| 485 | } |
| 486 | // delete pinfo |
| 487 | delete it->second; |
| 488 | procedures_.erase(it); |
| 489 | } |
| 490 | // delete file |
| 491 | fma_common::file_system::RemoveFile(impl_->GetPluginPath(name)); |
| 492 | // exception can only occure before txn commit, so no need to revert kv state |
| 493 | }); |
| 494 | |
| 495 | // load plugin from different type |
| 496 | std::string exe; |
| 497 | std::string all_codes; |
| 498 | if (code_type == plugin::CodeType::CPP) { |
| 499 | all_codes = MergeCodeFiles(code, filename, name); |
| 500 | } |
| 501 | switch (code_type) { |
| 502 | case plugin::CodeType::SO: |
| 503 | break; |
| 504 | case plugin::CodeType::PY: |
| 505 | if (code.size() != 1) { |
| 506 | THROW_CODE(InternalError, |
| 507 | FMA_FMT("code_type [{}] only supports uploading a single file.", code_type)); |