HDFS-15843. Make write cross-platform (#2710)

This commit is contained in:
Gautham B A 2021-03-16 21:36:51 +05:30 committed by GitHub
parent 73394fabc7
commit 47620f8821
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 210 additions and 15 deletions

View File

@ -23,5 +23,6 @@ set(LIBHDFSPP_DIR CACHE STRING ${CMAKE_INSTALL_PREFIX})
include_directories( ${LIBHDFSPP_DIR}/include ) include_directories( ${LIBHDFSPP_DIR}/include )
link_directories( ${LIBHDFSPP_DIR}/lib ) link_directories( ${LIBHDFSPP_DIR}/lib )
add_executable(connect_cancel_c connect_cancel.c) add_executable(connect_cancel_c $<TARGET_OBJECTS:x_platform_utils_obj_c_api> connect_cancel.c)
target_link_libraries(connect_cancel_c hdfspp_static uriparser2) target_link_libraries(connect_cancel_c hdfspp_static uriparser2)
target_include_directories(connect_cancel_c PRIVATE ../../lib)

View File

@ -26,10 +26,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
#include <unistd.h>
#include "hdfspp/hdfs_ext.h" #include "hdfspp/hdfs_ext.h"
#include "common/util_c.h" #include "common/util_c.h"
#include "x-platform/c_api.h"
#define ERROR_BUFFER_SIZE 1024 #define ERROR_BUFFER_SIZE 1024
@ -43,10 +43,10 @@ const char *catch_exit = "Exiting the signal handler.\n";
// Print to stdout without calling malloc or otherwise indirectly modify userspace state. // Print to stdout without calling malloc or otherwise indirectly modify userspace state.
// Write calls to stdout may still interleave with stuff coming from elsewhere. // Write calls to stdout may still interleave with stuff coming from elsewhere.
static void sighandler_direct_stdout(const char *msg) { static void sighandler_direct_stdout(const char *msg) {
if(!msg) if(!msg) {
return; return;
ssize_t res = write(1 /*posix stdout fd*/, msg, strlen(msg)); }
(void)res; x_platform_syscall_write_to_stdout(msg);
} }
static void sig_catch(int val) { static void sig_catch(int val) {

View File

@ -23,5 +23,6 @@ set(LIBHDFSPP_DIR CACHE STRING ${CMAKE_INSTALL_PREFIX})
include_directories( ${LIBHDFSPP_DIR}/include ) include_directories( ${LIBHDFSPP_DIR}/include )
link_directories( ${LIBHDFSPP_DIR}/lib ) link_directories( ${LIBHDFSPP_DIR}/lib )
add_executable(connect_cancel connect_cancel.cc) add_executable(connect_cancel $<TARGET_OBJECTS:x_platform_utils_obj> connect_cancel.cc)
target_link_libraries(connect_cancel hdfspp_static) target_link_libraries(connect_cancel hdfspp_static)
target_include_directories(connect_cancel PRIVATE ../../lib)

View File

@ -25,11 +25,12 @@
#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/common.h>
#include <signal.h> #include <signal.h>
#include <unistd.h>
#include <thread> #include <thread>
#include <iostream> #include <iostream>
#include "x-platform/syscall.h"
// Simple example of how to cancel an async connect call. // Simple example of how to cancel an async connect call.
// Here Control-C (SIGINT) is caught in order to invoke the FS level cancel and // Here Control-C (SIGINT) is caught in order to invoke the FS level cancel and
// properly tear down the process. Valgrind should show no leaked memory on exit // properly tear down the process. Valgrind should show no leaked memory on exit
@ -47,11 +48,10 @@ const std::string catch_exit("Exiting the signal handler.\n");
// It's possible that the write interleaves with another write call, // It's possible that the write interleaves with another write call,
// but it won't corrupt the stack or heap. // but it won't corrupt the stack or heap.
static void sighandler_direct_stdout(const std::string &msg) { static void sighandler_direct_stdout(const std::string &msg) {
ssize_t res = ::write(1 /*posix stdout FD*/, msg.data(), msg.size()); XPlatform::Syscall::WriteToStdout(msg);
// In production you'd want to check res, but error handling code will // In production you'd want to check the result of the above call,
// need to be fairly application specific if it's going to properly // but error handling code will need to be fairly application
// avoid reentrant calls to malloc. // specific if it's going to properly avoid reentrant calls to malloc.
(void)res;
} }
// Signal handler to make a SIGINT call cancel rather than exit(). // Signal handler to make a SIGINT call cancel rather than exit().

View File

@ -16,4 +16,11 @@
# limitations under the License. # limitations under the License.
# #
add_library(x_platform_utils_obj OBJECT utils.cc) if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
set(SYSCALL_SRC syscall_windows.cc)
else()
set(SYSCALL_SRC syscall_linux.cc)
endif()
add_library(x_platform_utils_obj OBJECT ${SYSCALL_SRC} utils.cc)
add_library(x_platform_utils_obj_c_api OBJECT $<TARGET_OBJECTS:x_platform_utils_obj> c_api.cc)

View File

@ -0,0 +1,23 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "syscall.h"
extern "C" int x_platform_syscall_write_to_stdout(const char* msg) {
return XPlatform::Syscall::WriteToStdout(msg) ? 1 : 0;
}

View File

@ -0,0 +1,28 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#ifndef NATIVE_LIBHDFSPP_LIB_CROSS_PLATFORM_C_API_H
#define NATIVE_LIBHDFSPP_LIB_CROSS_PLATFORM_C_API_H
/**
* C APIs for accessing XPlatform
*/
int x_platform_syscall_write_to_stdout(const char* msg);
#endif // NATIVE_LIBHDFSPP_LIB_CROSS_PLATFORM_C_API_H

View File

@ -0,0 +1,56 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#ifndef NATIVE_LIBHDFSPP_LIB_CROSS_PLATFORM_SYSCALL
#define NATIVE_LIBHDFSPP_LIB_CROSS_PLATFORM_SYSCALL
#include <string>
/**
* The {@link XPlatform} namespace contains components that
* aid in writing cross-platform code.
*/
namespace XPlatform {
class Syscall {
public:
/**
* Writes the given string to the application's
* standard output stream.
*
* @param message The string to write to stdout.
* @returns A boolean indicating whether the write
* was successful.
*/
static bool WriteToStdout(const std::string& message);
/**
* Writes the given char pointer to the application's
* standard output stream.
*
* @param message The char pointer to write to stdout.
* @returns A boolean indicating whether the write
* was successful.
*/
static int WriteToStdout(const char* message);
private:
static bool WriteToStdoutImpl(const char* message);
};
} // namespace XPlatform
#endif

View File

@ -0,0 +1,37 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <unistd.h>
#include <cstring>
#include "syscall.h"
bool XPlatform::Syscall::WriteToStdout(const std::string& message) {
return WriteToStdoutImpl(message.c_str());
}
int XPlatform::Syscall::WriteToStdout(const char* message) {
return WriteToStdoutImpl(message) ? 1 : 0;
}
bool XPlatform::Syscall::WriteToStdoutImpl(const char* message) {
const auto message_len = strlen(message);
const auto result = write(1, message, message_len);
return result == static_cast<ssize_t>(message_len);
}

View File

@ -0,0 +1,42 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Windows.h>
#include "syscall.h"
bool XPlatform::Syscall::WriteToStdout(const std::string& message) {
return WriteToStdoutImpl(message.c_str());
}
int XPlatform::Syscall::WriteToStdout(const char* message) {
return WriteToStdoutImpl(message) ? 1 : 0;
}
bool XPlatform::Syscall::WriteToStdoutImpl(const char* message) {
auto* const stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
if (stdout_handle == INVALID_HANDLE_VALUE || stdout_handle == nullptr) {
return false;
}
unsigned long bytes_written = 0;
const auto message_len = lstrlen(message);
const auto result =
WriteFile(stdout_handle, message, message_len, &bytes_written, nullptr);
return result && static_cast<unsigned long>(message_len) == bytes_written;
}

View File

@ -16,7 +16,7 @@
* limitations under the License. * limitations under the License.
*/ */
#include "x-platform/utils.h" #include "utils.h"
#include <filesystem> #include <filesystem>
#include <string> #include <string>