libvirt_ffi 0.2.1 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +78 -0
- data/Gemfile +7 -2
- data/Rakefile +6 -1
- data/bin/console +1 -0
- data/exe/libvirt +1 -0
- data/lib/libvirt.rb +14 -13
- data/lib/libvirt/base_info.rb +34 -0
- data/lib/libvirt/connection.rb +156 -47
- data/lib/libvirt/domain.rb +136 -8
- data/lib/libvirt/domain_callback_storage.rb +69 -0
- data/lib/libvirt/errors.rb +65 -0
- data/lib/libvirt/event.rb +60 -38
- data/lib/libvirt/ffi.rb +17 -0
- data/lib/libvirt/ffi/common.rb +8 -1
- data/lib/libvirt/ffi/domain.rb +796 -69
- data/lib/libvirt/ffi/error.rb +243 -0
- data/lib/libvirt/ffi/event.rb +30 -36
- data/lib/libvirt/ffi/helpers.rb +17 -0
- data/lib/libvirt/ffi/host.rb +122 -0
- data/lib/libvirt/ffi/storage.rb +149 -0
- data/lib/libvirt/ffi/stream.rb +74 -0
- data/lib/libvirt/node_info.rb +2 -41
- data/lib/libvirt/storage_pool.rb +70 -0
- data/lib/libvirt/storage_pool_info.rb +7 -0
- data/lib/libvirt/storage_volume.rb +51 -0
- data/lib/libvirt/storage_volume_info.rb +7 -0
- data/lib/libvirt/stream.rb +124 -0
- data/lib/libvirt/util.rb +75 -8
- data/lib/libvirt/version.rb +1 -1
- data/lib/libvirt/xml.rb +23 -0
- data/lib/libvirt/xml/disk.rb +59 -0
- data/lib/libvirt/xml/domain.rb +76 -0
- data/lib/libvirt/xml/generic.rb +252 -0
- data/lib/libvirt/xml/graphics.rb +14 -0
- data/lib/libvirt/xml/max_vcpu.rb +12 -0
- data/lib/libvirt/xml/memory.rb +14 -0
- data/lib/libvirt/xml/storage_pool.rb +24 -0
- data/lib/libvirt/xml/storage_volume.rb +32 -0
- data/lib/libvirt/xml/vcpu.rb +12 -0
- data/lib/libvirt_ffi.rb +2 -0
- data/libvirt.gemspec +5 -1
- data/test_usage/support/libvirt_async.rb +33 -31
- data/test_usage/support/log_formatter.rb +5 -10
- data/test_usage/test_domain.rb +43 -0
- data/test_usage/test_event_loop.rb +134 -33
- data/test_usage/test_libvirtd_restart.rb +63 -0
- data/test_usage/test_metadata.rb +104 -0
- data/test_usage/test_screenshot.rb +197 -0
- data/test_usage/test_storage.rb +52 -0
- metadata +46 -6
- data/lib/libvirt/error.rb +0 -6
- data/lib/libvirt/ffi/connection.rb +0 -84
- data/lib/libvirt/ffi/libvirt.rb +0 -17
- data/lib/libvirt/ffi/node_info.rb +0 -37
data/lib/libvirt/domain.rb
CHANGED
@@ -2,20 +2,35 @@
|
|
2
2
|
|
3
3
|
module Libvirt
|
4
4
|
class Domain
|
5
|
-
def
|
5
|
+
def self.load_ref(dom_ptr)
|
6
|
+
ref_result = FFI::Domain.virDomainRef(dom_ptr)
|
7
|
+
raise Errors::LibError, "Couldn't retrieve domain reference" if ref_result.negative?
|
8
|
+
|
9
|
+
new(dom_ptr)
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(dom_ptr)
|
6
13
|
@dom_ptr = dom_ptr
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
14
|
+
|
15
|
+
free = ->(obj_id) do
|
16
|
+
Util.log(:debug) { "Finalize Libvirt::Domain 0x#{obj_id.to_s(16)} @dom_ptr=#{@dom_ptr}," }
|
17
|
+
return unless @dom_ptr
|
18
|
+
|
19
|
+
fr_result = FFI::Domain.virDomainFree(@dom_ptr)
|
20
|
+
warn "Couldn't free Libvirt::Domain (0x#{obj_id.to_s(16)}) pointer #{@dom_ptr.address}" if fr_result.negative?
|
21
|
+
end
|
22
|
+
ObjectSpace.define_finalizer(self, free)
|
11
23
|
end
|
12
24
|
|
13
25
|
def get_state
|
14
26
|
state = ::FFI::MemoryPointer.new(:int)
|
15
27
|
reason = ::FFI::MemoryPointer.new(:int)
|
16
28
|
result = FFI::Domain.virDomainGetState(@dom_ptr, state, reason, 0)
|
17
|
-
raise
|
18
|
-
|
29
|
+
raise Errors::LibError, "Couldn't get domain state" if result.negative?
|
30
|
+
|
31
|
+
state_sym = FFI::Domain.enum_type(:state)[state.read_int]
|
32
|
+
reason_sym = FFI::Domain.state_reason(state_sym, reason.read_int)
|
33
|
+
[state_sym, reason_sym]
|
19
34
|
end
|
20
35
|
|
21
36
|
def to_ptr
|
@@ -25,7 +40,8 @@ module Libvirt
|
|
25
40
|
def uuid
|
26
41
|
buff = ::FFI::MemoryPointer.new(:char, FFI::Domain::UUID_STRING_BUFLEN)
|
27
42
|
result = FFI::Domain.virDomainGetUUIDString(@dom_ptr, buff)
|
28
|
-
raise
|
43
|
+
raise Errors::LibError, "Couldn't get domain uuid" if result.negative?
|
44
|
+
|
29
45
|
buff.read_string
|
30
46
|
end
|
31
47
|
|
@@ -56,5 +72,117 @@ module Libvirt
|
|
56
72
|
def xml_desc(flags = 0)
|
57
73
|
FFI::Domain.virDomainGetXMLDesc(@dom_ptr, flags)
|
58
74
|
end
|
75
|
+
|
76
|
+
def screenshot(stream, display = 0)
|
77
|
+
dbg { "#screenshot stream=#{stream}, display=#{display}," }
|
78
|
+
|
79
|
+
mime_type, pointer = FFI::Domain.virDomainScreenshot(@dom_ptr, stream.to_ptr, display, 0)
|
80
|
+
raise Errors::LibError, "Couldn't attach domain screenshot" if pointer.null?
|
81
|
+
|
82
|
+
# free pointer required
|
83
|
+
mime_type
|
84
|
+
end
|
85
|
+
|
86
|
+
def free_domain
|
87
|
+
result = FFI::Domain.virDomainFree(@dom_ptr)
|
88
|
+
raise Errors::LibError, "Couldn't free domain" if result.negative?
|
89
|
+
|
90
|
+
@dom_ptr = nil
|
91
|
+
end
|
92
|
+
|
93
|
+
def start(flags = 0)
|
94
|
+
result = FFI::Domain.virDomainCreateWithFlags(@dom_ptr, flags)
|
95
|
+
raise Errors::LibError, "Couldn't start domain" if result.negative?
|
96
|
+
end
|
97
|
+
|
98
|
+
def reboot(flags = 0)
|
99
|
+
result = FFI::Domain.virDomainReboot(@dom_ptr, flags)
|
100
|
+
raise Errors::LibError, "Couldn't reboot domain" if result.negative?
|
101
|
+
end
|
102
|
+
|
103
|
+
def shutdown(flags = :ACPI_POWER_BTN)
|
104
|
+
result = FFI::Domain.virDomainShutdownFlags(@dom_ptr, flags)
|
105
|
+
raise Errors::LibError, "Couldn't shutdown domain" if result.negative?
|
106
|
+
end
|
107
|
+
|
108
|
+
def power_off(flags = 0)
|
109
|
+
result = FFI::Domain.virDomainDestroyFlags(@dom_ptr, flags)
|
110
|
+
raise Errors::LibError, "Couldn't power off domain" if result.negative?
|
111
|
+
end
|
112
|
+
|
113
|
+
def reset(flags = 0)
|
114
|
+
result = FFI::Domain.virDomainReset(@dom_ptr, flags)
|
115
|
+
raise Errors::LibError, "Couldn't reset domain" if result.negative?
|
116
|
+
end
|
117
|
+
|
118
|
+
def suspend
|
119
|
+
result = FFI::Domain.virDomainSuspend(@dom_ptr)
|
120
|
+
raise Errors::LibError, "Couldn't suspend domain" if result.negative?
|
121
|
+
end
|
122
|
+
|
123
|
+
def resume
|
124
|
+
result = FFI::Domain.virDomainResume(@dom_ptr)
|
125
|
+
raise Errors::LibError, "Couldn't resume domain" if result.negative?
|
126
|
+
end
|
127
|
+
|
128
|
+
# Undefine a domain.
|
129
|
+
# If the domain is running, it's converted to transient domain, without stopping it.
|
130
|
+
# If the domain is inactive, the domain configuration is removed.
|
131
|
+
# @param options_or_flags [Array<Symbol>,Hash{Symbol=>Boolean},Integer,Symbol,nil]
|
132
|
+
# @see Libvirt::FFI::Domain enum :undefine_flags_values for acceptable keys
|
133
|
+
# @see Libvirt::Util.parse_flags for possible argument values
|
134
|
+
# @raise [Libvirt::Errors::LibError] if operation failed
|
135
|
+
def undefine(options_or_flags = nil)
|
136
|
+
flags = Util.parse_flags options_or_flags, FFI::Domain.enum_type(:undefine_flags_values)
|
137
|
+
result = FFI::Domain.virDomainUndefineFlags(@dom_ptr, flags)
|
138
|
+
raise Errors::LibError, "Couldn't resume domain" if result.negative?
|
139
|
+
end
|
140
|
+
|
141
|
+
# After save_memory(:PAUSED) you need to call #start and #resume
|
142
|
+
# to move domain to the running state.
|
143
|
+
def save_memory(flags = :PAUSED)
|
144
|
+
result = FFI::Domain.virDomainManagedSave(@dom_ptr, flags)
|
145
|
+
raise Errors::LibError, "Couldn't save domain memory" if result.negative?
|
146
|
+
end
|
147
|
+
|
148
|
+
# Sets metadata
|
149
|
+
# @param metadata [String] xml node for element type, text for other types
|
150
|
+
# DESCRIPTION 0x0 - Operate on <description>
|
151
|
+
# TITLE 0x1 - Operate on <title>
|
152
|
+
# ELEMENT 0x2 - Operate on <metadata>
|
153
|
+
# @param type [Integer,Symbol] one of :ELEMENT, :TITLE, :DESCRIPTION
|
154
|
+
# @param key [String] xml key (required for type element)
|
155
|
+
# @param uri [String] xml namespace (required for type element)
|
156
|
+
# @param flags [Integer,Symbol] one off AFFECT_CURRENT, AFFECT_CONFIG, AFFECT_LIVE
|
157
|
+
# AFFECT_CURRENT 0x0 - Affect current domain state.
|
158
|
+
# AFFECT_LIVE 0x1 - Affect running domain state.
|
159
|
+
# AFFECT_CONFIG 0x2 - Affect persistent domain state.
|
160
|
+
# @raise [Libvirt::Errors::LibError] if operation failed
|
161
|
+
def set_metadata(metadata, type: :ELEMENT, key: nil, uri: nil, flags: :AFFECT_CURRENT)
|
162
|
+
result = FFI::Domain.virDomainSetMetadata(@dom_ptr, type, metadata, key, uri, flags)
|
163
|
+
raise Errors::LibError, "Couldn't set domain metadata" if result.negative?
|
164
|
+
end
|
165
|
+
|
166
|
+
# Retrieves metadata
|
167
|
+
# @param type [Integer,Symbol] one of :ELEMENT, :TITLE, :DESCRIPTION
|
168
|
+
# @param uri [String] xml namespace (required for type element)
|
169
|
+
# @param flags [Integer,Symbol] one off AFFECT_CURRENT, AFFECT_CONFIG, AFFECT_LIVE
|
170
|
+
# AFFECT_CURRENT 0x0 - Affect current domain state.
|
171
|
+
# AFFECT_LIVE 0x1 - Affect running domain state.
|
172
|
+
# AFFECT_CONFIG 0x2 - Affect persistent domain state.
|
173
|
+
# @raise [Libvirt::Errors::LibError] if operation failed
|
174
|
+
# @return [String] xml node, title, or description.
|
175
|
+
def get_metadata(type: :ELEMENT, uri: nil, flags: :AFFECT_CURRENT)
|
176
|
+
result = FFI::Domain.virDomainGetMetadata(@dom_ptr, type, uri, flags)
|
177
|
+
raise Errors::LibError, "Couldn't get domain metadata" if result.nil?
|
178
|
+
|
179
|
+
result
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def dbg(&block)
|
185
|
+
Util.log(:debug, 'Libvirt::Domain', &block)
|
186
|
+
end
|
59
187
|
end
|
60
188
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Libvirt
|
4
|
+
class DomainCallbackStorage
|
5
|
+
class CallbackDataStruct < ::FFI::Struct
|
6
|
+
layout :connection_pointer, :pointer,
|
7
|
+
:callback_id, :int
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@inner_storage = Hash.new { |h, key| h[key] = {} }
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Array<2>]
|
15
|
+
# cb_data [Libvirt::DomainCallbackStorage::CallbackDataStruct],
|
16
|
+
# cb_data_free_func [FFI::Function]
|
17
|
+
def allocate_struct
|
18
|
+
dbg { '#allocate_struct' }
|
19
|
+
|
20
|
+
cb_data_ptr = ::FFI::MemoryPointer.new(:char, CallbackDataStruct.size, false)
|
21
|
+
cb_data = CallbackDataStruct.new(cb_data_ptr)
|
22
|
+
cb_data_free_func = FFI::Common.free_function do |pointer|
|
23
|
+
dbg { 'Libvirt::DomainCallbackStorage cb_data_free_func triggered' }
|
24
|
+
remove_struct(pointer)
|
25
|
+
end
|
26
|
+
[cb_data, cb_data_free_func]
|
27
|
+
end
|
28
|
+
|
29
|
+
def store_struct(cb_data, connection_pointer:, callback_id:, cb:, opaque:)
|
30
|
+
dbg { '#store_struct' }
|
31
|
+
|
32
|
+
cb_data[:connection_pointer] = connection_pointer
|
33
|
+
cb_data[:callback_id] = callback_id
|
34
|
+
@inner_storage[connection_pointer.address][callback_id] = { cb: cb, opaque: opaque, pointer: cb_data.pointer }
|
35
|
+
end
|
36
|
+
|
37
|
+
def remove_struct(pointer)
|
38
|
+
dbg { "#remove_struct pointer=#{pointer}" }
|
39
|
+
|
40
|
+
cb_data_struct = CallbackDataStruct.new(pointer)
|
41
|
+
connection_pointer = cb_data_struct[:connection_pointer]
|
42
|
+
callback_id = cb_data_struct[:callback_id]
|
43
|
+
dbg { "#remove_struct pointer=#{pointer}, connection_pointer=#{connection_pointer}, callback_id=#{callback_id}," }
|
44
|
+
|
45
|
+
cb_data = @inner_storage[connection_pointer.address].delete(callback_id)
|
46
|
+
@inner_storage.delete(connection_pointer.address) if @inner_storage[connection_pointer.address].empty?
|
47
|
+
|
48
|
+
cb_data[:opaque]
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param [::FFI::Pointer]
|
52
|
+
# @return [Array<2>] cb [Proc], opaque [Object]
|
53
|
+
def retrieve_from_pointer(pointer)
|
54
|
+
dbg { "#retrieve_from_pointer pointer=#{pointer}," }
|
55
|
+
|
56
|
+
cb_data_struct = CallbackDataStruct.new(pointer)
|
57
|
+
connection_pointer = cb_data_struct[:connection_pointer]
|
58
|
+
callback_id = cb_data_struct[:callback_id]
|
59
|
+
cb_data = @inner_storage[connection_pointer.address][callback_id]
|
60
|
+
[cb_data[:cb], cb_data[:opaque]]
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def dbg(&block)
|
66
|
+
Util.log(:debug, 'Libvirt::DomainCallbackStorage', &block)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Libvirt
|
4
|
+
module Errors
|
5
|
+
class Error < StandardError
|
6
|
+
# Generic error
|
7
|
+
end
|
8
|
+
|
9
|
+
class LibError < Error
|
10
|
+
# Object contains detailed error information retrieved from libvirt.
|
11
|
+
|
12
|
+
ERROR_FIELDS = [:code, :domain, :message, :level].freeze
|
13
|
+
|
14
|
+
attr_reader :client_message,
|
15
|
+
:error_data,
|
16
|
+
:error_code,
|
17
|
+
:error_domain,
|
18
|
+
:error_message,
|
19
|
+
:error_level
|
20
|
+
|
21
|
+
# @param client_message [String, nil] optional client message
|
22
|
+
# When client_message ommited and virGetLastError return error
|
23
|
+
# message will be following: "ERROR_LEVEL: ERROR_NUMBER (ERROR_DOMAIN) ERROR_MESSAGE".
|
24
|
+
# When client message provided and virGetLastError return error
|
25
|
+
# message will be following: "CLIENT_MESSAGE\nERROR_LEVEL: ERROR_NUMBER (ERROR_DOMAIN) ERROR_MESSAGE".
|
26
|
+
# When client message is provided and virGetLastError return no error
|
27
|
+
# message will be following: "CLIENT_MESSAGE".
|
28
|
+
def initialize(client_message = nil)
|
29
|
+
@client_message = client_message
|
30
|
+
ptr = FFI::Error.virGetLastError
|
31
|
+
unless ptr.null?
|
32
|
+
struct = FFI::Error::Struct.new(ptr)
|
33
|
+
@error_data = struct.members.map { |m| [m, struct[m]] }.to_h
|
34
|
+
@error_code = error_data[:code]
|
35
|
+
@error_domain = error_data[:domain]
|
36
|
+
@error_message = error_data[:message]
|
37
|
+
@error_level = error_data[:level]
|
38
|
+
end
|
39
|
+
|
40
|
+
super(build_message)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def build_message
|
46
|
+
if error_data.nil?
|
47
|
+
client_message
|
48
|
+
elsif client_message.nil?
|
49
|
+
format '%<level>s: %<code>s (%<domain>s) %<message>s',
|
50
|
+
level: error_level,
|
51
|
+
code: error_code,
|
52
|
+
domain: error_domain,
|
53
|
+
message: error_message
|
54
|
+
else
|
55
|
+
format "%<client_message>s\n%<level>s: %<code>s (%<domain>s) %<message>s",
|
56
|
+
client_message: client_message,
|
57
|
+
level: error_level,
|
58
|
+
code: error_code,
|
59
|
+
domain: error_domain,
|
60
|
+
message: error_message
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/libvirt/event.rb
CHANGED
@@ -9,24 +9,32 @@ module Libvirt
|
|
9
9
|
extend Forwardable
|
10
10
|
extend SingleForwardable
|
11
11
|
|
12
|
-
single_delegate [
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
12
|
+
single_delegate [
|
13
|
+
:register,
|
14
|
+
:unregister,
|
15
|
+
:registered?,
|
16
|
+
:debug,
|
17
|
+
:debug=,
|
18
|
+
:invoke_handle_callback,
|
19
|
+
:invoke_timeout_callback
|
20
|
+
] => :instance
|
21
|
+
|
22
|
+
attr_accessor :debug
|
23
|
+
|
24
|
+
Opaque = Struct.new(:cb, :opaque, :free_func)
|
25
|
+
|
26
|
+
def invoke_handle_callback(watch, fd, events, opaque)
|
27
|
+
cb = opaque.cb
|
28
|
+
op = opaque.opaque
|
29
|
+
dbg { "INVOKE_HANDLE_CALLBACK watch=#{watch} fd=#{fd} events=#{events} op=#{op}" }
|
30
|
+
cb.call(watch, fd, events, op)
|
31
|
+
end
|
23
32
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
33
|
+
def invoke_timeout_callback(timer, opaque)
|
34
|
+
cb = opaque.cb
|
35
|
+
op = opaque.opaque
|
36
|
+
dbg { "INVOKE_TIMEOUT_CALLBACK timer=#{timer} op=#{op}" }
|
37
|
+
cb.call(timer, op)
|
30
38
|
end
|
31
39
|
|
32
40
|
def registered?
|
@@ -51,20 +59,25 @@ module Libvirt
|
|
51
59
|
true
|
52
60
|
end
|
53
61
|
|
54
|
-
def
|
62
|
+
def schedule_operation(&block)
|
63
|
+
@schedule.call(&block)
|
64
|
+
end
|
65
|
+
|
66
|
+
def register(add_handle:, update_handle:, remove_handle:, add_timer:, update_timer:, remove_timer:, schedule:) # rubocop:disable Metrics/ParameterLists
|
55
67
|
@add_handle = add_handle
|
56
68
|
@update_handle = update_handle
|
57
69
|
@remove_handle = remove_handle
|
58
70
|
@add_timer = add_timer
|
59
71
|
@update_timer = update_timer
|
60
72
|
@remove_timer = remove_timer
|
73
|
+
@schedule = schedule
|
61
74
|
|
62
|
-
@add_handle_cb = FFI::Event.
|
63
|
-
@update_handle_cb =
|
64
|
-
@remove_handle_cb =
|
65
|
-
@add_timer_cb = FFI::Event.
|
66
|
-
@update_timer_cb =
|
67
|
-
@remove_timer_cb =
|
75
|
+
@add_handle_cb = FFI::Event.callback_function(:virEventAddHandleFunc, &method(:_add_handle))
|
76
|
+
@update_handle_cb = FFI::Event.callback_function(:virEventUpdateHandleFunc, &method(:_update_handle))
|
77
|
+
@remove_handle_cb = FFI::Event.callback_function(:virEventRemoveHandleFunc, &method(:_remove_handle))
|
78
|
+
@add_timer_cb = FFI::Event.callback_function(:virEventAddTimeoutFunc, &method(:_add_timer))
|
79
|
+
@update_timer_cb = FFI::Event.callback_function(:virEventUpdateTimeoutFunc, &method(:_update_timer))
|
80
|
+
@remove_timer_cb = FFI::Event.callback_function(:virEventRemoveTimeoutFunc, &method(:_remove_timer))
|
68
81
|
|
69
82
|
FFI::Event.virEventRegisterImpl(
|
70
83
|
@add_handle_cb,
|
@@ -79,45 +92,54 @@ module Libvirt
|
|
79
92
|
|
80
93
|
private
|
81
94
|
|
82
|
-
def _add_handle(fd, event, cb, opaque,
|
83
|
-
|
84
|
-
op = Opaque.new(cb, opaque,
|
95
|
+
def _add_handle(fd, event, cb, opaque, free_func)
|
96
|
+
dbg { "ADD_HANDLE fd=#{fd}, #{event}=event, cb=#{cb}, opaque=#{opaque}, free_func=#{free_func}" }
|
97
|
+
op = Opaque.new(cb, opaque, free_func)
|
85
98
|
@add_handle.call(fd, event, op)
|
86
99
|
end
|
87
100
|
|
88
101
|
def _update_handle(watch, event)
|
89
|
-
|
102
|
+
dbg { "UPDATE_HANDLE watch=#{watch}, event=#{event}" }
|
90
103
|
@update_handle.call(watch, event)
|
91
104
|
end
|
92
105
|
|
93
106
|
def _remove_handle(watch)
|
94
|
-
|
107
|
+
dbg { "REMOVE_HANDLE watch=#{watch}" }
|
95
108
|
op = @remove_handle.call(watch)
|
96
|
-
free_func = op.
|
109
|
+
free_func = op.free_func
|
97
110
|
opaque = op.opaque
|
98
|
-
|
111
|
+
schedule_operation do
|
112
|
+
dbg { "REMOVE_HANDLE delayed free_func watch=#{watch}" }
|
113
|
+
free_func.call(opaque) unless free_func.null?
|
114
|
+
end
|
99
115
|
0
|
100
116
|
end
|
101
117
|
|
102
|
-
def _add_timer(timeout, cb, opaque,
|
103
|
-
|
104
|
-
op = Opaque.new(cb, opaque,
|
118
|
+
def _add_timer(timeout, cb, opaque, free_func)
|
119
|
+
dbg { "ADD_TIMER timeout=#{timeout}, cb=#{cb}, opaque=#{opaque}, free_func=#{free_func}" }
|
120
|
+
op = Opaque.new(cb, opaque, free_func)
|
105
121
|
@add_timer.call(timeout, op)
|
106
122
|
end
|
107
123
|
|
108
124
|
def _update_timer(timer, timeout)
|
109
|
-
|
125
|
+
dbg { "UPDATE_TIMER timer=#{timer}, timeout=#{timeout}" }
|
110
126
|
@update_timer.call(timer, timeout)
|
111
127
|
end
|
112
128
|
|
113
129
|
def _remove_timer(timer)
|
114
|
-
|
130
|
+
dbg { "REMOVE_TIMER timer=#{timer}" }
|
115
131
|
op = @remove_timer.call(timer)
|
116
|
-
free_func = op.
|
132
|
+
free_func = op.free_func
|
117
133
|
opaque = op.opaque
|
118
|
-
|
134
|
+
schedule_operation do
|
135
|
+
dbg { "REMOVE_TIMER async free_func timer=#{timer}" }
|
136
|
+
free_func.call(opaque) unless free_func.null?
|
137
|
+
end
|
119
138
|
0
|
120
139
|
end
|
121
140
|
|
141
|
+
def dbg(&block)
|
142
|
+
Util.log(:debug, 'Libvirt::Event', &block)
|
143
|
+
end
|
122
144
|
end
|
123
145
|
end
|