]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/libs4c/keyval/keyvalpb.c
Included ARM LPC21xx related code from uLan project. The snapshot date is 2008-07-05
[lincan.git] / embedded / libs4c / keyval / keyvalpb.c
1 /*******************************************************************
2   Key Value Persistent Storage
3
4   keyvalpb.c    - key value parameters block
5
6   (C) Copyright 2003-2005 by Pavel Pisa - Originator
7   (C) Copyright 2004-2005 by Petr Smolik - Originator
8
9   The uLan utilities library can be used, copied and modified under
10   next licenses
11     - GPL - GNU General Public License
12     - LGPL - GNU Lesser General Public License
13     - MPL - Mozilla Public License
14     - and other licenses added by project originators
15   Code can be modified and re-distributed under any combination
16   of the above listed licenses. If contributor does not agree with
17   some of the licenses, he/she can delete appropriate line.
18   Warning, if you delete all lines, you are not allowed to
19   distribute source code and/or binaries utilizing code.
20   
21   See files COPYING and README for details.
22
23  *******************************************************************/
24
25 #include <string.h>
26 #include "keyvalpb.h"
27
28 /*
29  * kvpb_memsum - Compute checksum of given memory area
30  * @base: Pointer to the base of of the region
31  * @size: Size of utilized part of the region
32  *
33  * Return Value: Computed checksum value
34  * File: keyvalpb.c
35  */
36 kvpb_sum_t kvpb_memsum(KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size)
37 {
38   KVPB_LOCALDATA kvpb_sum_t sum=0;
39   KVPB_DPTRTYPE uint16_t *p=(KVPB_DPTRTYPE uint16_t *)base;
40   size=(size+1)>>1;
41   while(size--){
42     sum+=*(p++);
43   }
44   sum&=KVPB_SUM_MASK;
45   sum|=KVPB_SUM_OKVAL;
46   return sum;
47 }
48
49 #ifndef KVPB_WITHOUT_HADLE
50 /*
51  * kvpb_get_psum - Get pointer to the region check sum
52  * @kvpb_block: Pointer to the KVPB access information/state structure
53  * @base: Pointer to the base of of the region
54  * @size: Size of one data block region
55  *
56  * Return Value: Pointer to the actual region check sum placement
57  * File: keyvalpb.c
58  */
59 KVPB_DPTRTYPE kvpb_sum_t *kvpb_get_psum(kvpb_block_t *kvpb_block,
60                                   KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size) 
61 #else
62 KVPB_DPTRTYPE kvpb_sum_t *__kvpb_get_psum(
63                                   KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size) 
64 #endif
65 {
66   KVPB_DPTRTYPE kvpb_sum_t *psum;
67   psum=kvpb_psum_align(kvpb_block,(KVPB_DPTRTYPE kvpb_sum_t*)(base+size)-1);
68   while((KVPB_DPTRTYPE uint8_t*)psum>=base) {
69     if (*kvpb_psum_valid_loc(kvpb_block,psum)!=0) 
70       return psum;
71     psum=kvpb_psum_align(kvpb_block,psum-1);
72   }
73   return NULL;
74 }
75
76 #ifndef KVPB_WITHOUT_HADLE
77 /*
78  * kvpb_get_cfk - Get space where to place new key-value pair
79  * @kvpb_block: Pointer to the KVPB access information/state structure
80  * @mode: 0 .. work on active/valid data region;
81  *      1 .. work on the first copy/region, 2 .. work on the second copy/region
82  * @size: Size of required space for stored value
83  *
84  * Return Value: Pointer where next pair should be stored or %NULL
85  * File: keyvalpb.c
86  */
87 KVPB_DPTRTYPE kvpb_key_t *kvpb_get_cfk(kvpb_block_t *kvpb_block,uint8_t mode,int size)
88 #else
89 KVPB_DPTRTYPE kvpb_key_t *__kvpb_get_cfk(uint8_t mode,int size)
90 #endif
91 {
92   KVPB_DPTRTYPE kvpb_sum_t *psum;
93   KVPB_DPTRTYPE uint8_t    *p;
94   KVPB_DPTRTYPE uint8_t    *r;
95   p=kvpb_region_base(kvpb_block,0);
96   size=kvpb_chunk_align(kvpb_block,size+sizeof(kvpb_key_t))+
97        (kvpb_block->flags&KVPB_DESC_CHUNKWO?kvpb_chunk_size(kvpb_block):0);
98   psum=kvpb_block->psum1;
99   if((!mode && (kvpb_block->flags & KVPB_DESC_USE2ND))||(mode==2)) {
100     if(!(kvpb_block->flags&KVPB_DESC_DOUBLE))
101       return NULL;
102     p=kvpb_region_base(kvpb_block,1);
103     psum=kvpb_block->psum2;
104   }
105   do {
106     kvpb_size_t ksize=((KVPB_DPTRTYPE kvpb_key_t *)p)->size;
107     if(ksize==KVPB_EMPTY)
108       break;
109     if(((uint8_t*)psum-(uint8_t*)p)<ksize)
110       return NULL;
111     p+=kvpb_chunk_align(kvpb_block,ksize+sizeof(kvpb_key_t))+
112        (kvpb_block->flags&KVPB_DESC_CHUNKWO?kvpb_chunk_size(kvpb_block):0);
113   } while(1);
114   r=(KVPB_DPTRTYPE uint8_t*)p+size+sizeof(kvpb_key_t);
115   if(r<p)
116     return NULL;
117   if ((uint8_t*)kvpb_psum_align(kvpb_block,psum-1)<r) {
118     return NULL;
119   }
120   return (KVPB_DPTRTYPE kvpb_key_t*)p;
121 }
122
123
124 #ifndef KVPB_WITHOUT_HADLE
125 /**
126  * kvpb_check - Check data consistency of the KVPB storage
127  * @kvpb_block: Pointer to the KVPB access information/state structure
128  * @mode: if mode is nonzero, try to restore valid state or erase all data
129  *
130  * Return Value: 0 .. all regions are correct, 1 .. the first region is valid, the second
131  *      region is invalid or has been updated if @mode has been set, 2 .. the second region
132  *      is valid, the first is invalid or has been updated if @mode has been set, 3 .. both
133  *      regions has been erased and emptied, -1 .. the state is inconsistent and no valid
134  *      region has been found and state has not be corrected
135  * File: keyvalpb.c
136  */
137 int kvpb_check(kvpb_block_t *kvpb_block, uint8_t mode)
138 #else
139 int __kvpb_check(uint8_t mode)
140 #endif
141 {
142   KVPB_DPTRTYPE uint8_t *p;
143   KVPB_LOCALDATA int ret=-1;
144   KVPB_LOCALDATA kvpb_sum_t sum;
145   
146   kvpb_block->flags&=~KVPB_DESC_USE2ND;
147   
148   p=kvpb_region_base(kvpb_block,0);
149   kvpb_block->psum1=kvpb_get_psum(kvpb_block,p,kvpb_block->size);
150   if (kvpb_block->psum1) {
151     sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum1-p);
152     if(*kvpb_block->psum1==sum){
153       ret=1;
154     }
155   }
156
157   if(kvpb_block->flags&KVPB_DESC_DOUBLE){
158     p=kvpb_region_base(kvpb_block,1);
159     kvpb_block->psum2=kvpb_get_psum(kvpb_block,p,kvpb_block->size);
160     if (kvpb_block->psum2) {
161       sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum2-p);
162       if(*kvpb_block->psum2==sum) {
163         if(ret>=0){
164           ret=0;
165         } else {
166           ret=2;
167           kvpb_block->flags|=KVPB_DESC_USE2ND;
168         }
169       }
170     }
171   } else {
172     if(ret>=0)
173       ret=0;
174   }
175   
176   if(ret){
177     if(!mode) {
178       kvpb_block->flags|=KVPB_DESC_RO;
179     } else {
180       /* correct for FLASH */
181       if(ret<0){
182         p=kvpb_region_base(kvpb_block,0);
183         kvpb_block_erase(kvpb_block,p,kvpb_block->size);
184         kvpb_block->psum1=kvpb_psum_align(kvpb_block,(KVPB_DPTRTYPE kvpb_sum_t*)(p+kvpb_block->size)-1);
185         sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum1-p);
186         kvpb_block_copy(kvpb_block,kvpb_block->psum1,&sum,sizeof(kvpb_sum_t));
187         if(kvpb_block->flags&KVPB_DESC_DOUBLE){
188           p=kvpb_region_base(kvpb_block,1);
189           kvpb_block_erase(kvpb_block,p,kvpb_block->size);
190           kvpb_block->psum2=kvpb_psum_align(kvpb_block,(KVPB_DPTRTYPE kvpb_sum_t*)(p+kvpb_block->size)-1);
191           sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum2-p);
192           kvpb_block_copy(kvpb_block,kvpb_block->psum2,&sum,sizeof(kvpb_sum_t));
193         }
194         ret=3;
195       }else{
196         if(ret==1){
197           kvpb_block_erase(kvpb_block,kvpb_region_base(kvpb_block,1),kvpb_block->size);
198           kvpb_block_copy(kvpb_block,kvpb_region_base(kvpb_block,1),
199                           kvpb_region_base(kvpb_block,0),kvpb_block->size);
200
201         }else{
202           kvpb_block_erase(kvpb_block,kvpb_region_base(kvpb_block,0),kvpb_block->size);
203           kvpb_block_copy(kvpb_block,kvpb_region_base(kvpb_block,0),
204                           kvpb_region_base(kvpb_block,1),kvpb_block->size);
205         }
206       }
207       kvpb_block->flags&=~KVPB_DESC_RO;
208     }
209   }
210   kvpb_block_flush(kvpb_block); 
211   if(ret>=0) kvpb_block->flags|=KVPB_DESC_VALID;
212   return ret;
213 }
214
215 #ifndef KVPB_WITHOUT_HADLE
216 /**
217  * kvpb_first - Get pointer to the first key-value pair in the KVPB storage
218  * @kvpb_block: Pointer to the KVPB access information/state structure
219  * @mode: 0 .. iterate over active/valid data region;
220  *      1 .. iterate over first copy/region, 2 .. iterate over second copy/region
221  *
222  * Return Value: Pointer to the first key-value pair
223  *      or %NULL if no pair exist.
224  * File: keyvalpb.c
225  */
226 KVPB_DPTRTYPE kvpb_key_t *kvpb_first(kvpb_block_t *kvpb_block, uint8_t mode)
227 #else
228 KVPB_DPTRTYPE kvpb_key_t *__kvpb_first(uint8_t mode)
229 #endif
230 {
231   KVPB_DPTRTYPE kvpb_key_t *key=(KVPB_DPTRTYPE kvpb_key_t *)kvpb_region_base(kvpb_block,0);
232   if((!mode && (kvpb_block->flags & KVPB_DESC_USE2ND))||(mode==2)) {
233     if(!(kvpb_block->flags&KVPB_DESC_DOUBLE))
234       return NULL;
235     key=(KVPB_DPTRTYPE kvpb_key_t *)kvpb_region_base(kvpb_block,1);
236   }
237   while(*kvpb_keyid_valid(kvpb_block,key)==KVPB_KEYID_INVALID) {
238     key=kvpb_next(kvpb_block,key);
239     if (!key) 
240       return NULL;
241   }
242   return key->size!=KVPB_EMPTY?key:NULL;
243 }
244
245 #ifndef KVPB_WITHOUT_HADLE
246 /**
247  * kvpb_next - Iterate to the next consecutive key-value pair
248  * @kvpb_block: Pointer to the KVPB access information/state structure
249  * @key: Pointer to the previous key-value pair
250  *
251  * Return Value: Pointer to the next key-value pair
252  *      or %NULL if no/no-more pairs exist.
253  * File: keyvalpb.c
254  */
255 KVPB_DPTRTYPE kvpb_key_t *kvpb_next(kvpb_block_t *kvpb_block, KVPB_DPTRTYPE kvpb_key_t *key)
256 #else
257 KVPB_DPTRTYPE kvpb_key_t *__kvpb_next(KVPB_DPTRTYPE kvpb_key_t *key)
258 #endif
259 {
260   do {
261     key=(KVPB_DPTRTYPE kvpb_key_t *)((KVPB_DPTRTYPE uint8_t *)key+
262                                 kvpb_chunk_align(kvpb_block,key->size+sizeof(kvpb_key_t))+
263                                 (kvpb_block->flags&KVPB_DESC_CHUNKWO?kvpb_chunk_size(kvpb_block):0));
264     if (key->size==KVPB_EMPTY) return NULL;
265   } while(*kvpb_keyid_valid(kvpb_block,key)==KVPB_KEYID_INVALID);
266   return key;
267 }
268
269 #ifndef KVPB_WITHOUT_HADLE
270 /**
271  * kvpb_find - Find first of occurrence of given key ID
272  * @kvpb_block: Pointer to the KVPB access information/state structure
273  * @keyid: Ordinal value representing key ID
274  * @mode: iteration mode modifier: 0 .. search in the active/valid data region;
275  *      1 .. search in the first copy/region, 2 .. search in the second copy/region
276  * @key: Previous key occurrence pointer or %NULL value to find first key ID named key-value pair
277  *
278  * Return Value: Pointer to the first on subsequent occurrence of key-value pair addressed by given key ID
279  *      or %NULL if no/no-more occurrences exists.
280  * File: keyvalpb.c
281  */
282 KVPB_DPTRTYPE kvpb_key_t *kvpb_find(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key)
283 #else
284 KVPB_DPTRTYPE kvpb_key_t *__kvpb_find(kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key)
285 #endif
286 {
287   if(!(kvpb_block->flags&KVPB_DESC_VALID))
288     return NULL;
289   if (key) {
290       key=kvpb_next(kvpb_block, key);
291   } else {
292       key=kvpb_first(kvpb_block, mode);
293   }
294   while(key) {
295     if((key->keyid==keyid) || (keyid==0))
296       return key;
297     key=kvpb_next(kvpb_block, key);
298   }
299   return key;
300 }
301
302 #ifndef KVPB_WITHOUT_HADLE
303 /**
304  * kvpb_compact_region - Compact one KVPB data block/region
305  * @kvpb_block: Pointer to the KVPB access information/state structure
306  * @keyid: Key ID which should be omitted from compacted data
307  * @mode: 0 .. compact active/valid data region;
308  *      1 .. compact the first data copy, 2 .. compact the second copy
309  *
310  * Return Value: Operation cannot be finished.
311  * File: keyvalpb.c
312  */
313 int kvpb_compact_region(kvpb_block_t *kvpb_block, uint8_t mode, kvpb_keyid_t keyid) 
314 #else
315 int __kvpb_compact_region(uint8_t mode, kvpb_keyid_t keyid) 
316 #endif
317 {
318   KVPB_DPTRTYPE uint8_t *p;
319   KVPB_DPTRTYPE kvpb_key_t *des,*src;
320
321   p=kvpb_region_base(kvpb_block,0);
322   src=(KVPB_DPTRTYPE kvpb_key_t*)kvpb_region_base(kvpb_block,1);
323   des=(KVPB_DPTRTYPE kvpb_key_t*)p;
324   kvpb_block->psum1=kvpb_psum_align(kvpb_block,
325                     (KVPB_DPTRTYPE kvpb_sum_t*)(kvpb_region_base(kvpb_block,1))-1);
326   if((!mode && (kvpb_block->flags & KVPB_DESC_USE2ND))||(mode==2)) {
327     if(!(kvpb_block->flags&KVPB_DESC_DOUBLE))
328       return -1;
329     src=(KVPB_DPTRTYPE kvpb_key_t*)p;
330     des=(KVPB_DPTRTYPE kvpb_key_t*)kvpb_region_base(kvpb_block,1);
331     kvpb_block->psum2=kvpb_psum_align(kvpb_block,
332                       (KVPB_DPTRTYPE kvpb_sum_t*)(kvpb_region_base(kvpb_block,2))-1);
333   }
334   kvpb_block_flush(kvpb_block);
335   kvpb_block_erase(kvpb_block,des,kvpb_block->size);
336   while(src) {
337     int s=kvpb_chunk_align(kvpb_block,src->size+sizeof(kvpb_key_t));
338     if((*kvpb_keyid_valid(kvpb_block,src)!=KVPB_KEYID_INVALID) && (src->keyid!=keyid)) {
339       kvpb_block_copy(kvpb_block,des,src,s);    
340       if (kvpb_block->flags&KVPB_DESC_CHUNKWO) s+=kvpb_chunk_size(kvpb_block);
341       des=(KVPB_DPTRTYPE kvpb_key_t*)((uint8_t*)des+s);
342     }
343     src=kvpb_next(kvpb_block, src);
344   }
345   kvpb_block_flush(kvpb_block);
346   return 0;
347 }
348
349 #ifndef KVPB_WITHOUT_HADLE
350 /**
351  * kvpb_get_key - Get value for given key ID
352  * @kvpb_block: Pointer to the KVPB access information/state structure
353  * @keyid: Ordinal value representing key ID
354  * @size: The size of the buffer provided to store data into
355  * @buf: Pointer to the buffer, where retrieved data should be copied
356  *
357  * Return Value: Number of retrieved value bytes if operation is successful
358  *      or -1 if there is no such key ID or operation fails for other reason.
359  * File: keyvalpb.c
360  */
361 int kvpb_get_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, void *buf)
362 #else
363 int __kvpb_get_key(kvpb_keyid_t keyid, kvpb_size_t size, void *buf)
364 #endif
365 {
366   KVPB_DPTRTYPE kvpb_key_t *key;
367   key=kvpb_find(kvpb_block,keyid,0,NULL);
368   if(!key) return -1;
369   if(size && buf){
370     if(key->size<size)
371       size=key->size;
372     memcpy(buf,key+1,size);
373   }
374   return key->size;
375 }
376
377
378 #ifndef KVPB_WITHOUT_HADLE
379 /**
380  * kvpb_set_key - Set new value or define new key-value pair
381  * @kvpb_block: Pointer to the KVPB access information/state structure
382  * @keyid: Ordinal value representing key ID, if or-red with %KVPB_KEYID_DUPLIC,
383  *      the key ID can be defined/inserted  multiple times
384  * @size: Stored value size in bytes
385  * @buf: Pointer to the stored value data
386  *
387  * Return Value: Number of stored bytes (equal to @size) if operation is successful
388  *      or -1 if operation fails.
389  * File: keyvalpb.c
390  */
391 int kvpb_set_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, const void *buf)
392 #else
393 int __kvpb_set_key(kvpb_keyid_t keyid, kvpb_size_t size, const void *buf)
394 #endif
395 {
396   KVPB_LOCALDATA kvpb_sum_t sum;
397   KVPB_DPTRTYPE kvpb_sum_t *psum;
398   KVPB_DPTRTYPE kvpb_key_t *key;
399   KVPB_DPTRTYPE uint8_t *p;
400   
401   if(!(kvpb_block->flags&KVPB_DESC_VALID))
402     return -1;
403   if(kvpb_block->flags&KVPB_DESC_RO)
404     return -1;
405   
406   /*first region*/
407   psum=kvpb_psum_align(kvpb_block,kvpb_block->psum1);
408   sum=0;
409   kvpb_block_copy(kvpb_block,kvpb_psum_valid_loc(kvpb_block,psum),&sum,sizeof(kvpb_sum_t));
410   kvpb_block->psum1=kvpb_psum_align(kvpb_block,kvpb_block->psum1-1);
411   if (!(keyid&KVPB_KEYID_DUPLIC) || !buf) {
412     kvpb_each_from(kvpb_block,keyid,1,key) {
413       kvpb_keyid_t dkeyid=KVPB_KEYID_INVALID;
414       kvpb_block_copy(kvpb_block,kvpb_keyid_valid(kvpb_block,key),&dkeyid,sizeof(kvpb_keyid_t));
415     }
416   }
417   key=kvpb_get_cfk(kvpb_block,1,size);
418   if (!key) {
419     kvpb_compact_region(kvpb_block,1,(keyid&KVPB_KEYID_DUPLIC)?0:keyid);
420     key=kvpb_get_cfk(kvpb_block,1,size);
421   }
422   if (keyid && key && buf) {
423     kvpb_block_copy(kvpb_block,&key->size,&size,sizeof(kvpb_size_t));
424     kvpb_block_copy(kvpb_block,&key->keyid,&keyid,sizeof(kvpb_keyid_t));
425     kvpb_block_copy(kvpb_block,(uint8_t*)(key+1),buf,/*align???*/ size);
426   }
427   /* need flush data to count correct value of new check sum */
428   kvpb_block_flush(kvpb_block);
429
430   p=kvpb_region_base(kvpb_block,0);
431   sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum1-p);
432   kvpb_block_copy(kvpb_block,kvpb_block->psum1,&sum,sizeof(kvpb_sum_t));  
433   kvpb_block_flush(kvpb_block);
434   if(!(kvpb_block->flags&KVPB_DESC_DOUBLE))
435      return key?size:-1;
436
437   /*Write in the first region failed, switching to backup region */
438   if(kvpb_block->flags&KVPB_DESC_RO){
439     kvpb_block->flags|=KVPB_DESC_USE2ND;
440     return -1;
441   }
442
443   /*second region*/
444   psum=kvpb_psum_align(kvpb_block,kvpb_block->psum2);
445   sum=0;
446   kvpb_block_copy(kvpb_block,kvpb_psum_valid_loc(kvpb_block,psum),&sum,sizeof(kvpb_sum_t));
447   kvpb_block->psum2=kvpb_psum_align(kvpb_block,kvpb_block->psum2-1);
448   if (!(keyid&KVPB_KEYID_DUPLIC) || !buf) {
449     kvpb_each_from(kvpb_block,keyid,2,key) {
450       kvpb_keyid_t dkeyid=KVPB_KEYID_INVALID;
451       kvpb_block_copy(kvpb_block,kvpb_keyid_valid(kvpb_block,key),&dkeyid,sizeof(kvpb_keyid_t));
452     }
453   }
454   key=kvpb_get_cfk(kvpb_block,2,size);
455   if (!key) {
456     kvpb_compact_region(kvpb_block,2,(keyid&KVPB_KEYID_DUPLIC)?0:keyid);
457     key=kvpb_get_cfk(kvpb_block,2,size);
458   }
459   if (keyid && key && buf) {
460     kvpb_block_copy(kvpb_block,&key->size,&size,sizeof(kvpb_size_t));
461     kvpb_block_copy(kvpb_block,&key->keyid,&keyid,sizeof(kvpb_keyid_t));
462     kvpb_block_copy(kvpb_block,(uint8_t*)(key+1),buf,/*align???*/ size);
463   }
464   kvpb_block_flush(kvpb_block);
465         
466   p=kvpb_region_base(kvpb_block,1);
467   sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum2-p);
468   kvpb_block_copy(kvpb_block,kvpb_block->psum2,&sum,sizeof(kvpb_sum_t));
469   kvpb_block_flush(kvpb_block);
470   /*Write in the second region failed, switching to the first region */
471   if(kvpb_block->flags&KVPB_DESC_RO){
472     kvpb_block->flags&=~KVPB_DESC_USE2ND;
473     return -1;
474   }
475
476   return key?size:-1;
477 }
478
479 #ifndef KVPB_MINIMALIZED
480 /**
481  * kvpb_err_keys - Erase/delete key-value pair
482  * @kvpb_block: Pointer to the KVPB access information/state structure
483  * @keyid: Ordinal value representing key ID
484  *
485  * Return Value: Positive or zero value informs about successful operation,
486  *      -1 if operation fails.
487  * File: keyvalpb.c
488  */
489 int kvpb_err_keys(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid)
490 {
491   return kvpb_set_key(kvpb_block,keyid,0,NULL);
492 }
493 #endif  /*KVPB_MINIMALIZED*/
494