Skip to content

Commit 7871975

Browse files
authored
Merge branch 'main' into glob_filter
2 parents 9ebb01b + e18e343 commit 7871975

File tree

14 files changed

+212
-43
lines changed

14 files changed

+212
-43
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ jobs:
2929
- uses: actions/checkout@v3
3030
with:
3131
submodules: recursive
32+
- uses: actions/setup-go@v5
33+
with:
34+
go-version: '1.23.5'
3235
- name: install deps
3336
run: |
3437
sudo curl -L https://xrootd.web.cern.ch/repo/RPM-GPG-KEY.txt -o /etc/apt/trusted.gpg.d/xrootd.asc

CMakeLists.txt

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ option( VALGRIND "Run select unit tests under valgrind" OFF )
77
option( ASAN "Build the plugin with the address sanitizer" OFF )
88

99
set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake )
10-
set( CMAKE_BUILD_TYPE Debug )
10+
if( "${CMAKE_BUILD_TYPE}" STREQUAL "" )
11+
set( CMAKE_BUILD_TYPE Debug )
12+
endif()
1113

1214
find_package( XRootD REQUIRED COMPONENTS UTILS SERVER )
1315
find_package( CURL REQUIRED )
@@ -39,6 +41,8 @@ endif()
3941
# Our custom Filesystem module creates the std::filesystem library target for
4042
# any special dependencies needed for using std::filesystem.
4143
find_package( Filesystem REQUIRED )
44+
# Similar setup for libatomic; required only on 32-bit systems
45+
find_package( Atomic REQUIRED )
4246

4347
if( NOT XROOTD_EXTERNAL_TINYXML2 )
4448
include(FetchContent)
@@ -78,7 +82,7 @@ add_definitions( -D_FILE_OFFSET_BITS=64 )
7882
add_library(XrdS3Obj OBJECT src/CurlUtil.cc src/S3File.cc src/S3Directory.cc src/S3AccessInfo.cc src/S3FileSystem.cc src/AWSv4-impl.cc src/S3Commands.cc src/HTTPCommands.cc src/TokenFile.cc src/stl_string_utils.cc src/shortfile.cc src/logging.cc)
7983
set_target_properties(XrdS3Obj PROPERTIES POSITION_INDEPENDENT_CODE ON)
8084
target_include_directories(XrdS3Obj PRIVATE ${XRootD_INCLUDE_DIRS})
81-
target_link_libraries(XrdS3Obj ${XRootD_UTILS_LIBRARIES} ${XRootD_SERVER_LIBRARIES} CURL::libcurl OpenSSL::Crypto tinyxml2::tinyxml2 Threads::Threads std::filesystem)
85+
target_link_libraries( XrdS3Obj ${XRootD_UTILS_LIBRARIES} ${XRootD_SERVER_LIBRARIES} CURL::libcurl OpenSSL::Crypto tinyxml2::tinyxml2 Threads::Threads std::filesystem std::atomic )
8286

8387
add_library(XrdS3 MODULE "$<TARGET_OBJECTS:XrdS3Obj>")
8488
target_link_libraries(XrdS3 XrdS3Obj)
@@ -116,11 +120,11 @@ else()
116120
set_target_properties( XrdOssFilter PROPERTIES OUTPUT_NAME "XrdOssFilter-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/configs/export-lib-symbols" )
117121
endif()
118122

119-
SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Install path for libraries")
123+
include(GNUInstallDirs)
120124

121125
install(
122126
TARGETS XrdS3 XrdHTTPServer
123-
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
127+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
124128
)
125129

126130
if( BUILD_TESTING )
@@ -137,7 +141,18 @@ if( BUILD_TESTING )
137141
target_link_libraries( XrdOssFilterTesting XrdOssFilterObj )
138142
target_include_directories( XrdOssFilterTesting INTERFACE ${XRootD_INCLUDE_DIRS} )
139143

140-
# Ensure that GTest is available
144+
find_program(GoWrk go-wrk HINTS "$ENV{HOME}/go/bin")
145+
if( NOT GoWrk )
146+
# Try installing the go-wrk variable to generate a reasonable stress test
147+
execute_process( COMMAND go install github.com/bbockelm/go-wrk@92dbe19
148+
RESULT_VARIABLE go_install_result )
149+
if( go_install_result EQUAL 0 )
150+
find_program(GoWrk go-wrk HINTS "$ENV{HOME}/go/bin")
151+
else()
152+
message(ERROR "Failed to install the go-wrk binary" )
153+
endif()
154+
endif()
155+
141156
if( NOT XROOTD_PLUGINS_EXTERNAL_GTEST )
142157
include( FetchContent )
143158
set( GTEST_URL "${CMAKE_CURRENT_SOURCE_DIR}/googletest-1.15.2.tar.gz" )

cmake/FindAtomic.cmake

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
2+
# Ideas come from
3+
#
4+
# https://gitlab.kitware.com/cmake/cmake/-/issues/17834
5+
#
6+
# But applied to the use of libatomic instead of libstdc++fs.
7+
# The need to do this was highlighted as part of:
8+
# https://github.com/PelicanPlatform/xrootd-s3-http/pull/81
9+
# The original driving use case was 32-bit builds; if we
10+
# decide to drop those, we can rip out the target
11+
12+
include(CheckSourceCompiles)
13+
14+
function( check_working_cxx_atomics varname )
15+
CHECK_SOURCE_COMPILES( CXX "
16+
#include <cstdlib>
17+
#include <atomic>
18+
#include <cstdint>
19+
20+
int main() {
21+
std::atomic<uint8_t> a1;
22+
std::atomic<uint16_t> a2;
23+
std::atomic<uint32_t> a3;
24+
std::atomic<uint64_t> a4;
25+
return a1++ + a2++ + a3++ + a4++;
26+
}" ${varname}
27+
)
28+
endfunction( check_working_cxx_atomics varname )
29+
30+
31+
check_working_cxx_atomics( CXX_ATOMIC_NO_LINK_NEEDED )
32+
33+
set( _found FALSE )
34+
if( CXX_ATOMIC_NO_LINK_NEEDED )
35+
set( _found TRUE )
36+
else()
37+
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
38+
if (HAVE_LIBATOMIC)
39+
set( OLD_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} )
40+
list( APPEND CMAKE_REQUIRED_LIBRARIES "atomic" )
41+
check_working_cxx_atomics( HAVE_CXX_ATOMICS_WITH_LIB )
42+
set( CMAKE_REQUIRED_LIBRARIES ${OLD_CMAKE_REQUIRED_LIBRARIES} )
43+
set( HAVE_CXX_ATOMICS_WITH_LIB TRUE )
44+
set( _found TRUE )
45+
endif()
46+
endif()
47+
48+
add_library( std::atomic INTERFACE IMPORTED )
49+
50+
if( HAVE_CXX_ATOMICS_WITH_LIB )
51+
set_property( TARGET std::atomic APPEND PROPERTY INTERFACE_LINK_LIBRARIES atomic )
52+
endif()
53+
54+
set( Atomic_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::atomic" FORCE )
55+
if( Atomic_FIND_REQUIRED AND NOT Atomic_FOUND )
56+
message( FATAL_ERROR "Cannot run simple program using std::atomic" )
57+
endif()

rpm/xrootd-s3-http.spec

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
1-
Name: xrootd-s3-http
2-
Version: 0.0.2
3-
Release: 1%{?dist}
4-
Summary: S3/HTTP filesystem plugins for xrootd
5-
6-
Group: System Environment/Daemons
7-
License: BSD
8-
# Generated from:
9-
# git archive v%{version} --prefix=xrootd-s3-http-%{version}/ | gzip -7 > ~/rpmbuild/SOURCES/xrootd-s3-http-%{version}.tar.gz
10-
URL: https://github.com/pelicanplatform/xrootd-s3-http
11-
Source0: %{name}-%{version}.tar.gz
1+
Name: xrootd-s3-http
2+
Version: 0.2.1
3+
Release: 1%{?dist}
4+
Summary: S3/HTTP filesystem plugins for xrootd
5+
6+
License: Apache-2.0
7+
URL: https://github.com/PelicanPlatform/%{name}
8+
Source0: %{url}/archive/refs/tags/v%{version}/%{name}-%{version}.tar.gz
129

1310
%define xrootd_current_major 5
14-
%define xrootd_current_minor 5
11+
%define xrootd_current_minor 7
1512
%define xrootd_next_major 6
1613

17-
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
14+
BuildRequires: cmake3
15+
BuildRequires: gcc-c++
16+
BuildRequires: make
1817
BuildRequires: xrootd-server-libs >= 1:%{xrootd_current_major}
1918
BuildRequires: xrootd-server-libs < 1:%{xrootd_next_major}
2019
BuildRequires: xrootd-server-devel >= 1:%{xrootd_current_major}
2120
BuildRequires: xrootd-server-devel < 1:%{xrootd_next_major}
22-
BuildRequires: cmake3
23-
BuildRequires: gcc-c++
2421
BuildRequires: libcurl-devel
2522
BuildRequires: openssl-devel
23+
BuildRequires: tinyxml2-devel
2624

2725
Requires: xrootd-server >= 1:%{xrootd_current_major}.%{xrootd_current_minor}
2826
Requires: xrootd-server < 1:%{xrootd_next_major}.0.0-1
@@ -34,19 +32,22 @@ Requires: xrootd-server < 1:%{xrootd_next_major}.0.0-1
3432
%setup -q
3533

3634
%build
37-
%cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo .
38-
make VERBOSE=1 %{?_smp_mflags}
35+
%cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DXROOTD_EXTERNAL_TINYXML2=ON
36+
cmake --build redhat-linux-build --verbose
3937

4038
%install
41-
rm -rf $RPM_BUILD_ROOT
42-
make install DESTDIR=$RPM_BUILD_ROOT
39+
%cmake_install
4340

4441
%files
45-
%defattr(-,root,root,-)
46-
%{_libdir}/libXrdS3*.so
47-
%{_libdir}/libXrdHTTPServer*.so
42+
%{_libdir}/libXrdHTTPServer-5.so
43+
%{_libdir}/libXrdS3-5.so
44+
%doc README.md
45+
%license LICENSE
4846

4947
%changelog
48+
* Sat Feb 1 2025 Brian Bockelman <bbockelman@morgridge.org> - 0.2.1-1
49+
- Bump to upstream version 0.2.1.
50+
5051
* Tue Nov 28 2023 Justin Hiemstra <jhiemstra@wisc.edu> - 0.0.2-1
5152
- Add HTTPServer plugin
5253

src/CurlUtil.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
using namespace XrdHTTPServer;
3636

37-
thread_local std::vector<CURL *> HandlerQueue::m_handles;
37+
thread_local std::stack<CURL *> HandlerQueue::m_handles;
3838

3939
HandlerQueue::HandlerQueue() {
4040
int filedes[2];
@@ -85,16 +85,16 @@ CURL *GetHandle(bool verbose) {
8585
}
8686

8787
CURL *HandlerQueue::GetHandle() {
88-
if (m_handles.size()) {
89-
auto result = m_handles.back();
90-
m_handles.pop_back();
88+
if (!m_handles.empty()) {
89+
CURL *result = m_handles.top();
90+
m_handles.pop();
9191
return result;
9292
}
9393

9494
return ::GetHandle(false);
9595
}
9696

97-
void HandlerQueue::RecycleHandle(CURL *curl) { m_handles.push_back(curl); }
97+
void HandlerQueue::RecycleHandle(CURL *curl) { m_handles.push(curl); }
9898

9999
void HandlerQueue::Produce(HTTPRequest *handler) {
100100
std::unique_lock<std::mutex> lk{m_mutex};
@@ -258,6 +258,7 @@ void CurlWorker::Run() {
258258
<< curl_multi_strerror(mres);
259259
m_logger.Log(LogMask::Debug, "Run", ss.str().c_str());
260260
}
261+
m_op_map.erase(curl);
261262
op->Fail("E_CURL_LIB",
262263
"Unable to add operation to the curl multi-handle");
263264
continue;

src/CurlUtil.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
#include <deque>
2323
#include <memory>
2424
#include <mutex>
25+
#include <stack>
2526
#include <unordered_map>
26-
#include <vector>
2727

2828
// Forward dec'ls
2929
typedef void CURL;
@@ -58,7 +58,7 @@ class HandlerQueue {
5858

5959
private:
6060
std::deque<HTTPRequest *> m_ops;
61-
thread_local static std::vector<CURL *> m_handles;
61+
thread_local static std::stack<CURL *> m_handles;
6262
std::condition_variable m_cv;
6363
std::mutex m_mutex;
6464
const static unsigned m_max_pending_ops{20};

src/S3Commands.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ void AmazonS3Head::parseResponse() {
605605
size_t current_newline = 0;
606606
size_t next_newline = std::string::npos;
607607
size_t last_character = headers.size();
608-
while (current_newline != std::string::npos &&
608+
while (headers.size() && current_newline != std::string::npos &&
609609
current_newline != last_character - 1) {
610610
next_newline = headers.find("\r\n", current_newline + 2);
611611
line = substring(headers, current_newline + 2, next_newline);

src/S3File.cc

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,11 @@ S3File::DownloadBypass(off_t offset, size_t size, char *buffer) {
547547
return std::make_tuple(-1, 0, true);
548548
}
549549

550+
S3File::S3Cache::~S3Cache() {
551+
std::unique_lock lk(m_mutex);
552+
m_cv.wait(lk, [&] { return !m_a.m_inprogress && !m_b.m_inprogress; });
553+
}
554+
550555
bool S3File::S3Cache::CouldUseAligned(off_t req, off_t cache) {
551556
if (req < 0 || cache < 0) {
552557
return false;
@@ -974,14 +979,24 @@ void S3File::S3Cache::Entry::Download(S3File &file) {
974979
if (m_off + static_cast<off_t>(request_size) > file.content_length) {
975980
request_size = file.content_length - m_off;
976981
}
977-
if (!m_request->SendRequest(m_off, m_cache_entry_size)) {
982+
// This function is always called with m_mutex held; however,
983+
// SendRequest can block if the threads are all busy; the threads
984+
// will need to grab the lock to notify of completion. So, we
985+
// must release the lock here before calling a blocking function --
986+
// otherwise deadlock may occur.
987+
auto off = m_off;
988+
m_parent.m_mutex.unlock();
989+
if (!m_request->SendRequest(off, m_cache_entry_size)) {
990+
m_parent.m_mutex.lock();
978991
std::stringstream ss;
979992
ss << "Failed to send GetObject command: "
980993
<< m_request->getResponseCode() << "'"
981994
<< m_request->getResultString() << "'";
982995
file.m_log.Log(LogMask::Warning, "S3File::Read", ss.str().c_str());
983996
m_failed = true;
984997
m_request.reset();
998+
} else {
999+
m_parent.m_mutex.lock();
9851000
}
9861001
}
9871002

src/S3File.hh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ class S3File : public XrdOssDF {
291291

292292
// Trigger a blocking read from a given file
293293
ssize_t Read(S3File &file, char *buffer, off_t offset, size_t size);
294+
295+
// Shutdown the cache; ensure all reads are completed before
296+
// deleting the objects.
297+
~S3Cache();
294298
};
295299
S3Cache m_cache;
296300
};

test/CMakeLists.txt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ add_test(NAME HTTP::basic::setup
6262
set_tests_properties(HTTP::basic::setup
6363
PROPERTIES
6464
FIXTURES_SETUP HTTP::basic
65-
ENVIRONMENT "BINARY_DIR=${CMAKE_BINARY_DIR};SOURCE_DIR=${CMAKE_SOURCE_DIR}"
65+
ENVIRONMENT "BINARY_DIR=${CMAKE_BINARY_DIR};SOURCE_DIR=${CMAKE_SOURCE_DIR};XROOTD_BINDIR=${XRootD_DATA_DIR}/../bin"
6666
)
6767

6868
add_test(NAME HTTP::basic::teardown
@@ -96,7 +96,7 @@ add_test(NAME S3::s3_basic::setup
9696
set_tests_properties(S3::s3_basic::setup
9797
PROPERTIES
9898
FIXTURES_SETUP S3::s3_basic
99-
ENVIRONMENT "BINARY_DIR=${CMAKE_BINARY_DIR};SOURCE_DIR=${CMAKE_SOURCE_DIR}"
99+
ENVIRONMENT "BINARY_DIR=${CMAKE_BINARY_DIR};SOURCE_DIR=${CMAKE_SOURCE_DIR};XROOTD_BINDIR=${XRootD_DATA_DIR}/../bin"
100100
)
101101

102102
add_test(NAME S3::s3_basic::teardown
@@ -130,3 +130,17 @@ set_tests_properties(S3::s3_basic::stress_test
130130
ENVIRONMENT "BINARY_DIR=${CMAKE_BINARY_DIR}"
131131
ATTACHED_FILES_ON_FAIL "${S3_BASIC_TEST_LOGS}"
132132
)
133+
134+
#######################################
135+
# Stress-test using the go-wrk binary #
136+
#######################################
137+
138+
add_test( NAME S3::s3_basic::gowrk_test
139+
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/s3-gowrk-test.sh" s3_basic )
140+
141+
set_tests_properties( S3::s3_basic::gowrk_test
142+
PROPERTIES
143+
FIXTURES_REQUIRED S3::s3_basic
144+
ENVIRONMENT "BINARY_DIR=${CMAKE_BINARY_DIR};WRK_BIN=${GoWrk}"
145+
ATTACHED_FILES_ON_FAIL "${S3_BASIC_TEST_LOGS}"
146+
)

0 commit comments

Comments
 (0)