2 # -*- coding: utf-8 -*-
7 import libelliptics_python
8 from libelliptics_python
import log_level
, command_flags
, io_flags
11 class NodeStatus(libelliptics_python
.dnet_node_status
):
13 return "<NodeStatus nflags:%x, status_flags:%x, log_mask:%x>" % (self
.nflags
, self
.status_flags
, self
.log_mask
)
16 class Id(libelliptics_python
.elliptics_id
):
19 It has 2 constructors:
21 Id(list_id, group type)
23 list_id - list of 64 bytes, id of the object itself
24 group - group ID of the object
30 class Range(libelliptics_python
.elliptics_range
):
32 Structure that describes range request
33 start, end - IDs of the start and the end of the range
34 offset, size - offset to read from and size of bytes to read, applied for each key
35 cflags - command flags like locking so on (default is 0, see cflags class for defenitions)
36 ioflags - command IO flags (default is 0, see ioflags class for definitions)
37 group - group ID of the object
43 class Logger(libelliptics_python
.elliptics_log_file
):
45 Logger, that needed in Node constructor
46 Constructor takes 2 arguments: log file name (default is "/dev/stderr")
47 and log level (default is log_level.error, see log_level class for definitions)
50 llevel
= log_level
.error
52 def __init__(self
, log_file_name
= "/dev/stderr", llevel
= log_level
.error
):
54 log_file_name - name of the log file, default value is "/dev/stderr"
55 log_level - logging level, see log_level class for definitions
57 self
.log_file_name
= log_file_name
59 super(Logger
, self
).__init
__(log_file_name
, llevel
)
61 def log(self
, message
, level
):
63 log some message into elliptics log file
64 message - text message
65 level - log level, default is log_level.error (see log_level class for definitions)
67 super(Logger
, self
).log(level
, message
)
70 return "<Logger log_file_name:\"%s\" log_level:%d>" % (self
.log_file_name
, self
.llevel
)
73 class Node(libelliptics_python
.elliptics_node_python
):
75 Main client class. Constructor takes 1 argument: Logger object
78 def __init__(self
, log
=None):
82 super(Node
, self
).__init
__(log
or Logger())
84 def add_remote(self
, addr
, port
, family
=2):
86 Add address of elliptics storage node and connect to it
87 Usually you do not want to exit if client failed to connect to remote node, so catch up exceptions
88 But if no remote nodes were successfully added (check get_routes()) then client should not continue
89 addr - storage address
91 family - IP protocol family: 2 for IPv4 (default value) and 10 for IPv6
93 super(Node
, self
).add_remote(addr
, port
, family
)
95 class Session(libelliptics_python
.elliptics_session
):
97 Session class. Constructor takes 1 argument: Node object
100 def __init__(self
, node
=None):
104 super(Session
, self
).__init
__(node
)
106 def add_groups(self
, groups
):
108 Set groups to work with
109 groups - list of groups
111 super(Session
, self
).add_groups(groups
)
115 return super(Session
, self
).get_groups()
117 def get_routes(self
):
122 list - list of node addresses
124 return super(Session
, self
).get_routes()
131 string - storage nodes statistics
133 return super(Session
, self
).stat_log()
135 def lookup_addr(self
, *args
, **kwargs
):
137 Lookup where key should be located by its ID or key and group_id pair
139 lookup_addr(key, group_id)
142 key - remote key name
144 id - object of Id class
147 string - node address
149 return super(Session
, self
).lookup_addr(*args
, **{})
151 def read_file(self
, key
, filename
, offset
= 0, size
= 0, column
= 0):
153 Read file from elliptics by name/ID
155 read_file(key, filename, offset, size, column)
156 read_file(id, filename, offset, size)
158 key - remote key name
159 column - column type (default is 0, 1 is reserved for metadata)
160 id - object of Id class
162 filename - name of local file where data will be saved
163 offset - read file from this offset (default 0)
164 size - number of bytes to read, 0 means whole file (default is 0)
166 if isinstance(key
, basestring
):
167 new_args
= [str(key
), filename
, offset
, size
, column
]
169 new_args
= [key
, filename
, offset
, size
]
171 super(Session
, self
).read_file(*new_args
)
173 def write_file(self
, key
, filename
, local_offset
= 0, offset
= 0, size
= 0, \
174 cflags
= command_flags
.default
, ioflags
= io_flags
.default
, column
= 0):
176 Write file into elliptics by name/ID
178 write_file(key, filename, local_offset, offset, size, cflags, ioflags, column)
179 write_file(id, filename, local_offset, offset, size, cflags, ioflags)
181 key - remote key name
182 column - column type (default is 0, 1 is reserved for metadata)
183 id - object of Id class
185 filename - name of local file
186 local_offset - read local file from this offset (default 0)
187 offset - write file from this offset (default 0)
188 size - number of bytes to write, 0 means whole file (default is 0)
189 cflags - command flags (default is 0, see command_flags class for definitions)
190 ioflags - command IO flags (default is 0, see io_flags class for definitions)
192 if isinstance(key
, basestring
):
193 new_args
= [str(key
), filename
, local_offset
, offset
, size
, cflags
, ioflags
, column
]
195 new_args
= [key
, filename
, local_offset
, offset
, size
, cflags
, ioflags
]
197 super(Session
, self
).read_file(*new_args
)
199 def _create_read_args(self
, key
, offset
= 0, size
= 0, cflags
= command_flags
.default
, ioflags
= io_flags
.default
, column
= 0):
200 if isinstance(key
, basestring
):
201 return [str(key
), offset
, size
, cflags
, ioflags
, column
]
203 return [key
, offset
, size
, cflags
, ioflags
]
205 def read_data(self
, key
, offset
= 0, size
= 0, cflags
= command_flags
.default
, ioflags
= io_flags
.default
, column
= 0):
207 Read data from elliptics by name/ID
209 read_data(key, offset, size, cflags, ioflags, column)
210 read_data(id, offset, size, cflags, ioflags)
212 key - remote key name
213 column - column type (default is 0, 1 is reserved for metadata)
214 id - object of Id class
216 offset - read file from this offset (default 0)
217 size - number of bytes to read, 0 means whole file (default is 0)
218 cflags - command flags (default is 0, see command_flags class for definitions)
219 ioflags - command IO flags (default is 0, see io_flags class for definitions)
222 string - key value content
224 return super(Session
, self
).read_data(*self
._create
_read
_args
(key
, offset
, size
, cflags
, ioflags
, column
))
228 def read_latest(self
, key
, offset
= 0, size
= 0, cflags
= command_flags
.default
, ioflags
= io_flags
.default
, column
= 0):
230 Read data from elliptics by name/ID with the latest update_date in metadata
232 read_latest(key, offset, size, cflags, ioflags, column)
233 read_latest(id, offset, size, cflags, ioflags)
235 key - remote key name
236 column - column type (default is 0, 1 is reserved for metadata)
237 id - object of Id class
239 offset - read file from this offset (default 0)
240 size - number of bytes to read, 0 means whole file (default is 0)
241 cflags - command flags flags (default is 0, see command_flags class for definitions)
242 ioflags - command IO flags (default is 0, see io_flags class for definitions)
245 string - key value content
247 return super(Session
, self
).read_latest(*self
._create
_read
_args
(key
, offset
, size
, cflags
, ioflags
, column
))
249 def create_write_args(self
, key
, data
, offset
, ioflags
, cflags
, column
):
250 if isinstance(key
, basestring
):
251 return [str(key
), data
, offset
, cflags
, ioflags
, column
]
253 return [key
, data
, offset
, cflags
, ioflags
]
255 def write_data(self
, key
, data
, offset
= 0, cflags
= command_flags
.default
, ioflags
= io_flags
.default
, column
= 0):
257 Write data into elliptics by name/ID
259 write_data(key, data, offset, cflags, ioflags, column)
260 write_data(id, data, offset, cflags, ioflags)
262 key - remote key name
263 column - column type (default is 0, 1 is reserved for metadata)
264 id - object of Id class
266 data - data to be written
267 offset - write data in remote from this offset (default 0)
268 cflags - command flags flags (default is 0, see command_flags class for definitions)
269 ioflags - command IO flags (default is 0, see io_flags class for definitions)
272 string - nodes and paths where data was stored
274 return super(Session
, self
).write_data(*self
.create_write_args(key
, data
, offset
, ioflags
, cflags
, column
))
276 def write_metadata(self
, key
, cflags
= command_flags
.default
, name
= None, groups
= None):
278 Write metadata into elliptics by name/ID
280 write_metadata(key, cflags)
281 write_metadata(id, name, groups, cflags)
283 key - remote key name
284 id - object of Id class
287 groups - groups where data was stored
288 cflags - command flags (default is 0, see command_flags class for definitions)
290 if isinstance(key
, basestring
):
291 new_args
= [str(key
), cflags
]
293 new_args
= [key
, name
, groups
, cflags
]
295 super(Session
, self
).write_metadata(*new_args
)
297 def write(self
, key
, data
):
301 self
.write_data(key
, data
)
302 self
.write_metadata(key
)
304 def remove(self
, key
, cflags
= command_flags
.default
, ioflags
= io_flags
.default
, column
= 0):
306 Remove key by name/ID
308 remove(key, cflags, ioflags, column)
309 remove(id, cflags, ioflags)
311 key - remote key name
312 column - column type (default is 0, 1 is reserved for metadata)
313 id - object of Id class
315 cflags - command flags flags (default is 0, see command_flags class for definitions)
316 ioflags - command IO flags (default is 0, see io_flags class for definitions)
318 if isinstance(key
, basestring
):
319 new_args
= [str(key
), cflags
, ioflags
, column
]
321 new_args
= [key
, cflags
, ioflags
]
323 super(Session
, self
).remove(*new_args
)
325 def execute(self
, *args
, **kwargs
):
327 Execite server-side script
329 exec(id, event, data, binary)
330 exec(key, event, data, binary)
331 exec(event, data, binary)
333 key - remote key name
334 id - object of Id class
336 event - server-side event name
337 data - data for given event
338 binary - binary data (its logical meaning is the same as for data, it was added for convenience)
340 If execute() is called with 3 arguments script will be started on all storage nodes.
341 If id or key is specified script will be started on the node which hosts given key/id.
344 string - result of the script execution
346 return super(Session
, self
).execute(*args
, **{})
348 def update_status(self
, key
, status
= None, update
= 0):
350 Update elliptics status and log mask
352 update_status(id, status, update)
353 update_status((addr, port, family), status, update)
355 key - remote key name
356 id - object of Id class
358 addr - storage address
360 family - IP protocol family: 2 for IPv4 (default value) and 10 for IPv6
361 status - new node status, object of SessionStatus class
362 update - update status or just return current (default is 0)
364 If update = 0 status will not be changed
367 SessionStatus - current node status
369 status
= status
or SessionStatus()
370 if hasattr(key
, '__iter__'):
371 new_args
= (key
[0], key
[1], key
[2], status
, update
)
373 new_args
= (key
, status
, update
)
375 ret
= super(Session
, self
).update_status(*new_args
)
376 ret
.__class
__ = SessionStatus
379 def bulk_read(self
, keys
, cflags
= command_flags
.default
, raw
=False):
381 Bulk read keys from elliptics
382 keys - list of keys by name
383 cflags - command flags (default is 0, see command_flags class for definitions)
386 dict: key - original key, value - data itself
387 if raw is True: list - list of strings, each string consists of 64 byte key (sha-512 of original key), 8 byte data length and data itself
389 if type(keys
) in set([tuple, list, set, dict]):
392 rv
= super(Session
, self
).bulk_read(keys
, cflags
)
400 keys
= dict([(hashlib
.sha512(key
).hexdigest(), key
) for key
in keys
])
404 key
= binascii
.hexlify(r
[:64])
405 data_len
= struct
.unpack('Q', r
[64:72])[0]
406 data
= struct
.unpack("%ss" % data_len
, r
[72:72 + data_len
])[0]
407 rv_dict
[keys
[key
]] = data
410 def read_data_range(self
, read_range
):
412 Read keys from elliptics by range of IDs
413 read_range - object of Range class
416 list - list of strings, each string consists of 64 byte key, 8 byte data length and data itself
418 return super(Session
, self
).read_data_range(read_range
)