Refactor code out of nscd's two main poll loops.

We refactor the inotify file checking code and the
database clearing code out of the main_loop_poll and
mail_loop_epoll functions. We document some the related
functions with appropriate comments.
This commit is contained in:
Carlos O'Donell 2013-02-07 14:28:53 -05:00
parent b2d3c3befb
commit 471514d39d
2 changed files with 93 additions and 65 deletions

View File

@ -1,3 +1,13 @@
2013-02-08 Carlos O'Donell <carlos@redhat.com>
* nscd/connection.c (register_traced_file): Comment function.
[HAVE_INOTIFY] (union __inev): Define.
[HAVE_INOTIFY] (inotify_check_files): New function.
[HAVE_INOTIFY] (clear_db_cache): Likewise.
[HAVE_INOTIFY] (main_loop_poll): Call inotify_check_files and
clear_db_cache.
[HAVE_INOTIFY] (main_loop_epoll): Likewise.
2013-02-08 Carlos O'Donell <carlos@redhat.com>
* elf/dl-cache.c (_dl_load_cache_lookup): Comment that cache is

View File

@ -976,9 +976,25 @@ cannot change socket to nonblocking mode: %s"),
}
/* Register the file in FINFO as a traced file for the database DBS[DBIX].
We support registering multiple files per database. Each call to
register_traced_file adds to the list of registered files.
When we prune the database, either through timeout or a request to
invalidate, we will check to see if any of the registered files has changed.
When we accept new connections to handle a cache request we will also
check to see if any of the registered files has changed.
If we have inotify support then we install an inotify fd to notify us of
file deletion or modification, both of which will require we invalidate
the cache for the database. Without inotify support we stat the file and
store st_mtime to determine if the file has been modified. */
void
register_traced_file (size_t dbidx, struct traced_file *finfo)
{
/* If the database is disabled or file checking is disabled
then ignore the registration. */
if (! dbs[dbidx].enabled || ! dbs[dbidx].check_file)
return;
@ -1870,6 +1886,63 @@ restart_p (time_t now)
/* Array for times a connection was accepted. */
static time_t *starttime;
#ifdef HAVE_INOTIFY
/* Inotify event for changed file. */
union __inev
{
struct inotify_event i;
# ifndef PATH_MAX
# define PATH_MAX 1024
# endif
char buf[sizeof (struct inotify_event) + PATH_MAX];
};
/* Process the inotify event in INEV. If the event matches any of the files
registered with a database then mark that database as requiring its cache
to be cleared. We indicate the cache needs clearing by setting
TO_CLEAR[DBCNT] to true for the matching database. */
static inline void
inotify_check_files (bool *to_clear, union __inev *inev)
{
/* Check which of the files changed. */
for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
{
struct traced_file *finfo = dbs[dbcnt].traced_files;
while (finfo != NULL)
{
/* Inotify event watch descriptor matches. */
if (finfo->inotify_descr == inev->i.wd)
{
/* Mark cache as needing to be cleared and reinitialize. */
to_clear[dbcnt] = true;
if (finfo->call_res_init)
res_init ();
return;
}
finfo = finfo->next;
}
}
}
/* If an entry in the array of booleans TO_CLEAR is TRUE then clear the cache
for the associated database, otherwise do nothing. The TO_CLEAR array must
have LASTDB entries. */
static inline void
clear_db_cache (bool *to_clear)
{
for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
if (to_clear[dbcnt])
{
pthread_mutex_lock (&dbs[dbcnt].prune_lock);
dbs[dbcnt].clear_cache = 1;
pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
pthread_cond_signal (&dbs[dbcnt].prune_cond);
}
}
#endif
static void
__attribute__ ((__noreturn__))
@ -1976,15 +2049,10 @@ main_loop_poll (void)
if (conns[1].revents != 0)
{
bool to_clear[lastdb] = { false, };
union
{
# ifndef PATH_MAX
# define PATH_MAX 1024
# endif
struct inotify_event i;
char buf[sizeof (struct inotify_event) + PATH_MAX];
} inev;
union __inev inev;
/* Read all inotify events for files registered via
register_traced_file(). */
while (1)
{
ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
@ -2010,35 +2078,11 @@ disabled inotify after read error %d"),
}
/* Check which of the files changed. */
for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
{
struct traced_file *finfo = dbs[dbcnt].traced_files;
while (finfo != NULL)
{
if (finfo->inotify_descr == inev.i.wd)
{
to_clear[dbcnt] = true;
if (finfo->call_res_init)
res_init ();
goto next;
}
finfo = finfo->next;
}
}
next:;
inotify_check_files (to_clear, &inev);
}
/* Actually perform the cache clearing. */
for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
if (to_clear[dbcnt])
{
pthread_mutex_lock (&dbs[dbcnt].prune_lock);
dbs[dbcnt].clear_cache = 1;
pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
pthread_cond_signal (&dbs[dbcnt].prune_cond);
}
clear_db_cache (to_clear);
--n;
}
@ -2208,12 +2252,10 @@ main_loop_epoll (int efd)
else if (revs[cnt].data.fd == inotify_fd)
{
bool to_clear[lastdb] = { false, };
union
{
struct inotify_event i;
char buf[sizeof (struct inotify_event) + PATH_MAX];
} inev;
union __inev inev;
/* Read all inotify events for files registered via
register_traced_file(). */
while (1)
{
ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
@ -2235,35 +2277,11 @@ main_loop_epoll (int efd)
}
/* Check which of the files changed. */
for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
{
struct traced_file *finfo = dbs[dbcnt].traced_files;
while (finfo != NULL)
{
if (finfo->inotify_descr == inev.i.wd)
{
to_clear[dbcnt] = true;
if (finfo->call_res_init)
res_init ();
goto next;
}
finfo = finfo->next;
}
}
next:;
inotify_check_files(to_clear, &inev);
}
/* Actually perform the cache clearing. */
for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
if (to_clear[dbcnt])
{
pthread_mutex_lock (&dbs[dbcnt].prune_lock);
dbs[dbcnt].clear_cache = 1;
pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
pthread_cond_signal (&dbs[dbcnt].prune_cond);
}
clear_db_cache (to_clear);
}
# endif
# ifdef HAVE_NETLINK