list all library names and their code (enabled via `with_code`)
| 471 | |
| 472 | // list all library names and their code (enabled via `with_code`) |
| 473 | Status FunctionList(Server *srv, const redis::Connection *conn, engine::Context &ctx, const std::string &libname, |
| 474 | bool with_code, std::string *output) { |
| 475 | std::string start_key = engine::kLuaLibCodePrefix + libname; |
| 476 | std::string end_key = start_key; |
| 477 | end_key.back()++; |
| 478 | |
| 479 | rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); |
| 480 | rocksdb::Slice upper_bound(end_key); |
| 481 | read_options.iterate_upper_bound = &upper_bound; |
| 482 | |
| 483 | auto *cf = srv->storage->GetCFHandle(ColumnFamilyID::Propagate); |
| 484 | auto iter = util::UniqueIterator(ctx, read_options, cf); |
| 485 | std::vector<std::pair<std::string, std::string>> result; |
| 486 | for (iter->Seek(start_key); iter->Valid(); iter->Next()) { |
| 487 | Slice lib = iter->key(); |
| 488 | lib.remove_prefix(strlen(engine::kLuaLibCodePrefix)); |
| 489 | result.emplace_back(lib.ToString(), iter->value().ToString()); |
| 490 | } |
| 491 | |
| 492 | if (auto s = iter->status(); !s.ok()) { |
| 493 | return {Status::NotOK, s.ToString()}; |
| 494 | } |
| 495 | |
| 496 | output->append(redis::MultiLen(result.size())); |
| 497 | for (const auto &[lib, code] : result) { |
| 498 | output->append(conn->HeaderOfMap(with_code ? 2 : 1)); |
| 499 | output->append(redis::BulkString("library_name")); |
| 500 | output->append(redis::BulkString(lib)); |
| 501 | if (with_code) { |
| 502 | output->append(redis::BulkString("library_code")); |
| 503 | output->append(redis::BulkString(code)); |
| 504 | } |
| 505 | } |
| 506 | |
| 507 | return Status::OK(); |
| 508 | } |
| 509 | |
| 510 | // extension to Redis Function |
| 511 | // list all function names and their corresponding library names |
no test coverage detected