Commit b5e4d26a authored by Robert McQueen's avatar Robert McQueen

2005-11-15 Robert McQueen <robot101@debian.org>

	* bus/driver.c, bus/services.c, bus/services.h: Add a ReleaseName
	method to org.freedesktop.DBus to release a bus name or give up
	waiting in the queue for it.

	* dbus/dbus-bus.c, dbus/dbus-bus.h, dbus/dbus-shared.h: Add a
	dbus_bus_release_name method to send the ReleaseName method calls.
	Add constants for the return values to dbus/dbus-shared.h.

	* doc/dbus-specification.xml: Document the new ReleaseName method
	in the specification.

	* python/dbus_bindings.pyx: Add a low-level python binding for the
	release name method.

	* python/exceptions.py, python/service.py: Make freeing BusName
	objects release the name. Add a NameExistsException, and fix a
	bug with creating UnknownMethodException.

	* test/python/test-client.py: Add tests for freeing BusName
	objects causing names to be released.
parent d4595960
2005-11-15 Robert McQueen <robot101@debian.org>
* bus/driver.c, bus/services.c, bus/services.h: Add a ReleaseName
method to org.freedesktop.DBus to release a bus name or give up
waiting in the queue for it.
* dbus/dbus-bus.c, dbus/dbus-bus.h, dbus/dbus-shared.h: Add a
dbus_bus_release_name method to send the ReleaseName method calls.
Add constants for the return values to dbus/dbus-shared.h.
* doc/dbus-specification.xml: Document the new ReleaseName method
in the specification.
* python/dbus_bindings.pyx: Add a low-level python binding for the
release name method.
* python/exceptions.py, python/service.py: Make freeing BusName
objects release the name. Add a NameExistsException, and fix a
bug with creating UnknownMethodException.
* test/python/test-client.py: Add tests for freeing BusName
objects causing names to be released.
2005-11-14 Robert McQueen <robot101@debian.org>
* python/service.py: Include the traceback in the error reply when we
send an exception over the bus. _BEST_ _PATCH_ _EVER_
......
......@@ -470,7 +470,7 @@ bus_driver_handle_acquire_service (DBusConnection *connection,
DBusMessage *reply;
DBusString service_name;
const char *name;
int service_reply;
dbus_uint32_t service_reply;
dbus_uint32_t flags;
dbus_bool_t retval;
BusRegistry *registry;
......@@ -525,6 +525,67 @@ bus_driver_handle_acquire_service (DBusConnection *connection,
return retval;
}
static dbus_bool_t
bus_driver_handle_release_service (DBusConnection *connection,
BusTransaction *transaction,
DBusMessage *message,
DBusError *error)
{
DBusMessage *reply;
DBusString service_name;
const char *name;
dbus_uint32_t service_reply;
dbus_bool_t retval;
BusRegistry *registry;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
registry = bus_connection_get_registry (connection);
if (!dbus_message_get_args (message, error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
return FALSE;
_dbus_verbose ("Trying to release name %s\n", name);
retval = FALSE;
reply = NULL;
_dbus_string_init_const (&service_name, name);
if (!bus_registry_release_service (registry, connection,
&service_name, &service_reply,
transaction, error))
goto out;
reply = dbus_message_new_method_return (message);
if (reply == NULL)
{
BUS_SET_OOM (error);
goto out;
}
if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
{
BUS_SET_OOM (error);
goto out;
}
if (!bus_transaction_send_from_driver (transaction, connection, reply))
{
BUS_SET_OOM (error);
goto out;
}
retval = TRUE;
out:
if (reply)
dbus_message_unref (reply);
return retval;
}
static dbus_bool_t
bus_driver_handle_service_exists (DBusConnection *connection,
BusTransaction *transaction,
......@@ -1142,6 +1203,10 @@ struct
DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
DBUS_TYPE_UINT32_AS_STRING,
bus_driver_handle_acquire_service },
{ "ReleaseName",
DBUS_TYPE_STRING_AS_STRING,
DBUS_TYPE_UINT32_AS_STRING,
bus_driver_handle_release_service },
{ "StartServiceByName",
DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
DBUS_TYPE_UINT32_AS_STRING,
......
......@@ -433,6 +433,70 @@ bus_registry_acquire_service (BusRegistry *registry,
return retval;
}
dbus_bool_t
bus_registry_release_service (BusRegistry *registry,
DBusConnection *connection,
const DBusString *service_name,
dbus_uint32_t *result,
BusTransaction *transaction,
DBusError *error)
{
dbus_bool_t retval;
BusService *service;
retval = FALSE;
if (!_dbus_validate_bus_name (service_name, 0,
_dbus_string_get_length (service_name)))
{
dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
"Given bus name \"%s\" is not valid",
_dbus_string_get_const_data (service_name));
_dbus_verbose ("Attempt to release invalid service name\n");
goto out;
}
if (_dbus_string_get_byte (service_name, 0) == ':')
{
/* Not allowed; the base service name cannot be created or released */
dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
"Cannot release a service starting with ':' such as \"%s\"",
_dbus_string_get_const_data (service_name));
_dbus_verbose ("Attempt to release invalid base service name \"%s\"",
_dbus_string_get_const_data (service_name));
goto out;
}
service = bus_registry_lookup (registry, service_name);
if (service == NULL)
{
*result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
}
else if (!bus_service_has_owner (service, connection))
{
*result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
}
else
{
if (!bus_service_remove_owner (service, connection,
transaction, error))
goto out;
_dbus_assert (!bus_service_has_owner (service, connection));
*result = DBUS_RELEASE_NAME_REPLY_RELEASED;
}
retval = TRUE;
out:
return retval;
}
dbus_bool_t
bus_registry_set_service_context_table (BusRegistry *registry,
DBusHashTable *table)
......
......@@ -56,6 +56,12 @@ dbus_bool_t bus_registry_acquire_service (BusRegistry *registry
dbus_uint32_t *result,
BusTransaction *transaction,
DBusError *error);
dbus_bool_t bus_registry_release_service (BusRegistry *registry,
DBusConnection *connection,
const DBusString *service_name,
dbus_uint32_t *result,
BusTransaction *transaction,
DBusError *error);
dbus_bool_t bus_registry_set_service_context_table (BusRegistry *registry,
DBusHashTable *table);
......
......@@ -777,6 +777,71 @@ dbus_bus_request_name (DBusConnection *connection,
return result;
}
int
dbus_bus_release_name (DBusConnection *connection,
const char *name,
DBusError *error)
{
DBusMessage *message, *reply;
dbus_uint32_t result;
_dbus_return_val_if_fail (connection != NULL, 0);
_dbus_return_val_if_fail (name != NULL, 0);
_dbus_return_val_if_fail (_dbus_check_is_valid_bus_name (name), 0);
_dbus_return_val_if_error_is_set (error, 0);
message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"ReleaseName");
if (message == NULL)
{
_DBUS_SET_OOM (error);
return -1;
}
if (!dbus_message_append_args (message,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
{
dbus_message_unref (message);
_DBUS_SET_OOM (error);
return -1;
}
reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
error);
dbus_message_unref (message);
if (reply == NULL)
{
_DBUS_ASSERT_ERROR_IS_SET (error);
return -1;
}
if (dbus_set_error_from_message (error, reply))
{
_DBUS_ASSERT_ERROR_IS_SET (error);
dbus_message_unref (reply);
return -1;
}
if (!dbus_message_get_args (reply, error,
DBUS_TYPE_UINT32, &result,
DBUS_TYPE_INVALID))
{
_DBUS_ASSERT_ERROR_IS_SET (error);
dbus_message_unref (reply);
return -1;
}
dbus_message_unref (reply);
return result;
}
/**
* Checks whether a certain name has an owner.
*
......
......@@ -48,6 +48,9 @@ int dbus_bus_request_name (DBusConnection *connection,
const char *name,
unsigned int flags,
DBusError *error);
int dbus_bus_release_name (DBusConnection *connection,
const char *name,
DBusError *error);
dbus_bool_t dbus_bus_name_has_owner (DBusConnection *connection,
const char *name,
DBusError *error);
......
......@@ -77,6 +77,11 @@ typedef enum
#define DBUS_REQUEST_NAME_REPLY_EXISTS 3
#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4
/* Replies to releasing a name */
#define DBUS_RELEASE_NAME_REPLY_RELEASED 1
#define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT 2
#define DBUS_RELEASE_NAME_REPLY_NOT_OWNER 3
/* Replies to service starts */
#define DBUS_START_REPLY_SUCCESS 1
#define DBUS_START_REPLY_ALREADY_RUNNING 2
......
......@@ -2567,7 +2567,8 @@
A connection can request additional names to be associated with it using
the <literal>org.freedesktop.DBus.RequestName</literal> message. <xref
linkend="message-protocol-names-bus"/> describes the format of a valid
name.
name. These names can be released again using the
<literal>org.freedesktop.DBus.ReleaseName</literal> message.
</para>
<sect3 id="bus-messages-request-name">
......@@ -2700,6 +2701,101 @@
</tgroup>
</informaltable>
</para>
</sect3>
<sect3 id="bus-messages-release-name">
<title><literal>org.freedesktop.DBus.ReleaseName</literal></title>
<para>
As a method:
<programlisting>
UINT32 ReleaseName (in STRING name)
</programlisting>
Message arguments:
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>STRING</entry>
<entry>Name to release</entry>
</row>
</tbody>
</tgroup>
</informaltable>
Reply arguments:
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>UINT32</entry>
<entry>Return value</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
This method call should be sent to
<literal>org.freedesktop.DBus</literal> and asks the message bus to
release the method caller's claim to the given name. If the caller is
the primary owner, a new primary owner will be selected from the
queue if any other owners are waiting. If the caller is waiting in
the queue for the name, the caller will removed from the queue and
will not be made an owner of the name if it later becomes available.
If there are no other owners in the queue for the name, it will be
removed from the bus entirely.
The return code can be one of the following values:
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Conventional Name</entry>
<entry>Value</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>DBUS_RELEASE_NAME_REPLY_RELEASED</entry>
<entry>1</entry> <entry>The caller has released his claim on
the given name. Either the caller was the primary owner of
the name, and the name is now unused or taken by somebody
waiting in the queue for the name, or the caller was waiting
in the queue for the name and has now been removed from the
queue.</entry>
</row>
<row>
<entry>DBUS_RELEASE_NAME_REPLY_NON_EXISTENT</entry>
<entry>2</entry>
<entry>The given name does not exist on this bus.</entry>
</row>
<row>
<entry>DBUS_RELEASE_NAME_REPLY_NOT_OWNER</entry>
<entry>3</entry>
<entry>The caller was not the primary owner of this name,
and was also not waiting in the queue to own this name.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</sect3>
</sect2>
......
......@@ -1710,10 +1710,10 @@ def bus_get_unix_user(Connection connection, service_name):
return retval
#These are defines, not enums so they aren't auto generated
DBUS_START_REPLY_SUCCESS = 0
DBUS_START_REPLY_ALREADY_RUNNING = 1
# these are defines, not enums, so they aren't auto generated
DBUS_START_REPLY_SUCCESS = 0
DBUS_START_REPLY_ALREADY_RUNNING = 1
def bus_start_service_by_name(Connection connection, service_name, flags=0):
cdef DBusError error
dbus_error_init(&error)
......@@ -1771,9 +1771,30 @@ def bus_request_name(Connection connection, service_name, flags=0):
errormsg = error.message
dbus_error_free(&error)
raise DBusException, errormsg
return retval
RELEASE_NAME_REPLY_RELEASED = 1
RELEASE_NAME_REPLY_NON_EXISTENT = 2
RELEASE_NAME_REPLY_NOT_OWNER = 3
def bus_release_name(Connection connection, service_name):
cdef DBusError error
dbus_error_init(&error)
cdef int retval
cdef DBusConnection *conn
conn = connection._get_conn()
retval = dbus_bus_release_name(conn,
service_name,
&error)
if dbus_error_is_set(&error):
errormsg = error.message
dbus_error_free(&error)
raise DBusException, errormsg
return retval
def bus_name_has_owner(Connection connection, service_name):
cdef DBusError error
dbus_error_init(&error)
......
......@@ -17,9 +17,13 @@ class ValidationException(DBusException):
class IntrospectionParserException(DBusException):
def __init__(self, msg=''):
DBusException.__init__(self, "Error parsing introspect data: %s"%msg)
DBusException.__init__(self, "Error parsing introspect data: %s"%msg)
class UnknownMethodException(DBusException):
def __init__(self, msg=''):
DBusException.__init__("Unknown method: %s"%msg)
def __init__(self, method):
DBusException.__init__(self, "Unknown method: %s"%method)
class NameExistsException(DBusException):
def __init__(self, name):
DBusException.__init__(self, "Bus name already exists: %s"%name)
import dbus_bindings
import dbus_bindings
import _dbus
import operator
import traceback
from exceptions import NameExistsException
from exceptions import UnknownMethodException
from decorators import method
from decorators import signal
......@@ -31,13 +31,13 @@ class BusName(object):
# because you can't put flags in, but... who knows?
pass
elif retval == dbus_bindings.REQUEST_NAME_REPLY_EXISTS:
raise dbus_bindings.DBusException('requested name %s already exists' % name)
raise NameExistsException(name)
elif retval == dbus_bindings.REQUEST_NAME_REPLY_ALREADY_OWNER:
# if this is a shared bus which is being used by someone
# else in this process, this can happen legitimately
pass
else:
raise dbus_bindings.DBusException('requesting name %s returned unexpected value %s' % (name, retval))
raise RuntimeError('requesting bus name %s returned unexpected value %s' % (name, retval))
# and create the object
bus_name = object.__new__(cls)
......@@ -57,8 +57,7 @@ class BusName(object):
# we can delete the low-level name here because these objects
# are guaranteed to exist only once for each bus name
def __del__(self):
# FIXME: we don't have this function yet :)
#dbus_bindings.bus_release_name(self._bus.get_connection(), self._named_service)
dbus_bindings.bus_release_name(self._bus.get_connection(), self._name)
pass
def get_bus(self):
......
......@@ -252,8 +252,17 @@ class TestDBusBindings(unittest.TestCase):
else:
names[name] = busname
del busname
print
del names
bus = dbus.Bus()
ret = dbus.dbus_bindings.bus_name_has_owner(bus._connection, 'org.freedesktop.DBus.Python.TestName')
self.assert_(not ret, 'deleting reference failed to release BusName org.freedesktop.DBus.Python.TestName')
class TestDBusPythonToGLibBindings(unittest.TestCase):
def setUp(self):
self.bus = dbus.SessionBus()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment