Contagem de referência em objetos DBus exportados?

2

Estou trabalhando em um serviço DBus que precisa exportar objetos sob demanda quando solicitado por aplicativos de terceiros. Essa parte parece bastante estreito para a frente.

Mas eu também preciso "coletar lixo" nesses objetos quando ele tem zero consumidores. Eu poderia ter uma API que requer que os aplicativos de terceiros liberem explicitamente os objetos, mas a desvantagem é que, se o aplicativo consumidor falhar sem liberar as referências, os objetos não utilizados se acumularão.

Por que vale a pena, estou usando o DBus do Python via python3-dbus. Então eu tenho 2 perguntas, eu acho:

  1. Que tipo de mecanismos DBus fornece para contagem de referência em objetos exportados, existe uma maneira de saber quando processos zero estão atualmente "observando" um objeto?

  2. Qual é considerada a melhor prática para projetar uma API DBus, e o que as pessoas acham que é um bom exemplo a seguir? (A única coisa que consigo pensar são os objetos Avahi Browser.)

A minha pergunta provavelmente fará mais sentido se eu descrever o problema exato: O Dmedia é um sistema especializado de arquivos distribuídos voltado para arquivos de mídia. Os arquivos recebem um ID único globalmente baseado em seu hash de conteúdo. Quando um aplicativo precisar usar um arquivo (digamos, para reprodução ou exibição), ele usará a API DBUS Dmedia para resolver a ID do arquivo em um caminho de arquivo regular. Por exemplo, este ID:

5PULSAF3PFR4VPNJMLSAJ362HG475NDKKISDYXW7WUJCFUJN

Poderia, por exemplo, resolver no arquivo:

/media/MyDrive/.dmedia/files/5P/ULSAF3PFR4VPNJMLSAJ362HG475NDKKISDYXW7WUJCFUJN

Mas as coisas são mais complicadas do que isso. O arquivo pode não estar disponível localmente e, nesse caso, o Dmedia pode fazer o download do arquivo de um dos outros dispositivos do usuário ou da nuvem. Por isso, precisamos de sinais para o progresso do download e para sinalizar o que esse caminho de arquivo regular é quando um arquivo é baixado.

A resolução também pode mudar ao longo do tempo quando as unidades removíveis são conectadas ou desconectadas. Um usuário pode remover uma unidade, ponto no qual o arquivo não está disponível localmente e o Dmedia tentaria fazer o download. Ou o usuário pode conectar uma unidade adicional, e a resolução de um determinado arquivo pode ser alterada conforme o balanceamento de carga da Dmedia nas unidades.

Parece que ter um objeto DBus exportado por arquivo de interesse atual é uma abordagem razoável, mas talvez isso torne as coisas muito complicadas. Suponho que seja a diferença entre precisar de mais filtragem e inteligência no consumidor versus o lado do serviço. Uma coleção simples de sinais e métodos em um único objeto facilitaria as coisas para o serviço, mas sobrecarregaria o consumidor.

Se exportarmos um objeto DBus por arquivo de interesse, tenho certeza de que precisamos da coleta de lixo, pois um número muito grande de arquivos pode ser interessante em algum momento durante o ciclo de vida do serviço DBus.

Eu aprecio muito qualquer conselho sobre isso!

    
por jderose 06.12.2012 / 07:01

2 respostas

3

Primeiro, provavelmente vale a pena descompactar o que "observar" significa em:

  

Que tipo de mecanismos DBus fornece para contagem de referência em objetos exportados, existe uma maneira de saber quando processos zero estão atualmente "observando" um objeto?

O único sentido em que faz sentido perguntar se algo está "observando" um objeto DBus é se um cliente receberá qualquer sinal que o objeto aumente; não há outro conceito de observação, apenas passagem de mensagens. Os clientes fazem isso chamando AddMatch / RemoveMatch no barramento, então você poderia, teoricamente, referenciar as contagens. Isso parece um método propenso a erros - basicamente, você precisará reimplementar o manipulador de correspondência do daemon para ter certeza de que capturou todas as maneiras pelas quais um cliente pode ouvir seus sinais.

No entanto, se tudo o que você deseja é limpeza depois de travar clientes, existe uma maneira - cada cliente DBus obtém um ID de barramento exclusivo (por exemplo, :1.693 ) alocado pelo daemon. Quando um cliente solicita um arquivo através de sua API DBus, você pode gravar seu id de barramento e, em seguida, observar o sinal NameOwnerChanged de org.freedesktop.DBus . Este sinal tem 3 partes - o nome do barramento (que, nos casos em que estamos interessados, será o único ID do barramento), o id do barramento do novo proprietário e o ID do barramento do proprietário antigo.

Portanto, se você obtiver um sinal NameOwnerChanged com name=":1.693" , new_owner="" e old_owner=":1.693" , saberá que o cliente com id de barramento :1.693 foi desconectado do barramento e pode remover quaisquer objetos que o cliente estava usando.

Você gostaria de fazer isso além de ter clientes informando explicitamente seu serviço quando eles terminam com um arquivo, é claro.

Editar:

Quanto à sua pergunta global - o que deve ser a API - sugiro que isso pareça complexo o suficiente para que seus objetos DBus não sejam a API principal. Embrulhe isto em um python-dmedia-client (e possivelmente um C libdmedia-client ), e manuseie a contagem de ref e a complexidade lá.

    
por RAOF 06.12.2012 / 07:53
2

Eu encontrei um problema parecido e criei um mecanismo para fazer a contagem de referência no DBus. Acabou sendo bastante complicado, então criei o DBus bug # 38784 para propor a incorporação nas especificações do DBus como uma interface / mecanismo padrão para que os outros não tivessem que repetir o trabalho.

Você pode ler a proposta no formato de documento aqui .

Eu não acredito que tenha sido implementado nas ligações DBus do Python ou quaisquer outras ligações DBus publicamente disponíveis.

    
por Will Manley 20.12.2012 / 13:37