1# -----------------------------------------------------------------------------
2
3cdef dict datarep_registry = {}
4
5@cython.final
6@cython.internal
7cdef class _p_datarep:
8
9    cdef object read_fn
10    cdef object write_fn
11    cdef object extent_fn
12
13    def __cinit__(self, read_fn, write_fn, extent_fn):
14        self.read_fn   = read_fn
15        self.write_fn  = write_fn
16        self.extent_fn = extent_fn
17
18    cdef int read(self,
19                  void *userbuf,
20                  MPI_Datatype datatype,
21                  int count,
22                  void *filebuf,
23                  MPI_Offset position,
24                  ) except -1:
25        cdef MPI_Aint lb=0, extent=0
26        cdef int ierr = MPI_Type_get_extent(datatype, &lb, &extent)
27        if ierr != MPI_SUCCESS: return ierr
28        cdef MPI_Aint ulen = <MPI_Aint>(position+count) * extent
29        cdef MPI_Aint flen = <MPI_Aint>PY_SSIZE_T_MAX # XXX
30        cdef object ubuf = tomemory(userbuf, ulen)
31        cdef object fbuf = tomemory(filebuf, flen)
32        cdef Datatype dtype = Datatype.__new__(Datatype)
33        dtype.ob_mpi = datatype
34        try: self.read_fn(ubuf, dtype, count, fbuf, position)
35        finally: dtype.ob_mpi = MPI_DATATYPE_NULL
36        return MPI_SUCCESS
37
38    cdef int write(self,
39                  void *userbuf,
40                  MPI_Datatype datatype,
41                  int count,
42                  void *filebuf,
43                  MPI_Offset position,
44                  ) except -1:
45        cdef MPI_Aint lb=0, extent=0
46        cdef int ierr = MPI_Type_get_extent(datatype, &lb, &extent)
47        if ierr != MPI_SUCCESS: return ierr
48        cdef MPI_Aint ulen = <MPI_Aint>(position+count) * extent
49        cdef MPI_Aint flen = <MPI_Aint>PY_SSIZE_T_MAX # XXX
50        cdef object ubuf = tomemory(userbuf, ulen)
51        cdef object fbuf = tomemory(filebuf, flen)
52        cdef Datatype dtype = Datatype.__new__(Datatype)
53        dtype.ob_mpi = datatype
54        try: self.write_fn(ubuf, dtype, count, fbuf, position)
55        finally: dtype.ob_mpi = MPI_DATATYPE_NULL
56        return MPI_SUCCESS
57
58    cdef int extent(self,
59                    MPI_Datatype datatype,
60                    MPI_Aint *file_extent,
61                    ) except -1:
62        cdef Datatype dtype = Datatype.__new__(Datatype)
63        dtype.ob_mpi = datatype
64        try: file_extent[0] = self.extent_fn(dtype)
65        finally: dtype.ob_mpi = MPI_DATATYPE_NULL
66        return MPI_SUCCESS
67
68# ---
69
70cdef int datarep_read(
71    void *userbuf,
72    MPI_Datatype datatype,
73    int count,
74    void *filebuf,
75    MPI_Offset position,
76    void *extra_state,
77    ) except MPI_ERR_UNKNOWN with gil:
78    cdef _p_datarep state = <_p_datarep>extra_state
79    cdef int ierr = MPI_SUCCESS
80    cdef object exc
81    try:
82        state.read(userbuf, datatype, count, filebuf, position)
83    except MPIException as exc:
84        print_traceback()
85        ierr = exc.Get_error_code()
86    except:
87        print_traceback()
88        ierr = MPI_ERR_OTHER
89    return ierr
90
91cdef int datarep_write(
92    void *userbuf,
93    MPI_Datatype datatype,
94    int count,
95    void *filebuf,
96    MPI_Offset position,
97    void *extra_state,
98    ) except MPI_ERR_UNKNOWN with gil:
99    cdef _p_datarep state = <_p_datarep>extra_state
100    cdef int ierr = MPI_SUCCESS
101    cdef object exc
102    try:
103        state.write(userbuf, datatype, count, filebuf, position)
104    except MPIException as exc:
105        print_traceback()
106        ierr = exc.Get_error_code()
107    except:
108        print_traceback()
109        ierr = MPI_ERR_OTHER
110    return ierr
111
112cdef int datarep_extent(
113    MPI_Datatype datatype,
114    MPI_Aint *file_extent,
115    void *extra_state,
116    ) except MPI_ERR_UNKNOWN with gil:
117    cdef _p_datarep state = <_p_datarep>extra_state
118    cdef int ierr = MPI_SUCCESS
119    cdef object exc
120    try:
121        state.extent(datatype, file_extent)
122    except MPIException as exc:
123        print_traceback()
124        ierr = exc.Get_error_code()
125    except:
126        print_traceback()
127        ierr = MPI_ERR_OTHER
128    return ierr
129
130# ---
131
132@cython.callspec("MPIAPI")
133cdef int datarep_read_fn(
134    void *userbuf,
135    MPI_Datatype datatype,
136    int count,
137    void *filebuf,
138    MPI_Offset position,
139    void *extra_state
140    ) nogil:
141    if extra_state == NULL:
142        return MPI_ERR_INTERN
143    if not Py_IsInitialized():
144        return MPI_ERR_INTERN
145    return datarep_read(userbuf, datatype, count,
146                        filebuf, position, extra_state)
147
148@cython.callspec("MPIAPI")
149cdef int datarep_write_fn(
150    void *userbuf,
151    MPI_Datatype datatype,
152    int count,
153    void *filebuf,
154    MPI_Offset position,
155    void *extra_state
156    ) nogil:
157    if extra_state == NULL:
158        return MPI_ERR_INTERN
159    if not Py_IsInitialized():
160        return MPI_ERR_INTERN
161    return datarep_write(userbuf, datatype, count,
162                         filebuf, position, extra_state)
163
164@cython.callspec("MPIAPI")
165cdef int datarep_extent_fn(
166    MPI_Datatype datatype,
167    MPI_Aint *file_extent,
168    void *extra_state
169    ) nogil:
170    if extra_state == NULL:
171        return MPI_ERR_INTERN
172    if not Py_IsInitialized():
173        return MPI_ERR_INTERN
174    return datarep_extent(datatype, file_extent, extra_state)
175
176# -----------------------------------------------------------------------------
177