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 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
|
# -*- coding: utf-8 -*-
########################################################################
#
# License: BSD
# Created: November 25, 2009
# Author: Francesc Alted - faltet@pytables.com
#
# $Id$
#
########################################################################
"""Cython functions and classes for supporting links in HDF5."""
from tables.exceptions import HDF5ExtError
from hdf5extension cimport Node
from utilsextension cimport cstr_to_pystr
from libc.stdlib cimport malloc, free
from libc.string cimport strlen
from cpython cimport PY_MAJOR_VERSION
from cpython.unicode cimport PyUnicode_DecodeUTF8
from definitions cimport (H5P_DEFAULT,
const_char, hid_t, herr_t, hbool_t, int64_t, H5T_cset_t, haddr_t)
from tables._past import previous_api
#----------------------------------------------------------------------
# External declarations
cdef extern from "H5Lpublic.h" nogil:
ctypedef enum H5L_type_t:
H5L_TYPE_ERROR = (-1), # Invalid link type id
H5L_TYPE_HARD = 0, # Hard link id
H5L_TYPE_SOFT = 1, # Soft link id
H5L_TYPE_EXTERNAL = 64, # External link id
H5L_TYPE_MAX = 255 # Maximum link type id
# Information struct for link (for H5Lget_info)
cdef union _add_u:
haddr_t address # Address hard link points to
size_t val_size # Size of a soft link or UD link value
ctypedef struct H5L_info_t:
H5L_type_t type # Type of link
hbool_t corder_valid # Indicate if creation order is valid
int64_t corder # Creation order
H5T_cset_t cset # Character set of link name
_add_u u # Size of a soft link or UD link value
# Operations with links
herr_t H5Lcreate_hard(
hid_t obj_loc_id, char *obj_name, hid_t link_loc_id, char *link_name,
hid_t lcpl_id, hid_t lapl_id)
herr_t H5Lcreate_soft(
char *target_path, hid_t link_loc_id, char *link_name,
hid_t lcpl_id, hid_t lapl_id)
herr_t H5Lcreate_external(
char *file_name, char *object_name, hid_t link_loc_id, char *link_name,
hid_t lcpl_id, hid_t lapl_id)
herr_t H5Lget_info(
hid_t link_loc_id, char *link_name, H5L_info_t *link_buff,
hid_t lapl_id)
herr_t H5Lget_val(
hid_t link_loc_id, char *link_name, void *linkval_buff, size_t size,
hid_t lapl_id)
herr_t H5Lunpack_elink_val(
char *ext_linkval, size_t link_size, unsigned *flags,
const_char **filename, const_char **obj_path)
herr_t H5Lcopy(
hid_t src_loc_id, char *src_name, hid_t dest_loc_id, char *dest_name,
hid_t lcpl_id, hid_t lapl_id)
#----------------------------------------------------------------------
# Helper functions
def _get_link_class(parent_id, name):
"""Guess the link class."""
cdef herr_t ret
cdef H5L_info_t link_buff
cdef H5L_type_t link_type
ret = H5Lget_info(parent_id, name, &link_buff, H5P_DEFAULT)
if ret < 0:
raise HDF5ExtError("failed to get info about link")
link_type = link_buff.type
if link_type == H5L_TYPE_SOFT:
return "SoftLink"
elif link_type == H5L_TYPE_EXTERNAL:
return "ExternalLink"
else:
return "UnImplemented"
_getLinkClass = previous_api(_get_link_class)
def _g_create_hard_link(parentnode, str name, targetnode):
"""Create a hard link in the file."""
cdef herr_t ret
cdef bytes encoded_name = name.encode('utf-8')
cdef bytes encoded_v_name = targetnode._v_name.encode('utf-8')
ret = H5Lcreate_hard(targetnode._v_parent._v_objectid, encoded_v_name,
parentnode._v_objectid, <char*>encoded_name,
H5P_DEFAULT, H5P_DEFAULT)
if ret < 0:
raise HDF5ExtError("failed to create HDF5 hard link")
_g_createHardLink = previous_api(_g_create_hard_link)
#----------------------------------------------------------------------
# Public classes
cdef class Link(Node):
"""Extension class from which all link extensions inherits."""
def _g_copy(self, newparent, newname, recursive, _log=True, **kwargs):
"""Private part for the _f_copy() method."""
cdef herr_t ret
cdef object stats
cdef bytes encoded_name, encoded_newname
encoded_name = self.name.encode('utf-8')
encoded_newname = newname.encode('utf-8')
# @TODO: set property list --> utf-8
ret = H5Lcopy(self.parent_id, encoded_name, newparent._v_objectid,
encoded_newname, H5P_DEFAULT, H5P_DEFAULT)
if ret < 0:
raise HDF5ExtError("failed to copy HDF5 link")
# Update statistics if needed.
stats = kwargs.get('stats', None)
if stats is not None:
stats['links'] += 1
return newparent._v_file.get_node(newparent, newname)
cdef class SoftLink(Link):
"""Extension class representing a soft link."""
def _g_create(self):
"""Create the link in file."""
cdef herr_t ret
cdef bytes encoded_name = self.name.encode('utf-8')
cdef bytes encoded_target = self.target.encode('utf-8')
ret = H5Lcreate_soft(encoded_target, self.parent_id, encoded_name,
H5P_DEFAULT, H5P_DEFAULT)
if ret < 0:
raise HDF5ExtError("failed to create HDF5 soft link")
return 0 # Object ID is zero'ed, as HDF5 does not assign one for links
def _g_open(self):
"""Open the link in file."""
cdef herr_t ret
cdef H5L_info_t link_buff
cdef size_t val_size
cdef char *clinkval
cdef bytes encoded_name
encoded_name = self.name.encode('utf-8')
ret = H5Lget_info(self.parent_id, encoded_name, &link_buff, H5P_DEFAULT)
if ret < 0:
raise HDF5ExtError("failed to get info about soft link")
val_size = link_buff.u.val_size
clinkval = <char *>malloc(val_size)
ret = H5Lget_val(self.parent_id, encoded_name, clinkval, val_size,
H5P_DEFAULT)
if ret < 0:
raise HDF5ExtError("failed to get target value")
if PY_MAJOR_VERSION > 2:
self.target = PyUnicode_DecodeUTF8(clinkval, strlen(clinkval), NULL)
else:
self.target = clinkval
# Release resources
free(clinkval)
return 0 # Object ID is zero'ed, as HDF5 does not assign one for links
cdef class ExternalLink(Link):
"""Extension class representing an external link."""
def _g_create(self):
"""Create the link in file."""
cdef herr_t ret
cdef bytes encoded_name, encoded_filename, encoded_target
encoded_name = self.name.encode('utf-8')
filename, target = self._get_filename_node()
encoded_filename = filename.encode('utf-8')
encoded_target = target.encode('utf-8')
ret = H5Lcreate_external(<char*>encoded_filename, <char*>encoded_target,
self.parent_id, <char*>encoded_name,
H5P_DEFAULT, H5P_DEFAULT)
if ret < 0:
raise HDF5ExtError("failed to create HDF5 external link")
return 0 # Object ID is zero'ed, as HDF5 does not assign one for links
def _g_open(self):
"""Open the link in file."""
cdef herr_t ret
cdef H5L_info_t link_buff
cdef size_t val_size
cdef char *clinkval
cdef char *cfilename
cdef char *c_obj_path
cdef unsigned flags
cdef bytes encoded_name
cdef str filename, obj_path
encoded_name = self.name.encode('utf-8')
ret = H5Lget_info(self.parent_id, encoded_name, &link_buff, H5P_DEFAULT)
if ret < 0:
raise HDF5ExtError("failed to get info about external link")
val_size = link_buff.u.val_size
clinkval = <char *>malloc(val_size)
ret = H5Lget_val(self.parent_id, encoded_name, clinkval, val_size,
H5P_DEFAULT)
if ret < 0:
raise HDF5ExtError("failed to get target value")
ret = H5Lunpack_elink_val(clinkval, val_size, &flags,
<const_char **>&cfilename,
<const_char **>&c_obj_path)
if ret < 0:
raise HDF5ExtError("failed to unpack external link value")
filename = cstr_to_pystr(cfilename)
obj_path = cstr_to_pystr(c_obj_path)
self.target = filename+':'+obj_path
# Release resources
free(clinkval)
return 0 # Object ID is zero'ed, as HDF5 does not assign one for links
## Local Variables:
## mode: python
## py-indent-offset: 2
## tab-width: 2
## fill-column: 78
## End:
|