50 #define SVFS_SVFS_METHOD_SIZE_T_WRAPPER(method_name, docstring) \
52 cp_SparseVirtualFileSystem_svf_##method_name##_docstring, \
53 #method_name"(self, id: str) -> int\n\n" \
57 cp_SparseVirtualFileSystem_svf_##method_name(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs) { \
58 ASSERT_FUNCTION_ENTRY_SVFS(p_svfs); \
59 PyObject *ret = NULL; \
62 AcquireLockSVFS _lock(self); \
63 static const char *kwlist[] = { "id", NULL}; \
64 if (! PyArg_ParseTupleAndKeywords(args, kwargs, "s", (char **)kwlist, &c_id)) { \
67 cpp_id = std::string(c_id); \
69 if (self->p_svfs->has(cpp_id)) { \
70 const SVFS::SparseVirtualFile &svf = self->p_svfs->at(cpp_id); \
71 ret = PyLong_FromLong(svf.method_name()); \
73 PyErr_Format(PyExc_IndexError, "%s: No SVF ID \"%s\"", __FUNCTION__, c_id); \
76 } catch (const std::exception &err) { \
77 PyErr_Format(PyExc_RuntimeError, "%s: FATAL caught std::exception %s", __FUNCTION__, err.what()); \
80 assert(! PyErr_Occurred()); \
84 assert(PyErr_Occurred()); \
100 #ifdef PY_THREAD_SAFE
105 #ifdef PY_THREAD_SAFE
116 if (!PyThread_acquire_lock(
_pSVFS->
lock, NOWAIT_LOCK)) {
117 Py_BEGIN_ALLOW_THREADS
118 PyThread_acquire_lock(
_pSVFS->
lock, WAIT_LOCK);
145 #define ASSERT_FUNCTION_ENTRY_SVFS(member) do { \
147 assert(((cp_SparseVirtualFileSystem *)self)->member); \
148 assert(! PyErr_Occurred()); \
153 #pragma mark Construction and destruction
157 assert(!PyErr_Occurred());
162 #ifdef PY_THREAD_SAFE
168 assert(!PyErr_Occurred());
169 return (PyObject *)
self;
174 assert(!PyErr_Occurred());
175 static const char *kwlist[] = {
"overwrite_on_exit",
"compare_for_diff", NULL};
186 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"|pp", (
char **) kwlist, &overwrite_on_exit, &compare_for_diff)) {
187 assert(PyErr_Occurred());
197 #ifdef PY_THREAD_SAFE
198 self->lock = PyThread_allocate_lock();
199 if (self->lock == NULL) {
201 PyErr_SetString(PyExc_MemoryError,
"Unable to allocate thread lock.");
206 assert(!PyErr_Occurred());
212 #ifdef PY_THREAD_SAFE
214 PyThread_free_lock(self->lock);
219 Py_TYPE(
self)->tp_free((PyObject *)
self);
223 #pragma mark END: Construction and destruction
226 #pragma mark SVFS functions
229 cp_SparseVirtualFileSystem_keys_docstring,
230 "keys(self) -> typing.List[str]\n\n"
231 "Returns the IDs of all the Sparse Virtual Files in the Sparse Virtual File System."
238 Py_ssize_t index = 0;
239 PyObject * key = NULL;
241 PyObject * ret = PyList_New(self->p_svfs->size());
245 PyErr_Format(PyExc_RuntimeError,
"%s: Can create list of size %d", __FUNCTION__, self->p_svfs->size());
249 for (
const auto &cpp_key: self->p_svfs->keys()) {
250 key = PyUnicode_FromKindAndData(PyUnicode_1BYTE_KIND, cpp_key.c_str(), cpp_key.size());
252 PyErr_Format(PyExc_RuntimeError,
"%s: Can create key for %s", __FUNCTION__, cpp_key.c_str());
256 PyList_SET_ITEM(ret, index, key);
260 }
catch (
const std::exception &err) {
261 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
264 assert(!PyErr_Occurred());
268 assert(PyErr_Occurred());
270 for (Py_ssize_t i = 0; i < PyList_Size(ret); ++i) {
271 Py_XDECREF(PyList_GET_ITEM(ret, i));
281 cp_SparseVirtualFileSystem_insert_docstring,
282 "insert(self, id: str) -> None\n\n"
283 "Inserts a Sparse Virtual File of ID and Unix file modification time as a float."
290 PyObject * ret = NULL;
293 static const char *kwlist[] = {
"id",
"mod_time", NULL};
296 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"sd", (
char **) kwlist, &c_id, &mod_time)) {
300 self->p_svfs->insert(c_id, mod_time);
303 PyExc_RuntimeError,
"%s: Can not insert a new Sparse Virtual File ID = \"%s\". ERROR: %s",
304 __FUNCTION__, c_id, err.
message().c_str()
307 }
catch (
const std::exception &err) {
308 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
313 assert(!PyErr_Occurred());
317 assert(PyErr_Occurred());
325 cp_SparseVirtualFileSystem_remove_docstring,
326 "remove(self, id: str) -> None\n\n"
327 "Removes a Sparse Virtual File of ID freeing that file's memory. Will raise an ``IndexError`` if the ID is absent."
334 PyObject * ret = NULL;
336 static const char *kwlist[] = {
"id", NULL};
339 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"s", (
char **) kwlist, &c_id)) {
343 self->p_svfs->remove(c_id);
345 PyErr_Format(PyExc_IndexError,
"%s: Can not remove a Sparse Virtual File. ERROR: %s",
346 __FUNCTION__, err.
message().c_str()
349 }
catch (
const std::exception &err) {
350 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
355 assert(!PyErr_Occurred());
359 assert(PyErr_Occurred());
367 cp_SparseVirtualFileSystem_has_docstring,
368 "has(self, id: str) -> bool\n\n"
369 "Returns True if the Sparse Virtual File for the ID is in the Sparse Virtual File System."
376 PyObject * ret = NULL;
378 static const char *kwlist[] = {
"id", NULL};
380 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"s", (
char **) kwlist, &c_id)) {
384 if (self->p_svfs->has(c_id)) {
391 }
catch (
const std::exception &err) {
392 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
395 assert(!PyErr_Occurred());
399 assert(PyErr_Occurred());
407 cp_SparseVirtualFileSystem_total_size_of_docstring,
408 "total_size_of(self) -> int\n\n"
409 "Returns the estimate of total memory usage of the Sparse Virtual File System."
416 return PyLong_FromLong(self->p_svfs->size_of());
417 }
catch (
const std::exception &err) {
418 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
424 cp_SparseVirtualFileSystem_total_bytes_docstring,
425 "total_bytes(self) -> int\n\n"
426 "Returns the total number of file bytes held by the Sparse Virtual File System."
433 return PyLong_FromLong(self->p_svfs->num_bytes());
434 }
catch (
const std::exception &err) {
435 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
441 cp_SparseVirtualFileSystem_total_blocks_docstring,
442 "total_blocks(self) -> int\n\n"
443 "Returns the total number of blocks of data held by the Sparse Virtual File System."
450 return PyLong_FromLong(self->p_svfs->num_blocks());
451 }
catch (
const std::exception &err) {
452 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
458 cp_SparseVirtualFileSystem_svf_has_data_docstring,
459 "has_data(self, id: str, file_position: int, length: int) -> bool\n\n"
460 "Checks if the Sparse Virtual File of the ID has data at the given file_position and length."
461 " This takes a string as an id, a file position and a length."
462 " This returns True if the Sparse Virtual File of that id has the data, False otherwise."
463 " This will raise an ``IndexError`` if the SVF of that id does not exist."
470 PyObject * ret = NULL;
473 unsigned long long fpos = 0;
474 unsigned long long len = 0;
475 static const char *kwlist[] = {
"id",
"file_position",
"length", NULL};
478 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"sKK", (
char **) kwlist, &c_id, &fpos, &len)) {
481 cpp_id = std::string(c_id);
482 if (self->p_svfs->has(cpp_id)) {
485 if (svf.
has(fpos, len)) {
492 }
catch (
const std::exception &err) {
493 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
497 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID \"%s\"", __FUNCTION__, c_id);
500 assert(!PyErr_Occurred());
504 assert(PyErr_Occurred());
512 cp_SparseVirtualFileSystem_svf_write_docstring,
513 "write(self, id: str, file_position: int, data: bytes) -> None\n\n"
514 "Writes the data to the Sparse Virtual File of the given ID at file_position and length.\n\n"
515 "This takes a string as an id, a file position and data as a bytes object.\n"
516 "This will raise an ``IndexError`` if the SVF of that id does not exist.\n"
517 "This will raise an ``IOError`` if the given data is different than that seen before and only\n"
518 "new data up to this point will be written.\n"
519 "This will raise a ``RuntimeError`` if the data can not be written for any other reason.\n"
526 PyObject * ret = NULL;
529 unsigned long long fpos = 0;
530 PyObject * py_bytes_data = NULL;
531 static const char *kwlist[] = {
"id",
"file_position",
"data", NULL};
534 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"sKS", (
char **) kwlist, &c_id, &fpos, &py_bytes_data)) {
537 cpp_id = std::string(c_id);
539 if (self->p_svfs->has(cpp_id)) {
542 svf.
write(fpos, PyBytes_AS_STRING(py_bytes_data), PyBytes_Size(py_bytes_data));
544 PyErr_Format(PyExc_IOError,
545 "%s: Can not write to a SVF id = \"%s\" as the given data is different from what is there. ERROR: %s",
546 __FUNCTION__, c_id, err.
message().c_str());
549 PyErr_Format(PyExc_RuntimeError,
"%s: Can not write to a SVF id = \"%s\". ERROR: %s",
550 __FUNCTION__, c_id, err.
message().c_str());
554 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID \"%s\"", __FUNCTION__, c_id);
557 }
catch (
const std::exception &err) {
558 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
563 assert(!PyErr_Occurred());
567 assert(PyErr_Occurred());
575 cp_SparseVirtualFileSystem_svf_read_docstring,
576 "read(self, id: str, file_position: int, length: int) -> bytes\n\n"
577 "Read the data to the Sparse Virtual File at file_position and length returning a bytes object.\n"
578 "This takes a string as an id, a file position and a length.\n"
579 "\nThis will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist.\n"
580 "This will raise an ``IOError`` if any data is not present\n"
581 "This will raise a ``RuntimeError`` if the data can not be read for any other reason.\n"
588 PyObject * ret = NULL;
591 unsigned long long fpos = 0;
592 unsigned long long len = 0;
593 static const char *kwlist[] = {
"id",
"file_position",
"length", NULL};
596 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"sKK", (
char **) kwlist, &c_id, &fpos, &len)) {
599 cpp_id = std::string(c_id);
601 if (self->p_svfs->has(cpp_id)) {
604 ret = PyBytes_FromStringAndSize(NULL, len);
606 svf.
read(fpos, len, PyBytes_AS_STRING(ret));
608 PyErr_Format(PyExc_IOError,
"%s: Can not read from a SVF id= \"%s\". ERROR: %s",
609 __FUNCTION__, c_id, err.
message().c_str());
612 PyErr_Format(PyExc_RuntimeError,
"%s: Fatal error reading from a SVF id= \"%s\". ERROR: %s",
613 __FUNCTION__, c_id, err.
message().c_str());
617 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID \"%s\"", __FUNCTION__, c_id);
620 }
catch (
const std::exception &err) {
621 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
624 assert(!PyErr_Occurred());
628 assert(PyErr_Occurred());
636 cp_SparseVirtualFileSystem_svf_erase_docstring,
637 "erase(self, id: str, file_position: int) -> None\n\n"
638 "Erases the data block in the Sparse Virtual File at a file position.\n"
639 "This takes a string as an id and a file_position.\n"
640 "This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist.\n"
641 "This will raise an ``IOError`` if there is not a block at the position.\n"
642 "This will raise a ``RuntimeError`` if the data can not be read for any other reason.\n"
649 PyObject * ret = NULL;
652 unsigned long long fpos = 0;
653 static const char *kwlist[] = {
"id",
"file_position", NULL};
656 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"sK", (
char **) kwlist, &c_id, &fpos)) {
659 cpp_id = std::string(c_id);
661 if (self->p_svfs->has(cpp_id)) {
666 PyErr_Format(PyExc_IOError,
"%s: Can not erase block from a SVF id= \"%s\". ERROR: %s",
667 __FUNCTION__, c_id, err.
message().c_str());
670 PyErr_Format(PyExc_RuntimeError,
"%s: Fatal error erasing from a SVF id= \"%s\". ERROR: %s",
671 __FUNCTION__, c_id, err.
message().c_str());
675 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID \"%s\"", __FUNCTION__, c_id);
678 }
catch (
const std::exception &err) {
679 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
684 assert(!PyErr_Occurred());
688 assert(PyErr_Occurred());
696 cp_SparseVirtualFileSystem_svf_need_docstring,
697 "need(self, id: str, file_position: int, length: int, greedy_length: int = 0) -> typing.Tuple[typing.Tuple[int, int], ...]\n\n"
698 "Given a file_position and length this returns a ordered list ``[(file_position, length), ...]`` of seek/read"
699 " instructions of data that is required to be written to the Sparse Virtual File so that a subsequent read will succeed.\n"
700 "If greedy_length is > 0 then, if possible, blocks will be coalesced to reduce the size of the return value."
702 " if not svfs.has(identity, file_position, length):\n"
703 " for fpos, read_len in svfs.need(identity, file_position, length):\n"
704 " # Somehow get the data at that seek/read position...\n"
705 " svfs.write(identity, fpos, data)\n"
706 " return svfs.read(identity, file_position, length):\n"
713 PyObject * ret = NULL;
716 unsigned long long fpos = 0;
717 unsigned long long len = 0;
718 unsigned long long greedy_length = 0;
719 static const char *kwlist[] = {
"id",
"file_position",
"length",
"greedy_length", NULL};
722 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"sKK|K", (
char **) kwlist, &c_id, &fpos, &len, &greedy_length)) {
725 cpp_id = std::string(c_id);
727 if (self->p_svfs->has(cpp_id)) {
734 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID \"%s\"", __FUNCTION__, c_id);
737 }
catch (
const std::exception &err) {
738 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
741 assert(!PyErr_Occurred());
745 assert(PyErr_Occurred());
753 cp_SparseVirtualFileSystem_svf_need_many_docstring,
754 "need_many(self, id: str, seek_reads: typing.List[typing.Tuple[int, int]], greedy_length: int = 0) -> typing.Tuple[typing.Tuple[int, int], ...]\n\n"
755 "Given a list of (file_position, length) this returns a ordered list ``[(file_position, length), ...]`` of seek/read"
756 " instructions of data that is required to be written to the Sparse Virtual File so that a subsequent read will"
758 "If greedy_length is > 0 then, if possible, blocks will be coalesced to reduce the size of the return value."
760 "See also :py:meth:`svfsc.cSVFS.need`"
767 PyObject * ret = NULL;
771 PyObject * py_seek_reads = NULL;
772 unsigned long long greedy_len = 0;
773 static const char *kwlist[] = {
"id",
"seek_reads",
"greedy_length", NULL};
776 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"sO|K", (
char **) kwlist, &c_id, &py_seek_reads, &greedy_len)) {
779 cpp_id = std::string(c_id);
781 if (self->p_svfs->has(cpp_id)) {
788 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID \"%s\"", __FUNCTION__, c_id);
791 }
catch (
const std::exception &err) {
792 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
795 assert(!PyErr_Occurred());
799 assert(PyErr_Occurred());
830 cp_SparseVirtualFileSystem_svf_blocks_docstring,
831 "blocks(self, id: str) -> typing.Tuple[typing.Tuple[int, int], ...]\n\n"
832 "This returns a ordered tuple ((file_position, length), ...) of all the blocks held by the SVF identified"
834 "This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
841 PyObject * ret = NULL;
844 PyObject * insert_item = NULL;
845 static const char *kwlist[] = {
"id", NULL};
848 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"s", (
char **) kwlist, &c_id)) {
851 cpp_id = std::string(c_id);
853 if (self->p_svfs->has(cpp_id)) {
856 ret = PyTuple_New(seek_read.size());
858 PyErr_Format(PyExc_MemoryError,
"%s: Can not create tuple for return", __FUNCTION__);
861 for (
size_t i = 0; i < seek_read.size(); ++i) {
862 insert_item = Py_BuildValue(
"KK", seek_read[i].first, seek_read[i].second);
864 PyErr_Format(PyExc_MemoryError,
"%s: Can not create tuple", __FUNCTION__);
867 PyTuple_SET_ITEM(ret, i, insert_item);
871 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID %s", __FUNCTION__, c_id);
874 }
catch (
const std::exception &err) {
875 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
878 assert(!PyErr_Occurred());
882 assert(PyErr_Occurred());
884 for (Py_ssize_t i = 0; i < PyList_Size(ret); ++i) {
885 Py_XDECREF(PyList_GET_ITEM(ret, i));
896 "Returns the best guess of total memory usage used by the Sparse Virtual File identified by the given id."
897 " This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
902 "Returns the number of bytes of data held by the Sparse Virtual File identified by the given id."
903 " This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
908 "Returns the number of data blocks held by the Sparse Virtual File identified by the given id."
909 " This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
914 cp_SparseVirtualFileSystem_svf_block_touches_docstring,
915 "block_touches(self, id: str) -> typing.Dict[int, int]\n\n"
916 "This returns a dict ``{touch_int: file_position, ...}``"
917 " of the touch integer of each block mapped to the file position.\n"
918 "The caller can decide what older blocks can be used the erase(file_position)."
933 PyObject * ret = NULL;
935 static const char *kwlist[] = {
"id", NULL};
940 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"s", (
char **) kwlist, &c_id)) {
943 cpp_id = std::string(c_id);
945 if (self->p_svfs->has(cpp_id)) {
950 PyErr_Format(PyExc_MemoryError,
"%s: Can not create dict for return", __FUNCTION__);
953 for (
const auto &iter: svf_block_touches) {
954 PyObject * key = PyLong_FromLong(iter.first);
956 PyErr_Format(PyExc_MemoryError,
"%s: Can not create key", __FUNCTION__);
959 PyObject * val = PyLong_FromLong(iter.second);
961 PyErr_Format(PyExc_MemoryError,
"%s: Can not create value", __FUNCTION__);
964 PyDict_SetItem(ret, key, val);
969 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID \"%s\"", __FUNCTION__, c_id);
972 }
catch (
const std::exception &err) {
973 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
976 assert(!PyErr_Occurred());
980 assert(PyErr_Occurred());
988 cp_SparseVirtualFileSystem_svf_lru_punt_docstring,
989 "lru_punt(self, id: str, cache_size_upper_bound: int) -> int\n\n"
990 "Reduces the size of the cache to < the given size by removing older blocks, at least one block will be left.\n"
991 "There are limitations to this tactic, see the documentation in Technical Notes -> Cache Punting."
1006 PyObject * ret = NULL;
1007 size_t cache_size_upper_bound;
1009 static const char *kwlist[] = {
"id",
"cache_size_upper_bound", NULL};
1014 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"sK", (
char **) kwlist, &c_id, &cache_size_upper_bound)) {
1017 cpp_id = std::string(c_id);
1019 if (self->p_svfs->has(cpp_id)) {
1021 ret = Py_BuildValue(
"K", svf.
lru_punt(cache_size_upper_bound));
1023 PyErr_Format(PyExc_MemoryError,
"%s: Can not create long", __FUNCTION__);
1027 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID \"%s\"", __FUNCTION__, c_id);
1030 }
catch (
const std::exception &err) {
1031 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
1034 assert(!PyErr_Occurred());
1038 assert(PyErr_Occurred());
1046 cp_SparseVirtualFileSystem_svf_lru_punt_all_docstring,
1047 "lru_punt_all(self, cache_size_upper_bound: int) -> int\n\n"
1048 "Reduces the size of all IDs in the cache to < the given size by removing older blocks."
1049 " At least one block will be left for each ID.\n"
1050 "There are limitations to this tactic, see the documentation in Technical Notes -> Cache Punting."
1065 PyObject * ret = NULL;
1066 size_t cache_size_upper_bound;
1067 size_t total_removed = 0;
1068 static const char *kwlist[] = {
"cache_size_upper_bound", NULL};
1072 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"K", (
char **) kwlist, &cache_size_upper_bound)) {
1076 for (
const auto &iter: self->p_svfs->keys()) {
1078 total_removed += svf.
lru_punt(cache_size_upper_bound);
1080 }
catch (
const std::exception &err) {
1081 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
1084 ret = Py_BuildValue(
"K", total_removed);
1086 PyErr_Format(PyExc_MemoryError,
"%s: Can not create long", __FUNCTION__);
1089 assert(!PyErr_Occurred());
1093 assert(PyErr_Occurred());
1101 cp_SparseVirtualFileSystem_svf_file_mod_time_matches_docstring,
1102 "file_mod_time_matches(self, id: str) -> bool\n\n"
1103 "Returns True if the file modification time of the Sparse Virtual File identified by the given id the matches"
1104 "the given time as a float.\n"
1105 "This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
1113 PyObject * ret = NULL;
1115 double file_mod_time;
1117 static const char *kwlist[] = {
"id",
"file_mod_time", NULL};
1120 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"sd", (
char **) kwlist, &c_id, &file_mod_time)) {
1123 cpp_id = std::string(c_id);
1125 if (self->p_svfs->has(cpp_id)) {
1131 Py_INCREF(Py_False);
1135 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID \"%s\"", __FUNCTION__, c_id);
1138 }
catch (
const std::exception &err) {
1139 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
1142 assert(!PyErr_Occurred());
1146 assert(PyErr_Occurred());
1168 cp_SparseVirtualFileSystem_file_mod_time_docstring,
1169 "file_mod_time(self, id: str) -> float\n\n"
1170 "Returns the file modification time as a float in UNIX time of the Sparse Virtual File identified by the given id.\n"
1171 "This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
1179 PyObject * ret = NULL;
1182 static const char *kwlist[] = {
"id", NULL};
1185 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"s", (
char **) kwlist, &c_id)) {
1188 cpp_id = std::string(c_id);
1190 if (self->p_svfs->has(cpp_id)) {
1194 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID %s", __FUNCTION__, c_id);
1197 }
catch (
const std::exception &err) {
1198 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
1201 assert(!PyErr_Occurred());
1205 assert(PyErr_Occurred());
1214 "Returns the count of write operations on the Sparse Virtual File identified by the given id."
1215 " This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
1220 "Returns the count of read operations on the Sparse Virtual File identified by the given id."
1221 " This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
1226 "Returns the count of the number of bytes writen to the Sparse Virtual File identified by the given id."
1227 " This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
1232 "Returns the count of the number of bytes read from the Sparse Virtual File identified by the given id."
1233 " This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
1237 #define SVFS_SVFS_METHOD_DATETIME_WRAPPER(method_name) static PyObject * \
1238 cp_SparseVirtualFileSystem_svf_##method_name(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs) { \
1239 ASSERT_FUNCTION_ENTRY_SVFS(p_svfs); \
1240 PyObject *ret = NULL; \
1241 char *c_id = NULL; \
1242 std::string cpp_id; \
1243 static const char *kwlist[] = { "id", NULL }; \
1244 if (! PyArg_ParseTupleAndKeywords(args, kwargs, "s", (char **)kwlist, &c_id)) { \
1247 cpp_id = std::string(c_id); \
1248 if (self->p_svfs->has(cpp_id)) { \
1249 const SVFS::SparseVirtualFile &svf = self->p_svfs->at(cpp_id); \
1250 auto time = svf.method_name(); \
1251 const long seconds = std::chrono::time_point_cast<std::chrono::seconds>(time).time_since_epoch().count(); \
1252 int micro_seconds = std::chrono::time_point_cast<std::chrono::microseconds>(time).time_since_epoch().count() % 1000000; \
1253 const std::tm *p_struct_tm = std::gmtime(&seconds); \
1254 ret = datetime_from_struct_tm(p_struct_tm, micro_seconds); \
1256 PyErr_Format(PyExc_IndexError, "%s: No SVF ID \"%s\"", __FUNCTION__, c_id); \
1259 assert(! PyErr_Occurred()); \
1263 assert(PyErr_Occurred()); \
1273 cp_SparseVirtualFileSystem_svf_time_write_docstring,
1274 "time_write(self, id: str) -> typing.Optional[datetime.datetime]\n\n"
1275 "Returns the timestamp of the last write to the Sparse Virtual File identified by the given id as a datetime.datetime."
1276 "or None if no write has taken place.\n"
1277 "This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
1284 PyObject * ret = NULL;
1287 static const char *kwlist[] = {
"id", NULL};
1290 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"s", (
char **) kwlist, &c_id)) {
1293 cpp_id = std::string(c_id);
1295 if (self->p_svfs->has(cpp_id)) {
1299 const long seconds = std::chrono::time_point_cast<std::chrono::seconds>(
1300 time).time_since_epoch().count();
1302 std::chrono::time_point_cast<std::chrono::microseconds>(time).time_since_epoch().count() %
1304 const std::tm *p_struct_tm = std::gmtime(&seconds);
1314 PyErr_Format(PyExc_IndexError,
"%s: No SVF ID \"%s\"", __FUNCTION__, c_id);
1317 }
catch (
const std::exception &err) {
1318 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
1321 assert(!PyErr_Occurred());
1325 assert(PyErr_Occurred());
1334 cp_SparseVirtualFileSystem_svf_time_read_docstring,
1335 "time_read(self, id: str) -> typing.Optional[datetime.datetime]\n\n"
1336 "Returns the timestamp of the last read from the Sparse Virtual File identified by the given id as a datetime.datetime."
1337 "or None if no read has taken place.\n"
1338 "This will raise an ``IndexError`` if the Sparse Virtual File of that id does not exist."
1345 PyObject * ret = NULL;
1348 static const char *kwlist[] = {
"id", NULL};
1351 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"s", (
char **) kwlist, &c_id)) {
1354 cpp_id = std::string(c_id);
1356 if (self->p_svfs->has(cpp_id)) {
1360 const long seconds = std::chrono::time_point_cast<std::chrono::seconds>(
1361 time).time_since_epoch().count();
1363 std::chrono::time_point_cast<std::chrono::microseconds>(time).time_since_epoch().count() %
1365 const std::tm *p_struct_tm = std::gmtime(&seconds);
1375 PyErr_Format(PyExc_IndexError,
"%s: No Sparse Virtual File ID \"%s\"", __FUNCTION__, c_id);
1378 }
catch (
const std::exception &err) {
1379 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
1382 assert(!PyErr_Occurred());
1386 assert(PyErr_Occurred());
1394 cp_SparseVirtualFileSystem_config_docstring,
1395 "config(self) -> typing.Dict[str, bool]\n\n"
1396 "Returns the SVFS configuration as a dict."
1401 PyObject * ret = Py_BuildValue(
1406 "compare_for_diff", PyBool_FromLong(self->p_svfs->config().compare_for_diff ? 1 : 0),
1407 "overwrite_on_exit", PyBool_FromLong(self->p_svfs->config().overwrite_on_exit ? 1 : 0)
1414 #pragma mark END: SVFS functions
1422 }
catch (
const std::exception &err) {
1423 PyErr_Format(PyExc_RuntimeError,
"%s: FATAL caught std::exception %s", __FUNCTION__, err.what());
1431 {NULL, 0, 0, 0, NULL}
1437 cp_SparseVirtualFileSystem_keys_docstring
1442 cp_SparseVirtualFileSystem_insert_docstring
1447 cp_SparseVirtualFileSystem_remove_docstring
1452 cp_SparseVirtualFileSystem_has_docstring
1456 cp_SparseVirtualFileSystem_total_size_of_docstring
1460 cp_SparseVirtualFileSystem_total_bytes_docstring
1464 cp_SparseVirtualFileSystem_total_blocks_docstring
1469 cp_SparseVirtualFileSystem_svf_has_data_docstring
1474 cp_SparseVirtualFileSystem_svf_write_docstring
1479 cp_SparseVirtualFileSystem_svf_read_docstring
1484 cp_SparseVirtualFileSystem_svf_erase_docstring
1489 cp_SparseVirtualFileSystem_svf_need_docstring
1494 cp_SparseVirtualFileSystem_svf_need_many_docstring
1500 cp_SparseVirtualFileSystem_svf_blocks_docstring
1503 "size_of", (PyCFunction) cp_SparseVirtualFileSystem_svf_size_of, METH_VARARGS |
1505 cp_SparseVirtualFileSystem_svf_size_of_docstring
1508 "num_bytes", (PyCFunction) cp_SparseVirtualFileSystem_svf_num_bytes, METH_VARARGS |
1510 cp_SparseVirtualFileSystem_svf_num_bytes_docstring
1513 "num_blocks", (PyCFunction) cp_SparseVirtualFileSystem_svf_num_blocks, METH_VARARGS |
1515 cp_SparseVirtualFileSystem_svf_num_blocks_docstring
1521 cp_SparseVirtualFileSystem_svf_file_mod_time_matches_docstring
1527 cp_SparseVirtualFileSystem_file_mod_time_docstring
1530 "count_write", (PyCFunction) cp_SparseVirtualFileSystem_svf_count_write, METH_VARARGS |
1532 cp_SparseVirtualFileSystem_svf_count_write_docstring
1535 "count_read", (PyCFunction) cp_SparseVirtualFileSystem_svf_count_read, METH_VARARGS |
1537 cp_SparseVirtualFileSystem_svf_count_read_docstring
1540 "bytes_write", (PyCFunction) cp_SparseVirtualFileSystem_svf_bytes_write, METH_VARARGS |
1542 cp_SparseVirtualFileSystem_svf_bytes_write_docstring
1545 "bytes_read", (PyCFunction) cp_SparseVirtualFileSystem_svf_bytes_read, METH_VARARGS |
1547 cp_SparseVirtualFileSystem_svf_bytes_read_docstring
1552 cp_SparseVirtualFileSystem_svf_time_write_docstring
1557 cp_SparseVirtualFileSystem_svf_time_read_docstring
1561 cp_SparseVirtualFileSystem_config_docstring
1566 cp_SparseVirtualFileSystem_svf_block_touches_docstring
1571 cp_SparseVirtualFileSystem_svf_lru_punt_docstring
1576 cp_SparseVirtualFileSystem_svf_lru_punt_all_docstring
1578 {NULL, NULL, 0, NULL}
1591 "This class implements a Sparse Virtual File System where Sparse Virtual Files are mapped to a key (a string).\n"
1592 "This can be constructed with an optional boolean overwrite flag that ensures in-memory data is overwritten"
1593 " on destruction of any SVF."
1599 PyVarObject_HEAD_INIT(NULL, 0)
1600 .tp_name =
"svfsc.cSVFS",
1606 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1607 .tp_doc = svfs_cSVFS_doc,
1614 #pragma mark - END SVFS
static PyObject * cp_SparseVirtualFile_need_many_internal(PyObject *py_seek_reads, const SVFS::SparseVirtualFile *pSvf, unsigned long long greedy_len)
static PyObject * cp_SparseVirtualFile_need_internal(const SVFS::SparseVirtualFile *pSvf, unsigned long long fpos, unsigned long long len, unsigned long long greedy_len)
static PyObject * cp_SparseVirtualFileSystem_svf_block_touches(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static Py_ssize_t cp_SparseVirtualFileSystem_mapping_length(PyObject *self)
static PyObject * cp_SparseVirtualFileSystem_config(cp_SparseVirtualFileSystem *self)
static PyObject * cp_SparseVirtualFileSystem_total_blocks(cp_SparseVirtualFileSystem *self)
static PyObject * cp_SparseVirtualFileSystem_svf_time_write(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_remove(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
PyMappingMethods svfs_mapping_methods
static PyObject * cp_SparseVirtualFileSystem_insert(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_svf_lru_punt_all(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_svf_blocks(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_svf_need(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_file_mod_time(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_svf_has_data(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_svf_write(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static void cp_SparseVirtualFileSystem_dealloc(cp_SparseVirtualFileSystem *self)
static PyObject * cp_SparseVirtualFileSystem_keys(cp_SparseVirtualFileSystem *self)
static int cp_SparseVirtualFileSystem_init(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyTypeObject svfsc_cSVFS
static PyObject * cp_SparseVirtualFileSystem_svf_time_read(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_has(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_svf_erase(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
#define SVFS_SVFS_METHOD_SIZE_T_WRAPPER(method_name, docstring)
static PyMethodDef cp_SparseVirtualFileSystem_methods[]
static PyObject * cp_SparseVirtualFileSystem_svf_read(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_total_bytes(cp_SparseVirtualFileSystem *self)
static PyObject * cp_SparseVirtualFileSystem_svf_file_mod_time_matches(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_svf_lru_punt(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
#define ASSERT_FUNCTION_ENTRY_SVFS(member)
PyDoc_STRVAR(cp_SparseVirtualFileSystem_keys_docstring, "keys(self) -> typing.List[str]\n\n" "Returns the IDs of all the Sparse Virtual Files in the Sparse Virtual File System.")
static PyObject * cp_SparseVirtualFileSystem_svf_need_many(cp_SparseVirtualFileSystem *self, PyObject *args, PyObject *kwargs)
static PyObject * cp_SparseVirtualFileSystem_new(PyTypeObject *type, PyObject *Py_UNUSED(args), PyObject *Py_UNUSED(kwds))
static PyMemberDef cp_SparseVirtualFileSystem_members[]
static PyObject * cp_SparseVirtualFileSystem_total_size_of(cp_SparseVirtualFileSystem *self)
A RAII wrapper around the PyThread_type_lock for the CPython SVFS.
AcquireLockSVFS(cp_SparseVirtualFileSystem *pSVFS)
cp_SparseVirtualFileSystem * _pSVFS
Might be thrown during a write operation where the data differs.
Might be thrown during a erase operation where the file position is not at the exact beginning of a b...
Exception specialisation for the SparseVirtualFile.
const std::string & message() const
Might be thrown during a write operation where the data differs.
const std::string & message() const
Exception specialisation on insert error.
Exception specialisation on remove error.
Implementation of a Sparse Virtual File.
size_t lru_punt(size_t cache_size_upper_bound)
t_block_touches block_touches() const noexcept
Returns a std::map of latest touch value key and file position value.
double file_mod_time() const noexcept
The file modification time as a double representing UNIX seconds.
std::chrono::time_point< std::chrono::system_clock > time_write() const noexcept
void write(t_fpos fpos, const char *data, size_t len)
Write the data a the given file position.
std::chrono::time_point< std::chrono::system_clock > time_read() const noexcept
size_t erase(t_fpos fpos)
Remove a particular block.
size_t count_read() const noexcept
Count of read() operations.
bool has(t_fpos fpos, size_t len) const noexcept
Do I have the data at the given file position and length?
bool file_mod_time_matches(const double &file_mod_time) const noexcept
size_t count_write() const noexcept
Count of write() operations.
void read(t_fpos fpos, size_t len, char *p)
Read data and write to the buffer provided by the caller. This is non-const as it updates the non-con...
t_seek_reads blocks() const noexcept
The existing blocks as a list of (file_position, size) pairs.
A SparseVirtualFileSystem is a key/value store where the key is a file ID as a string and the value i...
std::vector< t_seek_read > t_seek_reads
std::map< t_block_touch, t_fpos > t_block_touches
Configuration for the Sparse Virtual File.
Python wrapper around a C++ SparseVirtualFile.
PyObject_HEAD SVFS::SparseVirtualFileSystem * p_svfs
PyObject * datetime_from_struct_tm(const std::tm *bdt, int usecond)