Insert a new entry before or after existing entry 'entry'. * * If after==1, the new value is inserted after 'entry', otherwise * the new value is inserted before 'entry'. */
| 853 | * If after==1, the new value is inserted after 'entry', otherwise |
| 854 | * the new value is inserted before 'entry'. */ |
| 855 | REDIS_STATIC void _quicklistInsert(quicklist *quicklist, quicklistEntry *entry, |
| 856 | void *value, const size_t sz, int after) { |
| 857 | int full = 0, at_tail = 0, at_head = 0, full_next = 0, full_prev = 0; |
| 858 | int fill = quicklist->fill; |
| 859 | quicklistNode *node = entry->node; |
| 860 | quicklistNode *new_node = NULL; |
| 861 | assert(sz < UINT32_MAX); /* TODO: add support for quicklist nodes that are sds encoded (not zipped) */ |
| 862 | |
| 863 | if (!node) { |
| 864 | /* we have no reference node, so let's create only node in the list */ |
| 865 | D("No node given!"); |
| 866 | new_node = quicklistCreateNode(); |
| 867 | new_node->zl = ziplistPush(ziplistNew(), value, sz, ZIPLIST_HEAD); |
| 868 | __quicklistInsertNode(quicklist, NULL, new_node, after); |
| 869 | new_node->count++; |
| 870 | quicklist->count++; |
| 871 | return; |
| 872 | } |
| 873 | |
| 874 | /* Populate accounting flags for easier boolean checks later */ |
| 875 | if (!_quicklistNodeAllowInsert(node, fill, sz)) { |
| 876 | D("Current node is full with count %d with requested fill %lu", |
| 877 | node->count, fill); |
| 878 | full = 1; |
| 879 | } |
| 880 | |
| 881 | if (after && (entry->offset == node->count)) { |
| 882 | D("At Tail of current ziplist"); |
| 883 | at_tail = 1; |
| 884 | if (!_quicklistNodeAllowInsert(node->next, fill, sz)) { |
| 885 | D("Next node is full too."); |
| 886 | full_next = 1; |
| 887 | } |
| 888 | } |
| 889 | |
| 890 | if (!after && (entry->offset == 0)) { |
| 891 | D("At Head"); |
| 892 | at_head = 1; |
| 893 | if (!_quicklistNodeAllowInsert(node->prev, fill, sz)) { |
| 894 | D("Prev node is full too."); |
| 895 | full_prev = 1; |
| 896 | } |
| 897 | } |
| 898 | |
| 899 | /* Now determine where and how to insert the new element */ |
| 900 | if (!full && after) { |
| 901 | D("Not full, inserting after current position."); |
| 902 | quicklistDecompressNodeForUse(node); |
| 903 | unsigned char *next = ziplistNext(node->zl, entry->zi); |
| 904 | if (next == NULL) { |
| 905 | node->zl = ziplistPush(node->zl, value, sz, ZIPLIST_TAIL); |
| 906 | } else { |
| 907 | node->zl = ziplistInsert(node->zl, next, value, sz); |
| 908 | } |
| 909 | node->count++; |
| 910 | quicklistNodeUpdateSz(node); |
| 911 | quicklistRecompressOnly(quicklist, node); |
| 912 | } else if (!full && !after) { |
no test coverage detected