Exemple #1
0
static void
g_tls_interaction_init (GTlsInteraction *interaction)
{
  interaction->priv = G_TYPE_INSTANCE_GET_PRIVATE (interaction, G_TYPE_TLS_INTERACTION,
                                                   GTlsInteractionPrivate);
  interaction->priv->context = g_main_context_ref_thread_default ();
}
Exemple #2
0
/**
 * g_io_scheduler_push_job:
 * @job_func: a #GIOSchedulerJobFunc.
 * @user_data: data to pass to @job_func
 * @notify: (allow-none): a #GDestroyNotify for @user_data, or %NULL
 * @io_priority: the <link linkend="io-priority">I/O priority</link>
 * of the request.
 * @cancellable: optional #GCancellable object, %NULL to ignore.
 *
 * Schedules the I/O job to run in another thread.
 *
 * @notify will be called on @user_data after @job_func has returned,
 * regardless whether the job was cancelled or has run to completion.
 * 
 * If @cancellable is not %NULL, it can be used to cancel the I/O job
 * by calling g_cancellable_cancel() or by calling 
 * g_io_scheduler_cancel_all_jobs().
 *
 * Deprecated: use #GThreadPool or g_task_run_in_thread()
 **/
void
g_io_scheduler_push_job (GIOSchedulerJobFunc  job_func,
			 gpointer             user_data,
			 GDestroyNotify       notify,
			 gint                 io_priority,
			 GCancellable        *cancellable)
{
  GIOSchedulerJob *job;
  GTask *task;

  g_return_if_fail (job_func != NULL);

  job = g_slice_new0 (GIOSchedulerJob);
  job->job_func = job_func;
  job->data = user_data;
  job->destroy_notify = notify;

  if (cancellable)
    job->cancellable = g_object_ref (cancellable);

  job->context = g_main_context_ref_thread_default ();

  G_LOCK (active_jobs);
  active_jobs = g_list_prepend (active_jobs, job);
  job->active_link = active_jobs;
  G_UNLOCK (active_jobs);

  task = g_task_new (NULL, cancellable, NULL, NULL);
  g_task_set_task_data (task, job, (GDestroyNotify)g_io_job_free);
  g_task_set_priority (task, io_priority);
  g_task_run_in_thread (task, io_job_thread);
  g_object_unref (task);
}
Exemple #3
0
/**
 * gda_worker_submit_job: (skip)
 * @worker: a #GdaWorker object
 * @callback_context: (allow-none): a #GMainContext, or %NULL (ignored if no setting has been defined with gda_worker_set_callback())
 * @func: the function to call from the worker thread
 * @data: (allow-none): the data to pass to @func, or %NULL
 * @data_destroy_func: (allow-none): a function to destroy @data, or %NULL
 * @result_destroy_func: (allow-none): a function to destroy the result, if any, of the execution of @func, or %NULL
 * @error: (allow-none): a place to store errors, or %NULL.
 *
 * Request that the worker thread call @func with the @data argument.
 *
 * Notes:
 * <itemizedlist>
 *   <listitem><para>if @data_destroy_func is not %NULL, then it will be called to destroy @data when the job is removed,
 *    which can occur within the context of the worker thread, or within the context of any thread using @worker.</para></listitem>
 *   <listitem><para>if @result_destroy_func is not %NULL, then it will be called to destroy the result produced by @func.
 *    Similarly to @data_destroy_func, if it is not %NULL (and if there is a non %NULL result), then that function can be
 *    called in the context of any thread.</para></listitem>
 *   <listitem><para>the error here can only report failures while executing gda_worker_submit_job(), not any error which may occur
 *    while executing @func from the worker thread.</para></listitem>
 *   <listitem><para>when this function returns, the job may already have been completed, so you should not assume that the job
 *    is in any specific state.</para></listitem>
 *  <listitem><para>passing %NULL for @callback_context is similar to passing the result of g_main_context_ref_thread_default()</para></listitem>
 * </itemizedlist>
 *
 * Returns: a job ID, or %0 if an error occurred
 *
 * Since: 6.0
 */
guint
gda_worker_submit_job (GdaWorker *worker, GMainContext *callback_context, GdaWorkerFunc func,
		       gpointer data, GDestroyNotify data_destroy_func,
		       GDestroyNotify result_destroy_func, GError **error)
{
	g_return_val_if_fail (worker, 0);
	g_return_val_if_fail (func, 0);
	if (!worker->callbacks_hash) {
		g_warning ("GdaWorker has been destroyed\n");
		return 0;
	}

	DeclaredCallback *dc;
	guint jid;
	GMainContext *co;
	gboolean unref_co = FALSE;

	co = callback_context;
	if (!co) {
		co = g_main_context_ref_thread_default ();
		unref_co = TRUE;
	}

	g_rec_mutex_lock (& worker->rmutex);
	dc = g_hash_table_lookup (worker->callbacks_hash, co);
	jid = _gda_worker_submit_job_with_its (worker, dc ? dc->its : NULL,
					       func, data, data_destroy_func, result_destroy_func, error);
	g_rec_mutex_unlock (& worker->rmutex);

	if (unref_co)
		g_main_context_unref (co);

	return jid;
}
GumScriptTask *
gum_script_task_new (GumScriptTaskFunc func,
                     gpointer source_object,
                     GCancellable * cancellable,
                     GAsyncReadyCallback callback,
                     gpointer callback_data)
{
  GumScriptTask * task;
  GumScriptTaskPrivate * priv;

  task = g_object_new (GUM_TYPE_SCRIPT_TASK, NULL);
  priv = task->priv;

  priv->func = func;
  priv->source_object =
      (source_object != NULL) ? g_object_ref (source_object) : NULL;
  priv->cancellable =
      (cancellable != NULL) ? g_object_ref (cancellable) : NULL;
  priv->callback = callback;
  priv->callback_data = callback_data;

  priv->context = g_main_context_ref_thread_default ();

  return task;
}
static void
gst_gl_window_default_run (GstGLWindow * window)
{
  GstGLWindowPrivate *priv = window->priv;

  if (g_main_context_get_thread_default ()) {
    if (priv->main_context)
      g_main_context_unref (priv->main_context);
    if (priv->loop)
      g_main_loop_unref (priv->loop);
    priv->main_context = g_main_context_ref_thread_default ();
    priv->loop = NULL;
    priv->alive = TRUE;
  } else {
    g_main_context_push_thread_default (priv->main_context);
  }

  g_main_loop_run (priv->loop);

  if (!priv->loop) {
    priv->alive = FALSE;
    g_main_context_unref (priv->main_context);
    priv->main_context = NULL;
  } else {
    g_main_context_pop_thread_default (priv->main_context);
  }
}
Exemple #6
0
static void
cockpit_web_server_init (CockpitWebServer *server)
{
  server->requests = g_hash_table_new_full (g_direct_hash, g_direct_equal,
                                            cockpit_request_free, NULL);
  server->main_context = g_main_context_ref_thread_default ();
  server->ssl_exception_prefix = g_string_new ("");
}
Exemple #7
0
static void
cockpit_stream_init (CockpitStream *self)
{
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, COCKPIT_TYPE_STREAM, CockpitStreamPrivate);
  self->priv->in_buffer = g_byte_array_new ();
  self->priv->out_queue = g_queue_new ();

  self->priv->context = g_main_context_ref_thread_default ();
}
Exemple #8
0
static void
do_call (Client *client, CallType call_type)
{
  GMainContext *current_context;

  /* only schedule in idle if we're not in the right thread */
  current_context = g_main_context_ref_thread_default ();
  if (current_context != client->main_context)
    schedule_call_in_idle (client, call_type);
  else
    actually_do_call (client, client->connection, client->name_owner, call_type);
  g_main_context_unref (current_context);
}
Exemple #9
0
static void
cockpit_pipe_init (CockpitPipe *self)
{
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, COCKPIT_TYPE_PIPE, CockpitPipePrivate);
  self->priv->in_buffer = g_byte_array_new ();
  self->priv->in_fd = -1;
  self->priv->out_queue = g_queue_new ();
  self->priv->out_fd = -1;
  self->priv->err_fd = -1;
  self->priv->status = -1;

  self->priv->context = g_main_context_ref_thread_default ();
}
Exemple #10
0
static gboolean
gst_gl_window_default_open (GstGLWindow * window, GError ** error)
{
  GstGLWindowPrivate *priv = window->priv;

  if (g_main_context_get_thread_default ()) {
    if (priv->main_context)
      g_main_context_unref (priv->main_context);
    if (priv->loop)
      g_main_loop_unref (priv->loop);
    priv->main_context = g_main_context_ref_thread_default ();
    priv->loop = NULL;
    priv->alive = TRUE;
  } else {
    g_main_context_push_thread_default (priv->main_context);
  }

  return TRUE;
}
Exemple #11
0
/**
 * g_bus_watch_name:
 * @bus_type: The type of bus to watch a name on.
 * @name: The name (well-known or unique) to watch.
 * @flags: Flags from the #GBusNameWatcherFlags enumeration.
 * @name_appeared_handler: (nullable): Handler to invoke when @name is known to exist or %NULL.
 * @name_vanished_handler: (nullable): Handler to invoke when @name is known to not exist or %NULL.
 * @user_data: User data to pass to handlers.
 * @user_data_free_func: (nullable): Function for freeing @user_data or %NULL.
 *
 * Starts watching @name on the bus specified by @bus_type and calls
 * @name_appeared_handler and @name_vanished_handler when the name is
 * known to have a owner respectively known to lose its
 * owner. Callbacks will be invoked in the
 * [thread-default main context][g-main-context-push-thread-default]
 * of the thread you are calling this function from.
 *
 * You are guaranteed that one of the handlers will be invoked after
 * calling this function. When you are done watching the name, just
 * call g_bus_unwatch_name() with the watcher id this function
 * returns.
 *
 * If the name vanishes or appears (for example the application owning
 * the name could restart), the handlers are also invoked. If the
 * #GDBusConnection that is used for watching the name disconnects, then
 * @name_vanished_handler is invoked since it is no longer
 * possible to access the name.
 *
 * Another guarantee is that invocations of @name_appeared_handler
 * and @name_vanished_handler are guaranteed to alternate; that
 * is, if @name_appeared_handler is invoked then you are
 * guaranteed that the next time one of the handlers is invoked, it
 * will be @name_vanished_handler. The reverse is also true.
 *
 * This behavior makes it very simple to write applications that want
 * to take action when a certain [name exists][gdbus-watching-names].
 * Basically, the application should create object proxies in
 * @name_appeared_handler and destroy them again (if any) in
 * @name_vanished_handler.
 *
 * Returns: An identifier (never 0) that an be used with
 * g_bus_unwatch_name() to stop watching the name.
 *
 * Since: 2.26
 */
guint
g_bus_watch_name (GBusType                  bus_type,
                  const gchar              *name,
                  GBusNameWatcherFlags      flags,
                  GBusNameAppearedCallback  name_appeared_handler,
                  GBusNameVanishedCallback  name_vanished_handler,
                  gpointer                  user_data,
                  GDestroyNotify            user_data_free_func)
{
  Client *client;

  g_return_val_if_fail (g_dbus_is_name (name), 0);

  G_LOCK (lock);

  client = g_new0 (Client, 1);
  client->ref_count = 1;
  client->id = g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */
  client->name = g_strdup (name);
  client->flags = flags;
  client->name_appeared_handler = name_appeared_handler;
  client->name_vanished_handler = name_vanished_handler;
  client->user_data = user_data;
  client->user_data_free_func = user_data_free_func;
  client->main_context = g_main_context_ref_thread_default ();

  if (map_id_to_client == NULL)
    {
      map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);
    }
  g_hash_table_insert (map_id_to_client,
                       GUINT_TO_POINTER (client->id),
                       client);

  g_bus_get (bus_type,
             NULL,
             connection_get_cb,
             client_ref (client));

  G_UNLOCK (lock);

  return client->id;
}
/**
 * g_bus_watch_name_on_connection:
 * @connection: A #GDBusConnection.
 * @name: The name (well-known or unique) to watch.
 * @flags: Flags from the #GBusNameWatcherFlags enumeration.
 * @name_appeared_handler: (allow-none): Handler to invoke when @name is known to exist or %NULL.
 * @name_vanished_handler: (allow-none): Handler to invoke when @name is known to not exist or %NULL.
 * @user_data: User data to pass to handlers.
 * @user_data_free_func: (allow-none): Function for freeing @user_data or %NULL.
 *
 * Like g_bus_watch_name() but takes a #GDBusConnection instead of a
 * #GBusType.
 *
 * Returns: An identifier (never 0) that an be used with
 * g_bus_unwatch_name() to stop watching the name.
 *
 * Since: 2.26
 */
guint g_bus_watch_name_on_connection (GDBusConnection          *connection,
                                      const gchar              *name,
                                      GBusNameWatcherFlags      flags,
                                      GBusNameAppearedCallback  name_appeared_handler,
                                      GBusNameVanishedCallback  name_vanished_handler,
                                      gpointer                  user_data,
                                      GDestroyNotify            user_data_free_func)
{
  Client *client;

  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
  g_return_val_if_fail (g_dbus_is_name (name), 0);

  G_LOCK (lock);

  client = g_new0 (Client, 1);
  client->ref_count = 1;
  client->id = next_global_id++; /* TODO: uh oh, handle overflow */
  client->name = g_strdup (name);
  client->flags = flags;
  client->name_appeared_handler = name_appeared_handler;
  client->name_vanished_handler = name_vanished_handler;
  client->user_data = user_data;
  client->user_data_free_func = user_data_free_func;
  client->main_context = g_main_context_ref_thread_default ();

  if (map_id_to_client == NULL)
    map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);

  g_hash_table_insert (map_id_to_client,
                       GUINT_TO_POINTER (client->id),
                       client);

  client->connection = g_object_ref (connection);
  G_UNLOCK (lock);

  has_connection (client);

  return client->id;
}
static void
dasom_server_init (DasomServer *server)
{
  g_debug (G_STRLOC ": %s", G_STRFUNC);

  GSettings *settings = g_settings_new ("org.freedesktop.Dasom");
  gchar **hotkeys = g_settings_get_strv (settings, "hotkeys");
  server->hotkeys = dasom_key_newv ((const gchar **) hotkeys);
  g_object_unref (settings);
  g_strfreev (hotkeys);

  server->candidate = dasom_candidate_new ();
  server->module_manager = dasom_module_manager_get_default ();
  server->instances = dasom_server_create_module_instances (server);

  server->main_context = g_main_context_ref_thread_default ();
  server->connections = g_hash_table_new_full (g_direct_hash,
                                               g_direct_equal,
                                               NULL,
                                               (GDestroyNotify) g_object_unref);
  server->agents_list = NULL;
}
Exemple #14
0
/** Set up the main context the session will be executing in.
 *
 * Must be called just before the session starts, by the thread which
 * will execute the session main loop. Once acquired, the main context
 * pointer is immutable for the duration of the session run.
 */
static int set_main_context(struct sr_session *session)
{
	GMainContext *main_context;

	g_mutex_lock(&session->main_mutex);

	/* May happen if sr_session_start() is called a second time
	 * while the session is still running.
	 */
	if (session->main_context) {
		sr_err("Main context already set.");

		g_mutex_unlock(&session->main_mutex);
		return SR_ERR;
	}
	main_context = g_main_context_ref_thread_default();
	/*
	 * Try to use an existing main context if possible, but only if we
	 * can make it owned by the current thread. Otherwise, create our
	 * own main context so that event source callbacks can execute in
	 * the session thread.
	 */
	if (g_main_context_acquire(main_context)) {
		g_main_context_release(main_context);

		sr_dbg("Using thread-default main context.");
	} else {
		g_main_context_unref(main_context);

		sr_dbg("Creating our own main context.");
		main_context = g_main_context_new();
	}
	session->main_context = main_context;

	g_mutex_unlock(&session->main_mutex);

	return SR_OK;
}
Exemple #15
0
gboolean
ostree_repo_pull (OstreeRepo               *self,
                  const char               *remote_name,
                  char                    **refs_to_fetch,
                  OstreeRepoPullFlags       flags,
                  OstreeAsyncProgress      *progress,
                  GCancellable             *cancellable,
                  GError                  **error)
{
  gboolean ret = FALSE;
  GHashTableIter hash_iter;
  gpointer key, value;
  gboolean tls_permissive = FALSE;
  OstreeFetcherConfigFlags fetcher_flags = 0;
  gs_free char *remote_key = NULL;
  gs_free char *path = NULL;
  gs_free char *baseurl = NULL;
  gs_free char *summary_data = NULL;
  gs_unref_hashtable GHashTable *requested_refs_to_fetch = NULL;
  gs_unref_hashtable GHashTable *updated_refs = NULL;
  gs_unref_hashtable GHashTable *commits_to_fetch = NULL;
  gs_free char *remote_mode_str = NULL;
  GSource *queue_src = NULL;
  OtPullData pull_data_real = { 0, };
  OtPullData *pull_data = &pull_data_real;
  SoupURI *summary_uri = NULL;
  GKeyFile *config = NULL;
  GKeyFile *remote_config = NULL;
  char **configured_branches = NULL;
  guint64 bytes_transferred;
  guint64 start_time;
  guint64 end_time;

  pull_data->async_error = error;
  pull_data->main_context = g_main_context_ref_thread_default ();
  pull_data->loop = g_main_loop_new (pull_data->main_context, FALSE);
  pull_data->flags = flags;

  pull_data->repo = self;
  pull_data->progress = progress;

  pull_data->scanned_metadata = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal,
                                                       (GDestroyNotify)g_variant_unref, NULL);
  pull_data->requested_content = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                        (GDestroyNotify)g_free, NULL);
  pull_data->requested_metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                         (GDestroyNotify)g_free, NULL);

  start_time = g_get_monotonic_time ();

  pull_data->remote_name = g_strdup (remote_name);
  config = ostree_repo_get_config (self);

  remote_key = g_strdup_printf ("remote \"%s\"", pull_data->remote_name);
  if (!repo_get_string_key_inherit (self, remote_key, "url", &baseurl, error))
    goto out;
  pull_data->base_uri = soup_uri_new (baseurl);

#ifdef HAVE_GPGME
  if (!ot_keyfile_get_boolean_with_default (config, remote_key, "gpg-verify",
                                            TRUE, &pull_data->gpg_verify, error))
    goto out;
#else
  pull_data->gpg_verify = FALSE;
#endif

  if (!ot_keyfile_get_boolean_with_default (config, remote_key, "tls-permissive",
                                            FALSE, &tls_permissive, error))
    goto out;
  if (tls_permissive)
    fetcher_flags |= OSTREE_FETCHER_FLAGS_TLS_PERMISSIVE;

  pull_data->fetcher = ostree_fetcher_new (pull_data->repo->tmp_dir,
                                           fetcher_flags);

  if (!pull_data->base_uri)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Failed to parse url '%s'", baseurl);
      goto out;
    }

  if (!load_remote_repo_config (pull_data, &remote_config, cancellable, error))
    goto out;

  if (!ot_keyfile_get_value_with_default (remote_config, "core", "mode", "bare",
                                          &remote_mode_str, error))
    goto out;

  if (!ostree_repo_mode_from_string (remote_mode_str, &pull_data->remote_mode, error))
    goto out;

  if (pull_data->remote_mode != OSTREE_REPO_MODE_ARCHIVE_Z2)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Can't pull from archives with mode \"%s\"",
                   remote_mode_str);
      goto out;
    }

  requested_refs_to_fetch = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
  updated_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
  commits_to_fetch = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);

  if (refs_to_fetch != NULL)
    {
      char **strviter;
      for (strviter = refs_to_fetch; *strviter; strviter++)
        {
          const char *branch = *strviter;
          char *contents;

          if (ostree_validate_checksum_string (branch, NULL))
            {
              char *key = g_strdup (branch);
              g_hash_table_insert (commits_to_fetch, key, key);
            }
          else
            {
              if (!fetch_ref_contents (pull_data, branch, &contents, cancellable, error))
                goto out;
      
              /* Transfer ownership of contents */
              g_hash_table_insert (requested_refs_to_fetch, g_strdup (branch), contents);
            }
        }
    }
  else
    {
      GError *temp_error = NULL;
      gboolean fetch_all_refs;

      configured_branches = g_key_file_get_string_list (config, remote_key, "branches", NULL, &temp_error);
      if (configured_branches == NULL && temp_error != NULL)
        {
          if (g_error_matches (temp_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND))
            {
              g_clear_error (&temp_error);
              fetch_all_refs = TRUE;
            }
          else
            {
              g_propagate_error (error, temp_error);
              goto out;
            }
        }
      else
        fetch_all_refs = FALSE;

      if (fetch_all_refs)
        {
          summary_uri = soup_uri_copy (pull_data->base_uri);
          path = g_build_filename (soup_uri_get_path (summary_uri), "refs", "summary", NULL);
          soup_uri_set_path (summary_uri, path);
          
          if (!fetch_uri_contents_utf8_sync (pull_data, summary_uri, &summary_data, cancellable, error))
            goto out;
          
          if (!parse_ref_summary (summary_data, &requested_refs_to_fetch, error))
            goto out;
        }
      else
        {
          char **branches_iter = configured_branches;

          if (!(branches_iter && *branches_iter))
            g_print ("No configured branches for remote %s\n", pull_data->remote_name);
          for (;branches_iter && *branches_iter; branches_iter++)
            {
              const char *branch = *branches_iter;
              char *contents;
              
              if (!fetch_ref_contents (pull_data, branch, &contents, cancellable, error))
                goto out;
              
              /* Transfer ownership of contents */
              g_hash_table_insert (requested_refs_to_fetch, g_strdup (branch), contents);
            }
        }
    }

  if (!ostree_repo_prepare_transaction (pull_data->repo, &pull_data->transaction_resuming,
                                        cancellable, error))
    goto out;

  pull_data->metadata_objects_to_fetch = ot_waitable_queue_new ();
  pull_data->metadata_objects_to_scan = ot_waitable_queue_new ();
  pull_data->metadata_thread = g_thread_new ("metadatascan", metadata_thread_main, pull_data);

  g_hash_table_iter_init (&hash_iter, commits_to_fetch);
  while (g_hash_table_iter_next (&hash_iter, &key, &value))
    {
      const char *commit = value;

      ot_waitable_queue_push (pull_data->metadata_objects_to_scan,
                              pull_worker_message_new (PULL_MSG_SCAN,
                                                       ostree_object_name_serialize (commit, OSTREE_OBJECT_TYPE_COMMIT)));
    }

  g_hash_table_iter_init (&hash_iter, requested_refs_to_fetch);
  while (g_hash_table_iter_next (&hash_iter, &key, &value))
    {
      const char *ref = key;
      const char *sha256 = value;

      ot_waitable_queue_push (pull_data->metadata_objects_to_scan,
                              pull_worker_message_new (PULL_MSG_SCAN,
                                                       ostree_object_name_serialize (sha256, OSTREE_OBJECT_TYPE_COMMIT)));
      g_hash_table_insert (updated_refs, g_strdup (ref), g_strdup (sha256));
    }
  
  {
    queue_src = ot_waitable_queue_create_source (pull_data->metadata_objects_to_fetch);
    g_source_set_callback (queue_src, (GSourceFunc)on_metadata_objects_to_fetch_ready, pull_data, NULL);
    g_source_attach (queue_src, pull_data->main_context);
    g_source_unref (queue_src);
  }

  /* Prime the message queue */
  pull_data->idle_serial++;
  ot_waitable_queue_push (pull_data->metadata_objects_to_scan,
                          pull_worker_message_new (PULL_MSG_MAIN_IDLE, GUINT_TO_POINTER (pull_data->idle_serial)));
  
  /* Now await work completion */
  if (!run_mainloop_monitor_fetcher (pull_data))
    goto out;
  

  g_hash_table_iter_init (&hash_iter, updated_refs);
  while (g_hash_table_iter_next (&hash_iter, &key, &value))
    {
      const char *ref = key;
      const char *checksum = value;
      gs_free char *remote_ref = NULL;
      gs_free char *original_rev = NULL;
          
      remote_ref = g_strdup_printf ("%s/%s", pull_data->remote_name, ref);

      if (!ostree_repo_resolve_rev (pull_data->repo, remote_ref, TRUE, &original_rev, error))
        goto out;
          
      if (original_rev && strcmp (checksum, original_rev) == 0)
        {
          g_print ("remote %s is unchanged from %s\n", remote_ref, original_rev);
        }
      else
        {
          ostree_repo_transaction_set_ref (pull_data->repo, pull_data->remote_name, ref, checksum);

          g_print ("remote %s is now %s\n", remote_ref, checksum);
        }
    }

  if (!ostree_repo_commit_transaction (pull_data->repo, NULL, cancellable, error))
    goto out;

  end_time = g_get_monotonic_time ();

  bytes_transferred = ostree_fetcher_bytes_transferred (pull_data->fetcher);
  if (bytes_transferred > 0)
    {
      guint shift; 
      if (bytes_transferred < 1024)
        shift = 1;
      else
        shift = 1024;
      g_print ("%u metadata, %u content objects fetched; %" G_GUINT64_FORMAT " %s transferred in %u seconds\n", 
               pull_data->n_fetched_metadata, pull_data->n_fetched_content,
               (guint64)(bytes_transferred / shift),
               shift == 1 ? "B" : "KiB",
               (guint) ((end_time - start_time) / G_USEC_PER_SEC));
    }

  ret = TRUE;
 out:
  if (pull_data->main_context)
    g_main_context_unref (pull_data->main_context);
  if (pull_data->loop)
    g_main_loop_unref (pull_data->loop);
  g_strfreev (configured_branches);
  g_clear_object (&pull_data->fetcher);
  g_free (pull_data->remote_name);
  if (pull_data->base_uri)
    soup_uri_free (pull_data->base_uri);
  if (queue_src)
    g_source_destroy (queue_src);
  if (pull_data->metadata_thread)
    {
      ot_waitable_queue_push (pull_data->metadata_objects_to_scan,
                              pull_worker_message_new (PULL_MSG_QUIT, NULL));
      g_thread_join (pull_data->metadata_thread);
    }
  g_clear_pointer (&pull_data->metadata_objects_to_scan, (GDestroyNotify) ot_waitable_queue_unref);
  g_clear_pointer (&pull_data->metadata_objects_to_fetch, (GDestroyNotify) ot_waitable_queue_unref);
  g_clear_pointer (&pull_data->scanned_metadata, (GDestroyNotify) g_hash_table_unref);
  g_clear_pointer (&pull_data->requested_content, (GDestroyNotify) g_hash_table_unref);
  g_clear_pointer (&pull_data->requested_metadata, (GDestroyNotify) g_hash_table_unref);
  g_clear_pointer (&remote_config, (GDestroyNotify) g_key_file_unref);
  if (summary_uri)
    soup_uri_free (summary_uri);
  return ret;
}
Exemple #16
0
/**
 * gda_worker_do_job: (skip)
 * @worker: a #GdaWorker object
 * @context: (allow-none): a #GMainContext to execute a main loop in (while waiting), or %NULL
 * @timeout_ms: the maximum number of milisecons to wait before returning, or %0 for unlimited wait
 * @out_result: (allow-none): a place to store the result, if any, of @func's execution, or %NULL
 * @out_job_id: (allow-none): a place to store the ID of the job having been submitted, or %NULL
 * @func: the function to call from the worker thread
 * @data: (allow-none): the data to pass to @func, or %NULL
 * @data_destroy_func: (allow-none): a function to destroy @data, or %NULL
 * @result_destroy_func: (allow-none): a function to destroy the result, if any, of @func's execution, or %NULL
 * @error: (allow-none): a place to store errors, or %NULL.
 *
 * Request that the worker thread call @func with the @data argument, much like gda_worker_submit_job(),
 * but waits (starting a #GMainLoop) for a maximum of @timeout_ms miliseconds for @func to be executed.
 *
 * If this function is called from within @worker's worker thread, then this function simply calls @func with @data and does not
 * use @context.
 *
 * The following cases are possible if this function is not called from within @worker's worker thread:
 * <itemizedlist>
 *  <listitem><para>the call to @func took less than @timeout_ms miliseconds: the return value is %TRUE and 
 *    @out_result contains the result of the @func's execution, and @out_job_id contains %NULL. Note in this
 *    case that @error may still contain an error code if @func's execution produced an error. Also note that in this case
 *    any setting defined by gda_worker_set_callback() is not applied (as the result is immediately returned)</para></listitem>
 *  <listitem><para>The call to @func takes more then @timeout_ms miliseconds: the return value is %TRUE and
 *    @out_result is %NULL and @out_job_id contains the ID of the job as if it had been submitted using gda_worker_submit_job().
 *    If @out_job_id is %NULL, and if no setting has been defined using gda_worker_set_callback(), then the job will be discarded
 *    (as if gda_worker_forget_job() had been called).
 *    </para></listitem>
 *  <listitem><para>The call to @func could not be done (some kind of plumbing error for instance): the returned value is %FALSE
 *    and @out_result and @out_job_id are set to %NULL (if they are not %NULL)</para></listitem>
 * </itemizedlist>
 *
 * Notes:
 * <itemizedlist>
 *  <listitem><para>@result_destroy_func is needed in case @out_result is %NULL (to avoid memory leaks)</para></listitem>
 *  <listitem><para>passing %NULL for @context is similar to passing the result of g_main_context_ref_thread_default()</para></listitem>
 * </itemizedlist>
 *
 * Returns: %TRUE if no error occurred
 *
 * Since: 6.0
 */
gboolean
gda_worker_do_job (GdaWorker *worker, GMainContext *context, gint timeout_ms,
		   gpointer *out_result, guint *out_job_id,
		   GdaWorkerFunc func, gpointer data, GDestroyNotify data_destroy_func,
		   GDestroyNotify result_destroy_func,
		   GError **error)
{
	if (out_result)
		*out_result = NULL;
	if (out_job_id)
		*out_job_id = 0;

	g_return_val_if_fail (worker, FALSE);
	g_return_val_if_fail (func, FALSE);
	if (!worker->callbacks_hash || !worker->jobs_hash) {
		g_warning ("GdaWorker has been destroyed\n");
		return FALSE;
	}

	if (gda_worker_thread_is_worker (worker)) {
		/* we are called from within the worker thread => call the function directly */
		gpointer result;
		result = func (data, error);
		if (data_destroy_func)
			data_destroy_func (data);
		if (out_result)
			*out_result = result;
		else if (result && result_destroy_func)
			result_destroy_func (result);
		return TRUE;
	}

	guint jid, itsid, timer = 0;

	/* determine which GMainContext to use */
	GMainContext *co;
	gboolean unref_co = FALSE;

	co = context;
	if (!co) {
		co = g_main_context_ref_thread_default ();
		unref_co = TRUE;
	}

	/* prepare main loop */
	GMainLoop *loop;
        loop = g_main_loop_new (co, FALSE);

	/* prepare ITSignaler to be notified */
	ITSignaler *its;
	its = itsignaler_new ();
	itsid = itsignaler_add (its, co, (ITSignalerFunc) do_itsignaler_cb,
				g_main_loop_ref (loop), (GDestroyNotify) g_main_loop_unref);

	/* push job */
	g_rec_mutex_lock (& worker->rmutex); /* required to call _gda_worker_submit_job_with_its() */
	jid = _gda_worker_submit_job_with_its (worker, its,
					       func, data, data_destroy_func, result_destroy_func, error);
	g_rec_mutex_unlock (& worker->rmutex);
	if (jid == 0) {
		/* an error occurred */
		g_assert (itsignaler_remove (its, co, itsid));
		itsignaler_unref (its);
		g_main_loop_unref (loop);

		if (unref_co)
			g_main_context_unref (co);

		return FALSE;
	}

	/* check if result is already here */
	WorkerJob *job;
	job = itsignaler_pop_notification (its, 0);
	if (!job) {
		if (timeout_ms > 0) {
			/* start timer to limit waiting time */
			GSource *timer_src;
			timer_src = g_timeout_source_new (timeout_ms);
			g_source_set_callback (timer_src, (GSourceFunc) do_timer_cb, loop, NULL);
			timer = g_source_attach (timer_src, co);
			g_source_unref (timer_src);
		}
		g_main_loop_run (loop);

		/* either timer has arrived or job has been done */
		job = itsignaler_pop_notification (its, 0);
	}
	g_main_loop_unref (loop);

	g_assert (itsignaler_remove (its, co, itsid));
	itsignaler_unref (its);

	if (job) {
		/* job done before the timer, if any, elapsed */

		if (timer > 0)
			g_assert (g_source_remove (timer));

		g_assert (gda_worker_fetch_job_result (worker, jid, out_result, error));
	}
	else {
		/* timer came first, job is not yet finished */

		/* apply settings from gda_worker_set_callback(), if any */
		g_rec_mutex_lock (&worker->rmutex);
		DeclaredCallback *dc;
		dc = g_hash_table_lookup (worker->callbacks_hash, co);
		if (dc) {
			job = g_hash_table_lookup (worker->jobs_hash, &jid);
			g_assert (job);
			g_assert (!job->reply_its);
			job->reply_its = itsignaler_ref (dc->its);
		}
		g_rec_mutex_unlock (& worker->rmutex);

		/* cleanups */
		if (out_job_id)
			*out_job_id = jid;
		else if (!dc)
			/* forget all about the job */
			gda_worker_forget_job (worker, jid);
	}

	if (unref_co)
		g_main_context_unref (co);

	return TRUE;
}
Exemple #17
0
static void
g_dbus_server_init (GDBusServer *server)
{
  server->main_context_at_construction = g_main_context_ref_thread_default ();
}
Exemple #18
0
/**
 * gda_worker_set_callback: (skip)
 * @worker: a #GdaWorker object
 * @context: (allow-none): a #GMainContext, or %NULL
 * @callback: (allow-none): the function to call when a job submitted from within the calling thread using gda_worker_submit_job() has finished being processed.
 * @user_data: argument passed to @callback
 * @error: (allow-none): a place to store errors, or %NULL
 *
 * Declare a callback function to be called when a job has been processed. If @callback is %NULL, then any previously
 * effect of this function is removed. If the same function is called with a different @callback value, then the previous one
 * is simply replaced.
 *
 * Since this function adds a new source of events to the specified #GMainContext (or the default one if @context is %NULL),
 *
 * Notes:
 * <itemizedlist>
 *  <listitem><para>before calling this function, @worker internally gets rid of the job, so the @jib_id passed
 *   to @callback does not actually designate a known job ID, and so calling gda_worker_fetch_job_result() for that
 *   job ID will fail</para></listitem>
 *  <listitem><para>the job's result, if any, has to be freed by @callback (@worker does not do it)</para></listitem>
 *  <listitem><para>any call to this function will only be honored for the jobs submitted _after_ calling it, the ones
 *   submitted before are not affected</para></listitem>
 *  <listitem><para>passing %NULL for @context is similar to passing the result of g_main_context_ref_thread_default()</para></listitem>
 * </itemizedlist>
 *
 * Returns: %TRUE if no error occurred.
 *
 * Since: 6.0
 */
gboolean
gda_worker_set_callback (GdaWorker *worker, GMainContext *context, GdaWorkerCallback callback,
			 gpointer user_data, GError **error)
{
	g_return_val_if_fail (worker, FALSE);
	g_return_val_if_fail (callback, FALSE);
	if (!worker->callbacks_hash) {
		g_warning ("GdaWorker has been destroyed\n");
		return FALSE;
	}

	GMainContext *co;
	gboolean unref_co = FALSE;

	co = context;
	if (!co) {
		co = g_main_context_ref_thread_default ();
		unref_co = TRUE;
	}

#ifdef DEBUG_NOTIFICATION
	g_print ("[W] %s() GMainContext=%p, thread=%p\n", __FUNCTION__, co, g_thread_self());
#endif
	g_rec_mutex_lock (& worker->rmutex);

	gboolean retval = TRUE;
	DeclaredCallback *dc = NULL;
	dc = g_hash_table_lookup (worker->callbacks_hash, co);

	if (dc) {
		if (callback) {
			/* change callback's attributes */
			dc->callback = callback;
			dc->user_data = user_data;
		}
		else {
			/* remove callback */
			g_hash_table_remove (worker->callbacks_hash, co);
		}
	}
	if (!dc) {
		if (callback) {
			/* add callback */
			dc = declared_callback_new (worker, co, callback, user_data);
			if (!dc) {
				g_set_error (error, GDA_WORKER_ERROR, GDA_WORKER_INTER_THREAD_ERROR,
					     _("Cannot build inter thread communication device"));
				g_rec_mutex_unlock (& worker->rmutex);
				return FALSE;
			}
			g_hash_table_insert (worker->callbacks_hash, co, dc);
			dc->source_sig_id = itsignaler_add (dc->its, co, (ITSignalerFunc) dc_callback, dc, NULL);
			if (dc->source_sig_id == 0) {
				g_hash_table_remove (worker->callbacks_hash, co);
				g_set_error (error, GDA_WORKER_ERROR, GDA_WORKER_INTER_THREAD_ERROR,
					     _("GdaWorker internal error"));
				retval = FALSE;
			}
		}
		else {
			/* nothing to do */
		}
	}

	g_rec_mutex_unlock (& worker->rmutex);

	if (unref_co)
		g_main_context_unref (co);

	return retval;
}