~ubuntu-branches/ubuntu/maverick/libtorrent-rasterbar/maverick

« back to all changes in this revision

Viewing changes to src/file_pool.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christophe Sauthier
  • Date: 2010-08-10 12:59:37 UTC
  • mfrom: (1.3.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20100810125937-jbcmmf17y8yo9hgz
Tags: 0.15.0-0ubuntu1
* New upstream version.
* debian/patches/100_fix_html_docs.patch: refreshed.
* debian/control: bump up standards-version to 3.9.1 (no changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
*/
32
32
 
33
33
#include <boost/version.hpp>
 
34
#include <boost/bind.hpp>
34
35
#include "libtorrent/pch.hpp"
35
36
#include "libtorrent/file_pool.hpp"
36
37
#include "libtorrent/error_code.hpp"
37
38
 
38
 
#include <iostream>
39
 
 
40
39
namespace libtorrent
41
40
{
42
 
        using boost::multi_index::nth_index;
43
 
        using boost::multi_index::get;
44
 
 
45
41
        boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
46
 
                , file::open_mode m, error_code& ec)
 
42
                , int m, error_code& ec)
47
43
        {
48
44
                TORRENT_ASSERT(st != 0);
49
45
                TORRENT_ASSERT(p.is_complete());
50
 
                TORRENT_ASSERT(m == file::in || m == (file::in | file::out));
 
46
                TORRENT_ASSERT((m & file::rw_mask) == file::read_only
 
47
                        || (m & file::rw_mask) == file::read_write);
51
48
                boost::mutex::scoped_lock l(m_mutex);
52
 
                typedef nth_index<file_set, 0>::type path_view;
53
 
                path_view& pt = get<0>(m_files);
54
 
                path_view::iterator i = pt.find(p);
55
 
                if (i != pt.end())
 
49
                file_set::iterator i = m_files.find(p.string());
 
50
                if (i != m_files.end())
56
51
                {
57
 
                        lru_file_entry e = *i;
 
52
                        lru_file_entry& e = i->second;
58
53
                        e.last_use = time_now();
59
54
 
60
 
                        if (e.key != st && (e.mode != file::in
61
 
                                || m != file::in))
 
55
                        if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
 
56
                                || (m & file::rw_mask) != file::read_only))
62
57
                        {
63
58
                                // this means that another instance of the storage
64
59
                                // is using the exact same file.
65
60
#if BOOST_VERSION >= 103500
66
 
                                ec = error_code(errors::file_collision, libtorrent_category);
 
61
                                ec = errors::file_collision;
67
62
#endif
68
63
                                return boost::shared_ptr<file>();
69
64
                        }
70
65
 
71
66
                        e.key = st;
72
 
                        if ((e.mode & m) != m)
 
67
                        // if we asked for a file in write mode,
 
68
                        // and the cached file is is not opened in
 
69
                        // write mode, re-open it
 
70
 
 
71
                        if ((((e.mode & file::rw_mask) != file::read_write)
 
72
                                && ((m & file::rw_mask) == file::read_write))
 
73
                                || (e.mode & file::no_buffer) != (m & file::no_buffer))
73
74
                        {
74
75
                                // close the file before we open it with
75
76
                                // the new read/write privilages
76
 
                                i->file_ptr.reset();
77
77
                                TORRENT_ASSERT(e.file_ptr.unique());
78
78
                                e.file_ptr->close();
79
79
                                if (!e.file_ptr->open(p, m, ec))
81
81
                                        m_files.erase(i);
82
82
                                        return boost::shared_ptr<file>();
83
83
                                }
 
84
#ifdef TORRENT_WINDOWS
 
85
// file prio is supported on vista and up
 
86
#if _WIN32_WINNT >= 0x0600
 
87
                                if (m_low_prio_io)
 
88
                                {
 
89
                                        FILE_IO_PRIORITY_HINT_INFO priorityHint;
 
90
                                        priorityHint.PriorityHint = IoPriorityHintLow;
 
91
                                        SetFileInformationByHandle(e.file_ptr->native_handle(),
 
92
                                                FileIoPriorityHintInfo, &priorityHint, sizeof(PriorityHint));
 
93
                                }
 
94
#endif
 
95
#endif
84
96
                                TORRENT_ASSERT(e.file_ptr->is_open());
85
97
                                e.mode = m;
86
98
                        }
87
 
                        pt.replace(i, e);
 
99
                        TORRENT_ASSERT((e.mode & file::no_buffer) == (m & file::no_buffer));
88
100
                        return e.file_ptr;
89
101
                }
90
102
                // the file is not in our cache
92
104
                {
93
105
                        // the file cache is at its maximum size, close
94
106
                        // the least recently used (lru) file from it
95
 
                        typedef nth_index<file_set, 1>::type lru_view;
96
 
                        lru_view& lt = get<1>(m_files);
97
 
                        lru_view::iterator i = lt.begin();
98
 
                        // the first entry in this view is the least recently used
99
 
                        TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
100
 
                        lt.erase(i);
 
107
                        remove_oldest();
101
108
                }
102
109
                lru_file_entry e;
103
110
                e.file_ptr.reset(new (std::nothrow)file);
110
117
                        return boost::shared_ptr<file>();
111
118
                e.mode = m;
112
119
                e.key = st;
113
 
                e.file_path = p;
114
 
                pt.insert(e);
 
120
                m_files.insert(std::make_pair(p.string(), e));
115
121
                TORRENT_ASSERT(e.file_ptr->is_open());
116
122
                return e.file_ptr;
117
123
        }
118
124
 
 
125
        void file_pool::remove_oldest()
 
126
        {
 
127
                file_set::iterator i = std::min_element(m_files.begin(), m_files.end()
 
128
                        , boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _1))
 
129
                                < boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _2)));
 
130
                if (i == m_files.end()) return;
 
131
                m_files.erase(i);
 
132
        }
 
133
 
119
134
        void file_pool::release(fs::path const& p)
120
135
        {
121
136
                boost::mutex::scoped_lock l(m_mutex);
122
137
 
123
 
                typedef nth_index<file_set, 0>::type path_view;
124
 
                path_view& pt = get<0>(m_files);
125
 
                path_view::iterator i = pt.find(p);
126
 
                if (i != pt.end()) pt.erase(i);
 
138
                file_set::iterator i = m_files.find(p.string());
 
139
                if (i != m_files.end()) m_files.erase(i);
127
140
        }
128
141
 
 
142
        // closes files belonging to the specified
 
143
        // storage. If 0 is passed, all files are closed
129
144
        void file_pool::release(void* st)
130
145
        {
131
146
                boost::mutex::scoped_lock l(m_mutex);
132
 
                TORRENT_ASSERT(st != 0);
133
 
                using boost::tie;
134
 
 
135
 
                typedef nth_index<file_set, 2>::type key_view;
136
 
                key_view& kt = get<2>(m_files);
137
 
 
138
 
                key_view::iterator start, end;
139
 
                tie(start, end) = kt.equal_range(st);
140
 
                kt.erase(start, end);
 
147
                if (st == 0)
 
148
                {
 
149
                        m_files.clear();
 
150
                        return;
 
151
                }
 
152
 
 
153
                for (file_set::iterator i = m_files.begin();
 
154
                        i != m_files.end();)
 
155
                {
 
156
                        if (i->second.key == st)
 
157
                                m_files.erase(i++);
 
158
                        else
 
159
                                ++i;
 
160
                }
141
161
        }
142
162
 
143
163
        void file_pool::resize(int size)
149
169
                if (int(m_files.size()) <= m_size) return;
150
170
 
151
171
                // close the least recently used files
152
 
                typedef nth_index<file_set, 1>::type lru_view;
153
 
                lru_view& lt = get<1>(m_files);
154
 
                lru_view::iterator i = lt.begin();
155
172
                while (int(m_files.size()) > m_size)
156
 
                {
157
 
                        // the first entry in this view is the least recently used
158
 
                        TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
159
 
                        lt.erase(i++);
160
 
                }
 
173
                        remove_oldest();
161
174
        }
162
175
 
163
176
}