关键词搜索

源码搜索 ×
×

漫话Redis源码之三十三

发布2021-12-12浏览574次

详情内容

第一个函数是分配新的rax,  返回的是指针。这个函数对异常的考虑也还很全,如果获取不到内存,就返回NULL

  1. /* Allocate a new rax and return its pointer. On out of memory the function
  2. * returns NULL. */
  3. rax *raxNew(void) {
  4. rax *rax = rax_malloc(sizeof(*rax));
  5. if (rax == NULL) return NULL;
  6. rax->numele = 0;
  7. rax->numnodes = 1;
  8. rax->head = raxNewNode(0,0);
  9. if (rax->head == NULL) {
  10. rax_free(rax);
  11. return NULL;
  12. } else {
  13. return rax;
  14. }
  15. }
  16. /* realloc the node to make room for auxiliary data in order
  17. * to store an item in that node. On out of memory NULL is returned. */
  18. raxNode *raxReallocForData(raxNode *n, void *data) {
  19. if (data == NULL) return n; /* No reallocation needed, setting isnull=1 */
  20. size_t curlen = raxNodeCurrentLength(n);
  21. return rax_realloc(n,curlen+sizeof(void*));
  22. }
  23. /* Set the node auxiliary data to the specified pointer. */
  24. void raxSetData(raxNode *n, void *data) {
  25. n->iskey = 1;
  26. if (data != NULL) {
  27. n->isnull = 0;
  28. void **ndata = (void**)
  29. ((char*)n+raxNodeCurrentLength(n)-sizeof(void*));
  30. memcpy(ndata,&data,sizeof(data));
  31. } else {
  32. n->isnull = 1;
  33. }
  34. }
  35. /* Get the node auxiliary data. */
  36. void *raxGetData(raxNode *n) {
  37. if (n->isnull) return NULL;
  38. void **ndata =(void**)((char*)n+raxNodeCurrentLength(n)-sizeof(void*));
  39. void *data;
  40. memcpy(&data,ndata,sizeof(data));
  41. return data;
  42. }
  43. /* Add a new child to the node 'n' representing the character 'c' and return
  44. * its new pointer, as well as the child pointer by reference. Additionally
  45. * '***parentlink' is populated with the raxNode pointer-to-pointer of where
  46. * the new child was stored, which is useful for the caller to replace the
  47. * child pointer if it gets reallocated.
  48. *
  49. * On success the new parent node pointer is returned (it may change because
  50. * of the realloc, so the caller should discard 'n' and use the new value).
  51. * On out of memory NULL is returned, and the old node is still valid. */
  52. raxNode *raxAddChild(raxNode *n, unsigned char c, raxNode **childptr, raxNode ***parentlink) {
  53. assert(n->iscompr == 0);
  54. size_t curlen = raxNodeCurrentLength(n);
  55. n->size++;
  56. size_t newlen = raxNodeCurrentLength(n);
  57. n->size--; /* For now restore the orignal size. We'll update it only on
  58. success at the end. */
  59. /* Alloc the new child we will link to 'n'. */
  60. raxNode *child = raxNewNode(0,0);
  61. if (child == NULL) return NULL;
  62. /* Make space in the original node. */
  63. raxNode *newn = rax_realloc(n,newlen);
  64. if (newn == NULL) {
  65. rax_free(child);
  66. return NULL;
  67. }
  68. n = newn;
  69. /* After the reallocation, we have up to 8/16 (depending on the system
  70. * pointer size, and the required node padding) bytes at the end, that is,
  71. * the additional char in the 'data' section, plus one pointer to the new
  72. * child, plus the padding needed in order to store addresses into aligned
  73. * locations.
  74. *
  75. * So if we start with the following node, having "abde" edges.
  76. *
  77. * Note:
  78. * - We assume 4 bytes pointer for simplicity.
  79. * - Each space below corresponds to one byte
  80. *
  81. * [HDR*][abde][Aptr][Bptr][Dptr][Eptr]|AUXP|
  82. *
  83. * After the reallocation we need: 1 byte for the new edge character
  84. * plus 4 bytes for a new child pointer (assuming 32 bit machine).
  85. * However after adding 1 byte to the edge char, the header + the edge
  86. * characters are no longer aligned, so we also need 3 bytes of padding.
  87. * In total the reallocation will add 1+4+3 bytes = 8 bytes:
  88. *
  89. * (Blank bytes are represented by ".")
  90. *
  91. * [HDR*][abde][Aptr][Bptr][Dptr][Eptr]|AUXP|[....][....]
  92. *
  93. * Let's find where to insert the new child in order to make sure
  94. * it is inserted in-place lexicographically. Assuming we are adding
  95. * a child "c" in our case pos will be = 2 after the end of the following
  96. * loop. */
  97. int pos;
  98. for (pos = 0; pos < n->size; pos++) {
  99. if (n->data[pos] > c) break;
  100. }
  101. /* Now, if present, move auxiliary data pointer at the end
  102. * so that we can mess with the other data without overwriting it.
  103. * We will obtain something like that:
  104. *
  105. * [HDR*][abde][Aptr][Bptr][Dptr][Eptr][....][....]|AUXP|
  106. */
  107. unsigned char *src, *dst;
  108. if (n->iskey && !n->isnull) {
  109. src = ((unsigned char*)n+curlen-sizeof(void*));
  110. dst = ((unsigned char*)n+newlen-sizeof(void*));
  111. memmove(dst,src,sizeof(void*));
  112. }
  113. /* Compute the "shift", that is, how many bytes we need to move the
  114. * pointers section forward because of the addition of the new child
  115. * byte in the string section. Note that if we had no padding, that
  116. * would be always "1", since we are adding a single byte in the string
  117. * section of the node (where now there is "abde" basically).
  118. *
  119. * However we have padding, so it could be zero, or up to 8.
  120. *
  121. * Another way to think at the shift is, how many bytes we need to
  122. * move child pointers forward *other than* the obvious sizeof(void*)
  123. * needed for the additional pointer itself. */
  124. size_t shift = newlen - curlen - sizeof(void*);
  125. /* We said we are adding a node with edge 'c'. The insertion
  126. * point is between 'b' and 'd', so the 'pos' variable value is
  127. * the index of the first child pointer that we need to move forward
  128. * to make space for our new pointer.
  129. *
  130. * To start, move all the child pointers after the insertion point
  131. * of shift+sizeof(pointer) bytes on the right, to obtain:
  132. *
  133. * [HDR*][abde][Aptr][Bptr][....][....][Dptr][Eptr]|AUXP|
  134. */
  135. src = n->data+n->size+
  136. raxPadding(n->size)+
  137. sizeof(raxNode*)*pos;
  138. memmove(src+shift+sizeof(raxNode*),src,sizeof(raxNode*)*(n->size-pos));
  139. /* Move the pointers to the left of the insertion position as well. Often
  140. * we don't need to do anything if there was already some padding to use. In
  141. * that case the final destination of the pointers will be the same, however
  142. * in our example there was no pre-existing padding, so we added one byte
  143. * plus thre bytes of padding. After the next memmove() things will look
  144. * like thata:
  145. *
  146. * [HDR*][abde][....][Aptr][Bptr][....][Dptr][Eptr]|AUXP|
  147. */
  148. if (shift) {
  149. src = (unsigned char*) raxNodeFirstChildPtr(n);
  150. memmove(src+shift,src,sizeof(raxNode*)*pos);
  151. }
  152. /* Now make the space for the additional char in the data section,
  153. * but also move the pointers before the insertion point to the right
  154. * by shift bytes, in order to obtain the following:
  155. *
  156. * [HDR*][ab.d][e...][Aptr][Bptr][....][Dptr][Eptr]|AUXP|
  157. */
  158. src = n->data+pos;
  159. memmove(src+1,src,n->size-pos);
  160. /* We can now set the character and its child node pointer to get:
  161. *
  162. * [HDR*][abcd][e...][Aptr][Bptr][....][Dptr][Eptr]|AUXP|
  163. * [HDR*][abcd][e...][Aptr][Bptr][Cptr][Dptr][Eptr]|AUXP|
  164. */
  165. n->data[pos] = c;
  166. n->size++;
  167. src = (unsigned char*) raxNodeFirstChildPtr(n);
  168. raxNode **childfield = (raxNode**)(src+sizeof(raxNode*)*pos);
  169. memcpy(childfield,&child,sizeof(child));
  170. *childptr = child;
  171. *parentlink = childfield;
  172. return n;
  173. }

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载