Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Joe Martin
OpenLDAP
Commits
bc05508d
Commit
bc05508d
authored
May 07, 2009
by
Quanah Gibson-Mount
Browse files
ITS#6095
parent
0643f060
Changes
6
Hide whitespace changes
Inline
Side-by-side
CHANGES
View file @
bc05508d
...
...
@@ -12,8 +12,9 @@ OpenLDAP 2.4.17 Engineering
Fixed slapd normalization of updated schema attributes (ITS#5540)
Fixed slapd pagedresults stacked control with overlays (ITS#6056)
Fixed slapd sockets usage on windows (ITS#6039)
Fixed slapd-bdb freeing of already freed entries (ITS#6074)
Fixed slapd-bdb entryinfo cleanup (ITS#6088)
Fixed slapd-hdb freeing of already freed entries (ITS#6074)
Fixed slapd-hdb entryinfo cleanup (ITS#6088)
Fixed slapd-hdb dncache lockups (ITS#6095)
Added slapo-rwm rwm-drop-unrequested-attrs config option (ITS#6057)
Fixed slapo-rwm dn passing (ITS#6070)
Fixed slapo-rwm entry free (ITS#6058)
...
...
servers/slapd/back-bdb/back-bdb.h
View file @
bc05508d
...
...
@@ -92,6 +92,7 @@ typedef struct bdb_entry_info {
#define CACHE_ENTRY_ONELEVEL 0x40
#define CACHE_ENTRY_REFERENCED 0x80
#define CACHE_ENTRY_NOT_CACHED 0x100
#define CACHE_ENTRY_PURGED 0x200
int
bei_finders
;
/*
...
...
servers/slapd/back-bdb/cache.c
View file @
bc05508d
...
...
@@ -94,10 +94,14 @@ bdb_cache_entryinfo_free( Cache *cache, EntryInfo *ei )
ei
->
bei_kids
=
NULL
;
ei
->
bei_lruprev
=
NULL
;
#if 0
ldap_pvt_thread_mutex_lock( &cache->c_eifree_mutex );
ei->bei_lrunext = cache->c_eifree;
cache->c_eifree = ei;
ldap_pvt_thread_mutex_unlock( &cache->c_eifree_mutex );
#else
ch_free
(
ei
);
#endif
}
#define LRU_DEL( c, e ) do { \
...
...
@@ -334,8 +338,8 @@ bdb_entryinfo_add_internal(
ei2
=
bdb_cache_entryinfo_new
(
&
bdb
->
bi_cache
);
ldap_pvt_thread_rdwr_wlock
(
&
bdb
->
bi_cache
.
c_rwlock
);
bdb_cache_entryinfo_lock
(
ei
->
bei_parent
);
ldap_pvt_thread_rdwr_wlock
(
&
bdb
->
bi_cache
.
c_rwlock
);
ei2
->
bei_id
=
ei
->
bei_id
;
ei2
->
bei_parent
=
ei
->
bei_parent
;
...
...
@@ -372,13 +376,11 @@ bdb_entryinfo_add_internal(
bdb
->
bi_cache
.
c_leaves
++
;
rc
=
avl_insert
(
&
ei
->
bei_parent
->
bei_kids
,
ei2
,
bdb_rdn_cmp
,
avl_dup_error
);
if
(
rc
)
{
/* This should never happen; entry cache is corrupt */
bdb
->
bi_dbenv
->
log_flush
(
bdb
->
bi_dbenv
,
NULL
);
assert
(
!
rc
);
}
#ifdef BDB_HIER
ei
->
bei_parent
->
bei_ckids
++
;
/* it's possible for hdb_cache_find_parent to beat us to it */
if
(
!
rc
)
{
ei
->
bei_parent
->
bei_ckids
++
;
}
#endif
}
...
...
@@ -443,6 +445,7 @@ bdb_cache_find_ndn(
ei
.
bei_nrdn
.
bv_len
=
ndn
->
bv_len
-
(
ei
.
bei_nrdn
.
bv_val
-
ndn
->
bv_val
);
eip
->
bei_finders
++
;
bdb_cache_entryinfo_unlock
(
eip
);
BDB_LOG_PRINTF
(
bdb
->
bi_dbenv
,
NULL
,
"slapd Reading %s"
,
...
...
@@ -452,6 +455,7 @@ bdb_cache_find_ndn(
rc
=
bdb_dn2id
(
op
,
&
ei
.
bei_nrdn
,
&
ei
,
txn
,
&
lock
);
if
(
rc
)
{
bdb_cache_entryinfo_lock
(
eip
);
eip
->
bei_finders
--
;
bdb_cache_entry_db_unlock
(
bdb
,
&
lock
);
*
res
=
eip
;
return
rc
;
...
...
@@ -464,6 +468,7 @@ bdb_cache_find_ndn(
ei
.
bei_nrdn
.
bv_len
=
len
;
rc
=
bdb_entryinfo_add_internal
(
bdb
,
&
ei
,
&
ei2
);
/* add_internal left eip and c_rwlock locked */
eip
->
bei_finders
--
;
ldap_pvt_thread_rdwr_wunlock
(
&
bdb
->
bi_cache
.
c_rwlock
);
bdb_cache_entry_db_unlock
(
bdb
,
&
lock
);
if
(
rc
)
{
...
...
@@ -480,8 +485,8 @@ bdb_cache_find_ndn(
*
res
=
eip
;
return
DB_NOTFOUND
;
}
bdb_cache_entryinfo_unlock
(
eip
);
bdb_cache_entryinfo_lock
(
ei2
);
bdb_cache_entryinfo_unlock
(
eip
);
eip
=
ei2
;
...
...
@@ -515,7 +520,7 @@ hdb_cache_find_parent(
{
struct
bdb_info
*
bdb
=
(
struct
bdb_info
*
)
op
->
o_bd
->
be_private
;
EntryInfo
ei
,
eip
,
*
ei2
=
NULL
,
*
ein
=
NULL
,
*
eir
=
NULL
;
int
rc
;
int
rc
,
add
;
ei
.
bei_id
=
id
;
ei
.
bei_kids
=
NULL
;
...
...
@@ -539,36 +544,53 @@ hdb_cache_find_parent(
ein
->
bei_bdb
=
bdb
;
#endif
ei
.
bei_ckids
=
0
;
add
=
1
;
/* This node is not fully connected yet */
ein
->
bei_state
|=
CACHE_ENTRY_NOT_LINKED
;
/* If this is the first time, save this node
* to be returned later.
*/
if
(
eir
==
NULL
)
{
eir
=
ein
;
ein
->
bei_finders
++
;
}
again:
/* Insert this node into the ID tree */
ldap_pvt_thread_rdwr_wlock
(
&
bdb
->
bi_cache
.
c_rwlock
);
if
(
avl_insert
(
&
bdb
->
bi_cache
.
c_idtree
,
(
caddr_t
)
ein
,
bdb_id_cmp
,
bdb_id_dup_err
)
)
{
EntryInfo
*
eix
=
ein
->
bei_lrunext
;
if
(
eix
->
bei_state
&
(
CACHE_ENTRY_PURGED
|
CACHE_ENTRY_DELETED
)
)
{
ldap_pvt_thread_rdwr_wunlock
(
&
bdb
->
bi_cache
.
c_rwlock
);
ldap_pvt_thread_yield
();
goto
again
;
}
ldap_pvt_thread_rdwr_wunlock
(
&
bdb
->
bi_cache
.
c_rwlock
);
/* Someone else created this node just before us.
* Free our new copy and use the existing one.
*/
bdb_cache_entryinfo_free
(
&
bdb
->
bi_cache
,
ein
);
ein
=
eix
;
/* Link in any kids we've already processed */
if
(
ei2
)
{
bdb_cache_entryinfo_lock
(
ein
);
avl_insert
(
&
ein
->
bei_kids
,
(
caddr_t
)
ei2
,
bdb_rdn_cmp
,
avl_dup_error
);
ein
->
bei_ckids
++
;
bdb_cache_entryinfo_unlock
(
ein
);
/* if it was the node we were looking for, just return it */
if
(
eir
==
ein
)
{
*
res
=
eix
;
rc
=
0
;
bdb_cache_entryinfo_lock
(
eix
);
break
;
}
}
/* If this is the first time, save this node
* to be returned later.
*/
if
(
eir
==
NULL
)
eir
=
ein
;
ein
=
ei2
;
ei2
=
eix
;
add
=
0
;
/* otherwise, link up what we have and return */
goto
gotparent
;
}
/* If there was a previous node, link it to this one */
if
(
ei2
)
ei2
->
bei_parent
=
ein
;
...
...
@@ -577,23 +599,29 @@ hdb_cache_find_parent(
if
(
eip
.
bei_id
)
{
ei2
=
(
EntryInfo
*
)
avl_find
(
bdb
->
bi_cache
.
c_idtree
,
(
caddr_t
)
&
eip
,
bdb_id_cmp
);
if
(
ei2
&&
(
ei2
->
bei_state
&
(
CACHE_ENTRY_PURGED
|
CACHE_ENTRY_DELETED
)))
{
ei2
=
NULL
;
}
}
else
{
ei2
=
&
bdb
->
bi_cache
.
c_dntree
;
}
bdb
->
bi_cache
.
c_eiused
++
;
if
(
ei2
&&
(
ei2
->
bei_kids
||
!
ei2
->
bei_id
))
if
(
add
)
{
bdb
->
bi_cache
.
c_eiused
++
;
if
(
ei2
&&
(
ei2
->
bei_kids
||
!
ei2
->
bei_id
))
bdb
->
bi_cache
.
c_leaves
++
;
}
ldap_pvt_thread_rdwr_wunlock
(
&
bdb
->
bi_cache
.
c_rwlock
);
gotparent:
/* Got the parent, link in and we're done. */
if
(
ei2
)
{
bdb_cache_entryinfo_lock
(
eir
);
bdb_cache_entryinfo_lock
(
ei2
);
bdb_cache_entryinfo_lock
(
eir
);
ein
->
bei_parent
=
ei2
;
avl_insert
(
&
ei2
->
bei_kids
,
(
caddr_t
)
ein
,
bdb_rdn_cmp
,
avl_dup_error
)
;
ei2
->
bei_ckids
++
;
if
(
avl_insert
(
&
ei2
->
bei_kids
,
(
caddr_t
)
ein
,
bdb_rdn_cmp
,
avl_dup_error
)
==
0
)
ei2
->
bei_ckids
++
;
/* Reset all the state info */
for
(
ein
=
eir
;
ein
!=
ei2
;
ein
=
ein
->
bei_parent
)
...
...
@@ -724,12 +752,18 @@ bdb_cache_lru_purge( struct bdb_info *bdb )
* or this node is being deleted, skip it.
*/
if
((
elru
->
bei_state
&
(
CACHE_ENTRY_NOT_LINKED
|
CACHE_ENTRY_DELETED
|
CACHE_ENTRY_LOADING
))
||
CACHE_ENTRY_DELETED
|
CACHE_ENTRY_LOADING
|
CACHE_ENTRY_ONELEVEL
))
||
elru
->
bei_finders
>
0
)
{
bdb_cache_entryinfo_unlock
(
elru
);
goto
bottom
;
}
if
(
bdb_cache_entryinfo_trylock
(
elru
->
bei_parent
))
{
bdb_cache_entryinfo_unlock
(
elru
);
goto
bottom
;
}
/* entryinfo is locked */
islocked
=
1
;
...
...
@@ -782,20 +816,13 @@ bdb_cache_lru_purge( struct bdb_info *bdb )
}
next:
if
(
islocked
)
if
(
islocked
)
{
bdb_cache_entryinfo_unlock
(
elru
);
bdb_cache_entryinfo_unlock
(
elru
->
bei_parent
);
}
if
(
count
>=
efree
&&
eicount
>=
eifree
)
{
if
(
count
||
ecount
>
bdb
->
bi_cache
.
c_cursize
)
{
ldap_pvt_thread_mutex_lock
(
&
bdb
->
bi_cache
.
c_count_mutex
);
/* HACK: we seem to be losing track, fix up now */
if
(
ecount
>
bdb
->
bi_cache
.
c_cursize
)
bdb
->
bi_cache
.
c_cursize
=
ecount
;
bdb
->
bi_cache
.
c_cursize
-=
count
;
ldap_pvt_thread_mutex_unlock
(
&
bdb
->
bi_cache
.
c_count_mutex
);
}
if
(
count
>=
efree
&&
eicount
>=
eifree
)
break
;
}
bottom:
if
(
elnext
==
bdb
->
bi_cache
.
c_lruhead
)
break
;
...
...
@@ -804,28 +831,19 @@ bottom:
#endif
}
if
(
count
||
ecount
>
bdb
->
bi_cache
.
c_cursize
)
{
ldap_pvt_thread_mutex_lock
(
&
bdb
->
bi_cache
.
c_count_mutex
);
/* HACK: we seem to be losing track, fix up now */
if
(
ecount
>
bdb
->
bi_cache
.
c_cursize
)
bdb
->
bi_cache
.
c_cursize
=
ecount
;
bdb
->
bi_cache
.
c_cursize
-=
count
;
ldap_pvt_thread_mutex_unlock
(
&
bdb
->
bi_cache
.
c_count_mutex
);
}
bdb
->
bi_cache
.
c_lruhead
=
elnext
;
ldap_pvt_thread_mutex_unlock
(
&
bdb
->
bi_cache
.
c_lru_mutex
);
bdb
->
bi_cache
.
c_purging
=
0
;
}
EntryInfo
*
bdb_cache_find_info
(
struct
bdb_info
*
bdb
,
ID
id
)
{
EntryInfo
ei
=
{
0
},
*
ei2
;
ei
.
bei_id
=
id
;
ldap_pvt_thread_rdwr_rlock
(
&
bdb
->
bi_cache
.
c_rwlock
);
ei2
=
(
EntryInfo
*
)
avl_find
(
bdb
->
bi_cache
.
c_idtree
,
(
caddr_t
)
&
ei
,
bdb_id_cmp
);
ldap_pvt_thread_rdwr_runlock
(
&
bdb
->
bi_cache
.
c_rwlock
);
return
ei2
;
}
/*
* cache_find_id - find an entry in the cache, given id.
* The entry is locked for Read upon return. Call with flag ID_LOCKED if
...
...
@@ -859,11 +877,12 @@ again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
if
(
*
eip
)
{
/* If the lock attempt fails, the info is in use */
if
(
bdb_cache_entryinfo_trylock
(
*
eip
))
{
int
del
=
(
*
eip
)
->
bei_state
&
CACHE_ENTRY_DELETED
;
ldap_pvt_thread_rdwr_runlock
(
&
bdb
->
bi_cache
.
c_rwlock
);
/* If this node is being deleted, treat
* as if the delete has already finished
*/
if
(
(
*
eip
)
->
bei_state
&
CACHE_ENTRY_DELETED
)
{
if
(
del
)
{
return
DB_NOTFOUND
;
}
/* otherwise, wait for the info to free up */
...
...
@@ -920,6 +939,10 @@ again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
}
else
{
(
*
eip
)
->
bei_finders
++
;
(
*
eip
)
->
bei_state
|=
CACHE_ENTRY_REFERENCED
;
if
(
flag
&
ID_NOENTRY
)
{
bdb_cache_entryinfo_unlock
(
*
eip
);
return
0
;
}
/* Make sure only one thread tries to load the entry */
load1:
#ifdef SLAP_ZONE_ALLOC
...
...
@@ -961,6 +984,8 @@ load1:
if
(
rc
==
0
)
{
ep
->
e_private
=
*
eip
;
#ifdef BDB_HIER
while
(
(
*
eip
)
->
bei_state
&
CACHE_ENTRY_NOT_LINKED
)
ldap_pvt_thread_yield
();
bdb_fix_dn
(
ep
,
0
);
#endif
(
*
eip
)
->
bei_e
=
ep
;
...
...
@@ -1037,7 +1062,7 @@ load1:
bdb
->
bi_cache
.
c_leaves
>
bdb
->
bi_cache
.
c_eimax
)
{
ldap_pvt_thread_mutex_lock
(
&
bdb
->
bi_cache
.
c_count_mutex
);
if
(
!
bdb
->
bi_cache
.
c_purging
)
{
if
(
!
(
flag
&
ID_NOCACHE
))
{
if
(
load
&&
!
(
flag
&
ID_NOCACHE
))
{
bdb
->
bi_cache
.
c_cursize
++
;
if
(
bdb
->
bi_cache
.
c_cursize
>
bdb
->
bi_cache
.
c_maxsize
)
{
purge
=
1
;
...
...
@@ -1124,6 +1149,12 @@ bdb_cache_add(
if
(
eip
->
bei_dkids
)
eip
->
bei_dkids
++
;
#endif
if
(
eip
->
bei_parent
)
{
bdb_cache_entryinfo_lock
(
eip
->
bei_parent
);
eip
->
bei_parent
->
bei_state
&=
~
CACHE_ENTRY_NO_GRANDKIDS
;
bdb_cache_entryinfo_unlock
(
eip
->
bei_parent
);
}
rc
=
bdb_entryinfo_add_internal
(
bdb
,
&
ei
,
&
new
);
/* bdb_csn_commit can cause this when adding the database root entry */
if
(
new
->
bei_e
)
{
...
...
@@ -1138,9 +1169,6 @@ bdb_cache_add(
e
->
e_private
=
new
;
new
->
bei_state
|=
CACHE_ENTRY_NO_KIDS
|
CACHE_ENTRY_NO_GRANDKIDS
;
eip
->
bei_state
&=
~
CACHE_ENTRY_NO_KIDS
;
if
(
eip
->
bei_parent
)
{
eip
->
bei_parent
->
bei_state
&=
~
CACHE_ENTRY_NO_GRANDKIDS
;
}
bdb_cache_entryinfo_unlock
(
eip
);
ldap_pvt_thread_rdwr_wunlock
(
&
bdb
->
bi_cache
.
c_rwlock
);
...
...
@@ -1320,8 +1348,10 @@ bdb_cache_delete(
/* Get write lock on the data */
rc
=
bdb_cache_entry_db_relock
(
bdb
,
txn
,
ei
,
1
,
0
,
lock
);
if
(
rc
)
{
bdb_cache_entryinfo_lock
(
ei
);
/* couldn't lock, undo and give up */
ei
->
bei_state
^=
CACHE_ENTRY_DELETED
;
bdb_cache_entryinfo_unlock
(
ei
);
return
rc
;
}
...
...
@@ -1331,7 +1361,10 @@ bdb_cache_delete(
/* set lru mutex */
ldap_pvt_thread_mutex_lock
(
&
bdb
->
bi_cache
.
c_lru_mutex
);
bdb_cache_entryinfo_lock
(
ei
->
bei_parent
);
bdb_cache_entryinfo_lock
(
ei
);
rc
=
bdb_cache_delete_internal
(
&
bdb
->
bi_cache
,
e
->
e_private
,
1
);
bdb_cache_entryinfo_unlock
(
ei
);
/* free lru mutex */
ldap_pvt_thread_mutex_unlock
(
&
bdb
->
bi_cache
.
c_lru_mutex
);
...
...
@@ -1373,11 +1406,12 @@ bdb_cache_delete_internal(
int
decr_leaf
=
0
;
/* already freed? */
if
(
!
e
->
bei_parent
)
if
(
!
e
->
bei_parent
)
{
assert
(
0
);
return
-
1
;
}
/* Lock the parent's kids tree */
bdb_cache_entryinfo_lock
(
e
->
bei_parent
);
e
->
bei_state
|=
CACHE_ENTRY_PURGED
;
#ifdef BDB_HIER
e
->
bei_parent
->
bei_ckids
--
;
...
...
@@ -1388,12 +1422,11 @@ bdb_cache_delete_internal(
==
NULL
)
{
rc
=
-
1
;
assert
(
0
);
}
if
(
e
->
bei_parent
->
bei_kids
)
decr_leaf
=
1
;
bdb_cache_entryinfo_unlock
(
e
->
bei_parent
);
ldap_pvt_thread_rdwr_wlock
(
&
cache
->
c_rwlock
);
/* id tree */
if
(
avl_delete
(
&
cache
->
c_idtree
,
(
caddr_t
)
e
,
bdb_id_cmp
))
{
...
...
@@ -1402,8 +1435,10 @@ bdb_cache_delete_internal(
cache
->
c_leaves
--
;
}
else
{
rc
=
-
1
;
assert
(
0
);
}
ldap_pvt_thread_rdwr_wunlock
(
&
cache
->
c_rwlock
);
bdb_cache_entryinfo_unlock
(
e
->
bei_parent
);
if
(
rc
==
0
){
/* lru */
...
...
servers/slapd/back-bdb/dn2id.c
View file @
bc05508d
...
...
@@ -1102,7 +1102,7 @@ hdb_dn2idl_internal(
cx
->
rc
=
cx
->
dbc
->
c_close
(
cx
->
dbc
);
done_one:
bdb_cache_entryinfo_lock
(
cx
->
ei
);
cx
->
ei
->
bei_state
^
=
CACHE_ENTRY_ONELEVEL
;
cx
->
ei
->
bei_state
&
=
~
CACHE_ENTRY_ONELEVEL
;
bdb_cache_entryinfo_unlock
(
cx
->
ei
);
if
(
cx
->
rc
)
return
cx
->
rc
;
...
...
@@ -1151,15 +1151,23 @@ gotit:
for
(
cx
->
id
=
bdb_idl_first
(
save
,
&
idcurs
);
cx
->
id
!=
NOID
;
cx
->
id
=
bdb_idl_next
(
save
,
&
idcurs
))
{
cx
->
ei
=
bdb_cache_find_info
(
cx
->
bdb
,
cx
->
id
);
EntryInfo
*
ei2
;
cx
->
ei
=
NULL
;
if
(
bdb_cache_find_id
(
cx
->
op
,
cx
->
txn
,
cx
->
id
,
&
cx
->
ei
,
ID_NOENTRY
,
NULL
))
continue
;
if
(
!
cx
->
ei
||
(
cx
->
ei
->
bei_state
&
CACHE_ENTRY_NO_KIDS
))
continue
;
ei2
=
cx
->
ei
;
BDB_ID2DISK
(
cx
->
id
,
&
cx
->
nid
);
hdb_dn2idl_internal
(
cx
);
if
(
!
BDB_IDL_IS_ZERO
(
cx
->
tmp
))
nokids
=
0
;
bdb_cache_entryinfo_lock
(
ei2
);
ei2
->
bei_finders
--
;
bdb_cache_entryinfo_unlock
(
ei2
);
}
cx
->
depth
--
;
cx
->
op
->
o_tmpfree
(
save
,
cx
->
op
->
o_tmpmemctx
);
...
...
servers/slapd/back-bdb/proto-bdb.h
View file @
bc05508d
...
...
@@ -501,7 +501,6 @@ void bdb_unlocked_cache_return_entry_rw( struct bdb_info *bdb, Entry *e, int rw
#define bdb_cache_delete BDB_SYMBOL(cache_delete)
#define bdb_cache_delete_cleanup BDB_SYMBOL(cache_delete_cleanup)
#define bdb_cache_find_id BDB_SYMBOL(cache_find_id)
#define bdb_cache_find_info BDB_SYMBOL(cache_find_info)
#define bdb_cache_find_ndn BDB_SYMBOL(cache_find_ndn)
#define bdb_cache_find_parent BDB_SYMBOL(cache_find_parent)
#define bdb_cache_modify BDB_SYMBOL(cache_modify)
...
...
@@ -544,13 +543,10 @@ int bdb_cache_find_ndn(
struct
berval
*
ndn
,
EntryInfo
**
res
);
EntryInfo
*
bdb_cache_find_info
(
struct
bdb_info
*
bdb
,
ID
id
);
#define ID_LOCKED 1
#define ID_NOCACHE 2
#define ID_NOENTRY 4
int
bdb_cache_find_id
(
Operation
*
op
,
DB_TXN
*
tid
,
...
...
servers/slapd/back-bdb/search.c
View file @
bc05508d
...
...
@@ -569,10 +569,6 @@ dn2entry_retry:
#ifdef SLAP_ZONE_ALLOC
slap_zn_runlock
(
bdb
->
bi_cache
.
c_zctx
,
e
);
#endif
if
(
e
!=
e_root
)
{
bdb_cache_return_entry_r
(
bdb
,
e
,
&
lock
);
}
e
=
NULL
;
/* select candidates */
if
(
op
->
oq_search
.
rs_scope
==
LDAP_SCOPE_BASE
)
{
...
...
@@ -595,6 +591,11 @@ cand_retry:
}
}
if
(
e
!=
e_root
)
{
bdb_cache_return_entry_r
(
bdb
,
e
,
&
lock
);
}
e
=
NULL
;
/* start cursor at beginning of candidates.
*/
cursor
=
0
;
...
...
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