*
* This value is controlled by the appinfo.poll-interval config file option.
*/
-int gAppInfoPollInterval = 0;
+static guint gAppInfoPollInterval = 0;
/**
* AppInfo gather loop timeout source.
*/
static GSource *gAppInfoTimeoutSource = NULL;
+static void TweakGatherLoop(ToolsAppCtx *ctx);
+
/*
*****************************************************************************
* AppInfoGather --
*
* Creates a new thread that collects all the desired application related
- * information and udates the VMX.
+ * information and updates the VMX. Tweaks the poll gather loop as per the
+ * tools configuration after creating the thread.
*
* @param[in] data The application context.
*
- * @return TRUE to indicate that the timer should be rescheduled.
+ * @return G_SOURCE_REMOVE to indicate that the timer should be removed.
*
*****************************************************************************
*/
AppInfoGather(gpointer data) // IN
{
ToolsAppCtx *ctx = data;
+
+ g_debug("%s: Submitting a task to capture application information.\n",
+ __FUNCTION__);
+
if (!ToolsCorePool_SubmitTask(ctx, AppInfoGatherTask, NULL, NULL)) {
- g_warning("%s: failed to start information gather thread\n",
- __FUNCTION__);
+ g_warning("%s: Failed to submit the task for capturing application "
+ "information\n", __FUNCTION__);
}
- return TRUE;
+ TweakGatherLoop(ctx);
+
+ return G_SOURCE_REMOVE;
}
/*
*****************************************************************************
- * TweakGatherLoop --
+ * TweakGatherLoopEx --
*
- * @brief Start, stop, reconfigure a GuestInfoGather poll loop.
+ * Start, stop, reconfigure a AppInfo Gather poll loop.
*
* This function is responsible for creating, manipulating, and resetting a
- * AppDiscoveryGather loop timeout source.
+ * AppInfo Gather loop timeout source. The poll loop will be disabled if
+ * the poll interval is 0.
*
* @param[in] ctx The application context.
- * @param[in] enable Whether to enable the gather loop.
+ * @param[in] pollInterval Poll interval in seconds. A value of 0 will
+ * disable the loop.
*
*****************************************************************************
*/
static void
-TweakGatherLoop(ToolsAppCtx *ctx, // IN
- gboolean enable) // IN
+TweakGatherLoopEx(ToolsAppCtx *ctx, // IN
+ guint pollInterval) // IN
{
- gint pollInterval = 0;
-
- if (enable) {
- pollInterval = APP_INFO_POLL_INTERVAL * 1000;
-
- /*
- * Check the config registry for custom poll interval,
- * converting from seconds to milliseconds.
- */
- if (g_key_file_has_key(ctx->config, CONFGROUPNAME_APPINFO,
- CONFNAME_APPINFO_POLLINTERVAL, NULL)) {
- GError *gError = NULL;
-
- pollInterval = g_key_file_get_integer(ctx->config,
- CONFGROUPNAME_APPINFO,
- CONFNAME_APPINFO_POLLINTERVAL,
- &gError);
- pollInterval *= 1000;
-
- if (pollInterval < 0 || gError) {
- g_warning("%s: Invalid %s.%s value. Using default %us.\n",
- __FUNCTION__,
- CONFGROUPNAME_APPINFO,
- CONFNAME_APPINFO_POLLINTERVAL,
- APP_INFO_POLL_INTERVAL);
- pollInterval = APP_INFO_POLL_INTERVAL * 1000;
- }
-
- g_clear_error(&gError);
- }
- }
-
if (gAppInfoTimeoutSource != NULL) {
/*
- * If the interval hasn't changed, let's not interfere with the existing
- * timeout source.
- */
- if (pollInterval == gAppInfoPollInterval) {
- ASSERT(pollInterval);
- return;
- }
-
- /*
- * Destroy the existing timeout source since the interval has changed.
+ * Destroy the existing timeout source.
*/
-
g_source_destroy(gAppInfoTimeoutSource);
gAppInfoTimeoutSource = NULL;
}
- /*
- * All checks have passed. Create a new timeout source and attach it.
- */
- gAppInfoPollInterval = pollInterval;
-
- if (gAppInfoPollInterval) {
- g_info("%s: New value for %s is %us.\n",
- __FUNCTION__,
- CONFNAME_APPINFO_POLLINTERVAL,
- gAppInfoPollInterval / 1000);
+ if (pollInterval > 0) {
+ if (gAppInfoPollInterval != pollInterval) {
+ g_info("%s: New value for %s is %us.\n",
+ __FUNCTION__,
+ CONFNAME_APPINFO_POLLINTERVAL,
+ pollInterval);
+ }
- gAppInfoTimeoutSource = g_timeout_source_new(gAppInfoPollInterval);
+ gAppInfoTimeoutSource = g_timeout_source_new(pollInterval * 1000);
VMTOOLSAPP_ATTACH_SOURCE(ctx, gAppInfoTimeoutSource,
AppInfoGather, ctx, NULL);
g_source_unref(gAppInfoTimeoutSource);
- } else {
+ } else if (gAppInfoPollInterval > 0) {
g_info("%s: Poll loop for %s disabled.\n",
__FUNCTION__, CONFNAME_APPINFO_POLLINTERVAL);
SetGuestInfo(ctx, APP_INFO_GUESTVAR_KEY, "");
}
+
+ gAppInfoPollInterval = pollInterval;
+}
+
+
+/*
+ *****************************************************************************
+ * TweakGatherLoop --
+ *
+ * Configues the AppInfo Gather poll loop based on the settings in the
+ * tools configuration.
+ *
+ * This function is responsible for creating, manipulating, and resetting a
+ * AppInfo Gather loop timeout source.
+ *
+ * @param[in] ctx The application context.
+ *
+ *****************************************************************************
+ */
+
+static void
+TweakGatherLoop(ToolsAppCtx *ctx) // IN
+{
+ gboolean disabled =
+ VMTools_ConfigGetBoolean(ctx->config,
+ CONFGROUPNAME_APPINFO,
+ CONFNAME_APPINFO_DISABLED,
+ APP_INFO_CONF_DEFAULT_DISABLED_VALUE);
+
+ gint pollInterval = 0;
+
+ if (!disabled) {
+ pollInterval = VMTools_ConfigGetInteger(ctx->config,
+ CONFGROUPNAME_APPINFO,
+ CONFNAME_APPINFO_POLLINTERVAL,
+ APP_INFO_POLL_INTERVAL);
+
+ if (pollInterval < 0) {
+ g_warning("%s: Invalid poll interval %d. Using default %us.\n",
+ __FUNCTION__, pollInterval, APP_INFO_POLL_INTERVAL);
+ pollInterval = APP_INFO_POLL_INTERVAL;
+ }
+ }
+
+ /*
+ * pollInterval can never be a negative value. Typecasting into
+ * guint should not be a problem.
+ */
+ TweakGatherLoopEx(ctx, (guint) pollInterval);
}
*****************************************************************************
* AppInfoServerConfReload --
*
- * @brief Reconfigures the poll loop interval upon config file reload.
+ * Reconfigures the poll loop interval upon config file reload.
*
* @param[in] src The source object.
* @param[in] ctx The application context.
ToolsAppCtx *ctx, // IN
gpointer data) // IN
{
- gboolean disabled =
- VMTools_ConfigGetBoolean(ctx->config,
- CONFGROUPNAME_APPINFO,
- CONFNAME_APPINFO_DISABLED,
- APP_INFO_CONF_DEFAULT_DISABLED_VALUE);
- TweakGatherLoop(ctx, !disabled);
+ g_info("%s: Reloading the tools configuration.\n", __FUNCTION__);
+
+ TweakGatherLoop(ctx);
}
* Cleanup internal data on shutdown.
*
* @param[in] src The source object.
- * @param[in] ctx Unused.
+ * @param[in] ctx Application context.
* @param[in] data Unused.
*
*****************************************************************************
}
+/*
+ ******************************************************************************
+ * AppInfoServerReset --
+ *
+ * Callback function that gets called whenever the RPC channel gets reset.
+ * Disables the poll loop and sets a one time poll.
+ *
+ * @param[in] src The source object.
+ * @param[in] ctx Application context.
+ * @param[in] data Unused.
+ *
+ ******************************************************************************
+ */
+
+static void
+AppInfoServerReset(gpointer src,
+ ToolsAppCtx *ctx,
+ gpointer data)
+{
+ /*
+ * gAppInfoTimeoutSource is used to figure out if the poll loop is
+ * enabled or not. If the poll loop is disabled, then
+ * gAppInfoTimeoutSource will be set to NULL.
+ */
+ if (gAppInfoTimeoutSource != NULL) {
+ guint interval;
+
+ ASSERT(gAppInfoPollInterval != 0);
+
+#define MIN_APPINFO_INTERVAL 30
+
+ if (gAppInfoPollInterval > MIN_APPINFO_INTERVAL) {
+ GRand *gRand = g_rand_new();
+
+ /*
+ * The RPC channel may get reset due to various conditions like
+ * snapshotting the VM, vmotion the VM, instant cloning of the VM.
+ * In order to avoid potential load spikes in case of instant clones,
+ * randomize the poll interval after a channel reset.
+ */
+
+ interval = g_rand_int_range(gRand,
+ MIN_APPINFO_INTERVAL,
+ gAppInfoPollInterval);
+ g_rand_free(gRand);
+ } else {
+ interval = gAppInfoPollInterval;
+ }
+
+#undef MIN_APPINFO_INTERVAL
+
+ g_info("%s: Using poll interval: %u.\n", __FUNCTION__, interval);
+
+ TweakGatherLoopEx(ctx, interval);
+ } else {
+ g_debug("%s: Poll loop disabled. Ignoring.\n", __FUNCTION__);
+ }
+}
+
+
/*
*****************************************************************************
* ToolsOnLoad --
if (ctx->rpc != NULL) {
ToolsPluginSignalCb sigs[] = {
{ TOOLS_CORE_SIG_CONF_RELOAD, AppInfoServerConfReload, NULL },
- { TOOLS_CORE_SIG_SHUTDOWN, AppInfoServerShutdown, NULL }
+ { TOOLS_CORE_SIG_SHUTDOWN, AppInfoServerShutdown, NULL },
+ { TOOLS_CORE_SIG_RESET, AppInfoServerReset, NULL }
};
ToolsAppReg regs[] = {
{ TOOLS_APP_SIGNALS,
}
};
- gboolean disabled = FALSE;
-
regData.regs = VMTools_WrapArray(regs,
sizeof *regs,
ARRAYSIZE(regs));
/*
* Set up the AppInfo gather loop.
*/
- disabled =
- VMTools_ConfigGetBoolean(ctx->config,
- CONFGROUPNAME_APPINFO,
- CONFNAME_APPINFO_DISABLED,
- APP_INFO_CONF_DEFAULT_DISABLED_VALUE);
- TweakGatherLoop(ctx, !disabled);
+ TweakGatherLoop(ctx);
return ®Data;
}
return NULL;
-}
\ No newline at end of file
+}