summaryrefslogtreecommitdiffstats
path: root/contrib/libs/apache/arrow_next/cpp/src/arrow/util/io_util.h
blob: 9ddbd1cf4aaffdfbc45d9dbd7c77e2cfa18225f2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
#pragma clang system_header
// 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.

#pragma once

#ifndef _WIN32
#  define ARROW_HAVE_SIGACTION 1
#endif

#include <atomic>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#if ARROW_HAVE_SIGACTION
#  include <csignal>  // Needed for struct sigaction
#endif

#include "contrib/libs/apache/arrow_next/cpp/src/arrow/result.h"
#include "contrib/libs/apache/arrow_next/cpp/src/arrow/status.h"
#include "contrib/libs/apache/arrow_next/cpp/src/arrow/type_fwd.h"
#include "contrib/libs/apache/arrow_next/cpp/src/arrow/util/macros.h"
#include "contrib/libs/apache/arrow_next/cpp/src/arrow/util/windows_fixup.h"

namespace arrow20::internal {

// NOTE: 8-bit path strings on Windows are encoded using UTF-8.
// Using MBCS would fail encoding some paths.

#if defined(_WIN32)
using NativePathString = std::wstring;
#else
using NativePathString = std::string;
#endif

class ARROW_EXPORT PlatformFilename {
 public:
  struct Impl;

  ~PlatformFilename();
  PlatformFilename();
  PlatformFilename(const PlatformFilename&);
  PlatformFilename(PlatformFilename&&);
  PlatformFilename& operator=(const PlatformFilename&);
  PlatformFilename& operator=(PlatformFilename&&);
  explicit PlatformFilename(NativePathString path);
  explicit PlatformFilename(const NativePathString::value_type* path);

  const NativePathString& ToNative() const;
  std::string ToString() const;

  PlatformFilename Parent() const;
  Result<PlatformFilename> Real() const;

  // These functions can fail for character encoding reasons.
  static Result<PlatformFilename> FromString(std::string_view file_name);
  Result<PlatformFilename> Join(std::string_view child_name) const;

  PlatformFilename Join(const PlatformFilename& child_name) const;

  bool operator==(const PlatformFilename& other) const;
  bool operator!=(const PlatformFilename& other) const;

  // Made public to avoid the proliferation of friend declarations.
  const Impl* impl() const { return impl_.get(); }

 private:
  std::unique_ptr<Impl> impl_;

  explicit PlatformFilename(Impl impl);
};

/// Create a directory if it doesn't exist.
///
/// Return whether the directory was created.
ARROW_EXPORT
Result<bool> CreateDir(const PlatformFilename& dir_path);

/// Create a directory and its parents if it doesn't exist.
///
/// Return whether the directory was created.
ARROW_EXPORT
Result<bool> CreateDirTree(const PlatformFilename& dir_path);

/// Delete a directory's contents (but not the directory itself) if it exists.
///
/// Return whether the directory existed.
ARROW_EXPORT
Result<bool> DeleteDirContents(const PlatformFilename& dir_path,
                               bool allow_not_found = true);

/// Delete a directory tree if it exists.
///
/// Return whether the directory existed.
ARROW_EXPORT
Result<bool> DeleteDirTree(const PlatformFilename& dir_path, bool allow_not_found = true);

// Non-recursively list the contents of the given directory.
// The returned names are the children's base names, not including dir_path.
ARROW_EXPORT
Result<std::vector<PlatformFilename>> ListDir(const PlatformFilename& dir_path);

/// Delete a file if it exists.
///
/// Return whether the file existed.
ARROW_EXPORT
Result<bool> DeleteFile(const PlatformFilename& file_path, bool allow_not_found = true);

/// Return whether a file exists.
ARROW_EXPORT
Result<bool> FileExists(const PlatformFilename& path);

// TODO expose this more publicly to make it available from io/file.h?
/// A RAII wrapper for a file descriptor.
///
/// The underlying file descriptor is automatically closed on destruction.
/// Moving is supported with well-defined semantics.
/// Furthermore, closing is idempotent.
class ARROW_EXPORT FileDescriptor {
 public:
  FileDescriptor() = default;
  explicit FileDescriptor(int fd) : fd_(fd) {}
  FileDescriptor(FileDescriptor&&);
  FileDescriptor& operator=(FileDescriptor&&);

  ~FileDescriptor();

  Status Close();

  /// May return -1 if closed or default-initialized
  int fd() const { return fd_.load(); }

  /// Detach and return the underlying file descriptor
  int Detach();

  bool closed() const { return fd_.load() == -1; }

 protected:
  static void CloseFromDestructor(int fd);

  std::atomic<int> fd_{-1};
};

/// Open a file for reading and return a file descriptor.
ARROW_EXPORT
Result<FileDescriptor> FileOpenReadable(const PlatformFilename& file_name);

/// Open a file for writing and return a file descriptor.
ARROW_EXPORT
Result<FileDescriptor> FileOpenWritable(const PlatformFilename& file_name,
                                        bool write_only = true, bool truncate = true,
                                        bool append = false);

/// Read from current file position.  Return number of bytes read.
ARROW_EXPORT
Result<int64_t> FileRead(int fd, uint8_t* buffer, int64_t nbytes);
/// Read from given file position.  Return number of bytes read.
ARROW_EXPORT
Result<int64_t> FileReadAt(int fd, uint8_t* buffer, int64_t position, int64_t nbytes);

ARROW_EXPORT
Status FileWrite(int fd, const uint8_t* buffer, const int64_t nbytes);
ARROW_EXPORT
Status FileTruncate(int fd, const int64_t size);

ARROW_EXPORT
Status FileSeek(int fd, int64_t pos);
ARROW_EXPORT
Status FileSeek(int fd, int64_t pos, int whence);
ARROW_EXPORT
Result<int64_t> FileTell(int fd);
ARROW_EXPORT
Result<int64_t> FileGetSize(int fd);

ARROW_EXPORT
Status FileClose(int fd);

struct Pipe {
  FileDescriptor rfd;
  FileDescriptor wfd;

  Status Close() { return rfd.Close() & wfd.Close(); }
};

ARROW_EXPORT
Result<Pipe> CreatePipe();

ARROW_EXPORT
Status SetPipeFileDescriptorNonBlocking(int fd);

class ARROW_EXPORT SelfPipe {
 public:
  static Result<std::shared_ptr<SelfPipe>> Make(bool signal_safe);
  virtual ~SelfPipe();

  /// \brief Wait for a wakeup.
  ///
  /// Status::Invalid is returned if the pipe has been shutdown.
  /// Otherwise the next sent payload is returned.
  virtual Result<uint64_t> Wait() = 0;

  /// \brief Wake up the pipe by sending a payload.
  ///
  /// This method is async-signal-safe if `signal_safe` was set to true.
  virtual void Send(uint64_t payload) = 0;

  /// \brief Wake up the pipe and shut it down.
  virtual Status Shutdown() = 0;
};

ARROW_EXPORT
int64_t GetPageSize();

struct MemoryRegion {
  void* addr;
  size_t size;
};

ARROW_EXPORT
Status MemoryMapRemap(void* addr, size_t old_size, size_t new_size, int fildes,
                      void** new_addr);
ARROW_EXPORT
Status MemoryAdviseWillNeed(const std::vector<MemoryRegion>& regions);

ARROW_EXPORT
Result<std::string> GetEnvVar(const char* name);
ARROW_EXPORT
Result<std::string> GetEnvVar(const std::string& name);
ARROW_EXPORT
Result<NativePathString> GetEnvVarNative(const char* name);
ARROW_EXPORT
Result<NativePathString> GetEnvVarNative(const std::string& name);

ARROW_EXPORT
Status SetEnvVar(const char* name, const char* value);
ARROW_EXPORT
Status SetEnvVar(const std::string& name, const std::string& value);
ARROW_EXPORT
Status DelEnvVar(const char* name);
ARROW_EXPORT
Status DelEnvVar(const std::string& name);

ARROW_EXPORT
std::string ErrnoMessage(int errnum);
#if _WIN32
ARROW_EXPORT
std::string WinErrorMessage(int errnum);
#endif

ARROW_EXPORT
std::shared_ptr<StatusDetail> StatusDetailFromErrno(int errnum);
ARROW_EXPORT
std::optional<int> ErrnoFromStatusDetail(const StatusDetail& detail);
#if _WIN32
ARROW_EXPORT
std::shared_ptr<StatusDetail> StatusDetailFromWinError(int errnum);
#endif
ARROW_EXPORT
std::shared_ptr<StatusDetail> StatusDetailFromSignal(int signum);

template <typename... Args>
Status StatusFromErrno(int errnum, StatusCode code, Args&&... args) {
  return Status::FromDetailAndArgs(code, StatusDetailFromErrno(errnum),
                                   std::forward<Args>(args)...);
}

template <typename... Args>
Status IOErrorFromErrno(int errnum, Args&&... args) {
  return StatusFromErrno(errnum, StatusCode::IOError, std::forward<Args>(args)...);
}

#if _WIN32
template <typename... Args>
Status StatusFromWinError(int errnum, StatusCode code, Args&&... args) {
  return Status::FromDetailAndArgs(code, StatusDetailFromWinError(errnum),
                                   std::forward<Args>(args)...);
}

template <typename... Args>
Status IOErrorFromWinError(int errnum, Args&&... args) {
  return StatusFromWinError(errnum, StatusCode::IOError, std::forward<Args>(args)...);
}
#endif

template <typename... Args>
Status StatusFromSignal(int signum, StatusCode code, Args&&... args) {
  return Status::FromDetailAndArgs(code, StatusDetailFromSignal(signum),
                                   std::forward<Args>(args)...);
}

template <typename... Args>
Status CancelledFromSignal(int signum, Args&&... args) {
  return StatusFromSignal(signum, StatusCode::Cancelled, std::forward<Args>(args)...);
}

ARROW_EXPORT
int ErrnoFromStatus(const Status&);

// Always returns 0 on non-Windows platforms (for Python).
ARROW_EXPORT
int WinErrorFromStatus(const Status&);

ARROW_EXPORT
int SignalFromStatus(const Status&);

class ARROW_EXPORT TemporaryDir {
 public:
  ~TemporaryDir();

  /// '/'-terminated path to the temporary dir
  const PlatformFilename& path() { return path_; }

  /// Create a temporary subdirectory in the system temporary dir,
  /// named starting with `prefix`.
  static Result<std::unique_ptr<TemporaryDir>> Make(const std::string& prefix);

 private:
  PlatformFilename path_;

  explicit TemporaryDir(PlatformFilename&&);
};

class ARROW_EXPORT SignalHandler {
 public:
  using Callback = void (*)(int);

  SignalHandler();
  explicit SignalHandler(Callback cb);
#if ARROW_HAVE_SIGACTION
  explicit SignalHandler(const struct sigaction& sa);
#endif

  Callback callback() const;
#if ARROW_HAVE_SIGACTION
  const struct sigaction& action() const;
#endif

 protected:
#if ARROW_HAVE_SIGACTION
  // Storing the full sigaction allows to restore the entire signal handling
  // configuration.
  struct sigaction sa_;
#else
  Callback cb_;
#endif
};

/// \brief Return the current handler for the given signal number.
ARROW_EXPORT
Result<SignalHandler> GetSignalHandler(int signum);

/// \brief Set a new handler for the given signal number.
///
/// The old signal handler is returned.
ARROW_EXPORT
Result<SignalHandler> SetSignalHandler(int signum, const SignalHandler& handler);

/// \brief Reinstate the signal handler
///
/// For use in signal handlers.  This is needed on platforms without sigaction()
/// such as Windows, as the default signal handler is restored there as
/// soon as a signal is raised.
ARROW_EXPORT
void ReinstateSignalHandler(int signum, SignalHandler::Callback handler);

/// \brief Send a signal to the current process
///
/// The thread which will receive the signal is unspecified.
ARROW_EXPORT
Status SendSignal(int signum);

/// \brief Send a signal to the given thread
///
/// This function isn't supported on Windows.
ARROW_EXPORT
Status SendSignalToThread(int signum, uint64_t thread_id);

/// \brief Get an unpredictable random seed
///
/// This function may be slightly costly, so should only be used to initialize
/// a PRNG, not to generate a large amount of random numbers.
/// It is better to use this function rather than std::random_device, unless
/// absolutely necessary (e.g. to generate a cryptographic secret).
ARROW_EXPORT
int64_t GetRandomSeed();

/// \brief Get the current thread id
///
/// In addition to having the same properties as std::thread, the returned value
/// is a regular integer value, which is more convenient than an opaque type.
ARROW_EXPORT
uint64_t GetThreadId();

/// \brief Get the current memory used by the current process in bytes
///
/// This function supports Windows, Linux, and Mac and will return 0 otherwise
ARROW_EXPORT
int64_t GetCurrentRSS();

/// \brief Get the total memory available to the system in bytes
///
/// This function supports Windows, Linux, and Mac and will return 0 otherwise
ARROW_EXPORT
int64_t GetTotalMemoryBytes();

/// \brief Load a dynamic library
///
/// This wraps dlopen() except on Windows, where LoadLibrary() is called.
/// These two platforms handle absolute paths consistently; relative paths
/// or the library's bare name may be handled but inconsistently.
///
/// \return An opaque handle for the dynamic library, which can be used for
///         subsequent symbol lookup. Nullptr will never be returned; instead
///         an error will be raised.
ARROW_EXPORT Result<void*> LoadDynamicLibrary(const PlatformFilename& path);

/// \brief Load a dynamic library
///
/// An overload taking null terminated string.
ARROW_EXPORT Result<void*> LoadDynamicLibrary(const char* path);

/// \brief Retrieve a symbol by name from a library handle.
///
/// This wraps dlsym() except on Windows, where GetProcAddress() is called.
///
/// \return The address associated with the named symbol. Nullptr will never be
///         returned; instead an error will be raised.
ARROW_EXPORT Result<void*> GetSymbol(void* handle, const char* name);

template <typename T>
Result<T*> GetSymbolAs(void* handle, const char* name) {
  ARROW_ASSIGN_OR_RAISE(void* sym, GetSymbol(handle, name));
  return reinterpret_cast<T*>(sym);
}

}  // namespace arrow20::internal