]> arthur.barton.de Git - netatalk.git/blobdiff - libevent/evmap.c
Writing metadata xattr on directories with sticky bit set, FR#94
[netatalk.git] / libevent / evmap.c
index 5521626cf2431137f542c94d406801fef2833328..69c1067d89fbcc99f653cfc8c5c2e50a109aab5e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2010 Niels Provos and Nick Mathewson
+ * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -127,7 +127,8 @@ HT_GENERATE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket,
                    },                                                  \
                    {                                                   \
                            _ent = mm_calloc(1,sizeof(struct event_map_entry)+fdinfo_len); \
-                           EVUTIL_ASSERT(_ent);                                \
+                           if (EVUTIL_UNLIKELY(_ent == NULL))          \
+                                   return (-1);                        \
                            _ent->fd = slot;                            \
                            (ctor)(&_ent->ent.type);                    \
                            _HT_FOI_INSERT(map_node, map, &_key, _ent, ptr) \
@@ -148,6 +149,7 @@ void evmap_io_clear(struct event_io_map *ctx)
                next = HT_NEXT_RMV(event_io_map, ctx, ent);
                mm_free(this);
        }
+       HT_CLEAR(event_io_map, ctx); /* remove all storage held by the ctx. */
 }
 #endif
 
@@ -158,15 +160,16 @@ void evmap_io_clear(struct event_io_map *ctx)
        (x) = (struct type *)((map)->entries[slot])
 /* As GET_SLOT, but construct the entry for 'slot' if it is not present,
    by allocating enough memory for a 'struct type', and initializing the new
-   value by calling the function 'ctor' on it.
+   value by calling the function 'ctor' on it.  Makes the function
+   return -1 on allocation failure.
  */
 #define GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \
        do {                                                            \
                if ((map)->entries[slot] == NULL) {                     \
-                       EVUTIL_ASSERT(ctor != NULL);                            \
                        (map)->entries[slot] =                          \
                            mm_calloc(1,sizeof(struct type)+fdinfo_len); \
-                       EVUTIL_ASSERT((map)->entries[slot] != NULL);            \
+                       if (EVUTIL_UNLIKELY((map)->entries[slot] == NULL)) \
+                               return (-1);                            \
                        (ctor)((struct type *)(map)->entries[slot]);    \
                }                                                       \
                (x) = (struct type *)((map)->entries[slot]);            \
@@ -722,3 +725,75 @@ event_changelist_del(struct event_base *base, evutil_socket_t fd, short old, sho
        return (0);
 }
 
+void
+evmap_check_integrity(struct event_base *base)
+{
+#define EVLIST_X_SIGFOUND 0x1000
+#define EVLIST_X_IOFOUND 0x2000
+
+       evutil_socket_t i;
+       struct event *ev;
+       struct event_io_map *io = &base->io;
+       struct event_signal_map *sigmap = &base->sigmap;
+#ifdef EVMAP_USE_HT
+       struct event_map_entry **mapent;
+#endif
+       int nsignals, ntimers, nio;
+       nsignals = ntimers = nio = 0;
+
+       TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
+               EVUTIL_ASSERT(ev->ev_flags & EVLIST_INSERTED);
+               EVUTIL_ASSERT(ev->ev_flags & EVLIST_INIT);
+               ev->ev_flags &= ~(EVLIST_X_SIGFOUND|EVLIST_X_IOFOUND);
+       }
+
+#ifdef EVMAP_USE_HT
+       HT_FOREACH(mapent, event_io_map, io) {
+               struct evmap_io *ctx = &(*mapent)->ent.evmap_io;
+               i = (*mapent)->fd;
+#else
+       for (i = 0; i < io->nentries; ++i) {
+               struct evmap_io *ctx = io->entries[i];
+
+               if (!ctx)
+                       continue;
+#endif
+
+               TAILQ_FOREACH(ev, &ctx->events, ev_io_next) {
+                       EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_IOFOUND));
+                       EVUTIL_ASSERT(ev->ev_fd == i);
+                       ev->ev_flags |= EVLIST_X_IOFOUND;
+                       nio++;
+               }
+       }
+
+       for (i = 0; i < sigmap->nentries; ++i) {
+               struct evmap_signal *ctx = sigmap->entries[i];
+               if (!ctx)
+                       continue;
+
+               TAILQ_FOREACH(ev, &ctx->events, ev_signal_next) {
+                       EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_SIGFOUND));
+                       EVUTIL_ASSERT(ev->ev_fd == i);
+                       ev->ev_flags |= EVLIST_X_SIGFOUND;
+                       nsignals++;
+               }
+       }
+
+       TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
+               if (ev->ev_events & (EV_READ|EV_WRITE)) {
+                       EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_IOFOUND);
+                       --nio;
+               }
+               if (ev->ev_events & EV_SIGNAL) {
+                       EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_SIGFOUND);
+                       --nsignals;
+               }
+       }
+
+       EVUTIL_ASSERT(nio == 0);
+       EVUTIL_ASSERT(nsignals == 0);
+       /* There is no "EVUTIL_ASSERT(ntimers == 0)": eventqueue is only for
+        * pending signals and io events.
+        */
+}