Changeset 1130


Ignore:
Timestamp:
02/13/10 20:20:20 (3 years ago)
Author:
rakshasa
Message:
  • Added support for Linux's fallocate and Darwin's fcntl(...,F_PREALLOCATE,...) to preallocate files by default. The 'system.file_allocate' setting will now only be used to indicate you want posix_fallocate called, which may block while it zeros out the file manually.
  • Added 'event.download.hash_failed' and 'event.download.hash_final_failed'.
Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtorrent/configure.ac

    r1120 r1130  
    4747TORRENT_WITH_KQUEUE 
    4848TORRENT_WITHOUT_EPOLL 
     49TORRENT_CHECK_FALLOCATE 
    4950TORRENT_WITH_POSIX_FALLOCATE 
    5051TORRENT_WITH_ADDRESS_SPACE 
  • trunk/libtorrent/scripts/checks.m4

    r1072 r1130  
    158158 
    159159 
     160AC_DEFUN([TORRENT_CHECK_FALLOCATE], [ 
     161  AC_MSG_CHECKING(for fallocate) 
     162 
     163  AC_COMPILE_IFELSE( 
     164    [[#include <fcntl.h> 
     165      int main() { 
     166        fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 0); 
     167        return 0; 
     168      } 
     169    ]], 
     170    [ 
     171      AC_DEFINE(HAVE_FALLOCATE, 1, Linux's fallocate supported.) 
     172      AC_MSG_RESULT(yes) 
     173    ], [ 
     174      AC_MSG_RESULT(no) 
     175    ]) 
     176]) 
     177 
     178 
    160179AC_DEFUN([TORRENT_CHECK_POSIX_FALLOCATE], [ 
    161180  AC_MSG_CHECKING(for posix_fallocate) 
  • trunk/libtorrent/src/data/socket_file.cc

    r939 r1130  
    4242#include <fcntl.h> 
    4343#include <unistd.h> 
     44#include <rak/error_number.h> 
    4445#include <rak/file_stat.h> 
    4546#include <sys/ioctl.h> 
     
    9091} 
    9192 
    92 // Reserve the space on disk if a system call is defined. 'length' 
    93 // of zero indicates to the end of the file. 
    94 #if !defined(USE_XFS) && !defined(USE_POSIX_FALLOCATE) 
    95 #define RESERVE_PARAM __UNUSED 
    96 #else 
    97 #define RESERVE_PARAM 
    98 #endif 
    99  
    100 bool 
    101 SocketFile::reserve(RESERVE_PARAM uint64_t offset, RESERVE_PARAM uint64_t length) { 
    102 #ifdef USE_XFS 
    103   struct xfs_flock64 flock; 
    104  
    105   flock.l_whence = SEEK_SET; 
    106   flock.l_start = offset; 
    107   flock.l_len = length; 
    108  
    109   if (ioctl(m_fd, XFS_IOC_RESVSP64, &flock) >= 0) 
    110     return true; 
    111 #endif 
    112  
    113 #ifdef USE_POSIX_FALLOCATE 
    114   return !posix_fallocate(m_fd, offset, length); 
    115 #else 
    116   return true; 
    117 #endif 
    118 } 
    119  
    120 #undef RESERVE_PARAM 
    121  
    12293uint64_t 
    12394SocketFile::size() const { 
     
    131102 
    132103bool 
    133 SocketFile::set_size(uint64_t size) const { 
     104SocketFile::set_size(uint64_t size, int flags) const { 
    134105  if (!is_open()) 
    135106    throw internal_error("SocketFile::set_size() called on a closed file"); 
    136107 
     108#ifdef HAVE_FALLOCATE 
     109  if (flags & flag_fallocate && fallocate(m_fd, 0, 0, size) == 0) 
     110    return true; 
     111#endif 
     112 
     113#ifdef USE_POSIX_FALLOCATE 
     114  if (flags & flag_fallocate && 
     115      flags & flag_fallocate_blocking && 
     116      posix_fallocate(m_fd, 0, size) == 0) 
     117    return true; 
     118#endif 
     119 
     120#ifdef SYS_DARWIN 
     121  if (flags & flag_fallocate) { 
     122    fstore_t fstore; 
     123    fstore.fst_flags = F_ALLOCATECONTIG; 
     124    fstore.fst_posmode = F_PEOFPOSMODE; 
     125    fstore.fst_offset = 0; 
     126    fstore.fst_length = size; 
     127    fstore.fst_bytesalloc = 0; 
     128 
     129    // Hmm... this shouldn't really be something we fail the set_size 
     130    // on... 
     131    // 
     132    // Yet is somehow fails with ENOSPC... 
     133    if (fcntl(m_fd, F_PREALLOCATE, &fstore) == -1) 
     134      throw internal_error("hack: fcntl failed" + std::string(strerror(errno))); 
     135 
     136    //    fcntl(m_fd, F_PREALLOCATE, &fstore); // Ignore result for now... 
     137  } 
     138#endif 
     139 
    137140  if (ftruncate(m_fd, size) == 0) 
    138141    return true; 
    139  
     142   
    140143  // Use workaround to resize files on vfat. It causes the whole 
    141144  // client to block while it is resizing the files, this really 
     
    145148      write(m_fd, &size, 1) == 1) 
    146149    return true; 
    147    
     150 
    148151  return false; 
    149152} 
  • trunk/libtorrent/src/data/socket_file.h

    r1090 r1130  
    5959  static const int o_nonblock             = O_NONBLOCK; 
    6060 
     61  static const int flag_fallocate          = (1 << 0); 
     62  static const int flag_fallocate_blocking = (1 << 1); 
     63 
    6164  SocketFile() : m_fd(invalid_fd) {} 
    6265  SocketFile(fd_type fd) : m_fd(fd) {} 
    6366 
     67  bool                is_open() const                                   { return m_fd != invalid_fd; } 
     68 
    6469  bool                open(const std::string& path, int prot, int flags, mode_t mode = 0666); 
    65  
    6670  void                close(); 
    6771   
    68   // Reserve the space on disk if a system call is defined. 'length' 
    69   // of zero indicates to the end of the file. (ERRR... nope, set 
    70   // length properly...) 
    71   bool                reserve(uint64_t offset = 0, uint64_t length = 0); 
    72  
    73   bool                is_open() const                                   { return m_fd != invalid_fd; } 
    74  
    7572  uint64_t            size() const; 
    76   bool                set_size(uint64_t s) const; 
     73  bool                set_size(uint64_t s, int flags = 0) const; 
    7774 
    7875  MemoryChunk         create_chunk(uint64_t offset, uint32_t length, int prot, int flags) const; 
  • trunk/libtorrent/src/torrent/data/file.cc

    r1090 r1130  
    169169    return true; 
    170170 
    171   if (!SocketFile(m_fd).set_size(m_size)) 
    172     return false; 
     171  // For now make it so that the fallocate flag indicates if we want 
     172  // to do potentially blocking allocation, while FS supported 
     173  // non-blocking allocation is done always. 
     174  int flags = SocketFile::flag_fallocate; 
    173175 
    174176  if (m_flags & flag_fallocate) 
    175     SocketFile(m_fd).reserve(0, m_size); 
     177    flags |= SocketFile::flag_fallocate_blocking; 
    176178 
    177   return true; 
     179  return SocketFile(m_fd).set_size(m_size, flags); 
    178180} 
    179181 
  • trunk/rtorrent/scripts/checks.m4

    r1027 r1130  
    6262]) 
    6363 
    64  
    6564AC_DEFUN([TORRENT_WITHOUT_EPOLL], [ 
    6665  AC_ARG_WITH(epoll, 
     
    7675 
    7776 
     77AC_DEFUN([TORRENT_CHECK_KQUEUE], [ 
     78  AC_MSG_CHECKING(for kqueue support) 
     79 
     80  AC_LINK_IFELSE( 
     81    [[#include <sys/time.h>  /* Because OpenBSD's sys/event.h fails to compile otherwise. Yeah... */ 
     82      #include <sys/event.h> 
     83      int main() { 
     84        int fd = kqueue(); 
     85        return 0; 
     86      } 
     87    ]], 
     88    [ 
     89      AC_DEFINE(USE_KQUEUE, 1, Use kqueue.) 
     90      AC_MSG_RESULT(yes) 
     91    ], [ 
     92      AC_MSG_RESULT(no) 
     93    ]) 
     94]) 
     95 
     96AC_DEFUN([TORRENT_CHECK_KQUEUE_SOCKET_ONLY], [ 
     97  AC_MSG_CHECKING(whether kqueue supports pipes and ptys) 
     98 
     99  AC_RUN_IFELSE( 
     100    [[#include <fcntl.h> 
     101      #include <stdlib.h> 
     102      #include <unistd.h> 
     103      #include <sys/event.h> 
     104      #include <sys/time.h> 
     105      int main() { 
     106        struct kevent ev[2], ev_out[2]; 
     107        struct timespec ts = { 0, 0 }; 
     108        int pfd[2], pty[2], kfd, n; 
     109        char buffer[9001]; 
     110        if (pipe(pfd) == -1) return 1; 
     111        if (fcntl(pfd[1], F_SETFL, O_NONBLOCK) == -1) return 2; 
     112        while ((n = write(pfd[1], buffer, sizeof(buffer))) == sizeof(buffer)); 
     113        if ((pty[0]=posix_openpt(O_RDWR | O_NOCTTY)) == -1) return 3; 
     114        if ((pty[1]=grantpt(pty[0])) == -1) return 4; 
     115        EV_SET(ev+0, pfd[1], EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, NULL); 
     116        EV_SET(ev+1, pty[1], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL); 
     117        if ((kfd = kqueue()) == -1) return 5; 
     118        if ((n = kevent(kfd, ev, 2, NULL, 0, NULL)) == -1) return 6; 
     119        if (ev_out[0].flags & EV_ERROR) return 7; 
     120        if (ev_out[1].flags & EV_ERROR) return 8; 
     121        read(pfd[0], buffer, sizeof(buffer)); 
     122        if ((n = kevent(kfd, NULL, 0, ev_out, 2, &ts)) < 1) return 9; 
     123        return 0; 
     124      } 
     125    ]], 
     126    [ 
     127      AC_MSG_RESULT(yes) 
     128    ], [ 
     129      AC_DEFINE(KQUEUE_SOCKET_ONLY, 1, kqueue only supports sockets.) 
     130      AC_MSG_RESULT(no) 
     131    ]) 
     132]) 
     133 
    78134AC_DEFUN([TORRENT_WITH_KQUEUE], [ 
    79135  AC_ARG_WITH(kqueue, 
     
    81137    [ 
    82138        if test "$withval" = "yes"; then 
    83             AC_DEFINE(USE_KQUEUE, 1, Enable kqueue.) 
     139          TORRENT_CHECK_KQUEUE 
     140          TORRENT_CHECK_KQUEUE_SOCKET_ONLY 
    84141        fi 
    85142    ]) 
     
    97154    ], [ 
    98155      AC_DEFINE(USE_VARIABLE_FDSET, 1, defined when we allow the use of fd_set's of any size) 
     156    ]) 
     157]) 
     158 
     159 
     160AC_DEFUN([TORRENT_CHECK_FALLOCATE], [ 
     161  AC_MSG_CHECKING(for fallocate) 
     162 
     163  AC_COMPILE_IFELSE( 
     164    [[#include <fcntl.h> 
     165      int main() { 
     166        fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 0); 
     167        return 0; 
     168      } 
     169    ]], 
     170    [ 
     171      AC_DEFINE(HAVE_FALLOCATE, 1, Linux's fallocate supported.) 
     172      AC_MSG_RESULT(yes) 
     173    ], [ 
     174      AC_MSG_RESULT(no) 
    99175    ]) 
    100176]) 
  • trunk/rtorrent/src/command_network.cc

    r1123 r1130  
    494494  // Not really network stuff: 
    495495  ADD_VARIABLE_BOOL  ("handshake_log", false); 
    496   ADD_VARIABLE_STRING("log.tracker", ""); 
    497 } 
     496  rpc::commands.call("system.method.insert", rpc::create_object_list("log.tracker", "string|const", "")); 
     497} 
  • trunk/rtorrent/src/core/download_list.cc

    r1126 r1130  
    439439    download->set_hash_failed(true); 
    440440     
    441     rpc::commands.call_catch("event.download.hash_done", rpc::make_target(download), torrent::Object(), "Download event action failed: "); 
     441    rpc::commands.call_catch("event.download.hash_failed", rpc::make_target(download), torrent::Object(), "Download event action failed: "); 
    442442    return; 
    443443  } 
     
    485485      download->set_message("Hash check on download completion found bad chunks, consider using \"safe_sync\"."); 
    486486      control->core()->push_log("Hash check on download completion found bad chunks, consider using \"safe_sync\"."); 
     487      rpc::commands.call_catch("event.download.hash_final_failed", rpc::make_target(download), torrent::Object(), "Download event action failed: "); 
    487488    } 
    488489     
     
    506507    throw torrent::internal_error("DownloadList::hash_queue(...) hashing already queued."); 
    507508 
    508 //   close_throw(download); 
    509509  // HACK 
    510510  if (download->is_open()) { 
  • trunk/rtorrent/src/main.cc

    r1126 r1130  
    208208       "system.method.insert = event.download.finished,multi\n" 
    209209       "system.method.insert = event.download.hash_done,multi\n" 
     210       "system.method.insert = event.download.hash_failed,multi\n" 
     211       "system.method.insert = event.download.hash_final_failed,multi\n" 
    210212       "system.method.insert = event.download.hash_removed,multi\n" 
    211213       "system.method.insert = event.download.hash_queued,multi\n" 
     
    265267       "view_add = complete\n" 
    266268       "view_filter = complete,d.get_complete=\n" 
    267        "view_filter_on    = complete,event.download.hash_done,event.download.finished\n" 
     269       "view_filter_on    = complete,event.download.hash_done,event.download.hash_failed,event.download.hash_final_failed,event.download.finished\n" 
    268270       "view_sort_new     = complete,less=d.get_state_changed=\n" 
    269271       "view_sort_current = complete,less=d.get_state_changed=\n" 
     
    271273       "view_add = incomplete\n" 
    272274       "view_filter = incomplete,not=$d.get_complete=\n" 
    273        "view_filter_on    = incomplete,event.download.hash_done,event.download.finished\n" 
     275       "view_filter_on    = incomplete,event.download.hash_done,event.download.hash_failed," 
     276       "event.download.hash_final_failed,event.download.finished\n" 
    274277       "view_sort_new     = incomplete,less=d.get_state_changed=\n" 
    275278       "view_sort_current = incomplete,less=d.get_state_changed=\n" 
     
    278281       "view_add = hashing\n" 
    279282       "view_filter = hashing,d.get_hashing=\n" 
    280        "view_filter_on = hashing,event.download.hash_queued,event.download.hash_removed,event.download.hash_done\n" 
     283       "view_filter_on = hashing,event.download.hash_queued,event.download.hash_removed," 
     284       "event.download.hash_done,event.download.hash_failed,event.download.hash_final_failed\n" 
    281285//        "view_sort_new     = hashing,less=d.get_state_changed=\n" 
    282286//        "view_sort_current = hashing,less=d.get_state_changed=\n" 
Note: See TracChangeset for help on using the changeset viewer.