Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
43078ff8
Commit
43078ff8
authored
Mar 28, 2010
by
Pieter Noordhuis
Browse files
implemented strategy that doesn't use free blocks in zipmaps
parent
570e43c8
Changes
1
Show whitespace changes
Inline
Side-by-side
zipmap.c
View file @
43078ff8
...
@@ -149,33 +149,24 @@ static unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) {
...
@@ -149,33 +149,24 @@ static unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) {
* (freelen is an integer pointer used both to signal the required length
* (freelen is an integer pointer used both to signal the required length
* and to get the reply from the function). If there is not a suitable
* and to get the reply from the function). If there is not a suitable
* free space block to hold the requested bytes, *freelen is set to 0. */
* free space block to hold the requested bytes, *freelen is set to 0. */
static
unsigned
char
*
zipmapLookupRaw
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
unsigned
int
*
totlen
,
unsigned
int
*
freeoff
,
unsigned
int
*
freelen
)
{
static
unsigned
char
*
zipmapLookupRaw
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
unsigned
int
*
totlen
)
{
unsigned
char
*
p
=
zm
+
1
;
unsigned
char
*
p
=
zm
+
1
,
*
k
=
NULL
;
unsigned
int
l
;
unsigned
int
l
;
unsigned
int
reqfreelen
=
0
;
/* initialized just to prevent warning */
if
(
freelen
)
{
reqfreelen
=
*
freelen
;
*
freelen
=
0
;
assert
(
reqfreelen
!=
0
);
}
while
(
*
p
!=
ZIPMAP_END
)
{
while
(
*
p
!=
ZIPMAP_END
)
{
if
(
*
p
==
ZIPMAP_EMPTY
)
{
l
=
zipmapDecodeLength
(
p
+
1
);
/* if the user want a free space report, and this space is
* enough, and we did't already found a suitable space... */
if
(
freelen
&&
l
>=
reqfreelen
&&
*
freelen
==
0
)
{
*
freelen
=
l
;
*
freeoff
=
p
-
zm
;
}
p
+=
l
;
zm
[
0
]
|=
ZIPMAP_STATUS_FRAGMENTED
;
}
else
{
unsigned
char
free
;
unsigned
char
free
;
/* Match or skip the key */
/* Match or skip the key */
l
=
zipmapDecodeLength
(
p
);
l
=
zipmapDecodeLength
(
p
);
if
(
l
==
klen
&&
!
memcmp
(
p
+
1
,
key
,
l
))
return
p
;
if
(
k
==
NULL
&&
l
==
klen
&&
!
memcmp
(
p
+
1
,
key
,
l
))
{
/* Only return when the user doesn't care
* for the total length of the zipmap. */
if
(
totlen
!=
NULL
)
{
k
=
p
;
}
else
{
return
p
;
}
}
p
+=
zipmapEncodeLength
(
NULL
,
l
)
+
l
;
p
+=
zipmapEncodeLength
(
NULL
,
l
)
+
l
;
/* Skip the value as well */
/* Skip the value as well */
l
=
zipmapDecodeLength
(
p
);
l
=
zipmapDecodeLength
(
p
);
...
@@ -183,9 +174,8 @@ static unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, uns
...
@@ -183,9 +174,8 @@ static unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, uns
free
=
p
[
0
];
free
=
p
[
0
];
p
+=
l
+
1
+
free
;
/* +1 to skip the free byte */
p
+=
l
+
1
+
free
;
/* +1 to skip the free byte */
}
}
}
if
(
totlen
!=
NULL
)
*
totlen
=
(
unsigned
int
)(
p
-
zm
)
+
1
;
if
(
totlen
!=
NULL
)
*
totlen
=
(
unsigned
int
)(
p
-
zm
)
+
1
;
return
NULL
;
return
k
;
}
}
static
unsigned
long
zipmapRequiredLength
(
unsigned
int
klen
,
unsigned
int
vlen
)
{
static
unsigned
long
zipmapRequiredLength
(
unsigned
int
klen
,
unsigned
int
vlen
)
{
...
@@ -224,28 +214,29 @@ static unsigned int zipmapRawEntryLength(unsigned char *p) {
...
@@ -224,28 +214,29 @@ static unsigned int zipmapRawEntryLength(unsigned char *p) {
return
l
+
zipmapRawValueLength
(
p
+
l
);
return
l
+
zipmapRawValueLength
(
p
+
l
);
}
}
static
inline
unsigned
char
*
zipmapResize
(
unsigned
char
*
zm
,
unsigned
int
len
)
{
zm
=
zrealloc
(
zm
,
len
);
zm
[
len
-
1
]
=
ZIPMAP_END
;
return
zm
;
}
/* Set key to value, creating the key if it does not already exist.
/* 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
* If 'update' is not NULL, *update is set to 1 if the key was
* already preset, otherwise to 0. */
* already preset, otherwise to 0. */
unsigned
char
*
zipmapSet
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
unsigned
char
*
val
,
unsigned
int
vlen
,
int
*
update
)
{
unsigned
char
*
zipmapSet
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
unsigned
char
*
val
,
unsigned
int
vlen
,
int
*
update
)
{
unsigned
int
oldlen
=
0
,
freeoff
=
0
,
free
len
;
unsigned
int
zm
len
;
unsigned
int
reqlen
=
zipmapRequiredLength
(
klen
,
vlen
);
unsigned
int
freelen
,
reqlen
=
zipmapRequiredLength
(
klen
,
vlen
);
unsigned
int
empty
,
vempty
;
unsigned
int
empty
,
vempty
;
unsigned
char
*
p
;
unsigned
char
*
p
;
freelen
=
reqlen
;
freelen
=
reqlen
;
if
(
update
)
*
update
=
0
;
if
(
update
)
*
update
=
0
;
p
=
zipmapLookupRaw
(
zm
,
key
,
klen
,
&
oldlen
,
&
freeoff
,
&
freelen
);
p
=
zipmapLookupRaw
(
zm
,
key
,
klen
,
&
zmlen
);
if
(
p
==
NULL
&&
freelen
==
0
)
{
if
(
p
==
NULL
)
{
/* Key not found, and not space for the new key. Enlarge */
/* Key not found: enlarge */
zm
=
zrealloc
(
zm
,
oldlen
+
reqlen
);
zm
=
zipmapResize
(
zm
,
zmlen
+
reqlen
);
p
=
zm
+
oldlen
-
1
;
p
=
zm
+
zmlen
-
1
;
zm
[
oldlen
+
reqlen
-
1
]
=
ZIPMAP_END
;
zmlen
=
zmlen
+
reqlen
;
freelen
=
reqlen
;
}
else
if
(
p
==
NULL
)
{
/* Key not found, but there is enough free space. */
p
=
zm
+
freeoff
;
/* note: freelen is already set in this case */
}
else
{
}
else
{
unsigned
char
*
b
=
p
;
unsigned
char
*
b
=
p
;
...
@@ -256,11 +247,14 @@ unsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int kle
...
@@ -256,11 +247,14 @@ unsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int kle
b
+=
freelen
;
b
+=
freelen
;
freelen
+=
zipmapRawValueLength
(
b
);
freelen
+=
zipmapRawValueLength
(
b
);
if
(
freelen
<
reqlen
)
{
if
(
freelen
<
reqlen
)
{
/* Mark this entry as free and recurse */
/* Move remaining entries to the current position, so this
p
[
0
]
=
ZIPMAP_EMPTY
;
* pair can be appended. Note: the +1 in memmove is caused
zipmapEncodeLength
(
p
+
1
,
freelen
);
* by the end-of-zipmap byte. */
zm
[
0
]
|=
ZIPMAP_STATUS_FRAGMENTED
;
memmove
(
p
,
p
+
freelen
,
zmlen
-
((
p
-
zm
)
+
freelen
+
1
));
return
zipmapSet
(
zm
,
key
,
klen
,
val
,
vlen
,
NULL
);
zm
=
zipmapResize
(
zm
,
zmlen
-
freelen
+
reqlen
);
p
=
zm
+
zmlen
-
1
-
freelen
;
zmlen
=
zmlen
-
1
-
freelen
+
reqlen
;
freelen
=
reqlen
;
}
}
}
}
...
@@ -270,14 +264,11 @@ unsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int kle
...
@@ -270,14 +264,11 @@ unsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int kle
/* If there is too much free space mark it as a free block instead
/* If there is too much free space mark it as a free block instead
* of adding it as trailing empty space for the value, as we want
* of adding it as trailing empty space for the value, as we want
* zipmaps to be very space efficient. */
* zipmaps to be very space efficient. */
if
(
empty
>
ZIPMAP_VALUE_MAX_FREE
)
{
if
(
empty
>=
ZIPMAP_VALUE_MAX_FREE
)
{
unsigned
char
*
e
;
memmove
(
p
+
reqlen
,
p
+
freelen
,
zmlen
-
((
p
-
zm
)
+
freelen
+
1
));
zmlen
-=
empty
;
e
=
p
+
reqlen
;
zm
=
zipmapResize
(
zm
,
zmlen
);
e
[
0
]
=
ZIPMAP_EMPTY
;
zipmapEncodeLength
(
e
+
1
,
empty
);
vempty
=
0
;
vempty
=
0
;
zm
[
0
]
|=
ZIPMAP_STATUS_FRAGMENTED
;
}
else
{
}
else
{
vempty
=
empty
;
vempty
=
empty
;
}
}
...
@@ -297,13 +288,12 @@ unsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int kle
...
@@ -297,13 +288,12 @@ unsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int kle
/* Remove the specified key. If 'deleted' is not NULL the pointed integer is
/* Remove the specified key. If 'deleted' is not NULL the pointed integer is
* set to 0 if the key was not found, to 1 if it was found and deleted. */
* set to 0 if the key was not found, to 1 if it was found and deleted. */
unsigned
char
*
zipmapDel
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
int
*
deleted
)
{
unsigned
char
*
zipmapDel
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
int
*
deleted
)
{
unsigned
char
*
p
=
zipmapLookupRaw
(
zm
,
key
,
klen
,
NULL
,
NULL
,
NULL
);
unsigned
int
zmlen
;
unsigned
char
*
p
=
zipmapLookupRaw
(
zm
,
key
,
klen
,
&
zmlen
);
if
(
p
)
{
if
(
p
)
{
unsigned
int
freelen
=
zipmapRawEntryLength
(
p
);
unsigned
int
freelen
=
zipmapRawEntryLength
(
p
);
memmove
(
p
,
p
+
freelen
,
zmlen
-
((
p
-
zm
)
+
freelen
+
1
));
p
[
0
]
=
ZIPMAP_EMPTY
;
zm
=
zipmapResize
(
zm
,
zmlen
-
freelen
);
zipmapEncodeLength
(
p
+
1
,
freelen
);
zm
[
0
]
|=
ZIPMAP_STATUS_FRAGMENTED
;
if
(
deleted
)
*
deleted
=
1
;
if
(
deleted
)
*
deleted
=
1
;
}
else
{
}
else
{
if
(
deleted
)
*
deleted
=
0
;
if
(
deleted
)
*
deleted
=
0
;
...
@@ -351,7 +341,7 @@ unsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *
...
@@ -351,7 +341,7 @@ unsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *
int
zipmapGet
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
unsigned
char
**
value
,
unsigned
int
*
vlen
)
{
int
zipmapGet
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
,
unsigned
char
**
value
,
unsigned
int
*
vlen
)
{
unsigned
char
*
p
;
unsigned
char
*
p
;
if
((
p
=
zipmapLookupRaw
(
zm
,
key
,
klen
,
NULL
,
NULL
,
NULL
))
==
NULL
)
return
0
;
if
((
p
=
zipmapLookupRaw
(
zm
,
key
,
klen
,
NULL
))
==
NULL
)
return
0
;
p
+=
zipmapRawKeyLength
(
p
);
p
+=
zipmapRawKeyLength
(
p
);
*
vlen
=
zipmapDecodeLength
(
p
);
*
vlen
=
zipmapDecodeLength
(
p
);
*
value
=
p
+
ZIPMAP_LEN_BYTES
(
*
vlen
)
+
1
;
*
value
=
p
+
ZIPMAP_LEN_BYTES
(
*
vlen
)
+
1
;
...
@@ -360,7 +350,7 @@ int zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned
...
@@ -360,7 +350,7 @@ int zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned
/* Return 1 if the key exists, otherwise 0 is returned. */
/* Return 1 if the key exists, otherwise 0 is returned. */
int
zipmapExists
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
)
{
int
zipmapExists
(
unsigned
char
*
zm
,
unsigned
char
*
key
,
unsigned
int
klen
)
{
return
zipmapLookupRaw
(
zm
,
key
,
klen
,
NULL
,
NULL
,
NULL
)
!=
NULL
;
return
zipmapLookupRaw
(
zm
,
key
,
klen
,
NULL
)
!=
NULL
;
}
}
/* Return the number of entries inside a zipmap */
/* Return the number of entries inside a zipmap */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment