D-BUS Tips 3.0: Performing asynchronous/synchronous method invocations and dbus-binding-tool

To easy perform a synchronous remote method invocation you have just to use GLib bindings  for DBus Proxy API (DBusGProxy), that is our first example. The second example shows how to use generated code by dbus-binding-tool to implement remote calls faster. Examples bellow are implemented accessing org.freedesktop.NetworkManager interface of NetworkManager API.

Example 1


int main()
{
	g_type_init();

	GError *error = NULL;
	DBusGConnection *conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);

	if (error != NULL) {
		g_error("D-BUS Connection error: %s", error->message);
		g_error_free(error);
	}

	if (!conn) {
		g_error("D-BUS connection cannot be created");
		return EXIT_FAILURE;
	}

	DBusGProxy *proxy = dbus_g_proxy_new_for_name(conn,
			"org.freedesktop.NetworkManager",
			"/org/freedesktop/NetworkManager",
			"org.freedesktop.NetworkManager");

	if (!proxy) {
		g_error("Cannot create proxy");
		return EXIT_FAILURE;
	}

	g_message("Calling NetworkManager.sate synchronously");
	guint state;
	GError *error = NULL;
	if (!dbus_g_proxy_call(proxy, "state", &error, G_TYPE_INVALID,
			G_TYPE_UINT, &state, G_TYPE_INVALID)) {
		if (error->domain == DBUS_GERROR && error->code
					== DBUS_GERROR_REMOTE_EXCEPTION) {
			g_error("Caught remote method exception %s: %s",
					dbus_g_error_get_name(error),
					error->message);
		} else {
			g_error("D-BUS: %s", error->message);
		}
	}
	print_network_manager_state(state);

	g_object_unref(proxy);
	dbus_g_connection_unref(conn);
	return EXIT_SUCCESS;
}

The code is self explaining. Be careful to use the right type parameters, otherwise the call will not work, at D-Bus tutorial page you can find GLib – DBus type mapping. If you want to use more complex types outside this mapping, GLib may show you the message “No marshaller for signature of …” and you will need to register a custom marshaller to this type, but this is a subject for future posts.

Example 2

A faster way to call a remote method is to generate client stub. First you need to get XML API of object interface, you can use d-feet tool to call DBus Introspectable interface and get that.

instrospect

Then execute the following command passing network-manager-api.xml file:


dbus-binding-tool --mode=glib-client network-manager-api.xml >  network-manager-client-stub.h

And you will simply get the code ready to execute D-BUS calls and they are properly typed according to method signatures. The example show you an asynchronous call using the stub:

#include "network-manager-client-stub.h"

void network_state_callback(DBusGProxy *proxy, guint state, GError *error, gpointer userdata)
{
	print_network_manager_state(state);
	g_main_loop_quit(loop);
}

static GMainLoop *loop;
int main()
{
	loop = g_main_loop_new(NULL, FALSE);
	g_type_init();

	GError *error = NULL;
	DBusGConnection *conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);

	if (error != NULL) {
		g_error("D-BUS Connection error: %s", error->message);
		g_error_free(error);
	}

	if (!conn) {
		g_error("D-BUS connection cannot be created");
		return EXIT_FAILURE;
	}

	DBusGProxy *proxy = dbus_g_proxy_new_for_name(conn,
			"org.freedesktop.NetworkManager",
			"/org/freedesktop/NetworkManager",
			"org.freedesktop.NetworkManager");

	if (!proxy) {
		g_error("Cannot create proxy");
		return EXIT_FAILURE;
	}

	g_message("Calling NetworkManager.sate asynchronously");
	org_freedesktop_NetworkManager_state_async(proxy, network_state_callback , NULL);

	g_message("Waiting D-BUS callback");
	g_main_loop_run(loop);

	g_message("Exiting glib mainloop");

	g_main_loop_unref(loop);
	g_object_unref(proxy);
	dbus_g_connection_unref(conn);
	return EXIT_SUCCESS;
}

See full code example in method-invocation.c at dbus-glib-sample project.

December 16, 2010 at 10:09 am Leave a comment

D-BUS Tips 2.0: Listening to D-BUS signals in C with D-Bus Glib bindings

I will present two ways to handle signals from D-BUS, the first consists in use a connection filter to register callback function that should be invoked when the corresponding match occurs, the second uses a proxy.

First, let us choose the signal we want to listen. To see current active D-BUS services on system (I am using Ubuntu 10.04), you can open a debugger tool like d-feet and see something like that:

debugger

Let us catch ‘StateChange’ signal from NetworkManager Interface (API definition link), in our test case to dispatch this signal, you should connect or disconnect your active network connection after run the code sample.

#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>

DBusHandlerResult signal_filter(DBusConnection *connection, DBusMessage *msg,
		void *user_data)
{
	if (dbus_message_is_signal(msg, "org.freedesktop.NetworkManager",
			"StateChange")) {
		read_network_manager_state_change(msg);
	}
	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}


int main()
{
	GMainLoop *loop = g_main_loop_new(NULL, FALSE);
	DBusError error;

	dbus_error_init(&error);
	DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);

	if (dbus_error_is_set(&error)) {
		g_error("Cannot get System BUS connection: %s", error.message);
		dbus_error_free(&error);
		return EXIT_FAILURE;
	}
	dbus_connection_setup_with_g_main(conn, NULL);

	char *rule = "type='signal',interface='org.freedesktop.NetworkManager'";
	g_message("Signal match rule: %s", rule);
	dbus_bus_add_match(conn, rule, &error);

	if (dbus_error_is_set(&error)) {
		g_error("Cannot add D-BUS match rule, cause: %s", error.message);
		dbus_error_free(&error);
		return EXIT_FAILURE;
	}

	g_message("Listening to D-BUS signals using a connection filter");
	dbus_connection_add_filter(conn, signal_filter, NULL, NULL);

	g_main_loop_run(loop);

	return EXIT_SUCCESS; 
}

The filter function return DBUS_HANDLER_RESULT_HANDLED, other handlers will not receive this message, but in example code we want the other BUS listeners catch the network connection signal.

Do not forget to call dbus_connection_setup_with_g_main function since the connection was created from dbus_bus_get function, otherwise the GLib mainloop and D-BUS callbacks will not work properly and will you be very sad, belive me.

To read the message you can use D-BUS Message API, it is part of D-Bus low-level public API.

void read_network_manager_state_change(DBusMessage *msg)
{
	DBusError error;
	dbus_error_init(&error);

	guint32 state = 0;

	if (!dbus_message_get_args(msg, &error, DBUS_TYPE_UINT32, &state,
			DBUS_TYPE_INVALID)) {
		g_error("Cannot read NetworkManager state change message, cause: %s", error.message);
		dbus_error_free(&error);
		return;
	}
	print_network_manager_state(state);
}

The second example show how to receive the same signal, but using a proxy from remote object.

#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>

void state_changed_callback(DBusGProxy *proxy, guint32 state,
		gpointer user_data)
{
	print_network_manager_state(state);
}

int main()
{
	GMainLoop *loop = g_main_loop_new(NULL, FALSE);

	g_type_init();

	GError *error = NULL;
	DBusGConnection *conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);

	if (error != NULL) {
		g_error("D-BUS Connection error: %s", error->message);
		g_error_free(error);
	}

	if (!conn) {
		g_error("D-BUS connection cannot be created");
		return EXIT_FAILURE;
	}

	DBusGProxy *proxy = dbus_g_proxy_new_for_name(conn,
			"org.freedesktop.NetworkManager",
			"/org/freedesktop/NetworkManager",
			"org.freedesktop.NetworkManager");

	if (!proxy) {
		g_error("Cannot create proxy");
		return EXIT_FAILURE;
	}

	dbus_g_proxy_add_signal(proxy, "StateChange", G_TYPE_UINT,
			G_TYPE_INVALID);

	dbus_g_proxy_connect_signal(proxy, "StateChange",
			G_CALLBACK(state_changed_callback), NULL, NULL);

	g_message("Waiting D-BUS proxy callback for signal");
	g_main_loop_run(loop);

	return EXIT_SUCCESS;
}

Next post I will talk about asynchronous/synchronous calls.

Download full example code at gitorious dbus-glib-sample project.

December 2, 2010 at 10:55 am Leave a comment

D-BUS Tips 1.0: Getting in D-BUS world

This is the first of a sequence of posts related to D-BUS communication. I guess this can help you to find an easy and painless way to work with this technology since official documentation is under development.

D-Bus is a system for interprocess communication (IPC), and it is a good way to integrate operating system/desktop applications on linux, the windows port is under development. You can find details about “what is D-BUS?” at tutorial page.

Next post will describe how to listen to application signals.

December 1, 2010 at 1:59 pm Leave a comment

Protocol Buffers

Olá pessoal, estou postando minha apresentação sobre protocol buffers no JATIC.

Esta tecnologia é uma alternativa de formato de serialização de dados frente aos que comumente usamos em aplicações (XML, JSON, CSV), ou outros formatos binários que seguem padrões estritos como ASN1, etc…

Consiste um uma maneira simples de especificar a estrutura de sua informação (IDL), e gerar automaticamente os objetos para encapsular as informações e métodos para serialização/deserialização.

Longe de se tornar um padrão internacional e inter-corporativo como XML, a proposta do PB é otimização da troca de dados, tamanho da informação, e compatibilidade com versões anteriores de mensagens, permitindo upgrades de serviço on-the-fly.

Por isso, desde que você tenha domínio/influência entre os serviços que irão conversar usando este protocolo sejam internos ou externos a sua corporação, pode ser uma boa alternativa de otimização.

Download (.pdf)

November 5, 2010 at 4:54 pm Leave a comment

Maemo Eclipse Integration 2nd Edition PreFinal Released

Para quem conhece os dipositivos da nokia que usam a plataforma maemo (maemo.org) segue uma boa notícia. Acabamos de lançar a versão pré-final do ambiente de desenvolvimento integrado com Eclipse IDE para estes dispositivos, daí o nome Maemo IDE Integration.  Ele também já suporta o mais novo dispositivo nokia para maemo e recém lançado no mercado,  é simplesmente uma máquina clique e vejam o N900 !!

Vejam as duas linhas do produto e os screenshots disponíveis em:

ESbox - IDE para aplicações C/C++ e Python, requer instalação de SDK para executar cross-compilation para o dispositivo.

PluThon-  IDE leve para aplicações  python utilizando diretamente o dispositivo como plataforma de desenvolvimento, não requer SDK.

Existem muitas features novas legais além de um novo sistema de ajuda sensível  para o desenvolvedor que é dinamicamente atualizado pelos mantenedores :P ! =]

Para criação destes dois produtos eclipse,  foi desenvolvido um o novo framework base: Mica (Maemo IDE Common Architecture -  http://mica.garage.maemo.org/2nd_edition/), matendo a aquitetura de cada produto bastante simplificada e fácil para quem desejar colaborar ou estender os mesmos ou ainda criar o seu….  hein? Sim o código é inteiramente open-source e tem licensa EPL .

O link oficial do anúncio: http://maemo.org/news/announcements/maemo_eclipse_integration_2nd_edition_prefinal_released/

September 11, 2009 at 7:10 pm Leave a comment

JEE Quick Start – Web Tier

Para aqueles que desejam entrar no mundo JEE Web e precisam de um ponta pé inicial, nada melhor que uma apresentação curta e grossa com uma visão simplificada do assunto.

Registre sua dúvida ou opinião sobre o mini-workshop http://fabricioepa.googlepages.com/jeequickstart-webtier

March 11, 2009 at 11:34 pm Leave a comment

JBean File Storage

Após um bomtempo sem publicar devido a minha dedicação ao projeto “Easy Accept Web” (mas isso fica para outro post), anuncio um novo componente para auxílio a manipulação e associação de caminhos de arquivos/diretórios com POJOS. Muito útil quando sua aplicação trabalha em conjunto com framework ORM (Hibernate like), onde se deseja por exemplo associar uma entidade com um determinado diretório de arquivos (para upload/download por exemplo), seu nome por enquanto é :

JBean File Storage

O componente ainda apesar de implementado ainda não está disponibilizado publicamente pois ainda necessita de revisão, documentação e algumas possíveis melhorias embora esta versão esteja presente em 2 projetos já em produção.

A idéia chave foi associar um caminho a um tipo java, eu mentiria se dissesse que a idéia foi completamente minha pois me baseei numa solução proposta por Luciano Logrado ao trabalharmos juntos em um outro projeto, digamos que eu incrementei a idéia para suportar polimorfismo e com isto será possível:

  • Associar um caminho a uma tipo (classe ou interface) e seus subtipos também estarão associados
  • Usar uma Expression Language (semelhante a do JSP 2.0) mínima para usar caminhos dinâmicos
  • Herdar um caminho dum outro POJO
  • Manter na hierarquia de diretórios a hierarquia nas associações dos POJOS

Estes dois últimos são importantes caso por exemplo existam dois POJO’s com relacionamento de pai/filho e ao excluir o pai os filhos devem ser excluídos:

Cliente ->* Conta

Desta forma o caminho de arquivos do cliente poderia ser:

$/Cliente_99

/Conta_33

MeuExtrato1.txt

/Conta_34

Extrato2008.txt

Com uma operação de exclusão do diretório do cliente haverá propagação no sistema de arquivo para os subdiretórios, ou seja, as contas. Além de manter a organização dos arquivos numa hierarquia de pastas de fácil entendimento visual e manipulação.

Veja detalhes do uso:

(more…)

August 20, 2008 at 6:36 pm 4 comments

Fundamentos do Controle de Versão e SVN

Olá pessoal, estou publicando em minha página pessoal uma apresentação rápida que fiz sobre alguns fundamentos para desenvolvimento de projetos em equipes de maneira colaborativa.

Em suporte a este propósito utilizei os recursos do Subversion (SVN), por ser open-source e de livre distribuição, além de integrar novos recursos em relação ao famoso sistema de controle de versão CVS.

O foco do estudo foi relacionado aos usuários de um repositório, como também o recurso de integração com Java/Eclipse IDE.

Enjoy it =) !

Fundamentos do Controle de Versão e SVN

April 21, 2008 at 9:50 pm Leave a comment

BugBuster 1.0 – Hibernate Exception: Illegally attempted to associate a proxy with two open Sessions

O referido erro também ocorre com mesagem semelhante:

Illegal attempt to associate a collection with two open sessions

Causa:

O erro é provocado quando um hiberObject associado a uma sessão tenta ser alterado por outra sessão do hibernate.

Solução:

Esqueça os métodos session.get/load/update você pode conseguir o mesmo efeito com session.refresh/merge.

Contexto do Problema:

Isso acontece devido a associação de um objeto gerenciado pelo hibernate (hiberOjbect) com a sessão que o carrega. Tecnicamente se um objeto foi carregado por uma sessão, até que o objeto seja desconectado (passando para o estado Detached) ele permanece associado a ela. O que pode ser feito invocando os métodos:

//Apenas se os relacionamentos do hiberOject
//que possuem cascade="evict" eles serão também desconectados
session.evict(hiberObject);
session.clear();
session.close();
 

Se outra sessão tentar alterá-lo sem ele estar destacado da última sessão, o erro será lançado.

Problemas Típicos:

1. 0 Quando se deseja usar um objeto em outra sessão sem fechar a primeira use o evict, lembrando que se os relacionamentos não possuirem cascade=”evict” o efeito do método não servirá para eles e provavelmente o mesmo erro ocorrerá para o “proxy” dos relcionamentos (que podem ser coleções causando Illegal attempt to associate a collection with two open sessions) .

2.0 Em Aplicações WEB Java tipicamente carregamos um hiberObject e o setamos em alguma variável do contexto web (request, session, sevletContext), após algum uso pela camada de apresentação fazemos outra chamada a camada do hibernate usando esse mesmo hiberObject onde ocorre falha com o dito erro. Neste caso temos dois pontos:

  • Se a sessão que o carregou anterior ainda estava aberta você recai no erro 1.0
  • Caso a velha sessão já tenha morrido, o seu hiberObject não está mais conectado a mesma, porém os seus relacionamentos ainda podem ter algum “proxy” para a velha sessão. Nesse caso é mais simples usar um dos metódos:


//Caso queira reconectar e recarregar
//no seu objeto os dados do banco
session.refresh(detachedHiberObject);

//Caso queira reconectar o objeto fazer um update no banco
//de dados com as novas informações setadas no objeto
connectedHiberObject = session.merge(detachedHiberObject);

 

O merge/refresh tem funções diferentes, mas ambos reconectam o objeto a uma sessão, seja a mesma ou não, sem provocar erro.

April 19, 2008 at 5:56 pm 4 comments

JavaTips 3.0 – Performance Generics + AutoBox/UnBox

AutoBox/UnBox é a conversão de forma automática entre objetos e tipos primitivos, dicas:

  • Use somente quando houver “descasamento” entre tipos primitivos e objetos empacotadores
  • Não abuse: um Integer não substitui um int (a performance é pior)
  • Cuidado, unboxing com objetos null lança exceção

Probolema:

  • Generics não trabalha com tipos primitivos

Após executar o seguinte teste de performance, constatou-se uma diferênça em média de 25% com uso do autobox. O algoritimo de teste baseou-se em comparar as duas execuções:

  1. faça 1000 vezes
    • varra um ArrayList<Integer>, capturando o valor sem fazer autobox
  2. faça 1000 vezes
    • varra um ArrayList<Integer> usando enhanced-loop fazendo automaticamente unbox para int, capturando o valor e fazendo autbox novamente para um objeto Integer.

Resultado da execução:

___________________________________

autoBoxUnBox()…java.lang.NullPointerException
Sem autoboxing = 6531ms
Com autobox/unbox= 8734ms
Diferença de 26%

___________________________________

Conclusão:

Se sua aplicação é “Performance Driven”, estruturas como o IntHashMap visto no blog anterior entre outras coleções da API que não trabalhem com Generics podem ser a melhor saída para escovar milisegundos de processamento.

Abaixo segue a classe usada no teste:

(more…)

March 19, 2008 at 4:18 pm Leave a comment

Older Posts


Categories

  • Lista de blogs

  • Feeds


    Follow

    Get every new post delivered to your Inbox.