| 1 | // Licensed to the Apache Software Foundation (ASF) under one |
| 2 | // or more contributor license agreements. See the NOTICE file |
| 3 | // distributed with this work for additional information |
| 4 | // regarding copyright ownership. The ASF licenses this file |
| 5 | // to you under the Apache License, Version 2.0 (the |
| 6 | // "License"); you may not use this file except in compliance |
| 7 | // with the License. You may obtain a copy of the License at |
| 8 | // |
| 9 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | // |
| 11 | // Unless required by applicable law or agreed to in writing, |
| 12 | // software distributed under the License is distributed on an |
| 13 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 14 | // KIND, either express or implied. See the License for the |
| 15 | // specific language governing permissions and limitations |
| 16 | // under the License. |
| 17 | |
| 18 | // This shim interface to libhdfs (for runtime shared library loading) has been |
| 19 | // adapted from the SFrame project, released under the ASF-compatible 3-clause |
| 20 | // BSD license |
| 21 | // |
| 22 | // Using this required having the $JAVA_HOME and $HADOOP_HOME environment |
| 23 | // variables set, so that libjvm and libhdfs can be located easily |
| 24 | |
| 25 | // Copyright (C) 2015 Dato, Inc. |
| 26 | // All rights reserved. |
| 27 | // |
| 28 | // This software may be modified and distributed under the terms |
| 29 | // of the BSD license. See the LICENSE file for details. |
| 30 | |
| 31 | #include "arrow/io/hdfs-internal.h" |
| 32 | |
| 33 | #include <cstdint> |
| 34 | #include <cstdlib> |
| 35 | #include <mutex> |
| 36 | #include <sstream> // IWYU pragma: keep |
| 37 | #include <string> |
| 38 | #include <vector> |
| 39 | |
| 40 | #ifndef _WIN32 |
| 41 | #include <dlfcn.h> |
| 42 | #endif |
| 43 | |
| 44 | #include <boost/filesystem.hpp> // NOLINT |
| 45 | |
| 46 | #include "arrow/status.h" |
| 47 | #include "arrow/util/logging.h" |
| 48 | |
| 49 | namespace fs = boost::filesystem; |
| 50 | |
| 51 | #ifndef _WIN32 |
| 52 | static void* libjvm_handle = NULL; |
| 53 | #else |
| 54 | static HINSTANCE libjvm_handle = NULL; |
| 55 | #endif |
| 56 | /* |
| 57 | * All the shim pointers |
| 58 | */ |
| 59 | |
| 60 | // Helper functions for dlopens |
| 61 | static std::vector<fs::path> get_potential_libjvm_paths(); |
| 62 | static std::vector<fs::path> get_potential_libhdfs_paths(); |
| 63 | static std::vector<fs::path> get_potential_libhdfs3_paths(); |
| 64 | static arrow::Status try_dlopen(std::vector<fs::path> potential_paths, const char* name, |
| 65 | #ifndef _WIN32 |
| 66 | void*& out_handle); |
| 67 | #else |
| 68 | HINSTANCE& out_handle); |
| 69 | #endif |
| 70 | |
| 71 | static std::vector<fs::path> get_potential_libhdfs_paths() { |
| 72 | std::vector<fs::path> libhdfs_potential_paths; |
| 73 | std::string file_name; |
| 74 | |
| 75 | // OS-specific file name |
| 76 | #ifdef _WIN32 |
| 77 | file_name = "hdfs.dll" ; |
| 78 | #elif __APPLE__ |
| 79 | file_name = "libhdfs.dylib" ; |
| 80 | #else |
| 81 | file_name = "libhdfs.so" ; |
| 82 | #endif |
| 83 | |
| 84 | // Common paths |
| 85 | std::vector<fs::path> search_paths = {fs::path("" ), fs::path("." )}; |
| 86 | |
| 87 | // Path from environment variable |
| 88 | const char* hadoop_home = std::getenv("HADOOP_HOME" ); |
| 89 | if (hadoop_home != nullptr) { |
| 90 | auto path = fs::path(hadoop_home) / "lib/native" ; |
| 91 | search_paths.push_back(path); |
| 92 | } |
| 93 | |
| 94 | const char* libhdfs_dir = std::getenv("ARROW_LIBHDFS_DIR" ); |
| 95 | if (libhdfs_dir != nullptr) { |
| 96 | search_paths.push_back(fs::path(libhdfs_dir)); |
| 97 | } |
| 98 | |
| 99 | // All paths with file name |
| 100 | for (auto& path : search_paths) { |
| 101 | libhdfs_potential_paths.push_back(path / file_name); |
| 102 | } |
| 103 | |
| 104 | return libhdfs_potential_paths; |
| 105 | } |
| 106 | |
| 107 | static std::vector<fs::path> get_potential_libhdfs3_paths() { |
| 108 | std::vector<fs::path> potential_paths; |
| 109 | std::string file_name; |
| 110 | |
| 111 | // OS-specific file name |
| 112 | #ifdef _WIN32 |
| 113 | file_name = "hdfs3.dll" ; |
| 114 | #elif __APPLE__ |
| 115 | file_name = "libhdfs3.dylib" ; |
| 116 | #else |
| 117 | file_name = "libhdfs3.so" ; |
| 118 | #endif |
| 119 | |
| 120 | // Common paths |
| 121 | std::vector<fs::path> search_paths = {fs::path("" ), fs::path("." )}; |
| 122 | |
| 123 | const char* libhdfs3_dir = std::getenv("ARROW_LIBHDFS3_DIR" ); |
| 124 | if (libhdfs3_dir != nullptr) { |
| 125 | search_paths.push_back(fs::path(libhdfs3_dir)); |
| 126 | } |
| 127 | |
| 128 | // All paths with file name |
| 129 | for (auto& path : search_paths) { |
| 130 | potential_paths.push_back(path / file_name); |
| 131 | } |
| 132 | |
| 133 | return potential_paths; |
| 134 | } |
| 135 | |
| 136 | static std::vector<fs::path> get_potential_libjvm_paths() { |
| 137 | std::vector<fs::path> libjvm_potential_paths; |
| 138 | |
| 139 | std::vector<fs::path> search_prefixes; |
| 140 | std::vector<fs::path> search_suffixes; |
| 141 | std::string file_name; |
| 142 | |
| 143 | // From heuristics |
| 144 | #ifdef __WIN32 |
| 145 | search_prefixes = {"" }; |
| 146 | search_suffixes = {"/jre/bin/server" , "/bin/server" }; |
| 147 | file_name = "jvm.dll" ; |
| 148 | #elif __APPLE__ |
| 149 | search_prefixes = {"" }; |
| 150 | search_suffixes = {"" , "/jre/lib/server" , "/lib/server" }; |
| 151 | file_name = "libjvm.dylib" ; |
| 152 | |
| 153 | // SFrame uses /usr/libexec/java_home to find JAVA_HOME; for now we are |
| 154 | // expecting users to set an environment variable |
| 155 | #else |
| 156 | search_prefixes = { |
| 157 | "/usr/lib/jvm/default-java" , // ubuntu / debian distros |
| 158 | "/usr/lib/jvm/java" , // rhel6 |
| 159 | "/usr/lib/jvm" , // centos6 |
| 160 | "/usr/lib64/jvm" , // opensuse 13 |
| 161 | "/usr/local/lib/jvm/default-java" , // alt ubuntu / debian distros |
| 162 | "/usr/local/lib/jvm/java" , // alt rhel6 |
| 163 | "/usr/local/lib/jvm" , // alt centos6 |
| 164 | "/usr/local/lib64/jvm" , // alt opensuse 13 |
| 165 | "/usr/local/lib/jvm/java-7-openjdk-amd64" , // alt ubuntu / debian distros |
| 166 | "/usr/lib/jvm/java-7-openjdk-amd64" , // alt ubuntu / debian distros |
| 167 | "/usr/local/lib/jvm/java-6-openjdk-amd64" , // alt ubuntu / debian distros |
| 168 | "/usr/lib/jvm/java-6-openjdk-amd64" , // alt ubuntu / debian distros |
| 169 | "/usr/lib/jvm/java-7-oracle" , // alt ubuntu |
| 170 | "/usr/lib/jvm/java-8-oracle" , // alt ubuntu |
| 171 | "/usr/lib/jvm/java-6-oracle" , // alt ubuntu |
| 172 | "/usr/local/lib/jvm/java-7-oracle" , // alt ubuntu |
| 173 | "/usr/local/lib/jvm/java-8-oracle" , // alt ubuntu |
| 174 | "/usr/local/lib/jvm/java-6-oracle" , // alt ubuntu |
| 175 | "/usr/lib/jvm/default" , // alt centos |
| 176 | "/usr/java/latest" , // alt centos |
| 177 | }; |
| 178 | search_suffixes = {"" , "/jre/lib/amd64/server" , "/lib/amd64/server" }; |
| 179 | file_name = "libjvm.so" ; |
| 180 | #endif |
| 181 | // From direct environment variable |
| 182 | char* env_value = NULL; |
| 183 | if ((env_value = getenv("JAVA_HOME" )) != NULL) { |
| 184 | search_prefixes.insert(search_prefixes.begin(), env_value); |
| 185 | } |
| 186 | |
| 187 | // Generate cross product between search_prefixes, search_suffixes, and file_name |
| 188 | for (auto& prefix : search_prefixes) { |
| 189 | for (auto& suffix : search_suffixes) { |
| 190 | auto path = (fs::path(prefix) / fs::path(suffix) / fs::path(file_name)); |
| 191 | libjvm_potential_paths.push_back(path); |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | return libjvm_potential_paths; |
| 196 | } |
| 197 | |
| 198 | #ifndef _WIN32 |
| 199 | static arrow::Status try_dlopen(std::vector<fs::path> potential_paths, const char* name, |
| 200 | void*& out_handle) { |
| 201 | std::vector<std::string> error_messages; |
| 202 | |
| 203 | for (auto& i : potential_paths) { |
| 204 | i.make_preferred(); |
| 205 | out_handle = dlopen(i.native().c_str(), RTLD_NOW | RTLD_LOCAL); |
| 206 | |
| 207 | if (out_handle != NULL) { |
| 208 | // std::cout << "Loaded " << i << std::endl; |
| 209 | break; |
| 210 | } else { |
| 211 | const char* err_msg = dlerror(); |
| 212 | if (err_msg != NULL) { |
| 213 | error_messages.push_back(std::string(err_msg)); |
| 214 | } else { |
| 215 | error_messages.push_back(std::string(" returned NULL" )); |
| 216 | } |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | if (out_handle == NULL) { |
| 221 | return arrow::Status::IOError("Unable to load " , name); |
| 222 | } |
| 223 | |
| 224 | return arrow::Status::OK(); |
| 225 | } |
| 226 | |
| 227 | #else |
| 228 | static arrow::Status try_dlopen(std::vector<fs::path> potential_paths, const char* name, |
| 229 | HINSTANCE& out_handle) { |
| 230 | std::vector<std::string> error_messages; |
| 231 | |
| 232 | for (auto& i : potential_paths) { |
| 233 | i.make_preferred(); |
| 234 | out_handle = LoadLibrary(i.string().c_str()); |
| 235 | |
| 236 | if (out_handle != NULL) { |
| 237 | break; |
| 238 | } else { |
| 239 | // error_messages.push_back(get_last_err_str(GetLastError())); |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | if (out_handle == NULL) { |
| 244 | return arrow::Status::IOError("Unable to load " , name); |
| 245 | } |
| 246 | |
| 247 | return arrow::Status::OK(); |
| 248 | } |
| 249 | #endif // _WIN32 |
| 250 | |
| 251 | static inline void* GetLibrarySymbol(void* handle, const char* symbol) { |
| 252 | if (handle == NULL) return NULL; |
| 253 | #ifndef _WIN32 |
| 254 | return dlsym(handle, symbol); |
| 255 | #else |
| 256 | |
| 257 | void* ret = reinterpret_cast<void*>( |
| 258 | GetProcAddress(reinterpret_cast<HINSTANCE>(handle), symbol)); |
| 259 | if (ret == NULL) { |
| 260 | // logstream(LOG_INFO) << "GetProcAddress error: " |
| 261 | // << get_last_err_str(GetLastError()) << std::endl; |
| 262 | } |
| 263 | return ret; |
| 264 | #endif |
| 265 | } |
| 266 | |
| 267 | #define GET_SYMBOL_REQUIRED(SHIM, SYMBOL_NAME) \ |
| 268 | do { \ |
| 269 | if (!SHIM->SYMBOL_NAME) { \ |
| 270 | *reinterpret_cast<void**>(&SHIM->SYMBOL_NAME) = \ |
| 271 | GetLibrarySymbol(SHIM->handle, "" #SYMBOL_NAME); \ |
| 272 | } \ |
| 273 | if (!SHIM->SYMBOL_NAME) \ |
| 274 | return Status::IOError("Getting symbol " #SYMBOL_NAME "failed"); \ |
| 275 | } while (0) |
| 276 | |
| 277 | #define GET_SYMBOL(SHIM, SYMBOL_NAME) \ |
| 278 | if (!SHIM->SYMBOL_NAME) { \ |
| 279 | *reinterpret_cast<void**>(&SHIM->SYMBOL_NAME) = \ |
| 280 | GetLibrarySymbol(SHIM->handle, "" #SYMBOL_NAME); \ |
| 281 | } |
| 282 | |
| 283 | namespace arrow { |
| 284 | namespace io { |
| 285 | namespace internal { |
| 286 | |
| 287 | static LibHdfsShim libhdfs_shim; |
| 288 | static LibHdfsShim libhdfs3_shim; |
| 289 | |
| 290 | hdfsBuilder* LibHdfsShim::NewBuilder(void) { return this->hdfsNewBuilder(); } |
| 291 | |
| 292 | void LibHdfsShim::BuilderSetNameNode(hdfsBuilder* bld, const char* nn) { |
| 293 | this->hdfsBuilderSetNameNode(bld, nn); |
| 294 | } |
| 295 | |
| 296 | void LibHdfsShim::BuilderSetNameNodePort(hdfsBuilder* bld, tPort port) { |
| 297 | this->hdfsBuilderSetNameNodePort(bld, port); |
| 298 | } |
| 299 | |
| 300 | void LibHdfsShim::BuilderSetUserName(hdfsBuilder* bld, const char* userName) { |
| 301 | this->hdfsBuilderSetUserName(bld, userName); |
| 302 | } |
| 303 | |
| 304 | void LibHdfsShim::BuilderSetKerbTicketCachePath(hdfsBuilder* bld, |
| 305 | const char* kerbTicketCachePath) { |
| 306 | this->hdfsBuilderSetKerbTicketCachePath(bld, kerbTicketCachePath); |
| 307 | } |
| 308 | |
| 309 | void LibHdfsShim::BuilderSetForceNewInstance(hdfsBuilder* bld) { |
| 310 | this->hdfsBuilderSetForceNewInstance(bld); |
| 311 | } |
| 312 | |
| 313 | hdfsFS LibHdfsShim::BuilderConnect(hdfsBuilder* bld) { |
| 314 | return this->hdfsBuilderConnect(bld); |
| 315 | } |
| 316 | |
| 317 | int LibHdfsShim::BuilderConfSetStr(hdfsBuilder* bld, const char* key, const char* val) { |
| 318 | return this->hdfsBuilderConfSetStr(bld, key, val); |
| 319 | } |
| 320 | |
| 321 | int LibHdfsShim::Disconnect(hdfsFS fs) { return this->hdfsDisconnect(fs); } |
| 322 | |
| 323 | hdfsFile LibHdfsShim::OpenFile(hdfsFS fs, const char* path, int flags, int bufferSize, |
| 324 | short replication, tSize blocksize) { // NOLINT |
| 325 | return this->hdfsOpenFile(fs, path, flags, bufferSize, replication, blocksize); |
| 326 | } |
| 327 | |
| 328 | int LibHdfsShim::CloseFile(hdfsFS fs, hdfsFile file) { |
| 329 | return this->hdfsCloseFile(fs, file); |
| 330 | } |
| 331 | |
| 332 | int LibHdfsShim::Exists(hdfsFS fs, const char* path) { |
| 333 | return this->hdfsExists(fs, path); |
| 334 | } |
| 335 | |
| 336 | int LibHdfsShim::Seek(hdfsFS fs, hdfsFile file, tOffset desiredPos) { |
| 337 | return this->hdfsSeek(fs, file, desiredPos); |
| 338 | } |
| 339 | |
| 340 | tOffset LibHdfsShim::Tell(hdfsFS fs, hdfsFile file) { return this->hdfsTell(fs, file); } |
| 341 | |
| 342 | tSize LibHdfsShim::Read(hdfsFS fs, hdfsFile file, void* buffer, tSize length) { |
| 343 | return this->hdfsRead(fs, file, buffer, length); |
| 344 | } |
| 345 | |
| 346 | bool LibHdfsShim::HasPread() { |
| 347 | GET_SYMBOL(this, hdfsPread); |
| 348 | return this->hdfsPread != nullptr; |
| 349 | } |
| 350 | |
| 351 | tSize LibHdfsShim::Pread(hdfsFS fs, hdfsFile file, tOffset position, void* buffer, |
| 352 | tSize length) { |
| 353 | GET_SYMBOL(this, hdfsPread); |
| 354 | DCHECK(this->hdfsPread); |
| 355 | return this->hdfsPread(fs, file, position, buffer, length); |
| 356 | } |
| 357 | |
| 358 | tSize LibHdfsShim::Write(hdfsFS fs, hdfsFile file, const void* buffer, tSize length) { |
| 359 | return this->hdfsWrite(fs, file, buffer, length); |
| 360 | } |
| 361 | |
| 362 | int LibHdfsShim::Flush(hdfsFS fs, hdfsFile file) { return this->hdfsFlush(fs, file); } |
| 363 | |
| 364 | int LibHdfsShim::Available(hdfsFS fs, hdfsFile file) { |
| 365 | GET_SYMBOL(this, hdfsAvailable); |
| 366 | if (this->hdfsAvailable) |
| 367 | return this->hdfsAvailable(fs, file); |
| 368 | else |
| 369 | return 0; |
| 370 | } |
| 371 | |
| 372 | int LibHdfsShim::Copy(hdfsFS srcFS, const char* src, hdfsFS dstFS, const char* dst) { |
| 373 | GET_SYMBOL(this, hdfsCopy); |
| 374 | if (this->hdfsCopy) |
| 375 | return this->hdfsCopy(srcFS, src, dstFS, dst); |
| 376 | else |
| 377 | return 0; |
| 378 | } |
| 379 | |
| 380 | int LibHdfsShim::Move(hdfsFS srcFS, const char* src, hdfsFS dstFS, const char* dst) { |
| 381 | GET_SYMBOL(this, hdfsMove); |
| 382 | if (this->hdfsMove) |
| 383 | return this->hdfsMove(srcFS, src, dstFS, dst); |
| 384 | else |
| 385 | return 0; |
| 386 | } |
| 387 | |
| 388 | int LibHdfsShim::Delete(hdfsFS fs, const char* path, int recursive) { |
| 389 | return this->hdfsDelete(fs, path, recursive); |
| 390 | } |
| 391 | |
| 392 | int LibHdfsShim::Rename(hdfsFS fs, const char* oldPath, const char* newPath) { |
| 393 | GET_SYMBOL(this, hdfsRename); |
| 394 | if (this->hdfsRename) |
| 395 | return this->hdfsRename(fs, oldPath, newPath); |
| 396 | else |
| 397 | return 0; |
| 398 | } |
| 399 | |
| 400 | char* LibHdfsShim::GetWorkingDirectory(hdfsFS fs, char* buffer, size_t bufferSize) { |
| 401 | GET_SYMBOL(this, hdfsGetWorkingDirectory); |
| 402 | if (this->hdfsGetWorkingDirectory) { |
| 403 | return this->hdfsGetWorkingDirectory(fs, buffer, bufferSize); |
| 404 | } else { |
| 405 | return NULL; |
| 406 | } |
| 407 | } |
| 408 | |
| 409 | int LibHdfsShim::SetWorkingDirectory(hdfsFS fs, const char* path) { |
| 410 | GET_SYMBOL(this, hdfsSetWorkingDirectory); |
| 411 | if (this->hdfsSetWorkingDirectory) { |
| 412 | return this->hdfsSetWorkingDirectory(fs, path); |
| 413 | } else { |
| 414 | return 0; |
| 415 | } |
| 416 | } |
| 417 | |
| 418 | int LibHdfsShim::MakeDirectory(hdfsFS fs, const char* path) { |
| 419 | return this->hdfsCreateDirectory(fs, path); |
| 420 | } |
| 421 | |
| 422 | int LibHdfsShim::SetReplication(hdfsFS fs, const char* path, int16_t replication) { |
| 423 | GET_SYMBOL(this, hdfsSetReplication); |
| 424 | if (this->hdfsSetReplication) { |
| 425 | return this->hdfsSetReplication(fs, path, replication); |
| 426 | } else { |
| 427 | return 0; |
| 428 | } |
| 429 | } |
| 430 | |
| 431 | hdfsFileInfo* LibHdfsShim::ListDirectory(hdfsFS fs, const char* path, int* numEntries) { |
| 432 | return this->hdfsListDirectory(fs, path, numEntries); |
| 433 | } |
| 434 | |
| 435 | hdfsFileInfo* LibHdfsShim::GetPathInfo(hdfsFS fs, const char* path) { |
| 436 | return this->hdfsGetPathInfo(fs, path); |
| 437 | } |
| 438 | |
| 439 | void LibHdfsShim::FreeFileInfo(hdfsFileInfo* hdfsFileInfo, int numEntries) { |
| 440 | this->hdfsFreeFileInfo(hdfsFileInfo, numEntries); |
| 441 | } |
| 442 | |
| 443 | char*** LibHdfsShim::GetHosts(hdfsFS fs, const char* path, tOffset start, |
| 444 | tOffset length) { |
| 445 | GET_SYMBOL(this, hdfsGetHosts); |
| 446 | if (this->hdfsGetHosts) { |
| 447 | return this->hdfsGetHosts(fs, path, start, length); |
| 448 | } else { |
| 449 | return NULL; |
| 450 | } |
| 451 | } |
| 452 | |
| 453 | void LibHdfsShim::FreeHosts(char*** blockHosts) { |
| 454 | GET_SYMBOL(this, hdfsFreeHosts); |
| 455 | if (this->hdfsFreeHosts) { |
| 456 | this->hdfsFreeHosts(blockHosts); |
| 457 | } |
| 458 | } |
| 459 | |
| 460 | tOffset LibHdfsShim::GetDefaultBlockSize(hdfsFS fs) { |
| 461 | GET_SYMBOL(this, hdfsGetDefaultBlockSize); |
| 462 | if (this->hdfsGetDefaultBlockSize) { |
| 463 | return this->hdfsGetDefaultBlockSize(fs); |
| 464 | } else { |
| 465 | return 0; |
| 466 | } |
| 467 | } |
| 468 | |
| 469 | tOffset LibHdfsShim::GetCapacity(hdfsFS fs) { return this->hdfsGetCapacity(fs); } |
| 470 | |
| 471 | tOffset LibHdfsShim::GetUsed(hdfsFS fs) { return this->hdfsGetUsed(fs); } |
| 472 | |
| 473 | int LibHdfsShim::Chown(hdfsFS fs, const char* path, const char* owner, |
| 474 | const char* group) { |
| 475 | return this->hdfsChown(fs, path, owner, group); |
| 476 | } |
| 477 | |
| 478 | int LibHdfsShim::Chmod(hdfsFS fs, const char* path, short mode) { // NOLINT |
| 479 | return this->hdfsChmod(fs, path, mode); |
| 480 | } |
| 481 | |
| 482 | int LibHdfsShim::Utime(hdfsFS fs, const char* path, tTime mtime, tTime atime) { |
| 483 | GET_SYMBOL(this, hdfsUtime); |
| 484 | if (this->hdfsUtime) { |
| 485 | return this->hdfsUtime(fs, path, mtime, atime); |
| 486 | } else { |
| 487 | return 0; |
| 488 | } |
| 489 | } |
| 490 | |
| 491 | Status LibHdfsShim::GetRequiredSymbols() { |
| 492 | GET_SYMBOL_REQUIRED(this, hdfsNewBuilder); |
| 493 | GET_SYMBOL_REQUIRED(this, hdfsBuilderSetNameNode); |
| 494 | GET_SYMBOL_REQUIRED(this, hdfsBuilderSetNameNodePort); |
| 495 | GET_SYMBOL_REQUIRED(this, hdfsBuilderSetUserName); |
| 496 | GET_SYMBOL_REQUIRED(this, hdfsBuilderSetKerbTicketCachePath); |
| 497 | GET_SYMBOL_REQUIRED(this, hdfsBuilderSetForceNewInstance); |
| 498 | GET_SYMBOL_REQUIRED(this, hdfsBuilderConfSetStr); |
| 499 | GET_SYMBOL_REQUIRED(this, hdfsBuilderConnect); |
| 500 | GET_SYMBOL_REQUIRED(this, hdfsCreateDirectory); |
| 501 | GET_SYMBOL_REQUIRED(this, hdfsDelete); |
| 502 | GET_SYMBOL_REQUIRED(this, hdfsDisconnect); |
| 503 | GET_SYMBOL_REQUIRED(this, hdfsExists); |
| 504 | GET_SYMBOL_REQUIRED(this, hdfsFreeFileInfo); |
| 505 | GET_SYMBOL_REQUIRED(this, hdfsGetCapacity); |
| 506 | GET_SYMBOL_REQUIRED(this, hdfsGetUsed); |
| 507 | GET_SYMBOL_REQUIRED(this, hdfsGetPathInfo); |
| 508 | GET_SYMBOL_REQUIRED(this, hdfsListDirectory); |
| 509 | GET_SYMBOL_REQUIRED(this, hdfsChown); |
| 510 | GET_SYMBOL_REQUIRED(this, hdfsChmod); |
| 511 | |
| 512 | // File methods |
| 513 | GET_SYMBOL_REQUIRED(this, hdfsCloseFile); |
| 514 | GET_SYMBOL_REQUIRED(this, hdfsFlush); |
| 515 | GET_SYMBOL_REQUIRED(this, hdfsOpenFile); |
| 516 | GET_SYMBOL_REQUIRED(this, hdfsRead); |
| 517 | GET_SYMBOL_REQUIRED(this, hdfsSeek); |
| 518 | GET_SYMBOL_REQUIRED(this, hdfsTell); |
| 519 | GET_SYMBOL_REQUIRED(this, hdfsWrite); |
| 520 | |
| 521 | return Status::OK(); |
| 522 | } |
| 523 | |
| 524 | Status ConnectLibHdfs(LibHdfsShim** driver) { |
| 525 | static std::mutex lock; |
| 526 | std::lock_guard<std::mutex> guard(lock); |
| 527 | |
| 528 | LibHdfsShim* shim = &libhdfs_shim; |
| 529 | |
| 530 | static bool shim_attempted = false; |
| 531 | if (!shim_attempted) { |
| 532 | shim_attempted = true; |
| 533 | |
| 534 | shim->Initialize(); |
| 535 | |
| 536 | std::vector<fs::path> libjvm_potential_paths = get_potential_libjvm_paths(); |
| 537 | RETURN_NOT_OK(try_dlopen(libjvm_potential_paths, "libjvm" , libjvm_handle)); |
| 538 | |
| 539 | std::vector<fs::path> libhdfs_potential_paths = get_potential_libhdfs_paths(); |
| 540 | RETURN_NOT_OK(try_dlopen(libhdfs_potential_paths, "libhdfs" , shim->handle)); |
| 541 | } else if (shim->handle == nullptr) { |
| 542 | return Status::IOError("Prior attempt to load libhdfs failed" ); |
| 543 | } |
| 544 | |
| 545 | *driver = shim; |
| 546 | return shim->GetRequiredSymbols(); |
| 547 | } |
| 548 | |
| 549 | Status ConnectLibHdfs3(LibHdfsShim** driver) { |
| 550 | static std::mutex lock; |
| 551 | std::lock_guard<std::mutex> guard(lock); |
| 552 | |
| 553 | LibHdfsShim* shim = &libhdfs3_shim; |
| 554 | |
| 555 | static bool shim_attempted = false; |
| 556 | if (!shim_attempted) { |
| 557 | shim_attempted = true; |
| 558 | |
| 559 | shim->Initialize(); |
| 560 | |
| 561 | std::vector<fs::path> libhdfs3_potential_paths = get_potential_libhdfs3_paths(); |
| 562 | RETURN_NOT_OK(try_dlopen(libhdfs3_potential_paths, "libhdfs3" , shim->handle)); |
| 563 | } else if (shim->handle == nullptr) { |
| 564 | return Status::IOError("Prior attempt to load libhdfs3 failed" ); |
| 565 | } |
| 566 | |
| 567 | *driver = shim; |
| 568 | return shim->GetRequiredSymbols(); |
| 569 | } |
| 570 | |
| 571 | } // namespace internal |
| 572 | } // namespace io |
| 573 | } // namespace arrow |
| 574 | |