GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_file.h Lines: 44 55 80.0 %
Date: 2020-08-22 22:13:06 Branches: 2 2 100.0 %

Line Branch Exec Source
1
#ifndef SRC_NODE_FILE_H_
2
#define SRC_NODE_FILE_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "node.h"
7
#include "aliased_buffer.h"
8
#include "node_messaging.h"
9
#include "stream_base.h"
10
#include <iostream>
11
12
namespace node {
13
namespace fs {
14
15
class FileHandleReadWrap;
16
17
8704
class BindingData : public BaseObject {
18
 public:
19
4817
  explicit BindingData(Environment* env, v8::Local<v8::Object> wrap)
20
4817
      : BaseObject(env, wrap),
21
        stats_field_array(env->isolate(), kFsStatsBufferLength),
22
4817
        stats_field_bigint_array(env->isolate(), kFsStatsBufferLength) {}
23
24
  AliasedFloat64Array stats_field_array;
25
  AliasedBigUint64Array stats_field_bigint_array;
26
27
  std::vector<BaseObjectPtr<FileHandleReadWrap>>
28
      file_handle_read_wrap_freelist;
29
30
  static constexpr FastStringKey binding_data_name { "fs" };
31
32
  void MemoryInfo(MemoryTracker* tracker) const override;
33
19
  SET_SELF_SIZE(BindingData)
34
19
  SET_MEMORY_INFO_NAME(BindingData)
35
};
36
37
// structure used to store state during a complex operation, e.g., mkdirp.
38
9880
class FSContinuationData : public MemoryRetainer {
39
 public:
40
  inline FSContinuationData(uv_fs_t* req, int mode, uv_fs_cb done_cb);
41
42
  inline void PushPath(std::string&& path);
43
  inline void PushPath(const std::string& path);
44
  inline std::string PopPath();
45
  // Used by mkdirp to track the first path created:
46
  inline void MaybeSetFirstPath(const std::string& path);
47
  inline void Done(int result);
48
49
10
  int mode() const { return mode_; }
50
10010
  const std::vector<std::string>& paths() const { return paths_; }
51
225
  const std::string& first_path() const { return first_path_; }
52
53
  void MemoryInfo(MemoryTracker* tracker) const override;
54
  SET_MEMORY_INFO_NAME(FSContinuationData)
55
  SET_SELF_SIZE(FSContinuationData)
56
57
 private:
58
  uv_fs_cb done_cb_;
59
  uv_fs_t* req_;
60
  int mode_;
61
  std::vector<std::string> paths_;
62
  std::string first_path_;
63
};
64
65
class FSReqBase : public ReqWrap<uv_fs_t> {
66
 public:
67
  typedef MaybeStackBuffer<char, 64> FSReqBuffer;
68
69
  inline FSReqBase(BindingData* binding_data,
70
                   v8::Local<v8::Object> req,
71
                   AsyncWrap::ProviderType type,
72
                   bool use_bigint);
73
  ~FSReqBase() override;
74
75
  inline void Init(const char* syscall,
76
                   const char* data,
77
                   size_t len,
78
                   enum encoding encoding);
79
  inline FSReqBuffer& Init(const char* syscall, size_t len,
80
                           enum encoding encoding);
81
82
  virtual void Reject(v8::Local<v8::Value> reject) = 0;
83
  virtual void Resolve(v8::Local<v8::Value> value) = 0;
84
  virtual void ResolveStat(const uv_stat_t* stat) = 0;
85
  virtual void SetReturnValue(
86
      const v8::FunctionCallbackInfo<v8::Value>& args) = 0;
87
88
4434
  const char* syscall() const { return syscall_; }
89
4434
  const char* data() const { return has_data_ ? *buffer_ : nullptr; }
90
6831
  enum encoding encoding() const { return encoding_; }
91
3930
  bool use_bigint() const { return use_bigint_; }
92
35999
  bool is_plain_open() const { return is_plain_open_; }
93
94
5764
  void set_is_plain_open(bool value) { is_plain_open_ = value; }
95
96
140
  FSContinuationData* continuation_data() const {
97
140
    return continuation_data_.get();
98
  }
99
14
  void set_continuation_data(std::unique_ptr<FSContinuationData> data) {
100
14
    continuation_data_ = std::move(data);
101
14
  }
102
103
54010
  static FSReqBase* from_req(uv_fs_t* req) {
104
54010
    return static_cast<FSReqBase*>(ReqWrap::from_req(req));
105
  }
106
107
  FSReqBase(const FSReqBase&) = delete;
108
  FSReqBase& operator=(const FSReqBase&) = delete;
109
110
  void MemoryInfo(MemoryTracker* tracker) const override;
111
112
4226
  BindingData* binding_data() { return binding_data_.get(); }
113
114
 private:
115
  std::unique_ptr<FSContinuationData> continuation_data_;
116
  enum encoding encoding_ = UTF8;
117
  bool has_data_ = false;
118
  bool use_bigint_ = false;
119
  bool is_plain_open_ = false;
120
  const char* syscall_ = nullptr;
121
122
  BaseObjectPtr<BindingData> binding_data_;
123
124
  // Typically, the content of buffer_ is something like a file name, so
125
  // something around 64 bytes should be enough.
126
  FSReqBuffer buffer_;
127
};
128
129
105248
class FSReqCallback final : public FSReqBase {
130
 public:
131
  inline FSReqCallback(BindingData* binding_data,
132
                       v8::Local<v8::Object> req,
133
                       bool use_bigint);
134
135
  void Reject(v8::Local<v8::Value> reject) override;
136
  void Resolve(v8::Local<v8::Value> value) override;
137
  void ResolveStat(const uv_stat_t* stat) override;
138
  void SetReturnValue(const v8::FunctionCallbackInfo<v8::Value>& args) override;
139
140
1
  SET_MEMORY_INFO_NAME(FSReqCallback)
141
1
  SET_SELF_SIZE(FSReqCallback)
142
143
  FSReqCallback(const FSReqCallback&) = delete;
144
  FSReqCallback& operator=(const FSReqCallback&) = delete;
145
};
146
147
template <typename NativeT, typename V8T>
148
void FillStatsArray(AliasedBufferBase<NativeT, V8T>* fields,
149
                    const uv_stat_t* s,
150
                    const size_t offset = 0);
151
152
inline v8::Local<v8::Value> FillGlobalStatsArray(BindingData* binding_data,
153
                                                 const bool use_bigint,
154
                                                 const uv_stat_t* s,
155
                                                 const bool second = false);
156
157
template <typename AliasedBufferT>
158
class FSReqPromise final : public FSReqBase {
159
 public:
160
  static inline FSReqPromise* New(BindingData* binding_data,
161
                                  bool use_bigint);
162
  inline ~FSReqPromise() override;
163
164
  inline void Reject(v8::Local<v8::Value> reject) override;
165
  inline void Resolve(v8::Local<v8::Value> value) override;
166
  inline void ResolveStat(const uv_stat_t* stat) override;
167
  inline void SetReturnValue(
168
      const v8::FunctionCallbackInfo<v8::Value>& args) override;
169
  inline void MemoryInfo(MemoryTracker* tracker) const override;
170
171
1
  SET_MEMORY_INFO_NAME(FSReqPromise)
172
1
  SET_SELF_SIZE(FSReqPromise)
173
174
  FSReqPromise(const FSReqPromise&) = delete;
175
  FSReqPromise& operator=(const FSReqPromise&) = delete;
176
  FSReqPromise(const FSReqPromise&&) = delete;
177
  FSReqPromise& operator=(const FSReqPromise&&) = delete;
178
179
 private:
180
  inline FSReqPromise(BindingData* binding_data,
181
                      v8::Local<v8::Object> obj,
182
                      bool use_bigint);
183
184
  bool finished_ = false;
185
  AliasedBufferT stats_field_array_;
186
};
187
188
class FSReqAfterScope final {
189
 public:
190
  FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req);
191
  ~FSReqAfterScope();
192
  void Clear();
193
194
  bool Proceed();
195
196
  void Reject(uv_fs_t* req);
197
198
  FSReqAfterScope(const FSReqAfterScope&) = delete;
199
  FSReqAfterScope& operator=(const FSReqAfterScope&) = delete;
200
  FSReqAfterScope(const FSReqAfterScope&&) = delete;
201
  FSReqAfterScope& operator=(const FSReqAfterScope&&) = delete;
202
203
 private:
204
  BaseObjectPtr<FSReqBase> wrap_;
205
  uv_fs_t* req_ = nullptr;
206
  v8::HandleScope handle_scope_;
207
  v8::Context::Scope context_scope_;
208
};
209
210
class FileHandle;
211
212
// A request wrap specifically for uv_fs_read()s scheduled for reading
213
// from a FileHandle.
214
class FileHandleReadWrap final : public ReqWrap<uv_fs_t> {
215
 public:
216
  FileHandleReadWrap(FileHandle* handle, v8::Local<v8::Object> obj);
217
  ~FileHandleReadWrap() override;
218
219
207
  static inline FileHandleReadWrap* from_req(uv_fs_t* req) {
220
207
    return static_cast<FileHandleReadWrap*>(ReqWrap::from_req(req));
221
  }
222
223
  void MemoryInfo(MemoryTracker* tracker) const override;
224
  SET_MEMORY_INFO_NAME(FileHandleReadWrap)
225
  SET_SELF_SIZE(FileHandleReadWrap)
226
227
 private:
228
  FileHandle* file_handle_;
229
  uv_buf_t buffer_;
230
231
  friend class FileHandle;
232
};
233
234
// A wrapper for a file descriptor that will automatically close the fd when
235
// the object is garbage collected
236
class FileHandle final : public AsyncWrap, public StreamBase {
237
 public:
238
  static FileHandle* New(BindingData* binding_data,
239
                         int fd,
240
                         v8::Local<v8::Object> obj = v8::Local<v8::Object>());
241
  ~FileHandle() override;
242
243
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
244
245
298
  int GetFD() override { return fd_; }
246
247
  // Will asynchronously close the FD and return a Promise that will
248
  // be resolved once closing is complete.
249
  static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
250
251
  // Releases ownership of the FD.
252
  static void ReleaseFD(const v8::FunctionCallbackInfo<v8::Value>& args);
253
254
  // StreamBase interface:
255
  int ReadStart() override;
256
  int ReadStop() override;
257
258
510
  bool IsAlive() override { return !closed_; }
259
212
  bool IsClosing() override { return closing_; }
260
356
  AsyncWrap* GetAsyncWrap() override { return this; }
261
262
  // In the case of file streams, shutting down corresponds to closing.
263
  ShutdownWrap* CreateShutdownWrap(v8::Local<v8::Object> object) override;
264
  int DoShutdown(ShutdownWrap* req_wrap) override;
265
266
  int DoWrite(WriteWrap* w,
267
              uv_buf_t* bufs,
268
              size_t count,
269
              uv_stream_t* send_handle) override;
270
271
  void MemoryInfo(MemoryTracker* tracker) const override;
272
273
  SET_MEMORY_INFO_NAME(FileHandle)
274
  SET_SELF_SIZE(FileHandle)
275
276
  FileHandle(const FileHandle&) = delete;
277
  FileHandle& operator=(const FileHandle&) = delete;
278
  FileHandle(const FileHandle&&) = delete;
279
  FileHandle& operator=(const FileHandle&&) = delete;
280
281
  TransferMode GetTransferMode() const override;
282
  std::unique_ptr<worker::TransferData> TransferForMessaging() override;
283
284
 private:
285
  class TransferData : public worker::TransferData {
286
   public:
287
    explicit TransferData(int fd);
288
    ~TransferData();
289
290
    BaseObjectPtr<BaseObject> Deserialize(
291
        Environment* env,
292
        v8::Local<v8::Context> context,
293
        std::unique_ptr<worker::TransferData> self) override;
294
295
    SET_NO_MEMORY_INFO()
296
    SET_MEMORY_INFO_NAME(FileHandleTransferData)
297
    SET_SELF_SIZE(TransferData)
298
299
   private:
300
    int fd_;
301
  };
302
303
  FileHandle(BindingData* binding_data, v8::Local<v8::Object> obj, int fd);
304
305
  // Synchronous close that emits a warning
306
  void Close();
307
  void AfterClose();
308
309
  class CloseReq final : public ReqWrap<uv_fs_t> {
310
   public:
311
    CloseReq(Environment* env,
312
             v8::Local<v8::Object> obj,
313
             v8::Local<v8::Promise> promise,
314
             v8::Local<v8::Value> ref);
315
    ~CloseReq() override;
316
317
    FileHandle* file_handle();
318
319
    void MemoryInfo(MemoryTracker* tracker) const override;
320
321
    SET_MEMORY_INFO_NAME(CloseReq)
322
    SET_SELF_SIZE(CloseReq)
323
324
    void Resolve();
325
326
    void Reject(v8::Local<v8::Value> reason);
327
328
291
    static CloseReq* from_req(uv_fs_t* req) {
329
291
      return static_cast<CloseReq*>(ReqWrap::from_req(req));
330
    }
331
332
    CloseReq(const CloseReq&) = delete;
333
    CloseReq& operator=(const CloseReq&) = delete;
334
    CloseReq(const CloseReq&&) = delete;
335
    CloseReq& operator=(const CloseReq&&) = delete;
336
337
   private:
338
    v8::Global<v8::Promise> promise_{};
339
    v8::Global<v8::Value> ref_{};
340
  };
341
342
  // Asynchronous close
343
  v8::MaybeLocal<v8::Promise> ClosePromise();
344
345
  int fd_;
346
  bool closing_ = false;
347
  bool closed_ = false;
348
  bool reading_ = false;
349
  int64_t read_offset_ = -1;
350
  int64_t read_length_ = -1;
351
352
  BaseObjectPtr<FileHandleReadWrap> current_read_;
353
354
  BaseObjectPtr<BindingData> binding_data_;
355
};
356
357
int MKDirpSync(uv_loop_t* loop,
358
               uv_fs_t* req,
359
               const std::string& path,
360
               int mode,
361
               uv_fs_cb cb = nullptr);
362
363
class FSReqWrapSync {
364
 public:
365
325622
  FSReqWrapSync() = default;
366
325622
  ~FSReqWrapSync() { uv_fs_req_cleanup(&req); }
367
  uv_fs_t req;
368
369
25346
  FSContinuationData* continuation_data() const {
370
25346
    return continuation_data_.get();
371
  }
372
4926
  void set_continuation_data(std::unique_ptr<FSContinuationData> data) {
373
4926
    continuation_data_ = std::move(data);
374
4926
  }
375
376
  FSReqWrapSync(const FSReqWrapSync&) = delete;
377
  FSReqWrapSync& operator=(const FSReqWrapSync&) = delete;
378
379
 private:
380
  std::unique_ptr<FSContinuationData> continuation_data_;
381
};
382
383
// TODO(addaleax): Currently, callers check the return value and assume
384
// that nullptr indicates a synchronous call, rather than a failure.
385
// Failure conditions should be disambiguated and handled appropriately.
386
inline FSReqBase* GetReqWrap(const v8::FunctionCallbackInfo<v8::Value>& args,
387
                             int index,
388
                             bool use_bigint = false);
389
390
// Returns nullptr if the operation fails from the start.
391
template <typename Func, typename... Args>
392
inline FSReqBase* AsyncDestCall(Environment* env, FSReqBase* req_wrap,
393
                                const v8::FunctionCallbackInfo<v8::Value>& args,
394
                                const char* syscall, const char* dest,
395
                                size_t len, enum encoding enc, uv_fs_cb after,
396
                                Func fn, Args... fn_args);
397
398
// Returns nullptr if the operation fails from the start.
399
template <typename Func, typename... Args>
400
inline FSReqBase* AsyncCall(Environment* env,
401
                            FSReqBase* req_wrap,
402
                            const v8::FunctionCallbackInfo<v8::Value>& args,
403
                            const char* syscall, enum encoding enc,
404
                            uv_fs_cb after, Func fn, Args... fn_args);
405
406
// Template counterpart of SYNC_CALL, except that it only puts
407
// the error number and the syscall in the context instead of
408
// creating an error in the C++ land.
409
// ctx must be checked using value->IsObject() before being passed.
410
template <typename Func, typename... Args>
411
inline int SyncCall(Environment* env, v8::Local<v8::Value> ctx,
412
                    FSReqWrapSync* req_wrap, const char* syscall,
413
                    Func fn, Args... args);
414
415
}  // namespace fs
416
417
}  // namespace node
418
419
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
420
421
#endif  // SRC_NODE_FILE_H_