25#include "ServiceManager.h"
31using namespace fbcpp::impl;
34static void emitVerboseChunk(
37 if (!verboseOutput || chunk.empty())
47 verboseOutput(pendingLine);
60 StatusWrapper statusWrapper{client};
62 auto spbBuilder =
fbUnique(client.
getUtil()->getXpbBuilder(&statusWrapper, fb::IXpbBuilder::SPB_ATTACH,
63 reinterpret_cast<const std::uint8_t*
>(options.
getSpb().data()),
64 static_cast<unsigned>(options.
getSpb().size())));
67 spbBuilder->insertString(&statusWrapper, isc_spb_user_name, userName->c_str());
70 spbBuilder->insertString(&statusWrapper, isc_spb_password, password->c_str());
72 if (
const auto role = options.
getRole())
73 spbBuilder->insertString(&statusWrapper, isc_spb_sql_role_name, role->c_str());
75 auto dispatcher =
fbRef(master->getDispatcher());
76 const auto spbBuffer = spbBuilder->getBuffer(&statusWrapper);
77 const auto spbBufferLen = spbBuilder->getBufferLength(&statusWrapper);
80 if (
const auto host = options.
getServer())
81 service = host.value() +
':' + service;
83 handle.reset(dispatcher->attachServiceManager(&statusWrapper, service.c_str(), spbBufferLen, spbBuffer));
91void ServiceManager::startAction(
const std::vector<std::uint8_t>& spb)
95 StatusWrapper statusWrapper{*client};
96 handle->start(&statusWrapper,
static_cast<unsigned>(spb.size()), spb.data());
99void ServiceManager::waitForCompletion(
const VerboseOutput& verboseOutput,
bool requestStdin)
103 StatusWrapper statusWrapper{*client};
104 auto receiveBuilder =
105 fbUnique(client->
getUtil()->getXpbBuilder(&statusWrapper, fb::IXpbBuilder::SPB_RECEIVE,
nullptr, 0));
106 receiveBuilder->insertTag(&statusWrapper, verboseOutput ? isc_info_svc_line : isc_info_svc_to_eof);
109 receiveBuilder->insertTag(&statusWrapper, isc_info_svc_stdin);
111 const auto receiveLength = receiveBuilder->getBufferLength(&statusWrapper);
112 const auto* receiveBuffer = receiveBuilder->getBuffer(&statusWrapper);
114 std::vector<std::uint8_t> buffer(16u * 1024u);
115 std::string pendingLine;
116 unsigned stdinRequest = 0;
118 for (
bool running =
true; running;)
121 fbUnique(client->
getUtil()->getXpbBuilder(&statusWrapper, fb::IXpbBuilder::SPB_SEND,
nullptr, 0));
126 std::fill(buffer.begin(), buffer.end(), 0);
127 handle->query(&statusWrapper, sendBuilder->getBufferLength(&statusWrapper),
128 sendBuilder->getBuffer(&statusWrapper), receiveLength, receiveBuffer,
static_cast<unsigned>(buffer.size()),
132 &statusWrapper, fb::IXpbBuilder::SPB_RESPONSE, buffer.data(),
static_cast<unsigned>(buffer.size())));
135 int outputLength = 0;
136 bool notReady =
false;
138 for (responseBuilder->rewind(&statusWrapper); running && !responseBuilder->isEof(&statusWrapper);
139 responseBuilder->moveNext(&statusWrapper))
141 switch (responseBuilder->getTag(&statusWrapper))
143 case isc_info_svc_line:
145 const auto* line = responseBuilder->getString(&statusWrapper);
146 const auto length =
static_cast<int>(responseBuilder->getLength(&statusWrapper));
147 if (verboseOutput && length > 0)
148 verboseOutput(std::string_view{line,
static_cast<size_t>(length)});
149 outputLength = length;
153 case isc_info_svc_to_eof:
155 const auto* bytes =
reinterpret_cast<const char*
>(responseBuilder->getBytes(&statusWrapper));
156 const auto length =
static_cast<int>(responseBuilder->getLength(&statusWrapper));
157 emitVerboseChunk(pendingLine, std::string_view{bytes,
static_cast<size_t>(length)}, verboseOutput);
158 outputLength = length;
162 case isc_info_svc_stdin:
163 stdinRequest =
static_cast<unsigned>(responseBuilder->getInt(&statusWrapper));
170 case isc_info_truncated:
171 case isc_info_data_not_ready:
172 case isc_info_svc_timeout:
181 if (outputLength || stdinRequest || notReady)
185 if (verboseOutput && !pendingLine.empty())
186 verboseOutput(pendingLine);
189void ServiceManager::detachHandle()
193 StatusWrapper statusWrapper{*client};
194 handle->detach(&statusWrapper);
Represents a Firebird client library instance.
fb::IUtil * getUtil()
Returns a Firebird IUtil interface.
fb::IMaster * getMaster() noexcept
Returns the Firebird IMaster interface.
Base exception class for all fb-cpp exceptions.
Represents options used when creating a ServiceManager object.
const std::vector< std::uint8_t > & getSpb() const
Returns the raw service attach SPB.
const std::optional< std::string > & getServer() const
Returns the server used to attach to the service manager.
const std::string & getServiceManagerName() const
Returns the service manager name.
const std::optional< std::string > & getPassword() const
Returns the password used to attach to the service manager.
const std::optional< std::string > & getUserName() const
Returns the user name used to attach to the service manager.
const std::optional< std::string > & getRole() const
Returns the role used to attach to the service manager.
ServiceManager(Client &client, const ServiceManagerOptions &options={})
Attaches to the service manager specified by the given options.
void disconnect()
Detaches from the service manager.
bool isValid() noexcept
Returns whether the ServiceManager object is valid.
std::function< void(std::string_view line)> VerboseOutput
Function invoked when a verbose service output line is available.
FbRef< T > fbRef(T *arg) noexcept
Creates a reference-counted smart pointer for a Firebird object.
FbUniquePtr< T > fbUnique(T *obj) noexcept
Creates a unique pointer for a Firebird disposable object.