| /* |
| * Copyright 2024-present Alibaba Cloud. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "JdoFileSystem.hpp" |
| |
| #include <cstdlib> |
| #include <iostream> |
| #include <memory> |
| #include <vector> |
| #include <cstdlib> |
| #include <pwd.h> |
| #include <unistd.h> |
| |
| #include "JdoStatus.hpp" |
| #include "JdoFileInfo.hpp" |
| #include "JdoListResult.hpp" |
| #include "JdoContentSummary.hpp" |
| |
| #include "jdo_common.h" |
| #include "jdo_api.h" |
| #include "jdo_defines.h" |
| #include "jdo_error.h" |
| #include "jdo_options.h" |
| #include "jdo_file_status.h" |
| #include "jdo_list_dir_result.h" |
| #include "jdo_content_summary.h" |
| #include "jdo_file_buffers.h" |
| #include "jdo_longs.h" |
| |
| #define START_CALL(fs) \ |
| JdoHandleCtx_t ctx = jdo_createHandleCtx1(fs); |
| |
| #define START_CALL2(fs, stream) \ |
| JdoHandleCtx_t ctx = jdo_createHandleCtx2(fs, stream); |
| |
| #define END_CALL() \ |
| auto errorCode = jdo_getHandleCtxErrorCode(ctx); \ |
| std::string errorMsg; \ |
| const char* msg = jdo_getHandleCtxErrorMsg(ctx); \ |
| if (msg != nullptr) { \ |
| errorMsg.assign(msg); \ |
| } \ |
| jdo_freeHandleCtx(ctx); |
| |
| static void covertToFileInfo(JdoFileStatus_t fileStatus, |
| JdoFileInfo* info) { |
| if (!fileStatus) return; |
| auto path = jdo_getFileStatusPath(fileStatus); |
| if (path) { |
| info->path = path; |
| } |
| auto user = jdo_getFileStatusUser(fileStatus); |
| if (user) { |
| info->user = user; |
| } |
| auto group = jdo_getFileStatusGroup(fileStatus); |
| if (group) { |
| info->group = group; |
| } |
| info->type = jdo_getFileStatusType(fileStatus); |
| info->perm = jdo_getFileStatusPerm(fileStatus); |
| info->length = jdo_getFileStatusSize(fileStatus); |
| info->mtime = jdo_getFileStatusMtime(fileStatus); |
| info->atime = jdo_getFileStatusAtime(fileStatus); |
| if (info->isDir() && info->path.back() != '/') { |
| info->path.push_back('/'); |
| } |
| } |
| |
| class JindoOperation : public JdoTask { |
| public: |
| JindoOperation(JdoStore_t store, JdoOperationCall_t call) |
| : JdoTask(), _store(store), _stream(nullptr), _call(call) {} |
| |
| JindoOperation(JdoStore_t store, JdoIOContext_t stream, JdoOperationCall_t call) |
| : JdoTask(), _store(store), _stream(stream), _call(call) {} |
| |
| ~JindoOperation() override { |
| if (_call) { |
| jdo_freeOperationCall(_call); |
| _call = nullptr; |
| } |
| } |
| |
| JdoStatus perform() override { |
| START_CALL2(_store, _stream) |
| jdo_perform(ctx, _call); |
| END_CALL(); |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "failed to perform, errmsg: ", errorMsg); |
| } |
| return JdoStatus::OK(); |
| } |
| |
| JdoStatus wait() override { |
| START_CALL2(_store, _stream) |
| jdo_wait(ctx, _call); |
| END_CALL(); |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "failed to wait, errmsg: ", errorMsg); |
| } |
| return JdoStatus::OK(); |
| } |
| |
| JdoStatus cancel() override { |
| START_CALL2(_store, _stream) |
| jdo_cancel(ctx, _call); |
| END_CALL(); |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "failed to cancel, errmsg: ", errorMsg); |
| } |
| return JdoStatus::OK(); |
| } |
| |
| private: |
| JdoStore_t _store = nullptr; |
| JdoIOContext_t _stream = nullptr; |
| JdoOperationCall_t _call = nullptr; |
| }; |
| |
| struct ReadArgs { |
| JdoStore_t store = nullptr; |
| JdoIOContext_t reader = nullptr; |
| std::string name; |
| size_t n = 0; |
| std::string_view *result; |
| char *scratch; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void readCallback(JdoHandleCtx_t ctx, int64_t num_read, void *userdata) { |
| ReadArgs *args = (ReadArgs *) userdata; |
| auto store = args->store; |
| auto reader = args->reader; |
| auto name = args->name; |
| auto n = args->n; |
| auto result = args->result; |
| auto scratch = args->scratch; |
| auto total_read = num_read; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| if (errorCode != 0) { |
| auto status = JdoStatus::InternalError(errorCode, "failed to read ", name, |
| " size ", n - total_read, " readed ", num_read, |
| ", errmsg: ", errorMsg); |
| if (callback) { |
| callback(status); |
| } |
| return; |
| } |
| |
| JdoStatus status; |
| if (total_read >= 0) { |
| while (n - total_read > 0) { |
| START_CALL2(store, reader) |
| num_read = jdo_read(ctx, scratch + total_read, n - total_read, nullptr); |
| END_CALL() |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "failed to read ", name, |
| " size ", n - total_read, " readed ", num_read, |
| ", errmsg: ", errorMsg); |
| if (callback) { |
| callback(status); |
| } |
| return; |
| } |
| if (num_read < 0) { |
| // isEOF |
| break; |
| } |
| total_read += num_read; |
| } |
| } |
| |
| if ((total_read < 0 || total_read < n) && num_read != -1) { |
| // if there was an error before satisfying the current read, this logic declares it an error |
| // and does not try to return any of the bytes read. Don't think it matters, so the code |
| // is just being conservative. |
| status = JdoStatus::IOError("Failed to read, ", name, |
| ", expect read ", n, " bytes" |
| ", but ", total_read, " bytes readed" |
| ", last read ", num_read, " bytes"); |
| if (callback) { |
| callback(status); |
| } |
| return; |
| } |
| |
| if (total_read < 0 || total_read < n) { |
| // This is not an error per se. The RandomAccessFile interface expects |
| // that Read returns OutOfRange if fewer bytes were read than requested. |
| status = JdoStatus::IOError("EOF reached, ", result->size(), |
| " bytes were read out of ", n, |
| " bytes requested."); |
| if (callback) { |
| callback(status); |
| } |
| return; |
| } |
| |
| if (callback) { |
| callback(JdoStatus::OK()); |
| } |
| } |
| |
| struct PreadArgs { |
| JdoStore_t store = nullptr; |
| JdoIOContext_t reader = nullptr; |
| std::string name; |
| int64_t offset = 0; |
| size_t n = 0; |
| std::string_view *result; |
| char *scratch; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void preadCallback(JdoHandleCtx_t ctx, int64_t num_read, void *userdata) { |
| PreadArgs *args = (PreadArgs *) userdata; |
| auto store = args->store; |
| auto reader = args->reader; |
| auto name = args->name; |
| auto offset = args->offset; |
| auto n = args->n; |
| auto result = args->result; |
| auto scratch = args->scratch; |
| auto total_read = num_read; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| if (errorCode != 0) { |
| auto status = JdoStatus::InternalError(errorCode, "failed to read ", name, " offset ", offset + total_read, |
| " size ", n - total_read, " readed ", num_read, |
| ", errmsg: ", errorMsg); |
| if (callback) { |
| callback(status); |
| } |
| return; |
| } |
| |
| JdoStatus status; |
| if (total_read >= 0) { |
| while (n - total_read > 0) { |
| START_CALL2(store, reader) |
| num_read = jdo_pread(ctx, scratch + total_read, n - total_read, offset + total_read, nullptr); |
| END_CALL() |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "failed to read ", name, " offset ", offset + total_read, |
| " size ", n - total_read, " readed ", num_read, |
| ", errmsg: ", errorMsg); |
| if (callback) { |
| callback(status); |
| } |
| return; |
| } |
| if (num_read < 0) { |
| // isEOF |
| break; |
| } |
| total_read += num_read; |
| } |
| |
| |
| // Set the results. |
| *result = std::string_view(scratch, total_read); |
| } |
| |
| if ((total_read < 0 || total_read < n) && num_read != -1) { |
| // if there was an error before satisfying the current read, this logic declares it an error |
| // and does not try to return any of the bytes read. Don't think it matters, so the code |
| // is just being conservative. |
| status = JdoStatus::IOError("Failed to read, ", name, |
| ", expect read ", n, " bytes" |
| ", but ", total_read, " bytes readed" |
| ", last read ", num_read, " bytes"); |
| if (callback) { |
| callback(status); |
| } |
| return; |
| } |
| |
| if (total_read < 0 || total_read < n) { |
| // This is not an error per se. The RandomAccessFile interface expects |
| // that Read returns OutOfRange if fewer bytes were read than requested. |
| status = JdoStatus::IOError("EOF reached, ", result->size(), |
| " bytes were read out of ", n, |
| " bytes requested."); |
| if (callback) { |
| callback(status); |
| } |
| return; |
| } |
| |
| if (callback) { |
| callback(JdoStatus::OK()); |
| } |
| } |
| |
| struct PreadvArgs { |
| JdoStore_t store = nullptr; |
| JdoIOContext_t reader = nullptr; |
| std::string name; |
| JdoLongs_t lengths; |
| JdoLongs_t offsets; |
| JdoFileBuffers_t buffers; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void preadvCallback(JdoHandleCtx_t ctx, int64_t ret, void *userdata) { |
| PreadvArgs *args = (PreadvArgs *) userdata; |
| auto store = args->store; |
| auto reader = args->reader; |
| auto name = args->name; |
| auto offsets = args->offsets; |
| auto lengths = args->lengths; |
| auto buffers = args->buffers; |
| auto rangeCnt = jdo_getFileBuffersSize(buffers); |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| jdo_freeFileBuffers(buffers); |
| jdo_freeLongs(lengths); |
| jdo_freeLongs(offsets); |
| |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "failed to preadv ", name, |
| " ranges ", std::to_string(rangeCnt), |
| ", errmsg: ", errorMsg); |
| } |
| |
| if (callback) { |
| callback(status); |
| } |
| } |
| |
| struct Int64Args { |
| JdoStore_t store = nullptr; |
| JdoIOContext_t reader = nullptr; |
| JdoIOContext_t writer = nullptr; |
| std::function<void(JdoStatus, int64_t)> callback; |
| }; |
| |
| static void tellCallback(JdoHandleCtx_t ctx, int64_t result, void *userdata) { |
| Int64Args* args = (Int64Args*) userdata; |
| auto store = args->store; |
| auto reader = args->reader; |
| std::function<void(JdoStatus, int64_t)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "file tell failed: ", errorMsg); |
| } |
| |
| if (callback) { |
| callback(status, result); |
| } |
| } |
| |
| static void seekCallback(JdoHandleCtx_t ctx, int64_t result, void *userdata) { |
| Int64Args* args = (Int64Args*) userdata; |
| auto store = args->store; |
| auto reader = args->reader; |
| std::function<void(JdoStatus, int64_t)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "file seek failed: ", errorMsg); |
| } |
| |
| if (callback) { |
| callback(status, result); |
| } |
| } |
| |
| static void getFileLengthCallback(JdoHandleCtx_t ctx, int64_t result, void *userdata) { |
| Int64Args* args = (Int64Args*) userdata; |
| auto store = args->store; |
| auto reader = args->reader; |
| std::function<void(JdoStatus, int64_t)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "get file length failed: ", errorMsg); |
| } |
| |
| if (callback) { |
| callback(status, result); |
| } |
| } |
| |
| struct CloseReaderArgs { |
| JdoStore_t store = nullptr; |
| JdoIOContext_t reader = nullptr; |
| std::string name; |
| std::atomic<bool>* isClosed = nullptr; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void closeReaderCallback(JdoHandleCtx_t ctx, bool result, void* userdata) { |
| CloseReaderArgs* args = (CloseReaderArgs*) userdata; |
| auto store = args->store; |
| auto reader = args->reader; |
| auto name = args->name; |
| std::atomic<bool>* isClosed = args->isClosed; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| |
| *isClosed = true; |
| |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "close file failed: ", errorMsg); |
| } |
| |
| if (callback) { |
| callback(status); |
| } |
| } |
| |
| class JindoReader : public JdoReader { |
| public: |
| JindoReader(const std::string &fname, |
| JdoStore_t store, |
| JdoIOContext_t reader) |
| : _name(fname), |
| _store(store), |
| _reader(reader), |
| _is_closed(false) { |
| } |
| |
| ~JindoReader() override { |
| if (_reader) { |
| if (!_is_closed) { |
| JdoHandleCtx_t ctx = jdo_createHandleCtx2(_store, _reader); |
| jdo_close(ctx, nullptr); |
| jdo_freeHandleCtx(ctx); |
| } |
| jdo_freeIOContext(_reader); |
| _reader = nullptr; |
| } |
| } |
| |
| bool closed() const override { |
| return _is_closed; |
| } |
| |
| JdoStatus name(std::string_view *result) const override { |
| *result = _name; |
| return JdoStatus::OK(); |
| } |
| |
| JdoStatus read(size_t n, std::string_view *result, char *scratch) override { |
| std::lock_guard<std::mutex> lock(_lock); |
| size_t total_read = 0; |
| int64_t num_read = 0; |
| while (n - total_read > 0) { |
| START_CALL2(_store, _reader) |
| num_read = jdo_read(ctx, scratch + total_read, n - total_read, nullptr); |
| END_CALL() |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "failed to read ", _name, " size ", n - total_read, " readed ", num_read, |
| ", errmsg: ", errorMsg); |
| } |
| if (num_read < 0) { |
| // isEOF |
| break; |
| } |
| total_read += num_read; |
| } |
| // Set the results. |
| *result = std::string_view(scratch, total_read); |
| |
| if (total_read < n && num_read != -1) { |
| // if there was an error before satisfying the current read, this logic declares it an error |
| // and does not try to return any of the bytes read. Don't think it matters, so the code |
| // is just being conservative. |
| return JdoStatus::IOError("Failed to read, ", _name, |
| ", expect read ", n, " bytes" |
| ", but ", total_read, " bytes readed" |
| ", last read ", num_read, " bytes"); |
| } |
| |
| if (total_read < n) { |
| // This is not an error per se. The RandomAccessFile interface expects |
| // that Read returns OutOfRange if fewer bytes were read than requested. |
| return JdoStatus::IOError("EOF reached, ", result->size(), |
| " bytes were read out of ", n, |
| " bytes requested."); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| JdoTaskPtr readAsync(size_t n, std::string_view *result, char *scratch, std::function<void(JdoStatus)> callback) override { |
| size_t total_read = 0; |
| int64_t num_read = 0; |
| ReadArgs *args = new ReadArgs(); |
| args->store = _store; |
| args->reader = _reader; |
| args->name = _name; |
| args->n = n; |
| args->result = result; |
| args->scratch = scratch; |
| args->callback = callback; |
| START_CALL2(_store, _reader) |
| auto options = jdo_createOptions(); |
| jdo_setInt64Callback(options, readCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_readAsync(ctx, scratch + total_read, n - total_read, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, _reader, operationCall); |
| } |
| |
| JdoStatus pread(int64_t offset, size_t n, std::string_view *result, char *scratch) override { |
| size_t total_read = 0; |
| int64_t num_read = 0; |
| while (n - total_read > 0) { |
| START_CALL2(_store, _reader) |
| num_read = jdo_pread(ctx, scratch + total_read, n - total_read, offset + total_read, nullptr); |
| END_CALL() |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "failed to read ", _name, " offset ", offset + total_read, |
| " size ", n - total_read, " readed ", num_read, |
| ", errmsg: ", errorMsg); |
| } |
| if (num_read < 0) { |
| // isEOF |
| break; |
| } |
| total_read += num_read; |
| } |
| // Set the results. |
| *result = std::string_view(scratch, total_read); |
| |
| if (total_read < n && num_read != -1) { |
| // if there was an error before satisfying the current read, this logic declares it an error |
| // and does not try to return any of the bytes read. Don't think it matters, so the code |
| // is just being conservative. |
| return JdoStatus::IOError("Failed to read, ", _name, |
| ", expect read ", n, " bytes" |
| ", but ", total_read, " bytes readed" |
| ", last read ", num_read, " bytes"); |
| } |
| |
| if (total_read < n) { |
| // This is not an error per se. The RandomAccessFile interface expects |
| // that Read returns OutOfRange if fewer bytes were read than requested. |
| return JdoStatus::IOError("EOF reached, ", result->size(), |
| " bytes were read out of ", n, |
| " bytes requested."); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| JdoTaskPtr preadAsync(int64_t offset, size_t n, std::string_view *result, char *scratch, |
| std::function<void(JdoStatus)> callback) override { |
| size_t total_read = 0; |
| int64_t num_read = 0; |
| PreadArgs *args = new PreadArgs(); |
| args->store = _store; |
| args->reader = _reader; |
| args->name = _name; |
| args->offset = offset; |
| args->n = n; |
| args->result = result; |
| args->scratch = scratch; |
| args->callback = callback; |
| START_CALL2(_store, _reader) |
| auto options = jdo_createOptions(); |
| jdo_setInt64Callback(options, preadCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_preadAsync(ctx, scratch + total_read, n - total_read, offset + total_read, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, _reader, operationCall); |
| } |
| |
| JdoStatus preadv(std::vector<int64_t>& offsets, std::vector<size_t>& lengths, std::vector<char*>& scratches) override { |
| START_CALL2(_store, _reader) |
| JdoLongs_t offs = jdo_createLongs(); |
| for (auto& offset : offsets) { |
| jdo_appendLong(offs, offset); |
| } |
| JdoLongs_t lens = jdo_createLongs(); |
| for (auto& len: lengths) { |
| jdo_appendLong(lens, len); |
| } |
| JdoFileBuffers_t fileBuffers = jdo_createFileBuffers(); |
| for (auto& scratch : scratches) { |
| jdo_appendFileBuffer(fileBuffers, scratch); |
| } |
| jdo_preadv(ctx, fileBuffers, lens, offs, nullptr); |
| END_CALL() |
| jdo_freeFileBuffers(fileBuffers); |
| jdo_freeLongs(lens); |
| jdo_freeLongs(offs); |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "failed to preadv ", _name, |
| " ranges ", scratches.size(), |
| ", errmsg: ", errorMsg); |
| } |
| return JdoStatus::OK(); |
| } |
| |
| JdoTaskPtr preadvAsync(std::vector<int64_t>& offsets, std::vector<size_t>& lengths, std::vector<char*>& scratches, |
| std::function<void(JdoStatus)> callback) override { |
| JdoLongs_t offs = jdo_createLongs(); |
| for (auto& offset : offsets) { |
| jdo_appendLong(offs, offset); |
| } |
| JdoLongs_t lens = jdo_createLongs(); |
| for (auto& len: lengths) { |
| jdo_appendLong(lens, len); |
| } |
| JdoFileBuffers_t fileBuffers = jdo_createFileBuffers(); |
| for (auto& scratch : scratches) { |
| jdo_appendFileBuffer(fileBuffers, scratch); |
| } |
| PreadvArgs *args = new PreadvArgs(); |
| args->store = _store; |
| args->reader = _reader; |
| args->name = _name; |
| args->offsets = offs; |
| args->lengths = lens; |
| args->buffers = fileBuffers; |
| args->callback = callback; |
| START_CALL2(_store, _reader) |
| auto options = jdo_createOptions(); |
| jdo_setInt64Callback(options, preadvCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_preadvAsync(ctx, fileBuffers, lens, offs, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, _reader, operationCall); |
| } |
| |
| JdoStatus tell(int64_t& offset) override { |
| START_CALL2(_store, _reader) |
| offset = jdo_tell(ctx, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "tell file failed: ", errorMsg); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| JdoTaskPtr tellAsync(std::function<void(JdoStatus, int64_t)> callback) override { |
| Int64Args *args = new Int64Args(); |
| args->store = _store; |
| args->reader = _reader; |
| args->callback = callback; |
| START_CALL2(_store, _reader) |
| auto options = jdo_createOptions(); |
| jdo_setInt64Callback(options, tellCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_tellAsync(ctx,options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, _reader, operationCall); |
| } |
| |
| |
| JdoStatus seek(int64_t offset) override { |
| START_CALL2(_store, _reader) |
| jdo_seek(ctx, offset, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "seek file failed: ", errorMsg); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| JdoTaskPtr seekAsync(int64_t offset, std::function<void(JdoStatus, int64_t)> callback) override { |
| Int64Args *args = new Int64Args(); |
| args->store = _store; |
| args->reader = _reader; |
| args->callback = callback; |
| START_CALL2(_store, _reader) |
| auto options = jdo_createOptions(); |
| jdo_setInt64Callback(options, seekCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_seekAsync(ctx, offset, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, _reader, operationCall); |
| } |
| |
| JdoStatus getFileLength(int64_t& length) override { |
| START_CALL2(_store, _reader) |
| length = jdo_getFileLength(ctx, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "tell file failed: ", errorMsg); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| JdoTaskPtr getFileLengthAsync(std::function<void(JdoStatus, int64_t)> callback) override { |
| Int64Args *args = new Int64Args(); |
| args->store = _store; |
| args->reader = _reader; |
| args->callback = callback; |
| START_CALL2(_store, _reader) |
| auto options = jdo_createOptions(); |
| jdo_setInt64Callback(options, getFileLengthCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_getFileLengthAsync(ctx,options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, _reader, operationCall); |
| } |
| |
| JdoStatus close() override { |
| START_CALL2(_store, _reader) |
| jdo_close(ctx, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "close file failed: ", errorMsg); |
| } |
| |
| _is_closed = true; |
| return JdoStatus::OK(); |
| } |
| |
| JdoTaskPtr closeAsync(std::function<void(JdoStatus)> callback) override { |
| CloseReaderArgs* args = new CloseReaderArgs(); |
| args->store = _store; |
| args->reader = _reader; |
| args->name = _name; |
| args->isClosed = &_is_closed; |
| args->callback = callback; |
| |
| START_CALL2(_store, _reader) |
| auto options = jdo_createOptions(); |
| jdo_setBoolCallback(options, closeReaderCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_closeAsync(ctx, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, _reader, operationCall); |
| } |
| |
| private: |
| std::mutex _lock; |
| std::string _name; |
| JdoStore_t _store; |
| JdoIOContext_t _reader = nullptr; |
| std::atomic<bool> _is_closed = false; |
| }; |
| |
| struct WriteArgs { |
| JdoStore_t store = nullptr; |
| JdoIOContext_t writer = nullptr; |
| std::string name; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void writeCallback(JdoHandleCtx_t ctx, int64_t result, void* userdata) { |
| WriteArgs* args = (WriteArgs*) userdata; |
| auto store = args->store; |
| auto writer = args->writer; |
| auto name = args->name; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "write file failed: ", errorMsg); |
| } |
| |
| if (callback) { |
| callback(status); |
| } |
| } |
| |
| struct FlushArgs { |
| JdoStore_t store = nullptr; |
| JdoIOContext_t writer = nullptr; |
| std::string name; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void flushCallback(JdoHandleCtx_t ctx, bool result, void* userdata) { |
| FlushArgs* args = (FlushArgs*) userdata; |
| auto store = args->store; |
| auto writer = args->writer; |
| auto name = args->name; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "flush file failed: ", errorMsg); |
| } |
| |
| if (callback) { |
| callback(status); |
| } |
| } |
| |
| struct CloseWriterArgs { |
| JdoStore_t store = nullptr; |
| JdoIOContext_t writer = nullptr; |
| std::string name; |
| std::atomic<bool>* isClosed = nullptr; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void closeWriterCallback(JdoHandleCtx_t ctx, bool result, void* userdata) { |
| CloseWriterArgs* args = (CloseWriterArgs*) userdata; |
| auto store = args->store; |
| auto writer = args->writer; |
| auto name = args->name; |
| std::atomic<bool>* isClosed = args->isClosed; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "close file failed: ", errorMsg); |
| } |
| |
| *isClosed = true; |
| |
| if (callback) { |
| callback(status); |
| } |
| } |
| |
| class JindoWriter : public JdoWriter { |
| public: |
| JindoWriter(const std::string& fname, |
| JdoStore_t store, |
| JdoIOContext_t writer) |
| : _name(fname), |
| _store(store), |
| _writer(writer), |
| _is_closed(false) { |
| } |
| |
| ~JindoWriter() override { |
| if (_writer) { |
| if (!_is_closed) { |
| JdoHandleCtx_t ctx = jdo_createHandleCtx2(_store, _writer); |
| jdo_close(ctx, nullptr); |
| jdo_freeHandleCtx(ctx); |
| } |
| jdo_freeIOContext(_writer); |
| _writer = nullptr; |
| } |
| } |
| |
| bool closed() const override { |
| return _is_closed; |
| } |
| |
| JdoStatus name(std::string_view* result) const override { |
| *result = _name; |
| return JdoStatus::OK(); |
| } |
| |
| JdoStatus write(std::string_view data) override { |
| JDO_RETURN_IF_ERROR(_CheckClosed()); |
| |
| START_CALL2(_store, _writer) |
| jdo_write(ctx, data.data(), data.size(), nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "write file failed: ", errorMsg); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| JdoTaskPtr writeAsync(std::string_view data, std::function<void(JdoStatus)> callback) override { |
| WriteArgs* args = new WriteArgs(); |
| args->store = _store; |
| args->writer = _writer; |
| args->name = _name; |
| args->callback = callback; |
| |
| START_CALL2(_store, _writer) |
| auto options = jdo_createOptions(); |
| jdo_setInt64Callback(options, writeCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_writeAsync(ctx, data.data(), data.size(), options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, _writer, operationCall); |
| } |
| |
| JdoStatus flush() override { |
| JDO_RETURN_IF_ERROR(_CheckClosed()); |
| |
| START_CALL2(_store, _writer) |
| jdo_flush(ctx, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "flush file failed: ", errorMsg); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| JdoStatus tell(int64_t& offset) override { |
| JDO_RETURN_IF_ERROR(_CheckClosed()); |
| |
| START_CALL2(_store, _writer) |
| offset = jdo_tell(ctx, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "tell file failed: ", errorMsg); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| |
| JdoTaskPtr tellAsync(std::function<void(JdoStatus, int64_t)> callback) override { |
| Int64Args *args = new Int64Args(); |
| args->store = _store; |
| args->writer = _writer; |
| args->callback = callback; |
| START_CALL2(_store, _writer) |
| auto options = jdo_createOptions(); |
| jdo_setInt64Callback(options, tellCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_tellAsync(ctx,options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, _writer, operationCall); |
| } |
| |
| JdoTaskPtr flushAsync(std::function<void(JdoStatus)> callback) override { |
| FlushArgs* args = new FlushArgs(); |
| args->store = _store; |
| args->writer = _writer; |
| args->name = _name; |
| args->callback = callback; |
| |
| START_CALL2(_store, _writer) |
| auto options = jdo_createOptions(); |
| jdo_setBoolCallback(options, flushCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_flushAsync(ctx, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, _writer, operationCall); |
| } |
| |
| JdoStatus close() override { |
| JDO_RETURN_IF_ERROR(_CheckClosed()); |
| |
| START_CALL2(_store, _writer) |
| jdo_close(ctx, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "close file failed: ", errorMsg); |
| } |
| _is_closed = true; |
| return JdoStatus::OK(); |
| } |
| |
| JdoTaskPtr closeAsync(std::function<void(JdoStatus)> callback) override { |
| CloseWriterArgs* args = new CloseWriterArgs(); |
| args->store = _store; |
| args->writer = _writer; |
| args->name = _name; |
| args->isClosed = &_is_closed; |
| args->callback = callback; |
| |
| START_CALL2(_store, _writer) |
| auto options = jdo_createOptions(); |
| jdo_setBoolCallback(options, closeWriterCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_closeAsync(ctx, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, _writer, operationCall); |
| } |
| |
| private: |
| JdoStatus _CheckClosed() { |
| if (_is_closed) { |
| return JdoStatus::IOError("Already closed."); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| std::string _name; |
| JdoStore_t _store; |
| JdoIOContext_t _writer = nullptr; |
| |
| std::atomic<bool> _is_closed = false; |
| }; |
| |
| JdoFileSystem::JdoFileSystem() { |
| } |
| |
| JdoFileSystem::~JdoFileSystem() { |
| if (_store != nullptr) { |
| jdo_freeStore(_store); |
| _store = nullptr; |
| } |
| if (_options != nullptr) { |
| jdo_freeOptions(_options); |
| _options = nullptr; |
| } |
| } |
| |
| JdoStatus JdoFileSystem::init(const std::string &uri, const std::string &user, const std::shared_ptr<JdoConfig>& config) { |
| if (_inited) { |
| return JdoStatus::InitError("already inited"); |
| } |
| |
| _options = jdo_createOptions(); |
| auto configMap = config->getAll(); |
| for (auto& kv : configMap) { |
| jdo_setOption(_options, kv.first.c_str(), kv.second.c_str()); |
| } |
| if (getenv("OSS_ENDPOINT")) { |
| jdo_setOption(_options, "fs.oss.endpoint", getenv("OSS_ENDPOINT")); |
| } |
| if (getenv("OSS_ACCESS_ID")) { |
| jdo_setOption(_options, "fs.oss.accessKeyId", getenv("OSS_ACCESS_ID")); |
| } |
| if (getenv("OSS_ACCESS_KEY")) { |
| jdo_setOption(_options, "fs.oss.accessKeySecret", getenv("OSS_ACCESS_KEY")); |
| } |
| |
| jdo_setOption(_options, "logger.appender", "file"); |
| |
| _store = jdo_createStore(_options, uri.c_str()); |
| |
| START_CALL(_store) |
| jdo_init(ctx, user.c_str()); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| destroy(); |
| return JdoStatus::InitError("create jdo filesystem failed" |
| ", uri: ", uri, |
| ", user: ", user, |
| ", error: ", errorMsg); |
| } |
| |
| _inited = true; |
| return JdoStatus::OK(); |
| } |
| |
| JdoStatus JdoFileSystem::destroy() { |
| if (!_inited) { |
| return JdoStatus::OK(); |
| } |
| |
| if (_store != nullptr) { |
| START_CALL(_store) |
| jdo_destroyStore(_store); |
| END_CALL() |
| jdo_freeStore(_store); |
| _store = nullptr; |
| } |
| if (_options != nullptr) { |
| jdo_freeOptions(_options); |
| _options = nullptr; |
| } |
| _inited = false; |
| |
| return JdoStatus::OK(); |
| } |
| |
| JdoStatus JdoFileSystem::openReader(const std::string &path, |
| std::unique_ptr<JdoReader> *result) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return err; |
| } |
| |
| START_CALL(store) |
| auto stream = jdo_open(ctx, path.c_str(), JDO_OPEN_FLAG_READ_ONLY, 0777, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "open file reader failed: ", errorMsg); |
| } |
| |
| result->reset(new JindoReader(path, store, stream)); |
| |
| return JdoStatus::OK(); |
| } |
| |
| JdoStatus JdoFileSystem::openWriter(const std::string &path, |
| std::unique_ptr<JdoWriter> *result) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return err; |
| } |
| |
| START_CALL(store) |
| auto flag = JDO_OPEN_FLAG_CREATE | JDO_OPEN_FLAG_OVERWRITE; |
| auto handle = jdo_open(ctx, path.c_str(), flag, 0777, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "open file writer failed: ", errorMsg); |
| } |
| |
| result->reset(new JindoWriter(path, store, handle)); |
| return JdoStatus::OK(); |
| } |
| |
| JdoStatus JdoFileSystem::mkdir(const std::string& path, bool recursive) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return err; |
| } |
| |
| START_CALL(store) |
| bool result = jdo_mkdir(ctx, path.c_str(), recursive, 0777, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "mkdir failed: ", errorMsg); |
| } else if (!result) { |
| return JdoStatus::IOError("mkdir failed: ", path); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| struct MkdirArgs { |
| std::string path; |
| bool recursive; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void mkdirCallback(JdoHandleCtx_t ctx, bool result, void* userdata) { |
| MkdirArgs* args = (MkdirArgs*) userdata; |
| auto path = args->path; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "mkdir failed: ", errorMsg); |
| } else if (!result) { |
| status = JdoStatus::IOError("mkdir failed: ", path); |
| } |
| if (callback) { |
| callback(status); |
| } |
| } |
| |
| JdoTaskPtr JdoFileSystem::mkdirAsync(const std::string& path, bool recursive, std::function<void(JdoStatus)> callback) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return nullptr; |
| } |
| |
| MkdirArgs* args = new MkdirArgs(); |
| args->path = path; |
| args->recursive = recursive; |
| args->callback = callback; |
| |
| START_CALL(store) |
| auto options = jdo_createOptions(); |
| jdo_setBoolCallback(options, mkdirCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_mkdirAsync(ctx, path.c_str(), recursive, 0777, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, operationCall); |
| } |
| |
| JdoStatus JdoFileSystem::rename(const std::string &oldpath, const std::string &newpath) { |
| auto [store, err] = GetJdoStore(oldpath); |
| if (!err.ok()) { |
| return err; |
| } |
| |
| if (exists(newpath).ok()) { |
| auto status = remove(newpath, false); |
| if (!status.ok()) { |
| return status; |
| } |
| } |
| |
| START_CALL(store) |
| bool result = jdo_rename(ctx, oldpath.c_str(), newpath.c_str(), nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "rename failed: ", errorMsg); |
| } else if (!result) { |
| return JdoStatus::IOError("rename failed," |
| " from ", oldpath, |
| " to ", newpath); |
| } |
| return JdoStatus::OK(); |
| } |
| |
| struct RenameArgs { |
| std::string oldpath; |
| std::string newpath; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void renameCallback(JdoHandleCtx_t ctx, bool result, void* userdata) { |
| RenameArgs* args = (RenameArgs*) userdata; |
| auto oldpath = args->oldpath; |
| auto newpath = args->newpath; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "rename failed: ", errorMsg); |
| } else if (!result) { |
| status = JdoStatus::IOError("rename failed," |
| " from ", oldpath, |
| " to ", newpath); |
| } |
| if (callback) { |
| callback(status); |
| } |
| } |
| |
| JdoTaskPtr JdoFileSystem::renameAsync(const std::string &oldpath, const std::string &newpath, std::function<void(JdoStatus)> callback) { |
| auto [store, err] = GetJdoStore(oldpath); |
| if (!err.ok()) { |
| return nullptr; |
| } |
| |
| if (exists(newpath).ok()) { |
| auto status = remove(newpath, false); |
| if (!status.ok()) { |
| return nullptr; |
| } |
| } |
| |
| RenameArgs* args = new RenameArgs(); |
| args->oldpath = oldpath; |
| args->newpath = newpath; |
| args->callback = callback; |
| |
| START_CALL(store) |
| auto options = jdo_createOptions(); |
| jdo_setBoolCallback(options, renameCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_renameAsync(ctx, oldpath.c_str(), newpath.c_str(), options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, operationCall); |
| } |
| |
| JdoStatus JdoFileSystem::remove(const std::string& path, bool recursive) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return err; |
| } |
| |
| START_CALL(store) |
| bool result = jdo_remove(ctx, path.c_str(), recursive, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "delete failed: ", errorMsg); |
| } else if (!result) { |
| return JdoStatus::IOError("delete failed: ", path, " recursive ", recursive); |
| } |
| return JdoStatus::OK(); |
| } |
| |
| struct RemoveArgs { |
| std::string path; |
| bool recursive; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void removeCallback(JdoHandleCtx_t ctx, bool result, void* userdata) { |
| RemoveArgs* args = (RemoveArgs*) userdata; |
| auto path = args->path; |
| auto recursive = args->recursive; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "delete failed: ", errorMsg); |
| } else if (!result) { |
| status = JdoStatus::IOError("delete failed: ", path, " recursive ", recursive); |
| } |
| if (callback) { |
| callback(status); |
| } |
| } |
| |
| JdoTaskPtr JdoFileSystem::removeAsync(const std::string& path, bool recursive, std::function<void(JdoStatus)> callback) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return nullptr; |
| } |
| |
| RemoveArgs* args = new RemoveArgs(); |
| args->path = path; |
| args->recursive = recursive; |
| args->callback = callback; |
| |
| START_CALL(store) |
| auto options = jdo_createOptions(); |
| jdo_setBoolCallback(options, removeCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_removeAsync(ctx, path.c_str(), recursive, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, operationCall); |
| } |
| |
| JdoStatus JdoFileSystem::exists(const std::string& path) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return JdoStatus::IOError(err); |
| } |
| |
| START_CALL(store) |
| bool result = jdo_exists(ctx, path.c_str(), nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "exists failed: ", errorMsg); |
| } else if (!result) { |
| return JdoStatus::NotFound(path, " doesn't exist."); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| struct ExistsArgs { |
| std::string path; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void existsCallback(JdoHandleCtx_t ctx, bool result, void* userdata) { |
| ExistsArgs* args = (ExistsArgs*) userdata; |
| auto path = args->path; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "exists failed: ", errorMsg); |
| } else if (!result) { |
| status = JdoStatus::NotFound(path, " doesn't exist."); |
| } |
| if (callback) { |
| callback(status); |
| } |
| } |
| |
| JdoTaskPtr JdoFileSystem::existsAsync(const std::string &path, std::function<void(JdoStatus)> callback) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return nullptr; |
| } |
| |
| ExistsArgs* args = new ExistsArgs(); |
| args->path = path; |
| args->callback = callback; |
| |
| START_CALL(store) |
| auto options = jdo_createOptions(); |
| jdo_setBoolCallback(options, existsCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_existsAsync(ctx, path.c_str(), options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, operationCall); |
| } |
| |
| JdoStatus JdoFileSystem::getFileInfo(const std::string& path, JdoFileInfo* stat) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return err; |
| } |
| |
| return getFileInfoInternal(store, path, stat); |
| } |
| |
| struct GetFileInfoArgs { |
| std::string path; |
| std::function<void(JdoStatus, JdoFileInfoPtr)> callback; |
| }; |
| |
| static void getFileInfoCallback(JdoHandleCtx_t ctx, JdoFileStatus_t fileStatus, void* userdata) { |
| GetFileInfoArgs* args = (GetFileInfoArgs*) userdata; |
| auto path = args->path; |
| std::function<void(JdoStatus, JdoFileInfoPtr)> callback = args->callback; |
| delete args; |
| |
| auto info = std::make_shared<JdoFileInfo>(); |
| covertToFileInfo(fileStatus, info.get()); |
| jdo_freeFileStatus(fileStatus); |
| |
| END_CALL() |
| JdoStatus status; |
| if (errorCode != 0) { |
| if (errorCode == JDO_FILE_NOT_FOUND_ERROR) { |
| status = JdoStatus::NotFound("cant not found ", path); |
| } else { |
| status = JdoStatus::InternalError(errorCode, "get status failed: ", errorMsg); |
| } |
| } |
| |
| if (callback) { |
| callback(status, info); |
| } |
| } |
| |
| JdoTaskPtr JdoFileSystem::getFileInfoAsync(const std::string &path, std::function<void(JdoStatus, JdoFileInfoPtr)> callback) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return nullptr; |
| } |
| |
| GetFileInfoArgs* args = new GetFileInfoArgs(); |
| args->path = path; |
| args->callback = callback; |
| |
| START_CALL(store) |
| auto options = jdo_createOptions(); |
| jdo_setFileStatusCallback(options, getFileInfoCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_getFileStatusAsync(ctx, path.c_str(), options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, operationCall); |
| } |
| |
| JdoStatus JdoFileSystem::listDir(const std::string &dir, bool recursive, JdoListResult *result) { |
| auto [store, err] = GetJdoStore(dir); |
| if (!err.ok()) { |
| return err; |
| } |
| |
| START_CALL(store) |
| JdoListDirResult_t listResult = jdo_listDir(ctx, dir.c_str(), recursive, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "get children failed: ", errorMsg); |
| } |
| |
| auto numEntries = jdo_getListDirResultSize(listResult); |
| for (int i = 0; i < numEntries; i++) { |
| auto fileStatus = jdo_getListDirFileStatus(listResult, i); |
| if (fileStatus == nullptr) { |
| continue; |
| } |
| JdoFileInfo info; |
| covertToFileInfo(fileStatus, &info); |
| result->infos.push_back(info); |
| } |
| result->truncated = jdo_isListDirResultTruncated(listResult); |
| auto nextMarker = jdo_getListDirResultNextMarker(listResult); |
| if (nextMarker) { |
| result->nextMarker = nextMarker; |
| } |
| |
| jdo_freeListDirResult(listResult); |
| return JdoStatus::OK(); |
| } |
| |
| struct listDirArgs { |
| std::string path; |
| std::function<void(JdoStatus, JdoListResultPtr)> callback; |
| }; |
| |
| static void listDirCallback(JdoHandleCtx_t ctx, JdoListDirResult_t listResult, void* userdata) { |
| listDirArgs* args = (listDirArgs*) userdata; |
| auto path = args->path; |
| std::function<void(JdoStatus, JdoListResultPtr result)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| JdoStatus status; |
| auto result = std::make_shared<JdoListResult>(); |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "get children failed: ", errorMsg); |
| callback(status, result); |
| return; |
| } |
| |
| auto numEntries = jdo_getListDirResultSize(listResult); |
| for (int i = 0; i < numEntries; i++) { |
| auto fileStatus = jdo_getListDirFileStatus(listResult, i); |
| if (fileStatus == nullptr) { |
| continue; |
| } |
| JdoFileInfo info; |
| covertToFileInfo(fileStatus, &info); |
| result->infos.push_back(info); |
| } |
| result->truncated = jdo_isListDirResultTruncated(listResult); |
| auto nextMarker = jdo_getListDirResultNextMarker(listResult); |
| if (nextMarker) { |
| result->nextMarker = nextMarker; |
| } |
| |
| jdo_freeListDirResult(listResult); |
| |
| if (callback) { |
| callback(status, result); |
| } |
| } |
| |
| JdoTaskPtr JdoFileSystem::listDirAsync(const std::string &path, bool recursive, std::function<void(JdoStatus, JdoListResultPtr)> callback) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return nullptr; |
| } |
| |
| listDirArgs* args = new listDirArgs(); |
| args->path = path; |
| args->callback = callback; |
| |
| START_CALL(store) |
| auto options = jdo_createOptions(); |
| jdo_setListDirResultCallback(options, listDirCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_listDirAsync(ctx, path.c_str(), false, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, operationCall); |
| } |
| |
| JdoStatus JdoFileSystem::getContentSummary(const std::string &dir, bool recursive, JdoContentSummary *result) { |
| auto [store, err] = GetJdoStore(dir); |
| if (!err.ok()) { |
| return err; |
| } |
| |
| START_CALL(store) |
| JdoContentSummary_t contentSummary = jdo_getContentSummary(ctx, dir.c_str(), recursive, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "get content summary failed: ", errorMsg); |
| } |
| |
| result->fileSize = jdo_getContentSummaryFileSize(contentSummary); |
| result->fileCount = jdo_getContentSummaryFileCount(contentSummary); |
| result->dirCount = jdo_getContentSummaryDirectoryCount(contentSummary); |
| |
| jdo_freeContentSummary(contentSummary); |
| return JdoStatus::OK(); |
| } |
| |
| struct GetContentSummaryArgs { |
| std::string path; |
| std::function<void(JdoStatus, JdoContentSummaryPtr)> callback; |
| }; |
| |
| static void getContentSummaryCallback(JdoHandleCtx_t ctx, JdoContentSummary_t contentSummary, void* userdata) { |
| GetContentSummaryArgs* args = (GetContentSummaryArgs*) userdata; |
| auto path = args->path; |
| std::function<void(JdoStatus, JdoContentSummaryPtr result)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| JdoStatus status; |
| auto result = std::make_shared<JdoContentSummary>(); |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "get content summary failed: ", errorMsg); |
| callback(status, result); |
| return; |
| } |
| |
| result->fileSize = jdo_getContentSummaryFileSize(contentSummary); |
| result->fileCount = jdo_getContentSummaryFileCount(contentSummary); |
| result->dirCount = jdo_getContentSummaryDirectoryCount(contentSummary); |
| |
| jdo_freeContentSummary(contentSummary); |
| |
| if (callback) { |
| callback(status, result); |
| } |
| } |
| |
| JdoTaskPtr JdoFileSystem::getContentSummaryAsync(const std::string &path, bool recursive, std::function<void(JdoStatus, JdoContentSummaryPtr)> callback) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return nullptr; |
| } |
| |
| GetContentSummaryArgs* args = new GetContentSummaryArgs(); |
| args->path = path; |
| args->callback = callback; |
| |
| START_CALL(store) |
| auto options = jdo_createOptions(); |
| jdo_setContentSummaryCallback(options, getContentSummaryCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_getContentSummaryAsync(ctx, path.c_str(), false, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, operationCall); |
| } |
| |
| JdoStatus JdoFileSystem::setPermission(const std::string& path, int16_t perm) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return err; |
| } |
| |
| START_CALL(store) |
| bool result = jdo_setPermission(ctx, path.c_str(), perm, nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "setPermission failed: ", errorMsg); |
| } else if (!result) { |
| return JdoStatus::IOError("setPermission failed: ", path); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| struct SetPermissionArgs { |
| std::string path; |
| int16_t perm; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void setPermissionCallback(JdoHandleCtx_t ctx, bool result, void* userdata) { |
| SetPermissionArgs* args = (SetPermissionArgs*) userdata; |
| auto path = args->path; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "setPermission failed: ", errorMsg); |
| } else if (!result) { |
| status = JdoStatus::IOError("setPermission failed: ", path); |
| } |
| if (callback) { |
| callback(status); |
| } |
| } |
| |
| JdoTaskPtr JdoFileSystem::setPermissionAsync(const std::string& path, int16_t perm, std::function<void(JdoStatus)> callback) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return nullptr; |
| } |
| |
| SetPermissionArgs* args = new SetPermissionArgs(); |
| args->path = path; |
| args->perm = perm; |
| args->callback = callback; |
| |
| START_CALL(store) |
| auto options = jdo_createOptions(); |
| jdo_setBoolCallback(options, setPermissionCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_setPermissionAsync(ctx, path.c_str(), perm, options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, operationCall); |
| } |
| |
| |
| JdoStatus JdoFileSystem::setOwner(const std::string& path, const std::string& user, const std::string& group) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return err; |
| } |
| |
| START_CALL(store) |
| bool result = jdo_setOwner(ctx, path.c_str(), user.c_str(), group.c_str(), nullptr); |
| END_CALL() |
| |
| if (errorCode != 0) { |
| return JdoStatus::InternalError(errorCode, "setOwner failed: ", errorMsg); |
| } else if (!result) { |
| return JdoStatus::IOError("setOwner failed: ", path); |
| } |
| |
| return JdoStatus::OK(); |
| } |
| |
| struct SetOwnerArgs { |
| std::string path; |
| std::string user; |
| std::string group; |
| std::function<void(JdoStatus)> callback; |
| }; |
| |
| static void setOwnerCallback(JdoHandleCtx_t ctx, bool result, void* userdata) { |
| SetOwnerArgs* args = (SetOwnerArgs*) userdata; |
| auto path = args->path; |
| std::function<void(JdoStatus)> callback = args->callback; |
| delete args; |
| |
| END_CALL() |
| JdoStatus status; |
| if (errorCode != 0) { |
| status = JdoStatus::InternalError(errorCode, "setOwner failed: ", errorMsg); |
| } else if (!result) { |
| status = JdoStatus::IOError("setOwner failed: ", path); |
| } |
| if (callback) { |
| callback(status); |
| } |
| } |
| |
| JdoTaskPtr JdoFileSystem::setOwnerAsync(const std::string& path, const std::string& user, const std::string& group, std::function<void(JdoStatus)> callback) { |
| auto [store, err] = GetJdoStore(path); |
| if (!err.ok()) { |
| return nullptr; |
| } |
| |
| SetOwnerArgs* args = new SetOwnerArgs(); |
| args->path = path; |
| args->user = user; |
| args->group = group; |
| args->callback = callback; |
| |
| START_CALL(store) |
| auto options = jdo_createOptions(); |
| jdo_setBoolCallback(options, setOwnerCallback); |
| jdo_setCallbackContext(options, args); |
| auto operationCall = jdo_setOwnerAsync(ctx, path.c_str(), user.c_str(), group.c_str(), options); |
| END_CALL() |
| jdo_freeOptions(options); |
| |
| return std::make_shared<JindoOperation>(_store, operationCall); |
| } |
| |
| JdoStatus JdoFileSystem::getFileInfoInternal(JdoStore_t store, |
| const std::string &path, |
| JdoFileInfo *info) { |
| START_CALL(store) |
| JdoFileStatus_t fileStatus = jdo_getFileStatus(ctx, path.c_str(), nullptr); |
| END_CALL() |
| |
| JdoStatus ret; |
| if (errorCode != 0) { |
| if (errorCode == JDO_FILE_NOT_FOUND_ERROR) { |
| return JdoStatus::NotFound("cant not found ", path); |
| } |
| return JdoStatus::InternalError(errorCode, "get status failed: ", errorMsg); |
| } |
| |
| covertToFileInfo(fileStatus, info); |
| |
| jdo_freeFileStatus(fileStatus); |
| return JdoStatus::OK(); |
| } |
| |
| std::tuple<JdoStore_t, JdoStatus> JdoFileSystem::GetJdoStore(const std::string &uri) { |
| if (!_inited) { |
| return {nullptr, JdoStatus::InitError()}; |
| } |
| return {_store, JdoStatus::OK()}; |
| } |
| |