关键词搜索

源码搜索 ×
×

漫话Redis源码之六

发布2021-11-21浏览602次

详情内容

redis中有很多内存操作的经典使用,越看越有意思:

  1. /* Return a ziplist element as an SDS string. */
  2. sds ziplistGetObject(unsigned char *sptr) {
  3. unsigned char *vstr;
  4. unsigned int vlen;
  5. long long vlong;
  6. serverAssert(sptr != NULL);
  7. serverAssert(ziplistGet(sptr,&vstr,&vlen,&vlong));
  8. if (vstr) {
  9. return sdsnewlen((char*)vstr,vlen);
  10. } else {
  11. return sdsfromlonglong(vlong);
  12. }
  13. }
  14. /* Compare element in sorted set with given element. */
  15. int zzlCompareElements(unsigned char *eptr, unsigned char *cstr, unsigned int clen) {
  16. unsigned char *vstr;
  17. unsigned int vlen;
  18. long long vlong;
  19. unsigned char vbuf[32];
  20. int minlen, cmp;
  21. serverAssert(ziplistGet(eptr,&vstr,&vlen,&vlong));
  22. if (vstr == NULL) {
  23. /* Store string representation of long long in buf. */
  24. vlen = ll2string((char*)vbuf,sizeof(vbuf),vlong);
  25. vstr = vbuf;
  26. }
  27. minlen = (vlen < clen) ? vlen : clen;
  28. cmp = memcmp(vstr,cstr,minlen);
  29. if (cmp == 0) return vlen-clen;
  30. return cmp;
  31. }
  32. unsigned int zzlLength(unsigned char *zl) {
  33. return ziplistLen(zl)/2;
  34. }
  35. /* Move to next entry based on the values in eptr and sptr. Both are set to
  36. * NULL when there is no next entry. */
  37. void zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {
  38. unsigned char *_eptr, *_sptr;
  39. serverAssert(*eptr != NULL && *sptr != NULL);
  40. _eptr = ziplistNext(zl,*sptr);
  41. if (_eptr != NULL) {
  42. _sptr = ziplistNext(zl,_eptr);
  43. serverAssert(_sptr != NULL);
  44. } else {
  45. /* No next entry. */
  46. _sptr = NULL;
  47. }
  48. *eptr = _eptr;
  49. *sptr = _sptr;
  50. }
  51. /* Move to the previous entry based on the values in eptr and sptr. Both are
  52. * set to NULL when there is no next entry. */
  53. void zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {
  54. unsigned char *_eptr, *_sptr;
  55. serverAssert(*eptr != NULL && *sptr != NULL);
  56. _sptr = ziplistPrev(zl,*eptr);
  57. if (_sptr != NULL) {
  58. _eptr = ziplistPrev(zl,_sptr);
  59. serverAssert(_eptr != NULL);
  60. } else {
  61. /* No previous entry. */
  62. _eptr = NULL;
  63. }
  64. *eptr = _eptr;
  65. *sptr = _sptr;
  66. }
  67. /* Returns if there is a part of the zset is in range. Should only be used
  68. * internally by zzlFirstInRange and zzlLastInRange. */
  69. int zzlIsInRange(unsigned char *zl, zrangespec *range) {
  70. unsigned char *p;
  71. double score;
  72. /* Test for ranges that will always be empty. */
  73. if (range->min > range->max ||
  74. (range->min == range->max && (range->minex || range->maxex)))
  75. return 0;
  76. p = ziplistIndex(zl,-1); /* Last score. */
  77. if (p == NULL) return 0; /* Empty sorted set */
  78. score = zzlGetScore(p);
  79. if (!zslValueGteMin(score,range))
  80. return 0;
  81. p = ziplistIndex(zl,1); /* First score. */
  82. serverAssert(p != NULL);
  83. score = zzlGetScore(p);
  84. if (!zslValueLteMax(score,range))
  85. return 0;
  86. return 1;
  87. }
  88. /* Find pointer to the first element contained in the specified range.
  89. * Returns NULL when no element is contained in the range. */
  90. unsigned char *zzlFirstInRange(unsigned char *zl, zrangespec *range) {
  91. unsigned char *eptr = ziplistIndex(zl,0), *sptr;
  92. double score;
  93. /* If everything is out of range, return early. */
  94. if (!zzlIsInRange(zl,range)) return NULL;
  95. while (eptr != NULL) {
  96. sptr = ziplistNext(zl,eptr);
  97. serverAssert(sptr != NULL);
  98. score = zzlGetScore(sptr);
  99. if (zslValueGteMin(score,range)) {
  100. /* Check if score <= max. */
  101. if (zslValueLteMax(score,range))
  102. return eptr;
  103. return NULL;
  104. }
  105. /* Move to next element. */
  106. eptr = ziplistNext(zl,sptr);
  107. }
  108. return NULL;
  109. }
  110. /* Find pointer to the last element contained in the specified range.
  111. * Returns NULL when no element is contained in the range. */
  112. unsigned char *zzlLastInRange(unsigned char *zl, zrangespec *range) {
  113. unsigned char *eptr = ziplistIndex(zl,-2), *sptr;
  114. double score;
  115. /* If everything is out of range, return early. */
  116. if (!zzlIsInRange(zl,range)) return NULL;
  117. while (eptr != NULL) {
  118. sptr = ziplistNext(zl,eptr);
  119. serverAssert(sptr != NULL);
  120. score = zzlGetScore(sptr);
  121. if (zslValueLteMax(score,range)) {
  122. /* Check if score >= min. */
  123. if (zslValueGteMin(score,range))
  124. return eptr;
  125. return NULL;
  126. }
  127. /* Move to previous element by moving to the score of previous element.
  128. * When this returns NULL, we know there also is no element. */
  129. sptr = ziplistPrev(zl,eptr);
  130. if (sptr != NULL)
  131. serverAssert((eptr = ziplistPrev(zl,sptr)) != NULL);
  132. else
  133. eptr = NULL;
  134. }
  135. return NULL;
  136. }
  137. int zzlLexValueGteMin(unsigned char *p, zlexrangespec *spec) {
  138. sds value = ziplistGetObject(p);
  139. int res = zslLexValueGteMin(value,spec);
  140. sdsfree(value);
  141. return res;
  142. }
  143. int zzlLexValueLteMax(unsigned char *p, zlexrangespec *spec) {
  144. sds value = ziplistGetObject(p);
  145. int res = zslLexValueLteMax(value,spec);
  146. sdsfree(value);
  147. return res;
  148. }

相关技术文章

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

提示信息

×

选择支付方式

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