#include "dbus-protocol.h"
#include "dbus-dataslot.h"
#include "dbus-string.h"
+#include "dbus-signature.h"
#include "dbus-pending-call.h"
#include "dbus-object-tree.h"
#include "dbus-threads-internal.h"
_dbus_assert (connection->generation == _dbus_current_generation);
HAVE_LOCK_CHECK (connection);
-
-#ifdef DBUS_HAVE_ATOMIC_INT
+
_dbus_atomic_inc (&connection->refcount);
-#else
- _dbus_assert (connection->refcount.value > 0);
- connection->refcount.value += 1;
-#endif
return connection;
}
_dbus_assert (connection != NULL);
- /* The connection lock is better than the global
- * lock in the atomic increment fallback
- */
-
-#ifdef DBUS_HAVE_ATOMIC_INT
last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
-#else
- _dbus_assert (connection->refcount.value > 0);
- connection->refcount.value -= 1;
- last_unref = (connection->refcount.value == 0);
-#if 0
- printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
-#endif
-#endif
-
if (last_unref)
_dbus_connection_last_unref (connection);
}
void
_dbus_connection_close_if_only_one_ref (DBusConnection *connection)
{
+ dbus_int32_t tmp_refcount;
+
CONNECTION_LOCK (connection);
-
- _dbus_assert (connection->refcount.value > 0);
- if (connection->refcount.value == 1)
+ /* We increment and then decrement the refcount, because there is no
+ * _dbus_atomic_get (mirroring the fact that there's no InterlockedGet
+ * on Windows). */
+ _dbus_atomic_inc (&connection->refcount);
+ tmp_refcount = _dbus_atomic_dec (&connection->refcount);
+
+ /* The caller should have one ref, and this function temporarily took
+ * one more, which is reflected in this count even though we already
+ * released it (relying on the caller's ref) due to _dbus_atomic_dec
+ * semantics */
+ _dbus_assert (tmp_refcount >= 2);
+
+ if (tmp_refcount == 2)
_dbus_connection_close_possibly_shared_and_unlock (connection);
else
CONNECTION_UNLOCK (connection);
{
_dbus_return_val_if_fail (connection != NULL, NULL);
_dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
-
- /* The connection lock is better than the global
- * lock in the atomic increment fallback
- *
- * (FIXME but for now we always use the atomic version,
- * to avoid taking the connection lock, due to
- * the mess with set_timeout_functions()/set_watch_functions()
- * calling out to the app without dropping locks)
- */
-
-#if 1
- _dbus_atomic_inc (&connection->refcount);
-#else
- CONNECTION_LOCK (connection);
- _dbus_assert (connection->refcount.value > 0);
- connection->refcount.value += 1;
- CONNECTION_UNLOCK (connection);
-#endif
+ _dbus_atomic_inc (&connection->refcount);
return connection;
}
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (connection->generation == _dbus_current_generation);
-
- /* The connection lock is better than the global
- * lock in the atomic increment fallback
- *
- * (FIXME but for now we always use the atomic version,
- * to avoid taking the connection lock, due to
- * the mess with set_timeout_functions()/set_watch_functions()
- * calling out to the app without dropping locks)
- */
-
-#if 1
- last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
-#else
- CONNECTION_LOCK (connection);
-
- _dbus_assert (connection->refcount.value > 0);
- connection->refcount.value -= 1;
- last_unref = (connection->refcount.value == 0);
+ last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
-#if 0
- printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
-#endif
-
- CONNECTION_UNLOCK (connection);
-#endif
-
if (last_unref)
{
#ifndef DBUS_DISABLE_CHECKS
* This function can be used to do runtime checking for types that
* might be unknown to the specific D-Bus client implementation
* version, i.e. it will return FALSE for all types this
- * implementation does not know.
+ * implementation does not know, including invalid or reserved types.
*
* @param connection the connection
* @param type the type to check
{
_dbus_return_val_if_fail (connection != NULL, FALSE);
- if (!_dbus_type_is_valid(type))
+ if (!dbus_type_is_valid (type))
return FALSE;
if (type != DBUS_TYPE_UNIX_FD)
DBusPendingCall *pending = data;
connection = _dbus_pending_call_get_connection_and_lock (pending);
+ _dbus_connection_ref_unlocked (connection);
_dbus_pending_call_queue_timeout_error_unlocked (pending,
connection);
/* Unlocks, and calls out to user code */
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
+ dbus_connection_unref (connection);
return TRUE;
}
*
* If -1 is passed for the timeout, a sane default timeout is used. -1
* is typically the best value for the timeout for this reason, unless
- * you want a very short or very long timeout. If INT_MAX is passed for
- * the timeout, no timeout will be set and the call will block forever.
+ * you want a very short or very long timeout. If #DBUS_TIMEOUT_INFINITE is
+ * passed for the timeout, no timeout will be set and the call will block
+ * forever.
*
* @warning if the connection is disconnected or you try to send Unix
* file descriptors on a connection that does not support them, the
* object, or #NULL if connection is disconnected or when you try to
* send Unix file descriptors on a connection that does not support
* them.
- * @param timeout_milliseconds timeout in milliseconds, -1 for default or INT_MAX for no timeout
+ * @param timeout_milliseconds timeout in milliseconds, -1 (or
+ * #DBUS_TIMEOUT_USE_DEFAULT) for default or #DBUS_TIMEOUT_INFINITE for no
+ * timeout
* @returns #FALSE if no memory, #TRUE otherwise.
*
*/
*
* @param connection the connection
* @param message the message to send
- * @param timeout_milliseconds timeout in milliseconds, -1 for default or INT_MAX for no timeout.
+ * @param timeout_milliseconds timeout in milliseconds, -1 (or
+ * #DBUS_TIMEOUT_USE_DEFAULT) for default or #DBUS_TIMEOUT_INFINITE for no
+ * timeout
* @param error return location for error message
* @returns the message that is the reply or #NULL with an error code if the
* function fails.
DBusPendingCall *pending;
dbus_int32_t reply_serial;
DBusDispatchStatus status;
+ dbus_bool_t found_object;
_dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
/* unlocks and calls user code */
_dbus_connection_update_dispatch_status_and_unlock (connection,
DBUS_DISPATCH_NEED_MEMORY);
-
- if (pending)
- dbus_pending_call_unref (pending);
dbus_connection_unref (connection);
return DBUS_DISPATCH_NEED_MEMORY;
HAVE_LOCK_CHECK (connection);
result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
- message);
+ message,
+ &found_object);
CONNECTION_LOCK (connection);
}
reply = dbus_message_new_error (message,
- DBUS_ERROR_UNKNOWN_METHOD,
+ found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT,
_dbus_string_get_const_data (&str));
_dbus_string_free (&str);
* @param user_data data to pass to functions in the vtable
* @param error address where an error can be returned
* @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
- * #DBUS_ERROR_ADDRESS_IN_USE) is reported
+ * #DBUS_ERROR_OBJECT_PATH_IN_USE) is reported
*/
dbus_bool_t
dbus_connection_try_register_object_path (DBusConnection *connection,
* @param path a '/' delimited string of path elements
* @param vtable the virtual table
* @param user_data data to pass to functions in the vtable
- * @returns #FALSE if not enough memory
+ * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
+ * #DBUS_ERROR_OBJECT_PATH_IN_USE) ocurred
*/
dbus_bool_t
dbus_connection_register_object_path (DBusConnection *connection,
dbus_free_string_array (decomposed_path);
- if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
+ if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
{
_dbus_warn ("%s\n", error.message);
dbus_error_free (&error);
* @param user_data data to pass to functions in the vtable
* @param error address where an error can be returned
* @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
- * #DBUS_ERROR_ADDRESS_IN_USE) is reported
+ * #DBUS_ERROR_OBJECT_PATH_IN_USE) is reported
*/
dbus_bool_t
dbus_connection_try_register_fallback (DBusConnection *connection,
* @param path a '/' delimited string of path elements
* @param vtable the virtual table
* @param user_data data to pass to functions in the vtable
- * @returns #FALSE if not enough memory
+ * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
+ * #DBUS_ERROR_OBJECT_PATH_IN_USE) occured
*/
dbus_bool_t
dbus_connection_register_fallback (DBusConnection *connection,
dbus_free_string_array (decomposed_path);
- if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
+ if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
{
_dbus_warn ("%s\n", error.message);
dbus_error_free (&error);
return res;
}
+#ifdef DBUS_ENABLE_STATS
+void
+_dbus_connection_get_stats (DBusConnection *connection,
+ dbus_uint32_t *in_messages,
+ dbus_uint32_t *in_bytes,
+ dbus_uint32_t *in_fds,
+ dbus_uint32_t *in_peak_bytes,
+ dbus_uint32_t *in_peak_fds,
+ dbus_uint32_t *out_messages,
+ dbus_uint32_t *out_bytes,
+ dbus_uint32_t *out_fds,
+ dbus_uint32_t *out_peak_bytes,
+ dbus_uint32_t *out_peak_fds,
+ dbus_uint32_t *link_cache_size)
+{
+ CONNECTION_LOCK (connection);
+
+ if (in_messages != NULL)
+ *in_messages = connection->n_incoming;
+
+ _dbus_transport_get_stats (connection->transport,
+ in_bytes, in_fds, in_peak_bytes, in_peak_fds);
+
+ if (out_messages != NULL)
+ *out_messages = connection->n_outgoing;
+
+ if (out_bytes != NULL)
+ *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
+
+ if (out_fds != NULL)
+ *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
+
+ if (out_peak_bytes != NULL)
+ *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
+
+ if (out_peak_fds != NULL)
+ *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
+
+ if (link_cache_size != NULL)
+ {
+ *link_cache_size = _dbus_list_get_length (&connection->link_cache) * sizeof (DBusList);
+ }
+
+ CONNECTION_UNLOCK (connection);
+}
+#endif /* DBUS_ENABLE_STATS */
+
/**
* Gets the approximate number of uni fds of all messages in the
* outgoing message queue.