mt-libuv 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.gitmodules +6 -0
- data/.rspec +1 -0
- data/.travis.yml +24 -0
- data/Gemfile +9 -0
- data/LICENSE +24 -0
- data/README.md +195 -0
- data/Rakefile +31 -0
- data/ext/README.md +6 -0
- data/ext/Rakefile +28 -0
- data/lib/mt-libuv/async.rb +51 -0
- data/lib/mt-libuv/check.rb +59 -0
- data/lib/mt-libuv/coroutines.rb +79 -0
- data/lib/mt-libuv/dns.rb +98 -0
- data/lib/mt-libuv/error.rb +88 -0
- data/lib/mt-libuv/ext/ext.rb +322 -0
- data/lib/mt-libuv/ext/platform/darwin_x64.rb +61 -0
- data/lib/mt-libuv/ext/platform/unix.rb +69 -0
- data/lib/mt-libuv/ext/platform/windows.rb +83 -0
- data/lib/mt-libuv/ext/tasks/mac.rb +24 -0
- data/lib/mt-libuv/ext/tasks/unix.rb +42 -0
- data/lib/mt-libuv/ext/tasks/win.rb +29 -0
- data/lib/mt-libuv/ext/tasks.rb +27 -0
- data/lib/mt-libuv/ext/types.rb +253 -0
- data/lib/mt-libuv/fiber_pool.rb +83 -0
- data/lib/mt-libuv/file.rb +309 -0
- data/lib/mt-libuv/filesystem.rb +263 -0
- data/lib/mt-libuv/fs_event.rb +37 -0
- data/lib/mt-libuv/handle.rb +108 -0
- data/lib/mt-libuv/idle.rb +59 -0
- data/lib/mt-libuv/mixins/accessors.rb +41 -0
- data/lib/mt-libuv/mixins/assertions.rb +25 -0
- data/lib/mt-libuv/mixins/fs_checks.rb +96 -0
- data/lib/mt-libuv/mixins/listener.rb +69 -0
- data/lib/mt-libuv/mixins/net.rb +42 -0
- data/lib/mt-libuv/mixins/resource.rb +30 -0
- data/lib/mt-libuv/mixins/stream.rb +276 -0
- data/lib/mt-libuv/pipe.rb +217 -0
- data/lib/mt-libuv/prepare.rb +59 -0
- data/lib/mt-libuv/q.rb +475 -0
- data/lib/mt-libuv/reactor.rb +567 -0
- data/lib/mt-libuv/signal.rb +62 -0
- data/lib/mt-libuv/spawn.rb +113 -0
- data/lib/mt-libuv/tcp.rb +465 -0
- data/lib/mt-libuv/timer.rb +107 -0
- data/lib/mt-libuv/tty.rb +42 -0
- data/lib/mt-libuv/udp.rb +302 -0
- data/lib/mt-libuv/version.rb +5 -0
- data/lib/mt-libuv/work.rb +86 -0
- data/lib/mt-libuv.rb +80 -0
- data/mt-libuv.gemspec +62 -0
- data/spec/async_spec.rb +67 -0
- data/spec/coroutines_spec.rb +121 -0
- data/spec/cpu_spec.rb +10 -0
- data/spec/defer_spec.rb +906 -0
- data/spec/dns_spec.rb +110 -0
- data/spec/dsl_spec.rb +43 -0
- data/spec/filesystem_spec.rb +270 -0
- data/spec/idle_spec.rb +44 -0
- data/spec/pipe_spec.rb +151 -0
- data/spec/spawn_spec.rb +119 -0
- data/spec/tcp_spec.rb +272 -0
- data/spec/test.sh +4 -0
- data/spec/test_fail.sh +3 -0
- data/spec/test_read.sh +3 -0
- data/spec/timer_spec.rb +14 -0
- data/spec/udp_spec.rb +73 -0
- data/spec/zen_spec.rb +34 -0
- metadata +196 -0
@@ -0,0 +1,309 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MTLibuv
|
4
|
+
class File < Q::DeferredPromise
|
5
|
+
include Assertions, Resource, Listener, FsChecks
|
6
|
+
|
7
|
+
|
8
|
+
fs_params = {
|
9
|
+
params: [Ext::FsRequest.by_ref],
|
10
|
+
lookup: :fs_lookup
|
11
|
+
}
|
12
|
+
define_callback function: :on_open, **fs_params
|
13
|
+
define_callback function: :on_close, **fs_params
|
14
|
+
define_callback function: :on_read, **fs_params
|
15
|
+
define_callback function: :on_write, **fs_params
|
16
|
+
define_callback function: :on_sync, **fs_params
|
17
|
+
define_callback function: :on_datasync, **fs_params
|
18
|
+
define_callback function: :on_truncate, **fs_params
|
19
|
+
define_callback function: :on_utime, **fs_params
|
20
|
+
define_callback function: :on_chmod, **fs_params
|
21
|
+
define_callback function: :on_chown, **fs_params
|
22
|
+
define_callback function: :on_stat, **fs_params
|
23
|
+
|
24
|
+
|
25
|
+
EOF = "0\r\n\r\n"
|
26
|
+
CRLF = "\r\n"
|
27
|
+
|
28
|
+
|
29
|
+
attr_reader :fileno, :closed
|
30
|
+
|
31
|
+
|
32
|
+
def initialize(thread, path, flags = 0, mode: 0)
|
33
|
+
super(thread, thread.defer)
|
34
|
+
|
35
|
+
@fileno = -1
|
36
|
+
@closed = true
|
37
|
+
@path, @flags, @mode = path, flags, mode
|
38
|
+
@request_refs = {}
|
39
|
+
|
40
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
41
|
+
pre_check @defer, request, ::MTLibuv::Ext.fs_open(@reactor, request, @path, @flags, @mode, callback(:on_open, request.address))
|
42
|
+
|
43
|
+
if block_given?
|
44
|
+
self.progress &Proc.new
|
45
|
+
else
|
46
|
+
@coroutine = @reactor.defer
|
47
|
+
@coroutine.promise.value
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def close
|
52
|
+
@closed = true
|
53
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
54
|
+
pre_check(@defer, request, ::MTLibuv::Ext.fs_close(@reactor.handle, request, @fileno, callback(:on_close, request.address)))
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def read(length, offset = 0, wait: true)
|
59
|
+
assert_type(Integer, length, "length must be an Integer")
|
60
|
+
assert_type(Integer, offset, "offset must be an Integer")
|
61
|
+
deferred = @reactor.defer
|
62
|
+
|
63
|
+
buffer1 = FFI::MemoryPointer.new(length)
|
64
|
+
buffer = ::MTLibuv::Ext.buf_init(buffer1, length)
|
65
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
66
|
+
|
67
|
+
@request_refs[request.address] = [deferred, buffer1]
|
68
|
+
|
69
|
+
promise = pre_check(deferred, request, ::MTLibuv::Ext.fs_read(@reactor.handle, request, @fileno, buffer, 1, offset, callback(:on_read, request.address)))
|
70
|
+
wait ? promise.value : promise
|
71
|
+
end
|
72
|
+
|
73
|
+
def write(data, offset = 0, wait: true)
|
74
|
+
assert_type(String, data, "data must be a String")
|
75
|
+
assert_type(Integer, offset, "offset must be an Integer")
|
76
|
+
deferred = @reactor.defer
|
77
|
+
|
78
|
+
length = data.respond_to?(:bytesize) ? data.bytesize : data.size
|
79
|
+
|
80
|
+
buffer1 = FFI::MemoryPointer.from_string(data)
|
81
|
+
buffer = ::MTLibuv::Ext.buf_init(buffer1, length)
|
82
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
83
|
+
|
84
|
+
@request_refs[request.address] = [deferred, buffer1]
|
85
|
+
|
86
|
+
respond wait, pre_check(deferred, request, ::MTLibuv::Ext.fs_write(@reactor.handle, request, @fileno, buffer, 1, offset, callback(:on_write, request.address)))
|
87
|
+
end
|
88
|
+
|
89
|
+
def sync(wait: false)
|
90
|
+
deferred = @reactor.defer
|
91
|
+
|
92
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
93
|
+
@request_refs[request.address] = deferred
|
94
|
+
|
95
|
+
respond wait, pre_check(deferred, request, ::MTLibuv::Ext.fs_fsync(@reactor.handle, request, @fileno, callback(:on_sync, request.address)))
|
96
|
+
end
|
97
|
+
|
98
|
+
def datasync(wait: false)
|
99
|
+
deferred = @reactor.defer
|
100
|
+
|
101
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
102
|
+
@request_refs[request.address] = deferred
|
103
|
+
|
104
|
+
respond wait, pre_check(deferred, request, ::MTLibuv::Ext.fs_fdatasync(@reactor.handle, request, @fileno, callback(:on_datasync, request.address)))
|
105
|
+
end
|
106
|
+
|
107
|
+
def truncate(offset, wait: true)
|
108
|
+
assert_type(Integer, offset, "offset must be an Integer")
|
109
|
+
deferred = @reactor.defer
|
110
|
+
|
111
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
112
|
+
@request_refs[request.address] = deferred
|
113
|
+
|
114
|
+
respond wait, pre_check(deferred, request, ::MTLibuv::Ext.fs_ftruncate(@reactor.handle, request, @fileno, offset, callback(:on_truncate, request.address)))
|
115
|
+
end
|
116
|
+
|
117
|
+
def utime(atime:, mtime:, wait: true)
|
118
|
+
assert_type(Integer, atime, "atime must be an Integer")
|
119
|
+
assert_type(Integer, mtime, "mtime must be an Integer")
|
120
|
+
deferred = @reactor.defer
|
121
|
+
|
122
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
123
|
+
@request_refs[request.address] = deferred
|
124
|
+
|
125
|
+
promise = pre_check deferred, request, ::MTLibuv::Ext.fs_futime(@reactor.handle, request, @fileno, atime, mtime, callback(:on_utime, request.address))
|
126
|
+
wait ? promise.value : promise
|
127
|
+
end
|
128
|
+
|
129
|
+
def chmod(mode, wait: true)
|
130
|
+
assert_type(Integer, mode, "mode must be an Integer")
|
131
|
+
deferred = @reactor.defer
|
132
|
+
|
133
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
134
|
+
@request_refs[request.address] = deferred
|
135
|
+
|
136
|
+
respond wait, pre_check(deferred, request, ::MTLibuv::Ext.fs_fchmod(@reactor.handle, request, @fileno, mode, callback(:on_chmod, request.address)))
|
137
|
+
end
|
138
|
+
|
139
|
+
def chown(uid:, gid:, wait: true)
|
140
|
+
assert_type(Integer, uid, "uid must be an Integer")
|
141
|
+
assert_type(Integer, gid, "gid must be an Integer")
|
142
|
+
deferred = @reactor.defer
|
143
|
+
|
144
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
145
|
+
@request_refs[request.address] = deferred
|
146
|
+
|
147
|
+
respond wait, pre_check(deferred, request, ::MTLibuv::Ext.fs_fchown(@reactor.handle, request, @fileno, uid, gid, callback(:on_chown, request.address)))
|
148
|
+
end
|
149
|
+
|
150
|
+
def send_file(stream, using: :raw, chunk_size: 4096, wait: true)
|
151
|
+
@transmit_failure ||= proc { |reason| @sending_file.reject(reason) }
|
152
|
+
@start_transmit ||= proc { |stats|
|
153
|
+
@file_stream_total = stats[:st_size]
|
154
|
+
next_chunk
|
155
|
+
}
|
156
|
+
@transmit_data ||= proc { |data| transmit_data(data) }
|
157
|
+
|
158
|
+
@sending_file = @reactor.defer
|
159
|
+
@file_stream = stream
|
160
|
+
@file_stream_type = using
|
161
|
+
@file_chunk_size = chunk_size
|
162
|
+
@file_chunk_count = 0
|
163
|
+
|
164
|
+
stat(wait: false).then @start_transmit, @transmit_failure
|
165
|
+
|
166
|
+
promise = @sending_file.promise
|
167
|
+
promise.finally { clean_up_send }
|
168
|
+
respond wait, promise
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
private
|
173
|
+
|
174
|
+
|
175
|
+
##
|
176
|
+
# File transmit functions -------------
|
177
|
+
def transmit_data(data)
|
178
|
+
@file_chunk_count += 1
|
179
|
+
if @file_stream_type == :http
|
180
|
+
resp = String.new
|
181
|
+
resp << data.bytesize.to_s(16) << CRLF
|
182
|
+
resp << data
|
183
|
+
resp << CRLF
|
184
|
+
data = resp
|
185
|
+
end
|
186
|
+
@file_stream.write(data, wait: :promise).then(proc { next_chunk }, @transmit_failure)
|
187
|
+
nil
|
188
|
+
end
|
189
|
+
|
190
|
+
def next_chunk
|
191
|
+
next_size = @file_chunk_size
|
192
|
+
next_offset = @file_chunk_size * @file_chunk_count
|
193
|
+
|
194
|
+
if next_offset >= @file_stream_total
|
195
|
+
if @file_stream_type == :http
|
196
|
+
@file_stream.write(EOF, wait: :promise).then(proc {
|
197
|
+
@sending_file.resolve(@file_stream_total)
|
198
|
+
}, @transmit_failure)
|
199
|
+
else
|
200
|
+
@sending_file.resolve(@file_stream_total)
|
201
|
+
end
|
202
|
+
else
|
203
|
+
if next_offset + next_size > @file_stream_total
|
204
|
+
next_size = @file_stream_total - next_offset
|
205
|
+
end
|
206
|
+
read(next_size, next_offset, wait: false).then(@transmit_data, @transmit_failure)
|
207
|
+
end
|
208
|
+
nil
|
209
|
+
end
|
210
|
+
|
211
|
+
def clean_up_send
|
212
|
+
@sending_file = nil
|
213
|
+
@file_stream = nil
|
214
|
+
@file_stream_type = nil
|
215
|
+
@file_chunk_size = nil
|
216
|
+
@file_chunk_count = nil
|
217
|
+
@file_stream_total = nil
|
218
|
+
end
|
219
|
+
# -------------------------------------
|
220
|
+
##
|
221
|
+
|
222
|
+
|
223
|
+
def on_open(req)
|
224
|
+
if post_check(req, @defer)
|
225
|
+
@fileno = req[:result]
|
226
|
+
cleanup(req)
|
227
|
+
@closed = false
|
228
|
+
@reactor.exec { @defer.notify(self) }
|
229
|
+
|
230
|
+
if @coroutine
|
231
|
+
@coroutine.resolve(nil)
|
232
|
+
@coroutine = nil
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def on_close(req)
|
238
|
+
if post_check(req, @defer)
|
239
|
+
cleanup(req)
|
240
|
+
@reactor.exec { @defer.resolve(nil) }
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def on_read(req)
|
245
|
+
deferred, buffer1 = @request_refs.delete req.to_ptr.address
|
246
|
+
if post_check(req, deferred)
|
247
|
+
data = buffer1.read_string(req[:result])
|
248
|
+
cleanup(req)
|
249
|
+
@reactor.exec { deferred.resolve(data) }
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def on_write(req)
|
254
|
+
deferred, buffer1 = @request_refs.delete req.to_ptr.address
|
255
|
+
if post_check(req, deferred)
|
256
|
+
cleanup(req)
|
257
|
+
@reactor.exec { deferred.resolve(nil) }
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def on_sync(req)
|
262
|
+
deferred = @request_refs.delete req.to_ptr.address
|
263
|
+
if post_check(req, deferred)
|
264
|
+
cleanup(req)
|
265
|
+
@reactor.exec { deferred.resolve(nil) }
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def on_datasync(req)
|
270
|
+
deferred = @request_refs.delete req.to_ptr.address
|
271
|
+
if post_check(req, deferred)
|
272
|
+
cleanup(req)
|
273
|
+
@reactor.exec { deferred.resolve(nil) }
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def on_truncate(req)
|
278
|
+
deferred = @request_refs.delete req.to_ptr.address
|
279
|
+
if post_check(req, deferred)
|
280
|
+
cleanup(req)
|
281
|
+
@reactor.exec { deferred.resolve(nil) }
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def on_utime(req)
|
286
|
+
deferred = @request_refs.delete req.to_ptr.address
|
287
|
+
if post_check(req, deferred)
|
288
|
+
cleanup(req)
|
289
|
+
@reactor.exec { deferred.resolve(nil) }
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def on_chmod(req)
|
294
|
+
deferred = @request_refs.delete req.to_ptr.address
|
295
|
+
if post_check(req, deferred)
|
296
|
+
cleanup(req)
|
297
|
+
@reactor.exec { deferred.resolve(nil) }
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def on_chown(req)
|
302
|
+
deferred = @request_refs.delete req.to_ptr.address
|
303
|
+
if post_check(req, deferred)
|
304
|
+
cleanup(req)
|
305
|
+
@reactor.exec { deferred.resolve(nil) }
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
@@ -0,0 +1,263 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MTLibuv
|
4
|
+
class Filesystem
|
5
|
+
include Assertions, Resource, Listener, FsChecks
|
6
|
+
|
7
|
+
|
8
|
+
fs_params = {
|
9
|
+
params: [Ext::FsRequest.by_ref],
|
10
|
+
lookup: :fs_lookup
|
11
|
+
}
|
12
|
+
define_callback function: :on_unlink, **fs_params
|
13
|
+
define_callback function: :on_mkdir, **fs_params
|
14
|
+
define_callback function: :on_rmdir, **fs_params
|
15
|
+
define_callback function: :on_readdir, **fs_params
|
16
|
+
define_callback function: :on_rename, **fs_params
|
17
|
+
define_callback function: :on_chmod, **fs_params
|
18
|
+
define_callback function: :on_utime, **fs_params
|
19
|
+
define_callback function: :on_stat, **fs_params
|
20
|
+
define_callback function: :on_link, **fs_params
|
21
|
+
define_callback function: :on_symlink, **fs_params
|
22
|
+
define_callback function: :on_readlink, **fs_params
|
23
|
+
define_callback function: :on_chown, **fs_params
|
24
|
+
|
25
|
+
|
26
|
+
def initialize(reactor)
|
27
|
+
@reactor = reactor
|
28
|
+
end
|
29
|
+
|
30
|
+
def unlink(path, wait: true)
|
31
|
+
assert_type(String, path, "path must be a String")
|
32
|
+
@unlink_deferred = @reactor.defer
|
33
|
+
|
34
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
35
|
+
pre_check @unlink_deferred, request, ::MTLibuv::Ext.fs_unlink(@reactor, request, path, callback(:on_unlink, request.address))
|
36
|
+
respond wait, @unlink_deferred.promise
|
37
|
+
end
|
38
|
+
|
39
|
+
def mkdir(path, mode = 0777, wait: true)
|
40
|
+
assert_type(String, path, "path must be a String")
|
41
|
+
assert_type(Integer, mode, "mode must be an Integer")
|
42
|
+
@mkdir_deferred = @reactor.defer
|
43
|
+
|
44
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
45
|
+
pre_check @mkdir_deferred, request, ::MTLibuv::Ext.fs_mkdir(@reactor, request, path, mode, callback(:on_mkdir, request.address))
|
46
|
+
respond wait, @mkdir_deferred.promise
|
47
|
+
end
|
48
|
+
|
49
|
+
def rmdir(path, wait: true)
|
50
|
+
assert_type(String, path, "path must be a String")
|
51
|
+
@rmdir_deferred = @reactor.defer
|
52
|
+
|
53
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
54
|
+
pre_check @rmdir_deferred, request, ::MTLibuv::Ext.fs_rmdir(@reactor, request, path, callback(:on_rmdir, request.address))
|
55
|
+
respond wait, @rmdir_deferred.promise
|
56
|
+
end
|
57
|
+
|
58
|
+
def readdir(path, wait: true)
|
59
|
+
assert_type(String, path, "path must be a String")
|
60
|
+
@readdir_deferred = @reactor.defer
|
61
|
+
|
62
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
63
|
+
pre_check @readdir_deferred, request, ::MTLibuv::Ext.fs_readdir(@reactor, request, path, 0, callback(:on_readdir, request.address))
|
64
|
+
respond wait, @readdir_deferred.promise
|
65
|
+
end
|
66
|
+
|
67
|
+
def rename(old_path, new_path, wait: true)
|
68
|
+
assert_type(String, old_path, "old_path must be a String")
|
69
|
+
assert_type(String, new_path, "new_path must be a String")
|
70
|
+
@rename_deferred = @reactor.defer
|
71
|
+
|
72
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
73
|
+
pre_check @rename_deferred, request, ::MTLibuv::Ext.fs_rename(@reactor, request, old_path, new_path, callback(:on_rename, request.address))
|
74
|
+
respond wait, @rename_deferred.promise
|
75
|
+
end
|
76
|
+
|
77
|
+
def chmod(path, mode, wait: true)
|
78
|
+
assert_type(String, path, "path must be a String")
|
79
|
+
assert_type(Integer, mode, "mode must be an Integer")
|
80
|
+
@chmod_deferred = @reactor.defer
|
81
|
+
|
82
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
83
|
+
pre_check @chmod_deferred, request, ::MTLibuv::Ext.fs_chmod(@reactor, request, path, mode, callback(:on_chmod, request.address))
|
84
|
+
respond wait, @chmod_deferred.promise
|
85
|
+
end
|
86
|
+
|
87
|
+
def utime(path, atime, mtime, wait: true)
|
88
|
+
assert_type(String, path, "path must be a String")
|
89
|
+
assert_type(Integer, atime, "atime must be an Integer")
|
90
|
+
assert_type(Integer, mtime, "mtime must be an Integer")
|
91
|
+
@utime_deferred = @reactor.defer
|
92
|
+
|
93
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
94
|
+
pre_check @utime_deferred, request, ::MTLibuv::Ext.fs_utime(@reactor, request, path, atime, mtime, callback(:on_utime, request.address))
|
95
|
+
respond wait, @utime_deferred.promise
|
96
|
+
end
|
97
|
+
|
98
|
+
def lstat(path, wait: true)
|
99
|
+
assert_type(String, path, "path must be a String")
|
100
|
+
@stat_deferred = @reactor.defer
|
101
|
+
|
102
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
103
|
+
pre_check @stat_deferred, request, ::MTLibuv::Ext.fs_lstat(@reactor, request, path, callback(:on_stat, request.address))
|
104
|
+
respond wait, @stat_deferred.promise
|
105
|
+
end
|
106
|
+
|
107
|
+
def link(old_path, new_path, wait: true)
|
108
|
+
assert_type(String, old_path, "old_path must be a String")
|
109
|
+
assert_type(String, new_path, "new_path must be a String")
|
110
|
+
@link_deferred = @reactor.defer
|
111
|
+
|
112
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
113
|
+
pre_check @link_deferred, request, ::MTLibuv::Ext.fs_link(@reactor, request, old_path, new_path, callback(:on_link, request.address))
|
114
|
+
respond wait, @link_deferred.promise
|
115
|
+
end
|
116
|
+
|
117
|
+
def symlink(old_path, new_path, wait: true)
|
118
|
+
assert_type(String, old_path, "old_path must be a String")
|
119
|
+
assert_type(String, new_path, "new_path must be a String")
|
120
|
+
@symlink_deferred = @reactor.defer
|
121
|
+
|
122
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
123
|
+
pre_check @symlink_deferred, request, ::MTLibuv::Ext.fs_symlink(@reactor, request, old_path, new_path, 0, callback(:on_symlink, request.address))
|
124
|
+
respond wait, @symlink_deferred.promise
|
125
|
+
end
|
126
|
+
|
127
|
+
def readlink(path, wait: true)
|
128
|
+
assert_type(String, path, "path must be a String")
|
129
|
+
@readlink_deferred = @reactor.defer
|
130
|
+
|
131
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
132
|
+
pre_check @readlink_deferred, request, ::MTLibuv::Ext.fs_readlink(@reactor, request, path, callback(:on_readlink, request.address))
|
133
|
+
respond wait, @readlink_deferred.promise
|
134
|
+
end
|
135
|
+
|
136
|
+
def chown(path, uid, gid, wait: true)
|
137
|
+
assert_type(String, path, "path must be a String")
|
138
|
+
assert_type(Integer, uid, "uid must be an Integer")
|
139
|
+
assert_type(Integer, gid, "gid must be an Integer")
|
140
|
+
@chown_deferred = @reactor.defer
|
141
|
+
|
142
|
+
request = ::MTLibuv::Ext.allocate_request_fs
|
143
|
+
pre_check @chown_deferred, request, ::MTLibuv::Ext.fs_chown(@reactor, request, path, uid, gid, callback(:on_chown, request.address))
|
144
|
+
respond wait, @chown_deferred.promise
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
|
151
|
+
def on_unlink(req)
|
152
|
+
if post_check(req, @unlink_deferred)
|
153
|
+
path = req[:path]
|
154
|
+
cleanup(req)
|
155
|
+
@reactor.exec { @unlink_deferred.resolve(path) }
|
156
|
+
end
|
157
|
+
@unlink_deferred = nil
|
158
|
+
end
|
159
|
+
|
160
|
+
def on_mkdir(req)
|
161
|
+
if post_check(req, @mkdir_deferred)
|
162
|
+
path = req[:path]
|
163
|
+
cleanup(req)
|
164
|
+
@reactor.exec { @mkdir_deferred.resolve(path) }
|
165
|
+
end
|
166
|
+
@mkdir_deferred = nil
|
167
|
+
end
|
168
|
+
|
169
|
+
def on_rmdir(req)
|
170
|
+
if post_check(req, @rmdir_deferred)
|
171
|
+
path = req[:path]
|
172
|
+
cleanup(req)
|
173
|
+
@reactor.exec { @rmdir_deferred.resolve(path) }
|
174
|
+
end
|
175
|
+
@rmdir_deferred = nil
|
176
|
+
end
|
177
|
+
|
178
|
+
def on_readdir(req)
|
179
|
+
if post_check(req, @readdir_deferred)
|
180
|
+
num_files = req[:result]
|
181
|
+
|
182
|
+
info = ::MTLibuv::Ext::UvDirent.new
|
183
|
+
files = []
|
184
|
+
ret = 1
|
185
|
+
loop do
|
186
|
+
ret = ::MTLibuv::Ext.fs_readdir_next(req, info)
|
187
|
+
files << [info[:name], info[:type]]
|
188
|
+
|
189
|
+
# EOF is the alternative
|
190
|
+
break unless ret == 0
|
191
|
+
end
|
192
|
+
|
193
|
+
cleanup(req)
|
194
|
+
@reactor.exec { @readdir_deferred.resolve(files) }
|
195
|
+
end
|
196
|
+
@readdir_deferred = nil
|
197
|
+
end
|
198
|
+
|
199
|
+
def on_rename(req)
|
200
|
+
if post_check(req, @rename_deferred)
|
201
|
+
path = req[:path]
|
202
|
+
cleanup(req)
|
203
|
+
@reactor.exec { @rename_deferred.resolve(path) }
|
204
|
+
end
|
205
|
+
@rename_deferred = nil
|
206
|
+
end
|
207
|
+
|
208
|
+
def on_chmod(req)
|
209
|
+
if post_check(req, @chmod_deferred)
|
210
|
+
path = req[:path]
|
211
|
+
cleanup(req)
|
212
|
+
@reactor.exec { @chmod_deferred.resolve(path) }
|
213
|
+
end
|
214
|
+
@chmod_deferred = nil
|
215
|
+
end
|
216
|
+
|
217
|
+
def on_utime(req)
|
218
|
+
if post_check(req, @utime_deferred)
|
219
|
+
path = req[:path]
|
220
|
+
cleanup(req)
|
221
|
+
@reactor.exec { @utime_deferred.resolve(path) }
|
222
|
+
end
|
223
|
+
@utime_deferred = nil
|
224
|
+
end
|
225
|
+
|
226
|
+
def on_link(req)
|
227
|
+
if post_check(req, @link_deferred)
|
228
|
+
path = req[:path]
|
229
|
+
cleanup(req)
|
230
|
+
@reactor.exec { @link_deferred.resolve(path) }
|
231
|
+
end
|
232
|
+
@link_deferred = nil
|
233
|
+
end
|
234
|
+
|
235
|
+
def on_symlink(req)
|
236
|
+
if post_check(req, @symlink_deferred)
|
237
|
+
path = req[:path]
|
238
|
+
cleanup(req)
|
239
|
+
@reactor.exec { @symlink_deferred.resolve(path) }
|
240
|
+
end
|
241
|
+
@symlink_deferred = nil
|
242
|
+
end
|
243
|
+
|
244
|
+
def on_readlink(req)
|
245
|
+
if post_check(req, @readlink_deferred)
|
246
|
+
string_ptr = req[:ptr]
|
247
|
+
path = string_ptr.null? ? nil : string_ptr.read_string_to_null
|
248
|
+
cleanup(req)
|
249
|
+
@reactor.exec { @readlink_deferred.resolve(path) }
|
250
|
+
end
|
251
|
+
@readlink_deferred = nil
|
252
|
+
end
|
253
|
+
|
254
|
+
def on_chown(req)
|
255
|
+
if post_check(req, @chown_deferred)
|
256
|
+
path = req[:path]
|
257
|
+
cleanup(req)
|
258
|
+
@reactor.exec { @chown_deferred.resolve(path) }
|
259
|
+
end
|
260
|
+
@chown_deferred = nil
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MTLibuv
|
4
|
+
class FSEvent < Handle
|
5
|
+
|
6
|
+
|
7
|
+
define_callback function: :on_fs_event, params: [:pointer, :string, :int, :int]
|
8
|
+
|
9
|
+
|
10
|
+
EVENTS = {1 => :rename, 2 => :change}.freeze
|
11
|
+
|
12
|
+
|
13
|
+
def initialize(reactor, path)
|
14
|
+
@reactor = reactor
|
15
|
+
|
16
|
+
fs_event_ptr = ::MTLibuv::Ext.allocate_handle_fs_event
|
17
|
+
error = check_result ::MTLibuv::Ext.fs_event_init(reactor.handle, fs_event_ptr, path, callback(:on_fs_event, fs_event_ptr.address), 0)
|
18
|
+
|
19
|
+
super(fs_event_ptr, error)
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
|
26
|
+
def on_fs_event(handle, filename, events, status)
|
27
|
+
e = check_result(status)
|
28
|
+
|
29
|
+
if e
|
30
|
+
reject(e)
|
31
|
+
else
|
32
|
+
# notify of a change
|
33
|
+
@reactor.exec { defer.notify(filename, EVENTS[events]) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|