annotate foosdk/sdk/foobar2000/helpers/readers.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #include "StdAfx.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2 #include "readers.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include "readers_lite.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 #include "fullFileBuffer.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 #include "fileReadAhead.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 #include <SDK/file_info_impl.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 #include <list>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 #include <memory>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 #include <pfc/event_std.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 t_size reader_membuffer_base::read(void * p_buffer, t_size p_bytes, abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 t_size max = get_buffer_size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 if (max < m_offset) uBugCheck();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 max -= m_offset;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 t_size delta = p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 if (delta > max) delta = max;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 memcpy(p_buffer, (char*)get_buffer() + m_offset, delta);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 m_offset += delta;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 return delta;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 void reader_membuffer_base::seek(t_filesize position, abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 t_filesize max = get_buffer_size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 if (position == filesize_invalid || position > max) throw exception_io_seek_out_of_range();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 m_offset = (t_size)position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 file::ptr fullFileBuffer::open(const char * path, abort_callback & abort, file::ptr hint, t_filesize sizeMax) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 //mutexScope scope(hMutex, abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 file::ptr f;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 if (hint.is_valid()) f = hint;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 else filesystem::g_open_read(f, path, abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 if (sizeMax != filesize_invalid) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 t_filesize fs = f->get_size(abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 if (fs > sizeMax) return f;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 try {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 service_ptr_t<reader_bigmem_mirror> r = new service_impl_t<reader_bigmem_mirror>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 r->init(f, abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 f = r;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 catch (std::bad_alloc const &) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 return f;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 #include <memory>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 #include <exception>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 #include <pfc/synchro.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 #include <pfc/threads.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 namespace {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 struct dynInfoEntry_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 file_info_impl m_info;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 t_filesize m_offset;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 struct readAheadInstance_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 file::ptr m_file;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 size_t m_readAhead, m_wakeUpThreschold;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 pfc::array_t<uint8_t> m_buffer;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 size_t m_bufferBegin, m_bufferEnd;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 pfc::event m_canRead;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 pfc::event_std m_canWrite;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 pfc::mutex m_guard;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 std::exception_ptr m_error;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 t_filesize m_seekto;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 abort_callback_impl m_abort;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 bool m_remote;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 bool m_atEOF = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 bool m_haveDynamicInfo;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 std::list<dynInfoEntry_t> m_dynamicInfo;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 typedef std::shared_ptr<readAheadInstance_t> readAheadInstanceRef;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 static constexpr t_filesize seek_reopen = (filesize_invalid-1);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 class fileReadAhead : public file_readonly_t< service_multi_inherit< service_multi_inherit<file_v2, file_dynamicinfo_v2 >, stream_receive > > {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 service_ptr m_metadata;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 readAheadInstanceRef m_instance;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 ~fileReadAhead() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 if ( m_instance ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 auto & i = *m_instance;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 pfc::mutexScope guard( i.m_guard );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 i.m_abort.set();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 i.m_canWrite.set_state(true);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 service_ptr get_metadata(abort_callback&) override { return m_metadata; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 void initialize( file::ptr chain, size_t readAhead, abort_callback & aborter ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 m_metadata = chain->get_metadata_(aborter);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 m_stats = chain->get_stats2_( stats2_all, aborter );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 if (!chain->get_content_type(m_contentType)) m_contentType = "";
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 m_canSeek = chain->can_seek();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 m_position = chain->get_position( aborter );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 auto i = std::make_shared<readAheadInstance_t>();;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 i->m_file = chain;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 i->m_remote = chain->is_remote();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 i->m_readAhead = readAhead;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 i->m_wakeUpThreschold = readAhead * 3 / 4;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 i->m_buffer.set_size_discard( readAhead * 2 );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 i->m_bufferBegin = 0; i->m_bufferEnd = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 i->m_canWrite.set_state(true);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 i->m_seekto = filesize_invalid;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 m_instance = i;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 file_dynamicinfo::ptr dyn;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 if (dyn &= chain) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 m_haveStaticInfo = dyn->get_static_info(m_staticInfo);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 i->m_haveDynamicInfo = dyn->is_dynamic_info_enabled();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 fb2k::splitTask( [i] {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 #ifdef PFC_SET_THREAD_DESCRIPTION
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 PFC_SET_THREAD_DESCRIPTION("Fb2k Read-Ahead Thread");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 worker(*i);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 } );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 t_size receive(void* p_buffer, t_size p_bytes, abort_callback& p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 return read_internal(p_buffer, p_bytes, p_abort, true);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142 t_size read(void* p_buffer, t_size p_bytes, abort_callback& p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 return read_internal(p_buffer, p_bytes, p_abort, false);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 t_size read_internal(void * p_buffer,t_size p_bytes,abort_callback & p_abort, bool bReceive) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 auto & i = * m_instance;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 size_t done = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 bool initial = true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 while( bReceive ? done == 0 : done < p_bytes ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 if ( !initial ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 // Do not invoke waiting with common case read with lots of data in the buffer
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 pfc::event::g_twoEventWait( i.m_canRead.get_handle(), p_abort.get_abort_event(), -1);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 p_abort.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 pfc::mutexScope guard ( i.m_guard );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156 size_t got = i.m_bufferEnd - i.m_bufferBegin;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 if (got == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 if (i.m_error) std::rethrow_exception(i.m_error);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 if ( initial && ! i.m_atEOF ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 initial = false; continue; // proceed to wait for more data
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 break; // EOF
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165 size_t delta = pfc::min_t<size_t>( p_bytes - done, got );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 const bool wakeUpBefore = got < i.m_wakeUpThreschold;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169 auto bufptr = i.m_buffer.get_ptr();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 if ( p_buffer != nullptr ) memcpy( (uint8_t*) p_buffer + done, bufptr + i.m_bufferBegin, delta );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 done += delta;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 i.m_bufferBegin += delta;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173 got -= delta;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 m_position += delta;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176 if (!i.m_error && !i.m_atEOF) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177 if ( got == 0 ) i.m_canRead.set_state( false );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
178 const bool wakeUpNow = got < i.m_wakeUpThreschold;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
179 // Only set the event when *crossing* the boundary
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180 // we will get a lot of wakeUpNow when nearing EOF
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181 if ( wakeUpNow && ! wakeUpBefore ) i.m_canWrite.set_state( true );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183 initial = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184 if ( i.m_atEOF ) break; // go no further
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186 // FB2K_console_formatter() << "ReadAhead read: " << p_bytes << " => " << done;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187 return done;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189 t_filesize get_size(abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190 p_abort.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 return m_stats.m_size;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193 t_filesize get_position(abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194 p_abort.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 return m_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198 void seek(t_filesize p_position,abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199 p_abort.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200 if (!m_canSeek) throw exception_io_object_not_seekable();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201 if ( m_stats.m_size != filesize_invalid && p_position > m_stats.m_size ) throw exception_io_seek_out_of_range();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203 auto posNow = get_position(p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205 if ( p_position >= posNow && p_position < posNow + m_instance->m_readAhead ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206 // FB2K_console_formatter() << "ReadAhead skip: " << posNow << " => " << p_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207 auto toSkip = p_position - posNow;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208 if ( toSkip > 0 ) read(nullptr, (size_t) toSkip, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
211 // FB2K_console_formatter() << "ReadAhead seek: " << posNow << " => " << p_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
212
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213 seekInternal( p_position );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215 bool can_seek() override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216 return m_canSeek;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218 bool get_content_type(pfc::string_base & p_out) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 if (m_contentType.length() == 0) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220 p_out = m_contentType; return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222 t_filestats2 get_stats2( uint32_t, abort_callback & p_abort ) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223 p_abort.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224 return m_stats;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227 bool is_remote() override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 return m_instance->m_remote;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 void reopen( abort_callback & p_abort ) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232 if ( get_position( p_abort ) == 0 ) return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233 seekInternal( seek_reopen );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236 bool get_static_info(class file_info & p_out) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237 if ( ! m_haveStaticInfo ) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 mergeInfo(p_out, m_staticInfo);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
241 bool is_dynamic_info_enabled() override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
242 return m_instance->m_haveDynamicInfo;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245 static void mergeInfo( file_info & out, const file_info & in ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246 out.copy_meta(in);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247 out.overwrite_info(in);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249 bool get_dynamic_info_v2(class file_info & out, t_filesize & outOffset) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250 auto & i = * m_instance;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 if ( ! i.m_haveDynamicInfo ) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
253 insync( i.m_guard );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
254 auto ptr = i.m_dynamicInfo.begin();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255 for ( ;; ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256 if ( ptr == i.m_dynamicInfo.end() ) break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257 if ( ptr->m_offset > m_position ) break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258 ++ ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261 if ( ptr == i.m_dynamicInfo.begin() ) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263 auto iter = ptr; --iter;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264 mergeInfo(out, iter->m_info);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265 outOffset = iter->m_offset;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266 i.m_dynamicInfo.erase( i.m_dynamicInfo.begin(), ptr );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271 void seekInternal( t_filesize p_position ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272 auto & i = * m_instance;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273 insync( i.m_guard );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
274 if (i.m_error) std::rethrow_exception(i.m_error);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
275 i.m_bufferBegin = i.m_bufferEnd = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276 i.m_canWrite.set_state(true);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277 i.m_seekto = p_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278 i.m_atEOF = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279 i.m_canRead.set_state(false);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281 m_position = ( p_position == seek_reopen ) ? 0 : p_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
282 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
283 static void worker( readAheadInstance_t & i ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
284 try {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
285 bool atEOF = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
286 uint8_t* bufptr = i.m_buffer.get_ptr();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
287 const size_t readAtOnceLimit = i.m_remote ? 64*1024 : 256 * 1024;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
288 for ( ;; ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
289 i.m_canWrite.wait_for(-1);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
290 size_t readHowMuch = 0, readOffset = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
291 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
292 pfc::mutexScope guard(i.m_guard);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
293 i.m_abort.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
294 if ( i.m_seekto != filesize_invalid ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
295 if ( i.m_seekto == seek_reopen ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
296 i.m_file->reopen( i.m_abort );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
297 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
298 i.m_file->seek( i.m_seekto, i.m_abort );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
299 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
300
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
301 i.m_seekto = filesize_invalid;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
302 atEOF = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
303 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
304 size_t got = i.m_bufferEnd - i.m_bufferBegin;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
305
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
306 if ( i.m_bufferBegin >= i.m_readAhead ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
307 memmove( bufptr, bufptr + i.m_bufferBegin, got );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
308 i.m_bufferBegin = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
309 i.m_bufferEnd = got;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
310 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
311
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
312 if ( got < i.m_readAhead ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
313 readHowMuch = i.m_readAhead - got;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
314 readOffset = i.m_bufferEnd;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
315 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
316 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
317
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
318 if ( readHowMuch > readAtOnceLimit ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
319 readHowMuch = readAtOnceLimit;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
320 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
321
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
322 bool dynInfoGot = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
323 dynInfoEntry_t dynInfo;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
324
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
325 if ( readHowMuch > 0 ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
326 readHowMuch = i.m_file->receive( bufptr + readOffset, readHowMuch, i.m_abort );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
327
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
328 if ( readHowMuch == 0 ) atEOF = true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
329
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
330 if ( i.m_haveDynamicInfo ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
331 file_dynamicinfo::ptr dyn;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
332 if ( dyn &= i.m_file ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
333 file_dynamicinfo_v2::ptr dyn2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
334 if ( dyn2 &= dyn ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
335 dynInfoGot = dyn2->get_dynamic_info_v2(dynInfo.m_info, dynInfo.m_offset);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
336 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
337 dynInfoGot = dyn->get_dynamic_info( dynInfo.m_info );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
338 if (dynInfoGot) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
339 dynInfo.m_offset = dyn->get_position( i.m_abort );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
340 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
341 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
342 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
343 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
344 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
345
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
346 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
347 pfc::mutexScope guard( i.m_guard );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
348 i.m_abort.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
349 if ( i.m_seekto != filesize_invalid ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
350 // Seek request happened while we were reading - discard and continue
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
351 continue;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
352 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
353 i.m_atEOF = atEOF;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
354 i.m_canRead.set_state( true );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
355 i.m_bufferEnd += readHowMuch;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
356 size_t got = i.m_bufferEnd - i.m_bufferBegin;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
357 if ( atEOF || got >= i.m_readAhead ) i.m_canWrite.set_state(false);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
358
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
359 if ( dynInfoGot ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
360 i.m_dynamicInfo.push_back( std::move(dynInfo) );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
361 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
362
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
363 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
364 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
365 } catch (...) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
366 pfc::mutexScope guard(i.m_guard);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
367 i.m_error = std::current_exception();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
368 i.m_canRead.set_state(true);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
369 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
370 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
371
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
372 bool m_canSeek;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
373 t_filestats2 m_stats;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
374 pfc::string8 m_contentType;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
375 t_filesize m_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
376
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
377
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
378 bool m_haveStaticInfo;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
379 file_info_impl m_staticInfo;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
380 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
381
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
382 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
383
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
384
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
385 file::ptr fileCreateReadAhead(file::ptr chain, size_t readAheadBytes, abort_callback & aborter ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
386 auto obj = fb2k::service_new<fileReadAhead>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
387 obj->initialize( chain, readAheadBytes, aborter );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
388
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
389 // Two paths to cast to file*, pick one explicitly to avoid compiler error
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
390 file_v2::ptr temp = std::move(obj);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
391 return std::move(temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
392 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
393
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
394
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
395
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
396 namespace {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
397 class CFileWithMemBlock : public reader_membuffer_base {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
398 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
399 CFileWithMemBlock(fb2k::memBlockRef mem, t_filestats const& stats, const char* contentType, bool remote) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
400 m_mem = mem;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
401 m_stats = stats;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
402 m_stats.m_size = mem->size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
403 if (contentType != nullptr) m_contentType = contentType;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
404 m_remote = remote;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
405 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
406 const void* get_buffer() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
407 return m_mem->get_ptr();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
408 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
409 t_size get_buffer_size() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
410 return m_mem->get_size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
411 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
412 t_filestats get_stats(abort_callback& p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
413 p_abort.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
414 return m_stats;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
415 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
416 bool get_content_type(pfc::string_base& out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
417 if (m_contentType.is_empty()) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
418 out = m_contentType;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
419 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
420 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
421 bool is_remote() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
422 return m_remote;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
423 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
424 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
425 bool m_remote;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
426 fb2k::memBlockRef m_mem;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
427 pfc::string8 m_contentType;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
428 t_filestats m_stats;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
429 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
430 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
431
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
432 file::ptr createFileWithMemBlock(fb2k::memBlock::ptr mem, t_filestats stats, const char* contentType, bool remote) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
433 return new service_impl_t< CFileWithMemBlock >(mem, stats, contentType, remote);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
434 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
435
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
436 file::ptr createFileLimited(file::ptr base, t_filesize offset, t_filesize size, abort_callback& abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
437 return reader_limited::g_create(base, offset, size, abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
438 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
439
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
440 file::ptr createFileBigMemMirror(file::ptr source, abort_callback& abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
441 if (source->is_in_memory()) return source;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
442 auto r = fb2k::service_new<reader_bigmem_mirror>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
443 r->init(source, abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
444 return r;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
445 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
446
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
447 file::ptr createFileMemMirror(file::ptr source, abort_callback& abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
448 file::ptr ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
449 if (!reader_membuffer_mirror::g_create(ret, source, abort)) ret = source;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
450 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
451 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
452
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
453 namespace {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
454 class file_memMirrorAsync : public file_readonly_t< file_v2 > {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
455 struct shared_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
456 abort_callback_impl m_abort;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
457 size_t m_size;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
458 pfc::mutex m_sync;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
459 file::ptr m_file;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
460
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
461 pfc::bigmem m_data;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
462 size_t m_dataAvailable = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
463
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
464 size_t m_triggerOffset = SIZE_MAX;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
465 pfc::event m_trigger;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
466 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
467 shared_t m_shared;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
468
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
469 static void worker(shared_t& s) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
470
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
471 constexpr size_t tempSize = 256 * 1024;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
472 auto temp = std::make_unique<uint8_t[]>(tempSize);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
473
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
474 while (s.m_dataAvailable < s.m_size) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
475 size_t got = s.m_file->receive(temp.get(), tempSize, s.m_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
476 if (got == 0) break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
477
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
478 PFC_INSYNC(s.m_sync);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
479 s.m_data.write(temp.get(), got, s.m_dataAvailable);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
480
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
481 auto before = s.m_dataAvailable;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
482 s.m_dataAvailable += got;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
483 if (before < s.m_triggerOffset && s.m_dataAvailable >= s.m_triggerOffset) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
484 s.m_trigger.set_state(true);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
485 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
486 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
487 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
488 t_filestats2 m_stats;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
489 bool m_is_remote = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
490 pfc::string8 m_contentType;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
491 service_ptr m_metadata;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
492 size_t m_position = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
493 fb2k::thread m_thread;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
494 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
495 ~file_memMirrorAsync() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
496 m_shared.m_abort.set();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
497 m_thread.waitTillDone();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
498 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
499 void open(file::ptr chain, completion_notify::ptr onDone, abort_callback& a) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
500 if ( chain->get_position(a) > 0 ) chain->reopen(a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
501 m_stats = chain->get_stats2_(stats2_all, a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
502 if (m_stats.m_size > SIZE_MAX) throw pfc::exception_overflow();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
503 m_is_remote = chain->is_remote();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
504 m_contentType = chain->get_content_type();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
505 m_metadata = chain->get_metadata_(a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
506 m_shared.m_size = (size_t)m_stats.m_size;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
507 m_shared.m_file = chain;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
508 m_shared.m_data.resize(m_shared.m_size);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
509 auto work = [this, onDone] {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
510 try {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
511 worker(this->m_shared);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
512 } catch (...) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
513 this->m_shared.m_file.release();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
514 if (onDone.is_valid()) onDone->on_completion(this->m_shared.m_size == this->m_shared.m_dataAvailable ? 1 : 0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
515 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
516 m_thread.startHere(work);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
517 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
518
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
519
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
520 service_ptr get_metadata(abort_callback& a) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
521 a.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
522 return m_metadata;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
523 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
524
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
525 t_filestats2 get_stats2(uint32_t, abort_callback& a) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
526 a.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
527 return m_stats;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
528 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
529
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
530 t_filesize get_position(abort_callback& p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
531 p_abort.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
532 return m_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
533 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
534
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
535 void seek(t_filesize p_position, abort_callback& p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
536 if (p_position > get_size(p_abort)) throw exception_io_seek_out_of_range();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
537 m_position = (size_t)p_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
538 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
539
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
540 bool can_seek() override { return true; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
541
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
542 bool get_content_type(pfc::string_base& p_out) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
543 bool rv = m_contentType.length() > 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
544 if (rv) p_out = m_contentType;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
545 return rv;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
546 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
547
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
548 void reopen(abort_callback& p_abort) override { seek(0, p_abort); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
549
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
550 bool is_remote() override { return m_is_remote; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
551
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
552 t_size read(void* p_buffer, t_size p_bytes, abort_callback& p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
553 auto limit = get_size(p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
554 auto left = limit - m_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
555 if (p_bytes > left) p_bytes = (size_t)left;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
556
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
557 const auto upper = m_position + p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
558
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
559 auto& shared = m_shared;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
560
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
561 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
562 PFC_INSYNC(shared.m_sync);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
563 if (shared.m_dataAvailable >= upper) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
564 shared.m_data.read(p_buffer, p_bytes, m_position);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
565 m_position += p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
566 return p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
567 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
568 shared.m_trigger.set_state(false);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
569 shared.m_triggerOffset = upper;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
570 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
571 p_abort.waitForEvent(shared.m_trigger);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
572
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
573 PFC_INSYNC(shared.m_sync);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
574 PFC_ASSERT(shared.m_dataAvailable >= upper);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
575 shared.m_data.read(p_buffer, p_bytes, m_position);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
576 m_position += p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
577 return p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
578 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
579 t_filesize skip(t_filesize p_bytes, abort_callback& p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
580 auto total = get_size(p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
581 PFC_ASSERT(total >= m_position );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
582 auto left = total - m_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
583 if (p_bytes > left) p_bytes = left;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
584 m_position += (size_t)p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
585 return p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
586 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
587 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
588 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
589
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
590 file::ptr createFileMemMirrorAsync(file::ptr source, completion_notify::ptr onDone, abort_callback & a) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
591 auto ret = fb2k::service_new<file_memMirrorAsync>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
592 ret->open(source, onDone, a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
593 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
594 }