Skip to content

Commit

Permalink
Implement seek function for curl posts
Browse files Browse the repository at this point in the history
This allows for redirects to be successful in POSTing data from curl
over REST. A new `BufferList::seek(offset, whence)` function was added
to facilitate this.
  • Loading branch information
Shelnutt2 committed Jul 20, 2020
1 parent 25fcb22 commit 604f2fa
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 3 deletions.
1 change: 1 addition & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* Source built curl only need HTTP support [#1712](https://github.com/TileDB-Inc/TileDB/pull/1712)
* AWS SDK version bumped to 1.8.6 [#1718](https://github.com/TileDB-Inc/TileDB/pull/1718)
* Split posix permissions into files and folers permissions [#1719](https://github.com/TileDB-Inc/TileDB/pull/1719)
* Support seeking for CURL to allow redirects for posting to REST [#1728](https://github.com/TileDB-Inc/TileDB/pull/1728)

## Deprecations

Expand Down
23 changes: 22 additions & 1 deletion tiledb/sm/buffer/buffer_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@ Status BufferList::read(void* dest, uint64_t nbytes, uint64_t* bytes_read) {
// Read from buffer
const uint64_t bytes_in_src = src.size() - current_relative_offset_;
const uint64_t bytes_from_src = std::min(bytes_in_src, bytes_left);
RETURN_NOT_OK(src.read(dest_ptr + dest_offset, bytes_from_src));
// If the destination pointer is not null, then read into it
// if it is null then we are just seeking
if (dest_ptr != nullptr)
RETURN_NOT_OK(src.read(dest_ptr + dest_offset, bytes_from_src));
bytes_left -= bytes_from_src;
dest_offset += bytes_from_src;

Expand All @@ -114,6 +117,24 @@ Status BufferList::read(void* dest, uint64_t nbytes, uint64_t* bytes_read) {
return Status::Ok();
}

Status BufferList::seek(off_t offset, int whence) {
switch (whence) {
case SEEK_SET:
// We just reset the offsets to 0/start, then fall through to seek_current
reset_offset();
// fall through
case SEEK_CUR:
return read(nullptr, offset);
case SEEK_END:
return Status::BufferError(
"SEEK_END operation not supported for BufferList");
default:
return Status::BufferError("Invalid seek operation for BufferList");
}

return Status::Ok();
}

void BufferList::reset_offset() {
offset_ = 0;
current_buffer_index_ = 0;
Expand Down
26 changes: 24 additions & 2 deletions tiledb/sm/buffer/buffer_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ class BufferList {
* Returns an error if the buffers contain less than the requested number of
* bytes starting from the current offset.
*
* @param dest The buffer to read the data into.
* @param dest The buffer to read the data into. If null then will perform
* seek.
* @param nbytes The number of bytes to read.
* @return Status
*/
Expand All @@ -99,6 +100,27 @@ class BufferList {
*/
Status read_at_most(void* dest, uint64_t nbytes, uint64_t* bytes_read);

/**
* Seek to an offset, similar to lseek or fseek
*
* Whence options are:
*
* SEEK_SET
* The offset is set to offset bytes.
*
* SEEK_CUR
* The offset is set to its current location plus offset bytes
*
* SEEK_END
* This is not supported. Its purpose in lseek would be to set
* the offset to the size of the BufferList plus offset bytes.
*
* @param offset Offset to seek to.
* @param whence Location to seek from.
* @return Status
*/
Status seek(off_t offset, int whence);

/** Resets the current offset for reading. */
void reset_offset();

Expand All @@ -121,7 +143,7 @@ class BufferList {
/**
* Reads from the current offset into the given destination.
*
* @param dest The buffer to read the data into.
* @param dest The buffer to read the data into. If null will perform seek.
* @param nbytes The number of bytes to read.
* @param bytes_read Set to the number of bytes actually read.
* @return Status
Expand Down
21 changes: 21 additions & 0 deletions tiledb/sm/rest/curl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,23 @@ size_t buffer_list_read_memory_callback(
return num_read;
}

/**
* Seek function to handle curl redirects
* @param userp user data (buffer list)
* @param offset offset to seek to
* @param origin whence to seek from
* @return SEEKFUNC status
*/
static int buffer_list_seek_callback(
void* userp, curl_off_t offset, int origin) {
BufferList* data = static_cast<BufferList*>(userp);
Status status = data->seek(offset, origin);
if (status.ok())
return CURL_SEEKFUNC_OK;

return CURL_SEEKFUNC_FAIL;
}

Curl::Curl()
: config_(nullptr)
, curl_(nullptr, curl_easy_cleanup) {
Expand Down Expand Up @@ -522,6 +539,10 @@ Status Curl::post_data_common(
/* pass our list of custom made headers */
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, *headers);

/* set seek for handling redirects */
curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, &buffer_list_seek_callback);
curl_easy_setopt(curl, CURLOPT_SEEKDATA, data);

return Status::Ok();
}

Expand Down

0 comments on commit 604f2fa

Please sign in to comment.