forked from daos-stack/daos
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdaos_cref.py
261 lines (215 loc) · 9.46 KB
/
daos_cref.py
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
#!/usr/bin/python
"""
(C) Copyright 2018 Intel Corporation.
Licensed 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.
GOVERNMENT LICENSE RIGHTS-OPEN SOURCE SOFTWARE
The Government's rights to use, modify, reproduce, release, perform, display,
or disclose this software are subject to the terms of the Apache License as
provided in Contract No. B609815.
Any reproduction of computer software, computer software documentation, or
portions thereof marked with this legend must also reproduce the markings.
"""
import ctypes
# DAOS api C structures
class RankList(ctypes.Structure):
""" For those DAOS calls that take a rank list """
_fields_ = [("rl_ranks", ctypes.POINTER(ctypes.c_uint32)),
("rl_nr", ctypes.c_uint)]
class IOV(ctypes.Structure):
_fields_ = [("iov_buf", ctypes.c_void_p),
("iov_buf_len", ctypes.c_size_t),
("iov_len", ctypes.c_size_t)]
class SGL(ctypes.Structure):
_fields_ = [("sg_nr", ctypes.c_uint32),
("sg_nr_out", ctypes.c_uint32),
("sg_iovs", ctypes.POINTER(IOV))]
class EpochRange(ctypes.Structure):
_fields_ = [("epr_lo", ctypes.c_uint64),
("epr_hi", ctypes.c_uint64)]
class TargetInfo(ctypes.Structure):
""" Represents info about a given target """
_fields_ = [("ta_type", ctypes.c_uint),
("ta_state", ctypes.c_uint),
("ta_perf", ctypes.c_int),
("ta_space", ctypes.c_int)]
class RebuildStatus(ctypes.Structure):
""" Structure to represent rebuild status info """
_fields_ = [("rs_version", ctypes.c_uint32),
("rs_pad_32", ctypes.c_uint32),
("rs_errno", ctypes.c_uint32),
("rs_done", ctypes.c_uint32),
("rs_toberb_obj_nr", ctypes.c_uint64),
("rs_obj_nr", ctypes.c_uint64),
("rs_rec_nr", ctypes.c_uint64)]
class Daos_handle_t(ctypes.Structure):
""" Structure to represent rebuild status info """
_fields_ = [("cookie", ctypes.c_uint64)]
class Daos_Space(ctypes.Structure):
""" Structure to represent Pool Target Space usage info """
_fields_ = [("s_total", ctypes.c_uint64 * 2),
("s_free", ctypes.c_uint64 * 2)]
class PoolSpace(ctypes.Structure):
""" Structure to represent Pool space usage info """
_fields_ = [("ps_space", Daos_Space),
("ps_free_min", ctypes.c_uint64 * 2),
("ps_free_max", ctypes.c_uint64 * 2),
("ps_free_mean", ctypes.c_uint64 * 2),
("ps_ntargets", ctypes.c_uint32),
("ps_padding", ctypes.c_uint32)]
class PoolInfo(ctypes.Structure):
""" Structure to represent information about a pool """
_fields_ = [("pi_uuid", ctypes.c_ubyte * 16),
("pi_ntargets", ctypes.c_uint32),
("pi_nnodes", ctypes.c_uint32),
("pi_ndisabled", ctypes.c_uint32),
("pi_map_ver", ctypes.c_uint32),
("pi_uid", ctypes.c_uint32),
("pi_gid", ctypes.c_uint32),
("pi_mode", ctypes.c_uint32),
("pi_leader", ctypes.c_uint32),
("pi_space", PoolSpace),
("pi_rebuild_st", RebuildStatus)]
class ContInfo(ctypes.Structure):
""" Structure to represent information about a container """
_fields_ = [("ci_uuid", ctypes.c_ubyte * 16),
("es_hce", ctypes.c_uint64),
("es_lre", ctypes.c_uint64),
("es_lhe", ctypes.c_uint64),
("es_ghce", ctypes.c_uint64),
("es_glre", ctypes.c_uint64),
("es_ghpce", ctypes.c_uint64),
("ci_nsnapshots", ctypes.c_uint32),
("ci_snapshots", ctypes.POINTER(ctypes.c_uint64)),
("ci_min_slipped_epoch", ctypes.c_uint64)]
class DaosEvent(ctypes.Structure):
_fields_ = [("ev_error", ctypes.c_int),
("ev_private", ctypes.c_ulonglong * 19),
("ev_debug", ctypes.c_ulonglong)]
class DaosObjClassAttr(ctypes.Structure):
_fields_ = [("ca_schema", ctypes.c_int),
("ca_resil_degree", ctypes.c_int),
("ca_resil", ctypes.c_int),
("ca_grp_nr", ctypes.c_uint),
("u", ctypes.c_uint * 2)]
class DaosObjAttr(ctypes.Structure):
_fields_ = [("oa_rank", ctypes.c_int),
("oa_oa", DaosObjClassAttr)]
class DaosObjId(ctypes.Structure):
_fields_ = [("lo", ctypes.c_uint64),
("hi", ctypes.c_uint64)]
# Note hard-coded number of ranks, might eventually be a problem
class DaosObjShard(ctypes.Structure):
_fields_ = [("os_replica_nr", ctypes.c_uint32),
("os_ranks", ctypes.c_uint32 * 5)]
# note the hard-coded number of ranks, might eventually be a problem
class DaosObjLayout(ctypes.Structure):
_fields_ = [("ol_ver", ctypes.c_uint32),
("ol_class", ctypes.c_uint32),
("ol_nr", ctypes.c_uint32),
("ol_shards", ctypes.POINTER(DaosObjShard * 5))]
class CheckSum(ctypes.Structure):
_fields_ = [("cs_type", ctypes.c_uint),
("cs_len", ctypes.c_ushort),
("cs_buf_len", ctypes.c_ushort),
("cs_csum", ctypes.c_void_p)]
class Extent(ctypes.Structure):
_fields_ = [("rx_idx", ctypes.c_uint64),
("rx_nr", ctypes.c_uint64)]
class DaosIODescriptor(ctypes.Structure):
_fields_ = [("iod_name", IOV),
("iod_kcsum", CheckSum),
("iod_type", ctypes.c_int),
("iod_size", ctypes.c_uint64),
("iod_nr", ctypes.c_uint32),
("iod_recxs", ctypes.POINTER(Extent)),
("iod_csums", ctypes.POINTER(CheckSum)),
("iod_eprs", ctypes.c_void_p)]
class CallbackEvent(object):
def __init__(self, obj, event):
self.obj = obj
self.event = event
def AsyncWorker1(func_ref, param_list, context, cb_func=None, obj=None):
""" Wrapper function that calls the daos C code. This can
be used to run the DAOS library functions in a thread
(or to just run them in the current thread too).
func_ref --which daos_api function to call
param_list --parameters the c function takes
context --the API context object
cb_func --optional if caller wants notification of completion
obj --optional passed to the callback function
This is done in a way that exercises the
DAOS event code which is cumbersome and done more simply
by other means. Its good for testing but replace this
implementation if this is used as something other than a test
tool.
"""
# TODO insufficient error handling in this function
# setup the asynchronous infrastructure the API requires
the_event = param_list[-1]
param_list[-1] = ctypes.byref(the_event)
qfunc = context.get_function('create-eq')
qhandle = ctypes.c_ulonglong(0)
rc = qfunc(ctypes.byref(qhandle))
efunc = context.get_function('init-event')
rc = efunc(param_list[-1], qhandle, None)
# calling the api function here
rc = func_ref(*param_list)
# use the API polling mechanism to tell when its done
efunc = context.get_function('poll-eq')
c_wait = ctypes.c_int(0)
c_timeout = ctypes.c_ulonglong(-1)
c_num = ctypes.c_uint(1)
anotherEvent = DaosEvent()
c_event_ptr = ctypes.pointer(anotherEvent)
# start polling, wait forever
rc = efunc(qhandle, c_wait, c_timeout, c_num, ctypes.byref(c_event_ptr))
# signal the caller that api function has completed
if cb_func is not None:
cb_event = CallbackEvent(obj, the_event)
cb_func(cb_event)
# clean up
qfunc = context.get_function('destroy-eq')
qfunc(ctypes.byref(qhandle))
def AsyncWorker2(func_ref, param_list, context, cb_func=None, obj=None):
"""
See AsyncWorker1 for details. This does the same thing but
uses different API functions (test instead of poll) for test
coverage purposes.
"""
# TODO insufficient error handling in this function
# setup the asynchronous infrastructure the API requires
the_event = param_list[-1]
param_list[-1] = ctypes.byref(the_event)
qfunc = context.get_function('create-eq')
qhandle = ctypes.c_ulonglong(0)
rc = qfunc(ctypes.byref(qhandle))
efunc = context.get_function('init-event')
rc = efunc(param_list[-1], qhandle, None)
# call the api function
rc = func_ref(*param_list)
# -1 means wait forever
c_timeout = ctypes.c_ulonglong(-1)
c_event_ptr = ctypes.byref(the_event)
efunc = context.get_function('test-event')
c_flag = ctypes.c_bool(0)
rc = efunc(c_event_ptr, c_timeout, ctypes.byref(c_flag))
# signal caller API function has completed
if cb_func is not None:
cb_event = CallbackEvent(obj, anotherEvent)
cb_func(cb_event)
# cleanup
qfunc = context.get_function('destroy-eq')
qfunc(ctypes.byref(qhandle))
class Logfac:
DEBUG = 0
INFO = 1
WARNING = 2
ERROR = 3