Skip to content

Commit

Permalink
MSVDI: use a configurable timeout when requesting the config
Browse files Browse the repository at this point in the history
  • Loading branch information
franku committed Aug 27, 2020
1 parent e6f679f commit e4f9560
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 13 deletions.
95 changes: 82 additions & 13 deletions core/src/win32/plugins/filed/mssqlvdi-fd.cc
Expand Up @@ -73,6 +73,7 @@ static const int debuglevel = 150;
" stopbeforemark=<log sequence number specification>:\n" \
" stopatmark=<log sequence number specification>:\n" \
" stopat=<timestamp>\n" \
" getconfigurationtimeout=<timeout-seconds>\n" \
" \n" \
" examples:\n" \
" timestamp: 'Apr 15, 2020 12:00 AM'\n" \
Expand Down Expand Up @@ -158,6 +159,7 @@ struct plugin_ctx {
char* ado_connect_string;
char* ado_query;
char* ado_errorstr;
uint32_t get_configuration_timeout;
wchar_t* vdsname;
int32_t backup_level;
IClientVirtualDeviceSet2* VDIDeviceSet;
Expand Down Expand Up @@ -189,7 +191,9 @@ enum plugin_argument_type
argument_recover_after_restore,
argument_stopbeforemark,
argument_stopatmark,
argument_stopat
argument_stopat,
argument_getoptions,
argument_get_configuration_timeout
};

struct plugin_argument {
Expand All @@ -209,6 +213,7 @@ static plugin_argument plugin_arguments[] = {
{"stopbeforemark", argument_stopbeforemark},
{"stopatmark", argument_stopatmark},
{"stopat", argument_stopat},
{"getconfigurationtimeout", argument_get_configuration_timeout}, // sec
{NULL, argument_none}};

#ifdef __cplusplus
Expand Down Expand Up @@ -525,6 +530,21 @@ static inline bool ParseBoolean(const char* argument_value)
}
}

/**
* Parse a uint32 value
*/
static inline bool ParseUnsignedInt(const char* argument_value,
uint32_t& value_out)
{
try {
value_out = std::stoul(argument_value);
return true;
} catch (std::invalid_argument& e) {
return false;
}
}


/**
* Only set destination to value when it has no previous setting.
*/
Expand Down Expand Up @@ -621,6 +641,7 @@ static bRC parse_plugin_definition(bpContext* ctx, void* value)
if (Bstrcasecmp(argument, plugin_arguments[i].name)) {
char** str_destination = NULL;
bool* bool_destination = NULL;
uint32_t* uint32_destination = NULL;

switch (plugin_arguments[i].type) {
case argument_server_address:
Expand Down Expand Up @@ -656,6 +677,9 @@ static bRC parse_plugin_definition(bpContext* ctx, void* value)
case argument_stopat:
str_destination = &p_ctx->stopat;
break;
case argument_get_configuration_timeout:
uint32_destination = &p_ctx->get_configuration_timeout;
break;
default:
break;
}
Expand All @@ -678,6 +702,15 @@ static bRC parse_plugin_definition(bpContext* ctx, void* value)
*bool_destination = ParseBoolean(argument_value);
}

if (uint32_destination) {
if (!ParseUnsignedInt(argument_value, *uint32_destination)) {
Jmsg(ctx, M_FATAL,
"Wrong value for argument %s (%s) in plugin definition, "
"should be integer number of seconds\n",
argument, argument_value);
}
}

/*
* When we have a match break the loop.
*/
Expand Down Expand Up @@ -1373,18 +1406,54 @@ static inline bool SetupVdiDevice(bpContext* ctx, struct io_pkt* io)
*/
p_ctx->AdoThreadStarted = true;

/*
* Wait for the database server to connect to the VDI deviceset.
*/
hr = p_ctx->VDIDeviceSet->GetConfiguration(VDI_DEFAULT_WAIT,
&p_ctx->VDIConfig);
if (!SUCCEEDED(hr)) {
Jmsg(ctx, M_FATAL,
"mssqlvdi-fd: IClientVirtualDeviceSet2::GetConfiguration failed\n");
Dmsg(ctx, debuglevel,
"mssqlvdi-fd: IClientVirtualDeviceSet2::GetConfiguration failed\n");
goto bail_out;
}
// GetConfiguration
{
uint32_t timeout = p_ctx->get_configuration_timeout == 0
? VDI_DEFAULT_WAIT
: p_ctx->get_configuration_timeout * 1000; // ms

Jmsg(ctx, M_INFO, "Calling GetConfiguration with a timeout of %d sec\n.",
timeout / 1000);

hr = p_ctx->VDIDeviceSet->GetConfiguration(timeout, &p_ctx->VDIConfig);

const char* err = "";
bool success = false;

switch (hr) {
case NOERROR:
err = "NOERROR";
success = true;
break;
case VD_E_ABORT:
err = "VD_E_ABORT";
break;
case VD_E_TIMEOUT:
err = "VD_E_TIMEOUT, you may want to increase getconfigurationtimeout";
break;
default:
err = "unspecific error";
break;
}

std::array<char, 300> error_msg;
const char* fmt =
"mssqlvdi-fd: IClientVirtualDeviceSet2::GetConfiguration "
"%s: %0#x (%s)\n";

if (success) {
snprintf(error_msg.data(), error_msg.size(), fmt, "successful",
static_cast<unsigned int>(hr), err);
Jmsg(ctx, M_INFO, error_msg.data());
Dmsg(ctx, debuglevel, error_msg.data());
} else {
sprintf(error_msg.data(), fmt, "failed", static_cast<unsigned int>(hr),
err);
Jmsg(ctx, M_FATAL, error_msg.data());
Dmsg(ctx, debuglevel, error_msg.data());
goto bail_out;
}
} // GetConfiguration

hr = p_ctx->VDIDeviceSet->OpenDevice(p_ctx->vdsname, &p_ctx->VDIDevice);
if (!SUCCEEDED(hr)) {
Expand Down
1 change: 1 addition & 0 deletions docs/manuals/source/Appendix/Howtos.rst
Expand Up @@ -148,6 +148,7 @@ Plugin Test
stopbeforemark=<log sequence number specification>:
stopatmark=<log sequence number specification>:
stopat=<timestamp>
getconfigurationtimeout=<timeout-seconds>
examples:
timestamp: 'Apr 15, 2020 12:00 AM'
Expand Down

0 comments on commit e4f9560

Please sign in to comment.