daemon fix and development
[platform/upstream/dbus.git] / dbus / dbus-resources.c
index bfe8a08..80fb55b 100644 (file)
@@ -20,6 +20,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
+
+#include <config.h>
 #include <dbus/dbus-resources.h>
 #include <dbus/dbus-internals.h>
 
@@ -29,7 +31,7 @@
  * @brief DBusCounter and other stuff related to resource limits
  *
  * Types and functions related to tracking resource limits,
- * such as the maximum amount of memory a connection can use
+ * such as the maximum amount of memory/unix fds a connection can use
  * for messages, etc.
  */
 
@@ -53,11 +55,20 @@ struct DBusCounter
 {
   int refcount;  /**< reference count */
 
-  long value;    /**< current counter value */
+  long size_value;       /**< current size counter value */
+  long unix_fd_value;    /**< current unix fd counter value */
+
+#ifdef DBUS_ENABLE_STATS
+  long peak_size_value;     /**< largest ever size counter value */
+  long peak_unix_fd_value;  /**< largest ever unix fd counter value */
+#endif
+
+  long notify_size_guard_value;    /**< call notify function when crossing this size value */
+  long notify_unix_fd_guard_value; /**< call notify function when crossing this unix fd value */
 
-  long notify_guard_value; /**< call notify function when crossing this value */
   DBusCounterNotifyFunction notify_function; /**< notify function */
   void *notify_data; /**< data for notify function */
+  dbus_bool_t notify_pending : 1; /**< TRUE if the guard value has been crossed */
 };
 
 /** @} */  /* end of resource limits internals docs */
@@ -78,17 +89,12 @@ _dbus_counter_new (void)
 {
   DBusCounter *counter;
 
-  counter = dbus_new (DBusCounter, 1);
+  counter = dbus_new0 (DBusCounter, 1);
   if (counter == NULL)
     return NULL;
-  
+
   counter->refcount = 1;
-  counter->value = 0;
 
-  counter->notify_guard_value = 0;
-  counter->notify_function = NULL;
-  counter->notify_data = NULL;
-  
   return counter;
 }
 
@@ -129,66 +135,156 @@ _dbus_counter_unref (DBusCounter *counter)
 }
 
 /**
- * Adjusts the value of the counter by the given
+ * Adjusts the value of the size counter by the given
  * delta which may be positive or negative.
- * Calls the notify function from _dbus_counter_set_notify()
- * if that function has been specified.
+ *
+ * This function may be called with locks held. After calling it, when
+ * any relevant locks are no longer held you must call _dbus_counter_notify().
  *
  * @param counter the counter
- * @param delta value to add to the counter's current value
+ * @param delta value to add to the size counter's current value
+ */
+void
+_dbus_counter_adjust_size (DBusCounter *counter,
+                           long         delta)
+{
+  long old = counter->size_value;
+
+  counter->size_value += delta;
+
+#ifdef DBUS_ENABLE_STATS
+  if (counter->peak_size_value < counter->size_value)
+    counter->peak_size_value = counter->size_value;
+#endif
+
+#if 0
+  _dbus_verbose ("Adjusting counter %ld by %ld = %ld\n",
+                 old, delta, counter->size_value);
+#endif
+
+  if (counter->notify_function != NULL &&
+      ((old < counter->notify_size_guard_value &&
+        counter->size_value >= counter->notify_size_guard_value) ||
+       (old >= counter->notify_size_guard_value &&
+        counter->size_value < counter->notify_size_guard_value)))
+    counter->notify_pending = TRUE;
+}
+
+/**
+ * Calls the notify function from _dbus_counter_set_notify(),
+ * if that function has been specified and the counter has crossed the
+ * guard value (in either direction) since the last call to this function.
+ *
+ * This function must not be called with locks held, since it can call out
+ * to user code.
  */
 void
-_dbus_counter_adjust (DBusCounter *counter,
-                      long         delta)
+_dbus_counter_notify (DBusCounter *counter)
 {
-  long old = counter->value;
+  if (counter->notify_pending)
+    {
+      counter->notify_pending = FALSE;
+      (* counter->notify_function) (counter, counter->notify_data);
+    }
+}
+
+/**
+ * Adjusts the value of the unix fd counter by the given
+ * delta which may be positive or negative.
+ *
+ * This function may be called with locks held. After calling it, when
+ * any relevant locks are no longer held you must call _dbus_counter_notify().
+ *
+ * @param counter the counter
+ * @param delta value to add to the unix fds counter's current value
+ */
+void
+_dbus_counter_adjust_unix_fd (DBusCounter *counter,
+                              long         delta)
+{
+  long old = counter->unix_fd_value;
   
-  counter->value += delta;
+  counter->unix_fd_value += delta;
+
+#ifdef DBUS_ENABLE_STATS
+  if (counter->peak_unix_fd_value < counter->unix_fd_value)
+    counter->peak_unix_fd_value = counter->unix_fd_value;
+#endif
 
 #if 0
   _dbus_verbose ("Adjusting counter %ld by %ld = %ld\n",
-                 old, delta, counter->value);
+                 old, delta, counter->unix_fd_value);
 #endif
   
   if (counter->notify_function != NULL &&
-      ((old < counter->notify_guard_value &&
-        counter->value >= counter->notify_guard_value) ||
-       (old >= counter->notify_guard_value &&
-        counter->value < counter->notify_guard_value)))
-    (* counter->notify_function) (counter, counter->notify_data);
+      ((old < counter->notify_unix_fd_guard_value &&
+        counter->unix_fd_value >= counter->notify_unix_fd_guard_value) ||
+       (old >= counter->notify_unix_fd_guard_value &&
+        counter->unix_fd_value < counter->notify_unix_fd_guard_value)))
+    counter->notify_pending = TRUE;
 }
 
 /**
- * Gets the current value of the counter.
+ * Gets the current value of the size counter.
  *
  * @param counter the counter
- * @returns its current value
+ * @returns its current size value
  */
 long
-_dbus_counter_get_value (DBusCounter *counter)
+_dbus_counter_get_size_value (DBusCounter *counter)
 {
-  return counter->value;
+  return counter->size_value;
+}
+
+/**
+ * Gets the current value of the unix fd counter.
+ *
+ * @param counter the counter
+ * @returns its current unix fd value
+ */
+long
+_dbus_counter_get_unix_fd_value (DBusCounter *counter)
+{
+  return counter->unix_fd_value;
 }
 
 /**
  * Sets the notify function for this counter; the notify function is
- * called whenever the counter's value crosses the guard value in
+ * called whenever the counter's values cross the guard values in
  * either direction (moving up, or moving down).
  *
  * @param counter the counter
- * @param guard_value the value we're notified if the counter crosses
+ * @param size_guard_value the value we're notified if the size counter crosses
+ * @param unix_fd_guard_value the value we're notified if the unix fd counter crosses
  * @param function function to call in order to notify
  * @param user_data data to pass to the function
  */
 void
 _dbus_counter_set_notify (DBusCounter               *counter,
-                          long                       guard_value,
+                          long                       size_guard_value,
+                          long                       unix_fd_guard_value,
                           DBusCounterNotifyFunction  function,
                           void                      *user_data)
 {
-  counter->notify_guard_value = guard_value;
+  counter->notify_size_guard_value = size_guard_value;
+  counter->notify_unix_fd_guard_value = unix_fd_guard_value;
   counter->notify_function = function;
   counter->notify_data = user_data;
+  counter->notify_pending = FALSE;
 }
 
+#ifdef DBUS_ENABLE_STATS
+long
+_dbus_counter_get_peak_size_value (DBusCounter *counter)
+{
+  return counter->peak_size_value;
+}
+
+long
+_dbus_counter_get_peak_unix_fd_value (DBusCounter *counter)
+{
+  return counter->peak_unix_fd_value;
+}
+#endif
+
 /** @} */  /* end of resource limits exported API */