ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libeio/eio.c
(Generate patch)

Comparing libeio/eio.c (file contents):
Revision 1.99 by root, Tue Jul 26 11:07:08 2011 UTC vs.
Revision 1.103 by root, Thu Sep 15 13:20:54 2011 UTC

43 43
44#include "eio.h" 44#include "eio.h"
45#include "ecb.h" 45#include "ecb.h"
46 46
47#ifdef EIO_STACKSIZE 47#ifdef EIO_STACKSIZE
48# define XTHREAD_STACKSIZE EIO_STACKSIZE 48# define X_STACKSIZE EIO_STACKSIZE
49#endif 49#endif
50#include "xthread.h" 50#include "xthread.h"
51 51
52#include <errno.h> 52#include <errno.h>
53#include <stddef.h> 53#include <stddef.h>
105#ifdef _WIN32 105#ifdef _WIN32
106 106
107 #undef PAGESIZE 107 #undef PAGESIZE
108 #define PAGESIZE 4096 /* GetSystemInfo? */ 108 #define PAGESIZE 4096 /* GetSystemInfo? */
109 109
110 /* TODO: look at how perl does stat (non-sloppy), unlink (ro-files), utime, link */
111
110 #ifdef EIO_STRUCT_STATI64 112 #ifdef EIO_STRUCT_STATI64
113 /* look at perl's non-sloppy stat */
111 #define stat(path,buf) _stati64 (path,buf) 114 #define stat(path,buf) _stati64 (path,buf)
112 #define fstat(fd,buf) _fstati64 (fd,buf) 115 #define fstat(fd,buf) _fstati64 (fd,buf)
113 #endif 116 #endif
114 #define lstat(path,buf) stat (path,buf) 117 #define lstat(path,buf) stat (path,buf)
115 #define fsync(fd) (FlushFileBuffers ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd)) ? 0 : EIO_ERRNO (EBADF, -1)) 118 #define fsync(fd) (FlushFileBuffers ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd)) ? 0 : EIO_ERRNO (EBADF, -1))
321static void (*done_poll_cb) (void); 324static void (*done_poll_cb) (void);
322 325
323static unsigned int max_poll_time; /* reslock */ 326static unsigned int max_poll_time; /* reslock */
324static unsigned int max_poll_reqs; /* reslock */ 327static unsigned int max_poll_reqs; /* reslock */
325 328
326static volatile unsigned int nreqs; /* reqlock */ 329static unsigned int nreqs; /* reqlock */
327static volatile unsigned int nready; /* reqlock */ 330static unsigned int nready; /* reqlock */
328static volatile unsigned int npending; /* reqlock */ 331static unsigned int npending; /* reqlock */
329static volatile unsigned int max_idle = 4; /* maximum number of threads that can idle indefinitely */ 332static unsigned int max_idle = 4; /* maximum number of threads that can idle indefinitely */
330static volatile unsigned int idle_timeout = 10; /* number of seconds after which an idle threads exit */ 333static unsigned int idle_timeout = 10; /* number of seconds after which an idle threads exit */
331 334
332static xmutex_t wrklock; 335static xmutex_t wrklock;
333static xmutex_t reslock; 336static xmutex_t reslock;
334static xmutex_t reqlock; 337static xmutex_t reqlock;
335static xcond_t reqwait; 338static xcond_t reqwait;
1703 dirp = FindFirstFile (path, &entp); 1706 dirp = FindFirstFile (path, &entp);
1704 free (path); 1707 free (path);
1705 1708
1706 if (dirp == INVALID_HANDLE_VALUE) 1709 if (dirp == INVALID_HANDLE_VALUE)
1707 { 1710 {
1708 dirp = 0;
1709
1710 /* should steal _dosmaperr */ 1711 /* should steal _dosmaperr */
1711 switch (GetLastError ()) 1712 switch (GetLastError ())
1712 { 1713 {
1713 case ERROR_FILE_NOT_FOUND: 1714 case ERROR_FILE_NOT_FOUND:
1714 req->result = 0; 1715 req->result = 0;
1715 break; 1716 break;
1716 1717
1717 case ERROR_INVALID_NAME: 1718 case ERROR_INVALID_NAME:
1718 case ERROR_PATH_NOT_FOUND: 1719 case ERROR_PATH_NOT_FOUND:
1719 case ERROR_NO_MORE_FILES: 1720 case ERROR_NO_MORE_FILES:
1720 errno = ENOENT; 1721 errno = ENOENT;
1721 break; 1722 break;
1722 1723
1723 case ERROR_NOT_ENOUGH_MEMORY: 1724 case ERROR_NOT_ENOUGH_MEMORY:
1724 errno = ENOMEM; 1725 errno = ENOMEM;
1725 break; 1726 break;
1726 1727
1727 default: 1728 default:
1728 errno = EINVAL; 1729 errno = EINVAL;
1729 break; 1730 break;
1730 } 1731 }
1732
1733 return;
1731 } 1734 }
1732 } 1735 }
1733#else 1736#else
1734 dirp = opendir (req->ptr1); 1737 dirp = opendir (req->ptr1);
1738
1739 if (!dirp)
1740 return;
1735#endif 1741#endif
1736 1742
1737 if (req->flags & EIO_FLAG_PTR1_FREE) 1743 if (req->flags & EIO_FLAG_PTR1_FREE)
1738 free (req->ptr1); 1744 free (req->ptr1);
1739 1745
1740 req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE; 1746 req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE;
1741 req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0; 1747 req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0;
1742 req->ptr2 = names = malloc (namesalloc); 1748 req->ptr2 = names = malloc (namesalloc);
1743 1749
1744 if (dirp && names && (!flags || dents)) 1750 if (!names || (flags && !dents))
1751 return;
1752
1745 for (;;) 1753 for (;;)
1746 { 1754 {
1747 int done; 1755 int done;
1748 1756
1749#ifdef _WIN32 1757#ifdef _WIN32
1750 done = !dirp; 1758 done = !dirp;
1751#else 1759#else
1752 errno = 0; 1760 errno = 0;
1753 entp = readdir (dirp); 1761 entp = readdir (dirp);
1754 done = !entp; 1762 done = !entp;
1755#endif 1763#endif
1756 1764
1757 if (done) 1765 if (done)
1758 { 1766 {
1759#ifndef _WIN32 1767#ifndef _WIN32
1760 int old_errno = errno; 1768 int old_errno = errno;
1761 closedir (dirp); 1769 closedir (dirp);
1762 errno = old_errno; 1770 errno = old_errno;
1763 1771
1764 if (errno) 1772 if (errno)
1765 break; 1773 break;
1766#endif 1774#endif
1767 1775
1768 /* sort etc. */ 1776 /* sort etc. */
1769 req->int1 = flags; 1777 req->int1 = flags;
1770 req->result = dentoffs; 1778 req->result = dentoffs;
1771 1779
1772 if (flags & EIO_READDIR_STAT_ORDER) 1780 if (flags & EIO_READDIR_STAT_ORDER)
1773 eio_dent_sort (dents, dentoffs, flags & EIO_READDIR_DIRS_FIRST ? 7 : 0, inode_bits); 1781 eio_dent_sort (dents, dentoffs, flags & EIO_READDIR_DIRS_FIRST ? 7 : 0, inode_bits);
1774 else if (flags & EIO_READDIR_DIRS_FIRST) 1782 else if (flags & EIO_READDIR_DIRS_FIRST)
1775 if (flags & EIO_READDIR_FOUND_UNKNOWN) 1783 if (flags & EIO_READDIR_FOUND_UNKNOWN)
1776 eio_dent_sort (dents, dentoffs, 7, inode_bits); /* sort by score and inode */ 1784 eio_dent_sort (dents, dentoffs, 7, inode_bits); /* sort by score and inode */
1777 else 1785 else
1786 {
1787 /* in this case, all is known, and we just put dirs first and sort them */
1788 eio_dirent *oth = dents + dentoffs;
1789 eio_dirent *dir = dents;
1790
1791 /* now partition dirs to the front, and non-dirs to the back */
1792 /* by walking from both sides and swapping if necessary */
1793 while (oth > dir)
1794 {
1795 if (dir->type == EIO_DT_DIR)
1796 ++dir;
1797 else if ((--oth)->type == EIO_DT_DIR)
1798 {
1799 eio_dirent tmp = *dir; *dir = *oth; *oth = tmp;
1800
1801 ++dir;
1802 }
1803 }
1804
1805 /* now sort the dirs only (dirs all have the same score) */
1806 eio_dent_sort (dents, dir - dents, 0, inode_bits);
1807 }
1808
1809 break;
1810 }
1811
1812 /* now add the entry to our list(s) */
1813 name = D_NAME (entp);
1814
1815 /* skip . and .. entries */
1816 if (name [0] != '.' || (name [1] && (name [1] != '.' || name [2])))
1817 {
1818 int len = D_NAMLEN (entp) + 1;
1819
1820 while (ecb_expect_false (namesoffs + len > namesalloc))
1821 {
1822 namesalloc *= 2;
1823 req->ptr2 = names = realloc (names, namesalloc);
1824
1825 if (!names)
1826 break;
1827 }
1828
1829 memcpy (names + namesoffs, name, len);
1830
1831 if (dents)
1832 {
1833 struct eio_dirent *ent;
1834
1835 if (ecb_expect_false (dentoffs == dentalloc))
1778 { 1836 {
1779 /* in this case, all is known, and we just put dirs first and sort them */ 1837 dentalloc *= 2;
1838 req->ptr1 = dents = realloc (dents, dentalloc * sizeof (eio_dirent));
1839
1840 if (!dents)
1841 break;
1842 }
1843
1780 eio_dirent *oth = dents + dentoffs; 1844 ent = dents + dentoffs;
1781 eio_dirent *dir = dents;
1782 1845
1783 /* now partition dirs to the front, and non-dirs to the back */ 1846 ent->nameofs = namesoffs; /* rather dirtily we store the offset in the pointer */
1784 /* by walking from both sides and swapping if necessary */ 1847 ent->namelen = len - 1;
1785 while (oth > dir) 1848 ent->inode = D_INO (entp);
1849
1850 inode_bits |= ent->inode;
1851
1852 switch (D_TYPE (entp))
1853 {
1854 default:
1855 ent->type = EIO_DT_UNKNOWN;
1856 flags |= EIO_READDIR_FOUND_UNKNOWN;
1857 break;
1858
1859 #ifdef DT_FIFO
1860 case DT_FIFO: ent->type = EIO_DT_FIFO; break;
1861 #endif
1862 #ifdef DT_CHR
1863 case DT_CHR: ent->type = EIO_DT_CHR; break;
1864 #endif
1865 #ifdef DT_MPC
1866 case DT_MPC: ent->type = EIO_DT_MPC; break;
1867 #endif
1868 #ifdef DT_DIR
1869 case DT_DIR: ent->type = EIO_DT_DIR; break;
1870 #endif
1871 #ifdef DT_NAM
1872 case DT_NAM: ent->type = EIO_DT_NAM; break;
1873 #endif
1874 #ifdef DT_BLK
1875 case DT_BLK: ent->type = EIO_DT_BLK; break;
1876 #endif
1877 #ifdef DT_MPB
1878 case DT_MPB: ent->type = EIO_DT_MPB; break;
1879 #endif
1880 #ifdef DT_REG
1881 case DT_REG: ent->type = EIO_DT_REG; break;
1882 #endif
1883 #ifdef DT_NWK
1884 case DT_NWK: ent->type = EIO_DT_NWK; break;
1885 #endif
1886 #ifdef DT_CMP
1887 case DT_CMP: ent->type = EIO_DT_CMP; break;
1888 #endif
1889 #ifdef DT_LNK
1890 case DT_LNK: ent->type = EIO_DT_LNK; break;
1891 #endif
1892 #ifdef DT_SOCK
1893 case DT_SOCK: ent->type = EIO_DT_SOCK; break;
1894 #endif
1895 #ifdef DT_DOOR
1896 case DT_DOOR: ent->type = EIO_DT_DOOR; break;
1897 #endif
1898 #ifdef DT_WHT
1899 case DT_WHT: ent->type = EIO_DT_WHT; break;
1900 #endif
1901 }
1902
1903 ent->score = 7;
1904
1905 if (flags & EIO_READDIR_DIRS_FIRST)
1906 {
1907 if (ent->type == EIO_DT_UNKNOWN)
1786 { 1908 {
1787 if (dir->type == EIO_DT_DIR) 1909 if (*name == '.') /* leading dots are likely directories, and, in any case, rare */
1788 ++dir; 1910 ent->score = 1;
1789 else if ((--oth)->type == EIO_DT_DIR) 1911 else if (!strchr (name, '.')) /* absense of dots indicate likely dirs */
1790 { 1912 ent->score = len <= 2 ? 4 - len : len <= 4 ? 4 : len <= 7 ? 5 : 6; /* shorter == more likely dir, but avoid too many classes */
1791 eio_dirent tmp = *dir; *dir = *oth; *oth = tmp;
1792
1793 ++dir;
1794 }
1795 } 1913 }
1796 1914 else if (ent->type == EIO_DT_DIR)
1797 /* now sort the dirs only (dirs all have the same score) */ 1915 ent->score = 0;
1798 eio_dent_sort (dents, dir - dents, 0, inode_bits);
1799 } 1916 }
1800
1801 break;
1802 }
1803
1804 /* now add the entry to our list(s) */
1805 name = D_NAME (entp);
1806
1807 /* skip . and .. entries */
1808 if (name [0] != '.' || (name [1] && (name [1] != '.' || name [2])))
1809 {
1810 int len = D_NAMLEN (entp) + 1;
1811
1812 while (ecb_expect_false (namesoffs + len > namesalloc))
1813 {
1814 namesalloc *= 2;
1815 req->ptr2 = names = realloc (names, namesalloc);
1816
1817 if (!names)
1818 break;
1819 } 1917 }
1820 1918
1821 memcpy (names + namesoffs, name, len);
1822
1823 if (dents)
1824 {
1825 struct eio_dirent *ent;
1826
1827 if (ecb_expect_false (dentoffs == dentalloc))
1828 {
1829 dentalloc *= 2;
1830 req->ptr1 = dents = realloc (dents, dentalloc * sizeof (eio_dirent));
1831
1832 if (!dents)
1833 break;
1834 }
1835
1836 ent = dents + dentoffs;
1837
1838 ent->nameofs = namesoffs; /* rather dirtily we store the offset in the pointer */
1839 ent->namelen = len - 1;
1840 ent->inode = D_INO (entp);
1841
1842 inode_bits |= ent->inode;
1843
1844 switch (D_TYPE (entp))
1845 {
1846 default:
1847 ent->type = EIO_DT_UNKNOWN;
1848 flags |= EIO_READDIR_FOUND_UNKNOWN;
1849 break;
1850
1851 #ifdef DT_FIFO
1852 case DT_FIFO: ent->type = EIO_DT_FIFO; break;
1853 #endif
1854 #ifdef DT_CHR
1855 case DT_CHR: ent->type = EIO_DT_CHR; break;
1856 #endif
1857 #ifdef DT_MPC
1858 case DT_MPC: ent->type = EIO_DT_MPC; break;
1859 #endif
1860 #ifdef DT_DIR
1861 case DT_DIR: ent->type = EIO_DT_DIR; break;
1862 #endif
1863 #ifdef DT_NAM
1864 case DT_NAM: ent->type = EIO_DT_NAM; break;
1865 #endif
1866 #ifdef DT_BLK
1867 case DT_BLK: ent->type = EIO_DT_BLK; break;
1868 #endif
1869 #ifdef DT_MPB
1870 case DT_MPB: ent->type = EIO_DT_MPB; break;
1871 #endif
1872 #ifdef DT_REG
1873 case DT_REG: ent->type = EIO_DT_REG; break;
1874 #endif
1875 #ifdef DT_NWK
1876 case DT_NWK: ent->type = EIO_DT_NWK; break;
1877 #endif
1878 #ifdef DT_CMP
1879 case DT_CMP: ent->type = EIO_DT_CMP; break;
1880 #endif
1881 #ifdef DT_LNK
1882 case DT_LNK: ent->type = EIO_DT_LNK; break;
1883 #endif
1884 #ifdef DT_SOCK
1885 case DT_SOCK: ent->type = EIO_DT_SOCK; break;
1886 #endif
1887 #ifdef DT_DOOR
1888 case DT_DOOR: ent->type = EIO_DT_DOOR; break;
1889 #endif
1890 #ifdef DT_WHT
1891 case DT_WHT: ent->type = EIO_DT_WHT; break;
1892 #endif
1893 }
1894
1895 ent->score = 7;
1896
1897 if (flags & EIO_READDIR_DIRS_FIRST)
1898 {
1899 if (ent->type == EIO_DT_UNKNOWN)
1900 {
1901 if (*name == '.') /* leading dots are likely directories, and, in any case, rare */
1902 ent->score = 1;
1903 else if (!strchr (name, '.')) /* absense of dots indicate likely dirs */
1904 ent->score = len <= 2 ? 4 - len : len <= 4 ? 4 : len <= 7 ? 5 : 6; /* shorter == more likely dir, but avoid too many classes */
1905 }
1906 else if (ent->type == EIO_DT_DIR)
1907 ent->score = 0;
1908 }
1909 }
1910
1911 namesoffs += len; 1919 namesoffs += len;
1912 ++dentoffs; 1920 ++dentoffs;
1913 } 1921 }
1914 1922
1915 if (EIO_CANCELLED (req)) 1923 if (EIO_CANCELLED (req))
1916 { 1924 {
1917 errno = ECANCELED; 1925 errno = ECANCELED;
1918 break; 1926 break;
1919 } 1927 }
1920 1928
1921#ifdef _WIN32 1929#ifdef _WIN32
1922 if (!FindNextFile (dirp, &entp)) 1930 if (!FindNextFile (dirp, &entp))
1923 { 1931 {
1924 FindClose (dirp); 1932 FindClose (dirp);
1925 dirp = 0; 1933 dirp = 0;
1926 } 1934 }
1927#endif 1935#endif
1928 } 1936 }
1929} 1937}
1930 1938
1931/*****************************************************************************/ 1939/*****************************************************************************/
1932 1940
1933#define ALLOC(len) \ 1941#define ALLOC(len) \

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines