aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Fernando J. Pereda <ferdy@ferdyx.org> 2008-02-06 23:07:30 +0000
committerAvatar Fernando J. Pereda <ferdy@ferdyx.org> 2008-02-06 23:07:30 +0000
commit2b8ee08102840f125b247b570d69936082453f5f (patch)
treeee624a61e8238df2b36970480f59fa25c5af5053
parent70e7b4d8c51be1aa06bdd6cecb2fc375185bc69a (diff)
downloadpaludis-2b8ee08102840f125b247b570d69936082453f5f.tar.gz
paludis-2b8ee08102840f125b247b570d69936082453f5f.tar.xz
Avoid doing as many stat calls as possible
-rw-r--r--configure.ac19
-rw-r--r--paludis/util/dir_iterator.cc16
-rw-r--r--paludis/util/fs_entry.cc67
-rw-r--r--paludis/util/fs_entry.hh3
4 files changed, 90 insertions, 15 deletions
diff --git a/configure.ac b/configure.ac
index 2fa0ba4..0c968fd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -481,6 +481,25 @@ if test "x$ac_cv_func_canonicalize_file_name" = "xyes"; then
fi
dnl }}}
+dnl {{{ check for dirent.d_type
+AC_MSG_CHECKING([for dirent.d_type])
+AC_COMPILE_IFELSE([
+#include <sys/types.h>
+#include <dirent.h>
+int main(int, char **)
+{
+ struct dirent dent;
+ dent.d_type = DT_LNK;
+}
+],
+ [have_dirent_dtype=yes],
+ [have_dirent_dtype=no])
+AC_MSG_RESULT([$have_dirent_dtype])
+if test "x$have_dirent_dtype" = "xyes"; then
+ AC_DEFINE([HAVE_DIRENT_DTYPE], [1], [Use dirent.d_type])
+fi
+dnl }}}
+
dnl {{{ check for cxxflags
if test x = x"$LET_ME_RICE"
then
diff --git a/paludis/util/dir_iterator.cc b/paludis/util/dir_iterator.cc
index ecc3f87..d001730 100644
--- a/paludis/util/dir_iterator.cc
+++ b/paludis/util/dir_iterator.cc
@@ -29,6 +29,8 @@
#include <cstring>
#include <cerrno>
+#include "config.h"
+
using namespace paludis;
#include <paludis/util/dir_iterator-se.cc>
@@ -88,7 +90,12 @@ DirIterator::DirIterator(const FSEntry & base, const DirIteratorOptions & option
{
if ('.' != de->d_name[0])
{
- _imp->items->insert(std::make_pair(de->d_ino, base / std::string(de->d_name)));
+#ifdef HAVE_DIRENT_DTYPE
+ FSEntry f(stringify(base / std::string(de->d_name)), de->d_type);
+#else
+ FSEntry f(stringify(base / std::string(de->d_name)), 0);
+#endif
+ _imp->items->insert(std::make_pair(de->d_ino, f));
if (options[dio_first_only])
break;
}
@@ -96,7 +103,12 @@ DirIterator::DirIterator(const FSEntry & base, const DirIteratorOptions & option
else if (! (de->d_name[0] == '.' &&
(de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0'))))
{
- _imp->items->insert(std::make_pair(de->d_ino, base / std::string(de->d_name)));
+#ifdef HAVE_DIRENT_DTYPE
+ FSEntry f(stringify(base / std::string(de->d_name)), de->d_type);
+#else
+ FSEntry f(stringify(base / std::string(de->d_name)), 0);
+#endif
+ _imp->items->insert(std::make_pair(de->d_ino, f));
if (options[dio_first_only])
break;
}
diff --git a/paludis/util/fs_entry.cc b/paludis/util/fs_entry.cc
index 6fcc3b1..b03e902 100644
--- a/paludis/util/fs_entry.cc
+++ b/paludis/util/fs_entry.cc
@@ -3,6 +3,7 @@
/*
* Copyright (c) 2005, 2006, 2007 Ciaran McCreesh
* Copyright (c) 2006 Mark Loeser
+ * Copyright (c) 2008 Fernando J. Pereda
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -34,6 +35,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <utime.h>
+#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
@@ -63,6 +65,15 @@ FSError::FSError(const std::string & our_message) throw () :
namespace paludis
{
+ enum CheckedInfo
+ {
+ ifse_none,
+ ifse_exists,
+ ifse_type,
+ ifse_full,
+ ifse_max
+ };
+
template <>
struct Implementation<FSEntry>
{
@@ -71,14 +82,30 @@ namespace paludis
mutable Mutex mutex;
mutable tr1::shared_ptr<struct ::stat> stat_info;
mutable bool exists;
- mutable bool checked;
+ mutable CheckedInfo checked;
Implementation(const std::string & p) :
path(p),
exists(false),
- checked(false)
+ checked(ifse_none)
+ {
+ }
+
+ Implementation(const std::string & p, unsigned char d_type) :
+ path(p),
+ exists(true),
+ checked(ifse_exists)
{
+#ifdef HAVE_DIRENT_DTYPE
+ if (DT_UNKNOWN != d_type)
+ {
+ stat_info.reset(new struct ::stat);
+ stat_info->st_mode = DTTOIF(d_type);
+ checked = ifse_type;
+ }
+#endif
}
+
};
}
@@ -97,6 +124,12 @@ FSEntry::FSEntry(const FSEntry & other) :
_imp->checked = other._imp->checked;
}
+FSEntry::FSEntry(const std::string & path, unsigned char d_type) :
+ PrivateImplementationPattern<FSEntry>(new Implementation<FSEntry>(path, d_type))
+{
+ _normalise();
+}
+
FSEntry::~FSEntry()
{
}
@@ -127,7 +160,7 @@ FSEntry::operator/= (const FSEntry & rhs)
_imp->path.append(rhs._imp->path);
}
- _imp->checked = false;
+ _imp->checked = ifse_none;
_imp->exists = false;
_imp->stat_info.reset();
@@ -155,7 +188,8 @@ FSEntry::operator== (const FSEntry & other) const
bool
FSEntry::exists() const
{
- _stat();
+ if (_imp->checked < ifse_exists)
+ _stat();
return _imp->exists;
}
@@ -163,7 +197,8 @@ FSEntry::exists() const
bool
FSEntry::is_directory() const
{
- _stat();
+ if (_imp->checked < ifse_type)
+ _stat();
if (_imp->exists)
return S_ISDIR((*_imp->stat_info).st_mode);
@@ -174,7 +209,8 @@ FSEntry::is_directory() const
bool
FSEntry::is_directory_or_symlink_to_directory() const
{
- _stat();
+ if (_imp->checked < ifse_type)
+ _stat();
if (_imp->exists)
return S_ISDIR((*_imp->stat_info).st_mode) ||
@@ -186,7 +222,8 @@ FSEntry::is_directory_or_symlink_to_directory() const
bool
FSEntry::is_fifo() const
{
- _stat();
+ if (_imp->checked < ifse_type)
+ _stat();
if (_imp->exists)
return S_ISFIFO((*_imp->stat_info).st_mode);
@@ -197,7 +234,8 @@ FSEntry::is_fifo() const
bool
FSEntry::is_device() const
{
- _stat();
+ if (_imp->checked < ifse_type)
+ _stat();
if (_imp->exists)
return S_ISBLK((*_imp->stat_info).st_mode) || S_ISCHR((*_imp->stat_info).st_mode);
@@ -208,7 +246,8 @@ FSEntry::is_device() const
bool
FSEntry::is_regular_file() const
{
- _stat();
+ if (_imp->checked < ifse_type)
+ _stat();
if (_imp->exists)
return S_ISREG((*_imp->stat_info).st_mode);
@@ -219,7 +258,8 @@ FSEntry::is_regular_file() const
bool
FSEntry::is_regular_file_or_symlink_to_regular_file() const
{
- _stat();
+ if (_imp->checked < ifse_type)
+ _stat();
if (_imp->exists)
return S_ISREG((*_imp->stat_info).st_mode) ||
@@ -231,7 +271,8 @@ FSEntry::is_regular_file_or_symlink_to_regular_file() const
bool
FSEntry::is_symbolic_link() const
{
- _stat();
+ if (_imp->checked < ifse_type)
+ _stat();
if (_imp->exists)
return S_ISLNK((*_imp->stat_info).st_mode);
@@ -351,7 +392,7 @@ void
FSEntry::_stat() const
{
Lock l(_imp->mutex);
- if (_imp->checked)
+ if (_imp->checked == ifse_full)
return;
Context context("When calling stat() on '" + stringify(_imp->path) + "':");
@@ -369,7 +410,7 @@ FSEntry::_stat() const
else
_imp->exists = true;
- _imp->checked = true;
+ _imp->checked = ifse_full;
}
std::string
diff --git a/paludis/util/fs_entry.hh b/paludis/util/fs_entry.hh
index 8efa744..87b9bd0 100644
--- a/paludis/util/fs_entry.hh
+++ b/paludis/util/fs_entry.hh
@@ -75,6 +75,7 @@ namespace paludis
private PrivateImplementationPattern<FSEntry>
{
friend std::ostream & operator<< (std::ostream & s, const FSEntry & f);
+ friend class DirIterator;
private:
void _normalise();
@@ -86,6 +87,8 @@ namespace paludis
*/
void _stat() const;
+ FSEntry(const std::string & path, unsigned char d_type);
+
public:
///\name Basic operations
///\{