MCPcopy Create free account
hub / github.com/Snapchat/KeyDB / zipmapSet

Function zipmapSet

src/zipmap.c:215–281  ·  view source on GitHub ↗

Set key to value, creating the key if it does not already exist. * If 'update' is not NULL, *update is set to 1 if the key was * already preset, otherwise to 0. */

Source from the content-addressed store, hash-verified

213 * If 'update' is not NULL, *update is set to 1 if the key was
214 * already preset, otherwise to 0. */
215unsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char *val, unsigned int vlen, int *update) {
216 unsigned int zmlen, offset;
217 unsigned int freelen, reqlen = zipmapRequiredLength(klen,vlen);
218 unsigned int empty, vempty;
219 unsigned char *p;
220
221 freelen = reqlen;
222 if (update) *update = 0;
223 p = zipmapLookupRaw(zm,key,klen,&zmlen);
224 if (p == NULL) {
225 /* Key not found: enlarge */
226 zm = zipmapResize(zm, zmlen+reqlen);
227 p = zm+zmlen-1;
228 zmlen = zmlen+reqlen;
229
230 /* Increase zipmap length (this is an insert) */
231 if (zm[0] < ZIPMAP_BIGLEN) zm[0]++;
232 } else {
233 /* Key found. Is there enough space for the new value? */
234 /* Compute the total length: */
235 if (update) *update = 1;
236 freelen = zipmapRawEntryLength(p);
237 if (freelen < reqlen) {
238 /* Store the offset of this key within the current zipmap, so
239 * it can be resized. Then, move the tail backwards so this
240 * pair fits at the current position. */
241 offset = p-zm;
242 zm = zipmapResize(zm, zmlen-freelen+reqlen);
243 p = zm+offset;
244
245 /* The +1 in the number of bytes to be moved is caused by the
246 * end-of-zipmap byte. Note: the *original* zmlen is used. */
247 memmove(p+reqlen, p+freelen, zmlen-(offset+freelen+1));
248 zmlen = zmlen-freelen+reqlen;
249 freelen = reqlen;
250 }
251 }
252
253 /* We now have a suitable block where the key/value entry can
254 * be written. If there is too much free space, move the tail
255 * of the zipmap a few bytes to the front and shrink the zipmap,
256 * as we want zipmaps to be very space efficient. */
257 empty = freelen-reqlen;
258 if (empty >= ZIPMAP_VALUE_MAX_FREE) {
259 /* First, move the tail <empty> bytes to the front, then resize
260 * the zipmap to be <empty> bytes smaller. */
261 offset = p-zm;
262 memmove(p+reqlen, p+freelen, zmlen-(offset+freelen+1));
263 zmlen -= empty;
264 zm = zipmapResize(zm, zmlen);
265 p = zm+offset;
266 vempty = 0;
267 } else {
268 vempty = empty;
269 }
270
271 /* Just write the key + value and we are done. */
272 /* Key: */

Callers 1

zipmapTestFunction · 0.85

Calls 5

zipmapRequiredLengthFunction · 0.85
zipmapLookupRawFunction · 0.85
zipmapResizeFunction · 0.85
zipmapRawEntryLengthFunction · 0.85
zipmapEncodeLengthFunction · 0.85

Tested by

no test coverage detected