1313 See the License for the specific language governing permissions and
1414 limitations under the License.
1515*/
16+ #include " bk_download.h"
1617#include < errno.h>
1718#include < list>
1819#include < set>
2425#include < photon/fs/localfs.h>
2526#include < photon/fs/throttled-file.h>
2627#include < photon/thread/thread.h>
27- #include < photon/common/event-loop.h>
28- #include < photon/io/fd-events.h>
29- #include " bk_download.h"
30-
3128#include < openssl/sha.h>
3229#include < sys/stat.h>
3330#include < unistd.h>
31+ #include " switch_file.h"
32+
3433using namespace photon ::fs;
3534
3635static constexpr size_t ALIGNMENT = 4096 ;
@@ -90,57 +89,10 @@ bool check_downloaded(const std::string &dir) {
9089
9190static std::set<std::string> lock_files;
9291
93- ssize_t filecopy (IFile *infile, IFile *outfile, size_t bs, int retry_limit, int &running) {
94- if (bs == 0 )
95- LOG_ERROR_RETURN (EINVAL, -1 , " bs should not be 0" );
96- void *buff = nullptr ;
97-
98- // buffer allocate, with 4K alignment
99- ::posix_memalign (&buff, ALIGNMENT, bs);
100- if (buff == nullptr )
101- LOG_ERROR_RETURN (ENOMEM, -1 , " Fail to allocate buffer with " , VALUE (bs));
102- DEFER (free (buff));
103- off_t offset = 0 ;
104- ssize_t count = bs;
105- while (count == (ssize_t )bs) {
106- if (running != 1 ) {
107- LOG_INFO (" image file exit when background downloading" );
108- return -1 ;
109- }
110-
111- int retry = retry_limit;
112- again_read:
113- if (!(retry--))
114- LOG_ERROR_RETURN (EIO, -1 , " Fail to read at " , VALUE (offset), VALUE (count));
115- auto rlen = infile->pread (buff, bs, offset);
116- if (rlen < 0 ) {
117- LOG_DEBUG (" Fail to read at " , VALUE (offset), VALUE (count), " retry..." );
118- goto again_read;
119- }
120- retry = retry_limit;
121- again_write:
122- if (!(retry--))
123- LOG_ERROR_RETURN (EIO, -1 , " Fail to write at " , VALUE (offset), VALUE (count));
124- // cause it might write into file with O_DIRECT
125- // keep write length as bs
126- auto wlen = outfile->pwrite (buff, bs, offset);
127- // but once write lenth larger than read length treats as OK
128- if (wlen < rlen) {
129- LOG_DEBUG (" Fail to write at " , VALUE (offset), VALUE (count), " retry..." );
130- goto again_write;
131- }
132- count = rlen;
133- offset += count;
134- }
135- // truncate after write, for O_DIRECT
136- outfile->ftruncate (offset);
137- return offset;
138- }
139-
14092void BkDownload::switch_to_local_file () {
14193 std::string path = dir + " /" + COMMIT_FILE_NAME;
14294 ((ISwitchFile *)sw_file)->set_switch_file (path.c_str ());
143- LOG_DEBUG (" set switch tag done. (localpath: `)" , path);
95+ LOG_DEBUG (" set switch done. (localpath: `)" , path);
14496}
14597
14698bool BkDownload::download_done () {
@@ -166,6 +118,7 @@ bool BkDownload::download_done() {
166118 photon::thread_usleep (-1UL );
167119 if (shares != digest) {
168120 LOG_ERROR (" verify checksum ` failed (expect: `, got: `)" , old_name, digest, shares);
121+ force_download = true ; // force redownload next time
169122 return false ;
170123 }
171124
@@ -224,13 +177,59 @@ bool BkDownload::download_blob(int &running) {
224177
225178 auto dst = open_localfile_adaptor (dl_file_path.c_str (), O_RDWR | O_CREAT, 0644 );
226179 if (dst == nullptr ) {
227- LOG_ERRNO_RETURN (0 , - 1 , " failed to open dst file `" , dl_file_path.c_str ());
180+ LOG_ERRNO_RETURN (0 , false , " failed to open dst file `" , dl_file_path.c_str ());
228181 }
229182 DEFER (delete dst;);
183+ dst->ftruncate (file_size);
230184
231- auto res = filecopy (src, dst, 1024UL * 1024 , 1 , running);
232- if (res < 0 )
233- return false ;
185+ size_t bs = 256 * 1024 ;
186+ off_t offset = 0 ;
187+ void *buff = nullptr ;
188+ // buffer allocate, with 4K alignment
189+ ::posix_memalign (&buff, ALIGNMENT, bs);
190+ if (buff == nullptr )
191+ LOG_ERRNO_RETURN (0 , false , " failed to allocate buffer with " , VALUE (bs));
192+ DEFER (free (buff));
193+
194+ while (offset < file_size) {
195+ if (running != 1 ) {
196+ LOG_INFO (" image file exit when background downloading" );
197+ return false ;
198+ }
199+ if (!force_download) {
200+ // check aleady downloaded.
201+ auto hole_pos = dst->lseek (offset, SEEK_HOLE);
202+ if (hole_pos >= offset + bs) {
203+ // alread downloaded
204+ offset += bs;
205+ continue ;
206+ }
207+ }
208+
209+ int retry = 2 ;
210+ auto count = bs;
211+ if (offset + count > file_size)
212+ count = file_size - offset;
213+ again_read:
214+ if (!(retry--))
215+ LOG_ERROR_RETURN (EIO, false , " failed to read at " , VALUE (offset), VALUE (count));
216+ auto rlen = src->pread (buff, bs, offset);
217+ if (rlen < 0 ) {
218+ LOG_WARN (" failed to read at " , VALUE (offset), VALUE (count), VALUE (errno), " retry..." );
219+ goto again_read;
220+ }
221+ retry = 2 ;
222+ again_write:
223+ if (!(retry--))
224+ LOG_ERROR_RETURN (EIO, false , " failed to write at " , VALUE (offset), VALUE (count));
225+ auto wlen = dst->pwrite (buff, count, offset);
226+ // but once write lenth larger than read length treats as OK
227+ if (wlen < rlen) {
228+ LOG_WARN (" failed to write at " , VALUE (offset), VALUE (count), VALUE (errno), " retry..." );
229+ goto again_write;
230+ }
231+ offset += count;
232+ }
234233 return true ;
235234}
236235
0 commit comments