MCPcopy Create free account
hub / github.com/antirez/ds4 / raxGenericInsert

Function raxGenericInsert

rax.c:629–1083  ·  view source on GitHub ↗

Insert the element 's' of size 'len', setting as auxiliary data * the pointer 'data'. If the element is already present, the associated * data is updated (only if 'overwrite' is set to 1), and 0 is returned, * otherwise the element is inserted and 1 is returned. On out of memory the * function returns 0 as well but sets errno to ENOMEM, otherwise errno will * be set to 0. */

Source from the content-addressed store, hash-verified

627 * be set to 0.
628 */
629int raxGenericInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old, int overwrite) {
630 size_t i;
631 int j = 0; /* Split position. If raxLowWalk() stops in a compressed
632 node, the index 'j' represents the char we stopped within the
633 compressed node, that is, the position where to split the
634 node for insertion. */
635 raxNode *h, **parentlink;
636
637 debugf("### Insert %.*s with value %p\n", (int)len, s, data);
638 int inline_leaf = 0;
639 i = raxLowWalk(rax,s,len,&h,&parentlink,&j,NULL,&inline_leaf);
640
641 /* If the key was found as an inline leaf, the value is stored
642 * directly in the parent's child pointer slot. Update it in place
643 * without any allocation. */
644 if (i == len && inline_leaf) {
645 void *curval;
646 memcpy(&curval,parentlink,sizeof(curval));
647 if (old) *old = curval;
648 if (overwrite) memcpy(parentlink,&data,sizeof(data));
649 errno = 0;
650 return 0; /* Element already exists. */
651 }
652
653 /* If we stopped because we hit an inline leaf but still have
654 * characters to insert, we must "un-inline" the leaf: allocate
655 * a real node for it so we can continue the insertion. */
656 if (inline_leaf && i < len) {
657 raxNode *leaf;
658 if (!raxMaterializeInlineLeaf(rax,h,parentlink,&leaf)) {
659 errno = ENOMEM;
660 return 0;
661 }
662 h = leaf;
663 j = 0;
664 /* h is now a real node with size=0 and iskey=1, iscompr=0.
665 * Neither ALGO 1 nor ALGO 2 will trigger. We fall through to
666 * the "insert remaining chars" loop. */
667 }
668
669 /* If i == len we walked following the whole string. If we are not
670 * in the middle of a compressed node, the string is either already
671 * inserted or this middle node is currently not a key, but can represent
672 * our key. We have just to reallocate the node and make space for the
673 * data pointer. */
674 if (i == len && (!h->iscompr || j == 0 /* not in the middle if j is 0 */)) {
675 debugf("### Insert: node representing key exists\n");
676 /* Make space for the value pointer if needed. */
677 if (!h->iskey || (h->isnull && overwrite)) {
678 h = raxReallocForData(h,data);
679 if (h) memcpy(parentlink,&h,sizeof(h));
680 }
681 if (h == NULL) {
682 errno = ENOMEM;
683 return 0;
684 }
685
686 /* Update the existing key if there is already one. */

Callers 2

raxInsertFunction · 0.85
raxTryInsertFunction · 0.85

Calls 12

raxLowWalkFunction · 0.85
raxMaterializeInlineLeafFunction · 0.85
raxReallocForDataFunction · 0.85
raxGetDataFunction · 0.85
raxSetDataFunction · 0.85
raxNewNodeFunction · 0.85
raxCompressNodeNoAllocFunction · 0.85
raxCompressNodeFunction · 0.85
raxNodeFindChildPosFunction · 0.85
raxAddChildNoAllocFunction · 0.85
raxAddChildFunction · 0.85
raxRemoveFunction · 0.85

Tested by

no test coverage detected