Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cPersistence.h 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*****************************************************************************
  2. Copyright (c) 2001, 2002 Zope Foundation and Contributors.
  3. All Rights Reserved.
  4. This software is subject to the provisions of the Zope Public License,
  5. Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
  6. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  7. WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  8. WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  9. FOR A PARTICULAR PURPOSE
  10. ****************************************************************************/
  11. #ifndef CPERSISTENCE_H
  12. #define CPERSISTENCE_H
  13. #include "_compat.h"
  14. #include "bytesobject.h"
  15. #include "ring.h"
  16. #define CACHE_HEAD \
  17. PyObject_HEAD \
  18. CPersistentRing ring_home; \
  19. int non_ghost_count; \
  20. Py_ssize_t total_estimated_size;
  21. struct ccobject_head_struct;
  22. typedef struct ccobject_head_struct PerCache;
  23. /* How big is a persistent object?
  24. 12 PyGC_Head is two pointers and an int
  25. 8 PyObject_HEAD is an int and a pointer
  26. 12 jar, oid, cache pointers
  27. 8 ring struct
  28. 8 serialno
  29. 4 state + extra
  30. 4 size info
  31. (56) so far
  32. 4 dict ptr
  33. 4 weaklist ptr
  34. -------------------------
  35. 68 only need 62, but obmalloc rounds up to multiple of eight
  36. Even a ghost requires 64 bytes. It's possible to make a persistent
  37. instance with slots and no dict, which changes the storage needed.
  38. */
  39. #define cPersistent_HEAD \
  40. PyObject_HEAD \
  41. PyObject *jar; \
  42. PyObject *oid; \
  43. PerCache *cache; \
  44. CPersistentRing ring; \
  45. char serial[8]; \
  46. signed state:8; \
  47. unsigned estimated_size:24;
  48. /* We recently added estimated_size. We originally added it as a new
  49. unsigned long field after a signed char state field and a
  50. 3-character reserved field. This didn't work because there
  51. are packages in the wild that have their own copies of cPersistence.h
  52. that didn't see the update.
  53. To get around this, we used the reserved space by making
  54. estimated_size a 24-bit bit field in the space occupied by the old
  55. 3-character reserved field. To fit in 24 bits, we made the units
  56. of estimated_size 64-character blocks. This allows is to handle up
  57. to a GB. We should never see that, but to be paranoid, we also
  58. truncate sizes greater than 1GB. We also set the minimum size to
  59. 64 bytes.
  60. We use the _estimated_size_in_24_bits and _estimated_size_in_bytes
  61. macros both to avoid repetition and to make intent a little clearer.
  62. */
  63. #define _estimated_size_in_24_bits(I) ((I) > 1073741696 ? 16777215 : (I)/64+1)
  64. #define _estimated_size_in_bytes(I) ((I)*64)
  65. #define cPersistent_GHOST_STATE -1
  66. #define cPersistent_UPTODATE_STATE 0
  67. #define cPersistent_CHANGED_STATE 1
  68. #define cPersistent_STICKY_STATE 2
  69. typedef struct {
  70. cPersistent_HEAD
  71. } cPersistentObject;
  72. typedef void (*percachedelfunc)(PerCache *, PyObject *);
  73. typedef struct {
  74. PyTypeObject *pertype;
  75. getattrofunc getattro;
  76. setattrofunc setattro;
  77. int (*changed)(cPersistentObject*);
  78. void (*accessed)(cPersistentObject*);
  79. void (*ghostify)(cPersistentObject*);
  80. int (*setstate)(PyObject*);
  81. percachedelfunc percachedel;
  82. int (*readCurrent)(cPersistentObject*);
  83. } cPersistenceCAPIstruct;
  84. #define cPersistenceType cPersistenceCAPI->pertype
  85. #ifndef DONT_USE_CPERSISTENCECAPI
  86. static cPersistenceCAPIstruct *cPersistenceCAPI;
  87. #endif
  88. #define cPersistanceModuleName "cPersistence"
  89. #define PER_TypeCheck(O) PyObject_TypeCheck((O), cPersistenceCAPI->pertype)
  90. #define PER_USE_OR_RETURN(O,R) {if((O)->state==cPersistent_GHOST_STATE && cPersistenceCAPI->setstate((PyObject*)(O)) < 0) return (R); else if ((O)->state==cPersistent_UPTODATE_STATE) (O)->state=cPersistent_STICKY_STATE;}
  91. #define PER_CHANGED(O) (cPersistenceCAPI->changed((cPersistentObject*)(O)))
  92. #define PER_READCURRENT(O, E) \
  93. if (cPersistenceCAPI->readCurrent((cPersistentObject*)(O)) < 0) { E; }
  94. #define PER_GHOSTIFY(O) (cPersistenceCAPI->ghostify((cPersistentObject*)(O)))
  95. /* If the object is sticky, make it non-sticky, so that it can be ghostified.
  96. The value is not meaningful
  97. */
  98. #define PER_ALLOW_DEACTIVATION(O) ((O)->state==cPersistent_STICKY_STATE && ((O)->state=cPersistent_UPTODATE_STATE))
  99. #define PER_PREVENT_DEACTIVATION(O) ((O)->state==cPersistent_UPTODATE_STATE && ((O)->state=cPersistent_STICKY_STATE))
  100. /*
  101. Make a persistent object usable from C by:
  102. - Making sure it is not a ghost
  103. - Making it sticky.
  104. IMPORTANT: If you call this and don't call PER_ALLOW_DEACTIVATION,
  105. your object will not be ghostified.
  106. PER_USE returns a 1 on success and 0 failure, where failure means
  107. error.
  108. */
  109. #define PER_USE(O) \
  110. (((O)->state != cPersistent_GHOST_STATE \
  111. || (cPersistenceCAPI->setstate((PyObject*)(O)) >= 0)) \
  112. ? (((O)->state==cPersistent_UPTODATE_STATE) \
  113. ? ((O)->state=cPersistent_STICKY_STATE) : 1) : 0)
  114. #define PER_ACCESSED(O) (cPersistenceCAPI->accessed((cPersistentObject*)(O)))
  115. #endif