@@ -161,6 +161,11 @@ bool S3fsCurl::InitS3fsCurl()
161
161
if (sCurlPoolSize < std::max (GetMaxParallelCount (), GetMaxMultiRequest ())){
162
162
sCurlPoolSize = std::max (GetMaxParallelCount (), GetMaxMultiRequest ());
163
163
}
164
+
165
+ if (direct_read && sCurlPoolSize < direct_read_max_prefetch_thread_count) {
166
+ sCurlPoolSize = direct_read_max_prefetch_thread_count;
167
+ }
168
+
164
169
sCurlPool = new CurlHandlerPool (sCurlPoolSize );
165
170
if (!sCurlPool ->Init ()) {
166
171
return false ;
@@ -704,6 +709,35 @@ size_t S3fsCurl::DownloadWriteCallback(void* ptr, size_t size, size_t nmemb, voi
704
709
return totalwrite;
705
710
}
706
711
712
+ size_t S3fsCurl::DownloadWriteStreamCallback (void * ptr, size_t size, size_t nmemb, void * userp)
713
+ {
714
+ S3fsCurl* pCurl = static_cast <S3fsCurl*>(userp);
715
+
716
+ if (1 > (size * nmemb)){
717
+ return 0 ;
718
+ }
719
+ if (!pCurl-> partdata.streambuffer || 0 >= pCurl->partdata .size ){
720
+ return 0 ;
721
+ }
722
+
723
+ // Buffer initial bytes in case it is an XML error response.
724
+ if (pCurl->bodydata .size () < GET_OBJECT_RESPONSE_LIMIT){
725
+ pCurl->bodydata .Append (ptr, std::min (size * nmemb, GET_OBJECT_RESPONSE_LIMIT - pCurl->bodydata .size ()));
726
+ }
727
+
728
+ // write size
729
+ ssize_t copysize = (size * nmemb) < (size_t )pCurl->partdata .size ? (size * nmemb) : (size_t )pCurl->partdata .size ;
730
+
731
+ // write
732
+ memcpy (&((char *)pCurl->partdata .streambuffer )[pCurl->partdata .streampos ], ptr, copysize);
733
+
734
+ pCurl->partdata .startpos += copysize;
735
+ pCurl->partdata .size -= copysize;
736
+ pCurl->partdata .streampos += copysize;
737
+
738
+ return copysize;
739
+ }
740
+
707
741
bool S3fsCurl::SetCheckCertificate (bool isCertCheck)
708
742
{
709
743
bool old = S3fsCurl::is_cert_check;
@@ -1628,6 +1662,31 @@ bool S3fsCurl::PreGetObjectRequestSetCurlOpts(S3fsCurl* s3fscurl)
1628
1662
return true ;
1629
1663
}
1630
1664
1665
+ bool S3fsCurl::PreGetObjectStreamRequestSetCurlOpts (S3fsCurl* s3fscurl)
1666
+ {
1667
+ if (!s3fscurl) {
1668
+ return false ;
1669
+ }
1670
+ if (!s3fscurl->CreateCurlHandle ()){
1671
+ return false ;
1672
+ }
1673
+
1674
+ if (CURLE_OK != curl_easy_setopt (s3fscurl->hCurl , CURLOPT_URL, s3fscurl->url .c_str ())){
1675
+ return false ;
1676
+ }
1677
+ if (CURLE_OK != curl_easy_setopt (s3fscurl->hCurl , CURLOPT_WRITEFUNCTION, DownloadWriteStreamCallback)){
1678
+ return false ;
1679
+ }
1680
+ if (CURLE_OK != curl_easy_setopt (s3fscurl->hCurl , CURLOPT_WRITEDATA, (void *)s3fscurl)){
1681
+ return false ;
1682
+ }
1683
+ if (!S3fsCurl::AddUserAgent (s3fscurl->hCurl )){ // put User-Agent
1684
+ return false ;
1685
+ }
1686
+
1687
+ return true ;
1688
+ }
1689
+
1631
1690
bool S3fsCurl::PreHeadRequestSetCurlOpts (S3fsCurl* s3fscurl)
1632
1691
{
1633
1692
if (!s3fscurl){
@@ -1761,6 +1820,7 @@ S3fsCurl::S3fsCurl(bool ahbe) :
1761
1820
hCurl(NULL ), type(REQTYPE_UNSET), requestHeaders(NULL ),
1762
1821
LastResponseCode(S3FSCURL_RESPONSECODE_NOTSET), postdata(NULL ), postdata_remaining(0 ), is_use_ahbe(ahbe),
1763
1822
retry_count(0 ), b_infile(NULL ), b_postdata(NULL ), b_postdata_remaining(0 ), b_partdata_startpos(0 ), b_partdata_size(0 ),
1823
+ b_partdata_streambuff(NULL ), b_partdata_streampos(0 ),
1764
1824
b_ssekey_pos(-1 ), b_ssetype(sse_type_t ::SSE_DISABLE),
1765
1825
sem(NULL ), completed_tids_lock(NULL ), completed_tids(NULL ), fpLazySetup(NULL ), curlCode(CURLE_OK)
1766
1826
{
@@ -2015,7 +2075,8 @@ bool S3fsCurl::RemakeHandle()
2015
2075
postdata_remaining = b_postdata_remaining;
2016
2076
partdata.startpos = b_partdata_startpos;
2017
2077
partdata.size = b_partdata_size;
2018
-
2078
+ partdata.streambuffer = b_partdata_streambuff;
2079
+ partdata.streampos = b_partdata_streampos;
2019
2080
// reset handle
2020
2081
ResetHandle ();
2021
2082
@@ -2285,6 +2346,18 @@ bool S3fsCurl::RemakeHandle()
2285
2346
}
2286
2347
break ;
2287
2348
2349
+ case REQTYPE_GET_STREAM:
2350
+ if (CURLE_OK != curl_easy_setopt (hCurl, CURLOPT_URL, url.c_str ())){
2351
+ return false ;
2352
+ }
2353
+ if (CURLE_OK != curl_easy_setopt (hCurl, CURLOPT_WRITEFUNCTION, S3fsCurl::DownloadWriteStreamCallback)){
2354
+ return false ;
2355
+ }
2356
+ if (CURLE_OK != curl_easy_setopt (hCurl, CURLOPT_WRITEDATA, (void *)this )){
2357
+ return false ;
2358
+ }
2359
+ break ;
2360
+
2288
2361
default :
2289
2362
S3FS_PRN_ERR (" request type is unknown(%d)" , type);
2290
2363
return false ;
@@ -3502,6 +3575,94 @@ int S3fsCurl::GetObjectRequest(const char* tpath, int fd, off_t start, off_t siz
3502
3575
return result;
3503
3576
}
3504
3577
3578
+ int S3fsCurl::PreGetObjectStreamRequest (const char * tpath, char * buf, off_t start, off_t size, sse_type_t ssetype, const std::string& ssevalue)
3579
+ {
3580
+ S3FS_PRN_INFO3 (" [tpath=%s][start=%lld][size=%lld]" , SAFESTRPTR (tpath), static_cast <long long >(start), static_cast <long long >(size));
3581
+
3582
+ if (!tpath || !buf || 0 > start || 0 > size){
3583
+ return -EINVAL;
3584
+ }
3585
+
3586
+ std::string resource;
3587
+ std::string turl;
3588
+ MakeUrlResource (get_realpath (tpath).c_str (), resource, turl);
3589
+ url = prepare_url (turl.c_str ());
3590
+ path = get_realpath (tpath);
3591
+ requestHeaders = NULL ;
3592
+ responseHeaders.clear ();
3593
+
3594
+ if (0 < size) {
3595
+ std::string range = " bytes=" ;
3596
+ range += str (start);
3597
+ range += " -" ;
3598
+ range += str (start + size - 1 );
3599
+ requestHeaders = curl_slist_sort_insert (requestHeaders, " Range" , range.c_str ());
3600
+ requestHeaders = curl_slist_sort_insert (requestHeaders, " x-oss-range-behavior" , " standard" );
3601
+ }
3602
+
3603
+ // SSE
3604
+ if (!AddSseRequestHead (ssetype, ssevalue, true , false )){
3605
+ S3FS_PRN_WARN (" Failed to set SSE header, but continue..." );
3606
+ }
3607
+
3608
+ if (S3fsCurl::download_traffic_limit != 0 ){
3609
+ char buff[64 ];
3610
+ sprintf (buff, " %ld" , S3fsCurl::download_traffic_limit);
3611
+ requestHeaders = curl_slist_sort_insert (requestHeaders, " x-oss-traffic-limit" , buff);
3612
+ }
3613
+
3614
+ op = " GET" ;
3615
+ type = REQTYPE_GET_STREAM;
3616
+
3617
+ // set lazy function
3618
+ fpLazySetup = PreGetObjectStreamRequestSetCurlOpts;
3619
+
3620
+ // set info for callback func.
3621
+ partdata.clear ();
3622
+ partdata.startpos = start;
3623
+ partdata.size = size;
3624
+ partdata.streambuffer = buf;
3625
+ partdata.streampos = 0 ;
3626
+ b_partdata_startpos = start;
3627
+ b_partdata_size = size;
3628
+ b_partdata_streambuff = buf;
3629
+ b_partdata_streampos = 0 ;
3630
+ b_ssetype = ssetype;
3631
+ b_ssevalue = ssevalue;
3632
+ b_ssekey_pos = -1 ;
3633
+
3634
+ return 0 ;
3635
+ }
3636
+
3637
+ int S3fsCurl::GetObjectStreamRequest (const char * tpath, char * buf, off_t start, off_t size, ssize_t & rsize)
3638
+ {
3639
+ int result;
3640
+ S3FS_PRN_INFO3 (" [tpath=%s][start=%lld][size=%lld]" , SAFESTRPTR (tpath), static_cast <long long >(start), static_cast <long long >(size));
3641
+
3642
+ if (!tpath) {
3643
+ return -EINVAL;
3644
+ }
3645
+ sse_type_t ssetype = sse_type_t ::SSE_DISABLE;
3646
+ std::string ssevalue;
3647
+ if (!get_object_sse_type (tpath, ssetype, ssevalue)){
3648
+ S3FS_PRN_WARN (" Failed to get SSE type for file(%s)." , SAFESTRPTR (tpath));
3649
+ }
3650
+
3651
+ if (0 != (result = PreGetObjectStreamRequest (tpath, buf, start, size, ssetype, ssevalue))){
3652
+ return result;
3653
+ }
3654
+ if (!fpLazySetup ||!fpLazySetup (this )){
3655
+ S3FS_PRN_INFO3 (" Failed to lazy setup in single get object request." );
3656
+ return -EIO;
3657
+ }
3658
+
3659
+ result = RequestPerform ();
3660
+ rsize = (ssize_t )partdata.streampos ;
3661
+ partdata.clear ();
3662
+
3663
+ return result;
3664
+ }
3665
+
3505
3666
int S3fsCurl::CheckBucket (const char * check_path)
3506
3667
{
3507
3668
S3FS_PRN_INFO3 (" check a bucket." );
0 commit comments