| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* vlv_srch.c */
- #include "back-ldbm.h"
- #include "vlv_srch.h"
- /* Attributes for vlvSearch */
- char* const type_vlvName = "cn";
- char* const type_vlvBase = "vlvBase";
- char* const type_vlvScope = "vlvScope";
- char* const type_vlvFilter = "vlvFilter";
- /* Attributes for vlvIndex */
- char* const type_vlvSort = "vlvSort";
- char* const type_vlvFilename = "vlvFilename";
- char* const type_vlvEnabled = "vlvEnabled";
- char* const type_vlvUses = "vlvUses";
- static const char *file_prefix= "vlv#"; /* '#' used to avoid collision with real attributes */
- static const char *file_suffix= LDBM_FILENAME_SUFFIX;
- static int vlvIndex_createfilename(struct vlvIndex* pIndex, char **ppc);
- static int vlvIndex_equal(const struct vlvIndex* p1, const sort_spec* sort_control);
- static void vlvIndex_checkforindex(struct vlvIndex* p, backend *be);
- /*
- * Create a new vlvSearch object
- */
- struct vlvSearch*
- vlvSearch_new()
- {
- struct vlvSearch* p = (struct vlvSearch*)slapi_ch_calloc(1,sizeof(struct vlvSearch));
- if(p!=NULL)
- {
- p->vlv_e= NULL;
- p->vlv_dn= NULL;
- p->vlv_name= NULL;
- p->vlv_base= NULL;
- p->vlv_scope= LDAP_SCOPE_BASE;
- p->vlv_filter= NULL;
- p->vlv_slapifilter= NULL;
- p->vlv_index= NULL;
- p->vlv_next= NULL;
- }
- return p;
- }
- /*
- * Trim spaces off the end of the string
- */
- static void
- trimspaces(char *s)
- {
- if (s) {
- PRUint32 i= strlen(s) - 1;
- while(i > 0 && isascii(s[i]) && isspace(s[i]))
- {
- s[i]= '\0';
- i--;
- }
- }
- }
- /*
- * Re-Initialise a vlvSearch object
- */
- void
- vlvSearch_reinit(struct vlvSearch* p, const struct backentry *base)
- {
- if (p->vlv_initialized) {
- return; /* no work to do */
- }
- if (LDAP_SCOPE_ONELEVEL != p->vlv_scope) {
- /* Only kind we re-init is onelevel searches */
- return;
- }
- /* Now down to work */
- if (NULL != p->vlv_slapifilter) {
- slapi_filter_free(p->vlv_slapifilter,1);
- }
- p->vlv_slapifilter= slapi_str2filter( p->vlv_filter );
- filter_normalize(p->vlv_slapifilter);
- /* make (&(parentid=idofbase)(|(originalfilter)(objectclass=referral))) */
- {
- Slapi_Filter *fid2kids= NULL;
- Slapi_Filter *focref= NULL;
- Slapi_Filter *fand= NULL;
- Slapi_Filter *forr= NULL;
- p->vlv_slapifilter= create_onelevel_filter(p->vlv_slapifilter, base, 0 /* managedsait */, &fid2kids, &focref, &fand, &forr);
- }
- }
- /*
- * Initialise a vlvSearch object
- */
- void
- vlvSearch_init(struct vlvSearch* p, Slapi_PBlock *pb, const Slapi_Entry *e, ldbm_instance *inst)
- {
- /* VLV specification */
- /* Need to copy the entry here because this one is in the cache,
- * not forever ! */
- p->vlv_e= slapi_entry_dup( e );
- p->vlv_dn= slapi_sdn_dup(slapi_entry_get_sdn_const(e));
- p->vlv_name= slapi_entry_attr_get_charptr(e,type_vlvName);
- p->vlv_base= slapi_sdn_new_dn_passin(slapi_entry_attr_get_charptr(e,type_vlvBase));
- p->vlv_scope= slapi_entry_attr_get_int(e,type_vlvScope);
- p->vlv_filter= slapi_entry_attr_get_charptr(e,type_vlvFilter);
- p->vlv_initialized = 1;
- /* JCM: Should perform some validation and report errors to the error log */
- /* JCM: Add brackets around the filter if none are there... */
- trimspaces(p->vlv_name);
- trimspaces(p->vlv_filter);
- if(strlen(p->vlv_filter)>0)
- {
- /* Convert the textual filter, into a Slapi_Filter structure */
- p->vlv_slapifilter= slapi_str2filter( p->vlv_filter );
- filter_normalize(p->vlv_slapifilter);
- }
- /* JCM: Really should convert the slapifilter into a string and use that. */
- /* Convert the filter based on the scope of the search */
- switch(p->vlv_scope)
- {
- case LDAP_SCOPE_BASE:
- /* Don't need to alter the filter */
- break;
- case LDAP_SCOPE_ONELEVEL:
- {
- /*
- * Get the base object for the search.
- * The entry "" will never be contained in the database,
- * so treat it as a special case.
- */
- struct backentry *e= NULL;
- if ( !slapi_sdn_isempty(p->vlv_base)) {
- Slapi_Backend *oldbe = NULL;
- entry_address addr;
- /* switch context to the target backend */
- slapi_pblock_get(pb, SLAPI_BACKEND, &oldbe);
- slapi_pblock_set(pb, SLAPI_BACKEND, inst->inst_be);
- slapi_pblock_set(pb, SLAPI_PLUGIN, inst->inst_be->be_database);
- addr.dn = (char*)slapi_sdn_get_ndn (p->vlv_base);
- addr.uniqueid = NULL;
- e = find_entry( pb, inst->inst_be, &addr, NULL );
- /* Check to see if the entry is absent. If it is, mark this search
- * as not initialized */
- if (NULL == e) {
- p->vlv_initialized = 0;
- /* We crash on anyhow, and rely on the fact that the filter
- * we create is bogus to prevent chaos */
- }
- /* switch context back to the DSE backend */
- slapi_pblock_set(pb, SLAPI_BACKEND, oldbe);
- slapi_pblock_set(pb, SLAPI_PLUGIN, oldbe->be_database);
- }
- /* make (&(parentid=idofbase)(|(originalfilter)(objectclass=referral))) */
- {
- Slapi_Filter *fid2kids= NULL;
- Slapi_Filter *focref= NULL;
- Slapi_Filter *fand= NULL;
- Slapi_Filter *forr= NULL;
- p->vlv_slapifilter= create_onelevel_filter(p->vlv_slapifilter, e, 0 /* managedsait */, &fid2kids, &focref, &fand, &forr);
- /* jcm: fid2kids, focref, fand, and forr get freed when we free p->vlv_slapifilter */
- cache_return(&inst->inst_cache,&e);
- }
- }
- break;
- case LDAP_SCOPE_SUBTREE:
- {
- /* make (|(originalfilter)(objectclass=referral))) */
- /* No need for scope-filter since we apply a scope test before the filter test */
- Slapi_Filter *focref= NULL;
- Slapi_Filter *forr= NULL;
- p->vlv_slapifilter= create_subtree_filter(p->vlv_slapifilter, 0 /* managedsait */, &focref, &forr);
- /* jcm: focref and forr get freed when we free p->vlv_slapifilter */
- }
- break;
- }
- }
- /*
- * Destroy an existing vlvSearch object
- */
- void
- vlvSearch_delete(struct vlvSearch** ppvs)
- {
- if(ppvs!=NULL && *ppvs!=NULL)
- {
- struct vlvIndex *pi, *ni;
- slapi_sdn_free(&((*ppvs)->vlv_dn));
- slapi_ch_free((void**)&((*ppvs)->vlv_name));
- slapi_sdn_free(&((*ppvs)->vlv_base));
- slapi_ch_free((void**)&((*ppvs)->vlv_filter));
- slapi_filter_free((*ppvs)->vlv_slapifilter,1);
- for(pi= (*ppvs)->vlv_index;pi!=NULL;)
- {
- ni= pi->vlv_next;
- if(pi->vlv_be != NULL) {
- vlvIndex_go_offline(pi,pi->vlv_be);
- }
- vlvIndex_delete(&pi);
- pi= ni;
- }
- slapi_ch_free((void**)ppvs);
- *ppvs= NULL;
- }
- }
- /*
- * Add a search to a list.
- *
- * We add it to the end of the list because there could
- * be other threads traversing the list at this time.
- */
- void
- vlvSearch_addtolist(struct vlvSearch* p, struct vlvSearch** pplist)
- {
- if(pplist!=NULL && p!=NULL)
- {
- p->vlv_next= NULL;
- if(*pplist==NULL)
- {
- *pplist= p;
- }
- else
- {
- struct vlvSearch* last= *pplist;
- for(;last->vlv_next!=NULL;last=last->vlv_next);
- last->vlv_next= p;
- }
- }
- }
- /*
- * Compare two VLV Searches to see if they're the same, based on their VLV Search specification.
- */
- static struct vlvIndex *
- vlvSearch_equal(const struct vlvSearch* p1, const Slapi_DN *base, int scope, const char *filter, const sort_spec* sort_control)
- {
- struct vlvIndex *pi= NULL;
- int r= (slapi_sdn_compare(p1->vlv_base,base)==0);
- if(r) r= (p1->vlv_scope==scope);
- if(r) r= (strcasecmp(p1->vlv_filter,filter)==0);
- if(r)
- {
- pi= p1->vlv_index;
- r= 0;
- for(;!r && pi!=NULL;)
- {
- r= vlvIndex_equal(pi, sort_control);
- if(!r)
- {
- pi= pi->vlv_next;
- }
- }
- }
- return pi;
- }
- /*
- * Find an enabled VLV Search in a list which matches the
- * description provided in "base, scope, filter, sort_control"
- */
- struct vlvIndex*
- vlvSearch_findenabled(backend *be,struct vlvSearch* plist, const Slapi_DN *base, int scope, const char *filter, const sort_spec* sort_control)
- {
- struct vlvSearch *t= plist;
- struct vlvIndex *pi= NULL;
- for(; (t!=NULL) && (pi == NULL); t= t->vlv_next)
- {
- pi= vlvSearch_equal(t,base,scope,filter,sort_control);
- if(pi!=NULL)
- {
- if(!vlvIndex_enabled(pi))
- {
- /*
- * A VLV Spec which matched the search criteria was found.
- * But it hasn't been enabled yet. Check to see if the
- * index is there. But, only check once every 60 seconds.
- */
- time_t curtime = current_time();
- if(curtime>pi->vlv_lastchecked+60)
- {
- vlvIndex_checkforindex(pi, be);
- pi->vlv_lastchecked= current_time();
- }
- }
- if(!vlvIndex_enabled(pi))
- {
- pi= NULL;
- }
- }
- }
- return pi;
- }
- /*
- * Find a VLV Search in a list which matches the name
- */
- struct vlvIndex*
- vlvSearch_findname(const struct vlvSearch* plist, const char *name)
- {
- const struct vlvSearch* t= plist;
- for(; t!=NULL ; t= t->vlv_next)
- {
- struct vlvIndex *pi= t->vlv_index;
- for(;pi!=NULL;pi= pi->vlv_next)
- {
- if(strcasecmp(pi->vlv_name,name)==0)
- {
- return pi;
- }
- }
- }
- return NULL;
- }
- /*
- * Find a VLV Search in a list which matches the index name
- */
- struct vlvIndex*
- vlvSearch_findindexname(const struct vlvSearch* plist, const char *name)
- {
- const struct vlvSearch* t= plist;
- for(; t!=NULL ; t= t->vlv_next)
- {
- struct vlvIndex *pi= t->vlv_index;
- for(;pi!=NULL;pi= pi->vlv_next)
- {
- if(strcasecmp(pi->vlv_attrinfo->ai_type,name)==0)
- {
- return pi;
- }
- }
- }
- return NULL;
- }
- /*
- * Get a list of VLV Index names.
- * The returned pointer must be freed with slapi_ch_free
- */
- char *
- vlvSearch_getnames(const struct vlvSearch* plist)
- {
- /* Work out how long the string will be */
- char *text;
- int length= 5; /* enough to hold 'none' */
- const struct vlvSearch* t= plist;
- for(; t!=NULL ; t= t->vlv_next)
- {
- struct vlvIndex *pi= t->vlv_index;
- for(;pi!=NULL;pi= pi->vlv_next)
- {
- length+= strlen(pi->vlv_name) + 4;
- }
- }
- /* Build a comma delimited list of Index names */
- text= slapi_ch_malloc(length);
- if(length==5)
- {
- strcpy(text,"none");
- }
- else
- {
- text[0]= '\0';
- t= plist;
- for(; t!=NULL ; t= t->vlv_next)
- {
- struct vlvIndex *pi= t->vlv_index;
- for(;pi!=NULL;pi= pi->vlv_next)
- {
- sprintf(text + strlen(text),"'%s', ",pi->vlv_name);
- }
- }
- }
- return text;
- }
- /*
- * Find a VLV Search in a list, based on the DN.
- */
- struct vlvSearch*
- vlvSearch_finddn(const struct vlvSearch* plist, const Slapi_DN *dn)
- {
- const struct vlvSearch* curr= plist;
- for(; curr!=NULL && slapi_sdn_compare(curr->vlv_dn,dn)!=0; curr= curr->vlv_next);
- return (struct vlvSearch*)curr;
- }
- /*
- * Remove a VLV Search from a list, based on the DN.
- */
- void
- vlvSearch_removefromlist(struct vlvSearch** pplist, const Slapi_DN *dn)
- {
- int done= 0;
- struct vlvSearch* prev= NULL;
- struct vlvSearch* curr= *pplist;
- while(curr!=NULL && !done)
- {
- if(slapi_sdn_compare(curr->vlv_dn,dn)==0)
- {
- if(curr==*pplist)
- {
- *pplist= curr->vlv_next;
- }
- else
- {
- prev->vlv_next= curr->vlv_next;
- }
- done= 1;
- }
- else
- {
- prev= curr;
- curr= curr->vlv_next;
- }
- }
- }
- /*
- * Access Control Check to see if the client is allowed to use this VLV Search.
- */
- int
- vlvSearch_accessallowed(struct vlvSearch *p, Slapi_PBlock *pb)
- {
- char *attrs[2] = { NULL, NULL};
- attrs[0] = type_vlvName;
- return (plugin_call_acl_plugin ( pb, (Slapi_Entry*)p->vlv_e, attrs, NULL,
- SLAPI_ACL_READ, ACLPLUGIN_ACCESS_READ_ON_VLV, NULL ) );
- }
- const Slapi_DN *vlvSearch_getBase(struct vlvSearch* p)
- {
- return p->vlv_base;
- }
- int vlvSearch_getScope(struct vlvSearch* p)
- {
- return p->vlv_scope;
- }
- Slapi_Filter *vlvSearch_getFilter(struct vlvSearch* p)
- {
- return p->vlv_slapifilter;
- }
- int vlvSearch_isVlvSearchEntry(Slapi_Entry *e)
- {
- return slapi_entry_attr_hasvalue(e, "objectclass", "vlvsearch");
- }
- void vlvSearch_addIndex(struct vlvSearch *pSearch, struct vlvIndex *pIndex)
- {
- pIndex->vlv_next= NULL;
- if(pSearch->vlv_index==NULL)
- {
- pSearch->vlv_index= pIndex;
- }
- else
- {
- struct vlvIndex* last= pSearch->vlv_index;
- for(;last->vlv_next!=NULL;last=last->vlv_next);
- last->vlv_next= pIndex;
- }
- }
- /* ============================================================================================== */
- /*
- * Create a new vlvIndex object
- */
- struct vlvIndex*
- vlvIndex_new()
- {
- struct vlvIndex* p = (struct vlvIndex*)slapi_ch_calloc(1,sizeof(struct vlvIndex));
- if(p!=NULL)
- {
- p->vlv_sortspec= NULL;
- p->vlv_attrinfo= attrinfo_new();
- p->vlv_sortkey= NULL;
- p->vlv_filename= NULL;
- p->vlv_mrpb= NULL;
- p->vlv_syntax_plugin= NULL;
- p->vlv_indexlength_lock= PR_NewLock();
- p->vlv_indexlength_cached= 0;
- p->vlv_indexlength= 0;
- p->vlv_online = 1;
- p->vlv_enabled = 0;
- p->vlv_lastchecked= 0;
- p->vlv_uses= 0;
- p->vlv_search= NULL;
- p->vlv_next= NULL;
- }
- return p;
- }
- /*
- * Destroy an existing vlvIndex object
- */
- void
- vlvIndex_delete(struct vlvIndex** ppvs)
- {
- if(ppvs!=NULL && *ppvs!=NULL)
- {
- slapi_ch_free((void**)&((*ppvs)->vlv_sortspec));
- {
- int n;
- for(n=0;(*ppvs)->vlv_sortkey[n]!=NULL;n++)
- {
- if((*ppvs)->vlv_mrpb[n] != NULL) {
- destroy_matchrule_indexer((*ppvs)->vlv_mrpb[n]);
- slapi_pblock_destroy((*ppvs)->vlv_mrpb[n]);
- }
- }
- }
- internal_ldap_free_sort_keylist((*ppvs)->vlv_sortkey);
- attrinfo_delete(&((*ppvs)->vlv_attrinfo));
- slapi_ch_free((void**)&((*ppvs)->vlv_name));
- slapi_ch_free((void**)&((*ppvs)->vlv_filename));
- slapi_ch_free((void**)&((*ppvs)->vlv_mrpb));
- slapi_ch_free((void**)&((*ppvs)->vlv_syntax_plugin));
- PR_DestroyLock((*ppvs)->vlv_indexlength_lock);
- slapi_ch_free((void**)ppvs);
- *ppvs= NULL;
- }
- }
- /*
- * Initialise a vlvSearch object
- */
- void
- vlvIndex_init(struct vlvIndex* p, backend *be, struct vlvSearch* pSearch, const Slapi_Entry *e)
- {
- struct ldbminfo *li = (struct ldbminfo *) be->be_database->plg_private;
- char *filename= NULL;
- if (NULL == p)
- return;
- /* JCM: Should perform some validation and report errors to the error log */
- /* JCM: Add brackets around the filter if none are there... */
- p->vlv_sortspec= slapi_entry_attr_get_charptr(e,type_vlvSort);
- trimspaces(p->vlv_sortspec);
- p->vlv_name= slapi_entry_attr_get_charptr(e,type_vlvName);
- trimspaces(p->vlv_name);
- p->vlv_search= pSearch;
- /* Convert the textual sort specification into a keylist structure */
- internal_ldap_create_sort_keylist(&(p->vlv_sortkey),p->vlv_sortspec);
- {
- /*
- * For each sort attribute find the appropriate syntax plugin,
- * and if it has a matching rule, create a matching rule indexer object.
- */
- int n;
- for(n=0;p->vlv_sortkey[n]!=NULL;n++);
- p->vlv_mrpb= (Slapi_PBlock**)slapi_ch_calloc(n+1,sizeof(Slapi_PBlock*));
- p->vlv_syntax_plugin= (void **)(Slapi_PBlock**)slapi_ch_calloc(n+1,sizeof(Slapi_PBlock*));
- for(n=0;p->vlv_sortkey[n]!=NULL;n++)
- {
- slapi_attr_type2plugin( p->vlv_sortkey[n]->sk_attrtype, &p->vlv_syntax_plugin[n] );
- if(p->vlv_sortkey[n]->sk_matchruleoid!=NULL)
- {
- create_matchrule_indexer(&p->vlv_mrpb[n],p->vlv_sortkey[n]->sk_matchruleoid,p->vlv_sortkey[n]->sk_attrtype);
- }
- }
- }
- /* Create an index filename for the search */
- if(vlvIndex_createfilename(p,&filename))
- {
- p->vlv_filename= slapi_ch_smprintf("%s%s%s",file_prefix,filename,file_suffix);
- /* Create an attrinfo structure */
- p->vlv_attrinfo->ai_type= slapi_ch_smprintf("%s%s",file_prefix,filename);
- p->vlv_attrinfo->ai_indexmask= INDEX_VLV;
- /* Check if the index file actually exists */
- if(li!=NULL)
- {
- vlvIndex_checkforindex(p, be);
- }
- p->vlv_lastchecked= current_time();
- }
- slapi_ch_free((void**)&filename);
- }
- /*
- * Determine how many {key,data} pairs there are in the VLV Index.
- * We only work out the length of the index once, then we cache
- * it and maintain it.
- */
- PRUint32
- vlvIndex_get_indexlength(struct vlvIndex* p, DB *db, back_txn *txn)
- {
- if (NULL == p)
- return 0;
- if(!p->vlv_indexlength_cached)
- {
- DBC *dbc = NULL;
- DB_TXN *db_txn = NULL;
- int err= 0;
- if (NULL != txn)
- {
- db_txn = txn->back_txn_txn;
- }
- err = db->cursor(db, db_txn, &dbc, 0);
- if(err==0)
- {
- DBT key= {0};
- DBT data= {0};
- key.flags= DB_DBT_MALLOC;
- data.flags= DB_DBT_MALLOC;
- err= dbc->c_get(dbc,&key,&data,DB_LAST);
- if(err==0)
- {
- slapi_ch_free(&(key.data));
- slapi_ch_free(&(data.data));
- err= dbc->c_get(dbc,&key,&data,DB_GET_RECNO);
- if(err==0)
- {
- PR_Lock(p->vlv_indexlength_lock);
- p->vlv_indexlength_cached= 1;
- p->vlv_indexlength= *((db_recno_t*)data.data);
- PR_Unlock(p->vlv_indexlength_lock);
- slapi_ch_free(&(data.data));
- }
- }
- dbc->c_close(dbc);
- }
- else
- {
- /* couldn't get cursor??? */
- }
- }
- return p->vlv_indexlength;
- }
- /*
- * Increment the index length count.
- * We keep track of the index length for efficiency.
- */
- void
- vlvIndex_increment_indexlength(struct vlvIndex* p, DB *db, back_txn *txn)
- {
- if (NULL == p)
- return;
- if(p->vlv_indexlength_cached)
- {
- PR_Lock(p->vlv_indexlength_lock);
- p->vlv_indexlength++;
- PR_Unlock(p->vlv_indexlength_lock);
- }
- else
- {
- p->vlv_indexlength= vlvIndex_get_indexlength(p, db, txn);
- }
- }
- /*
- * Decrement the index length count.
- * We keep track of the index length for efficiency.
- */
- void
- vlvIndex_decrement_indexlength(struct vlvIndex* p, DB *db, back_txn *txn)
- {
- if (NULL == p)
- return;
- if(p->vlv_indexlength_cached)
- {
- /* jcm: Check for underflow? */
- PR_Lock(p->vlv_indexlength_lock);
- p->vlv_indexlength--;
- PR_Unlock(p->vlv_indexlength_lock);
- }
- else
- {
- p->vlv_indexlength= vlvIndex_get_indexlength(p, db, txn);
- }
- }
- /*
- * Increment the usage counter
- */
- void
- vlvIndex_incrementUsage(struct vlvIndex* p)
- {
- if (NULL == p)
- return;
- p->vlv_uses++;
- }
- /*
- * Get the filename of the index.
- */
- const char *
- vlvIndex_filename(const struct vlvIndex* p)
- {
- if (NULL == p)
- return NULL;
- return p->vlv_filename;
- }
- /*
- * Check if the index is available.
- */
- int vlvIndex_enabled(const struct vlvIndex* p)
- {
- if (NULL == p)
- return 0;
- return p->vlv_enabled;
- }
- int vlvIndex_online(const struct vlvIndex *p)
- {
- if (NULL == p)
- return 0;
- return p->vlv_online;
- }
- void vlvIndex_go_offline(struct vlvIndex *p, backend *be)
- {
- if (NULL == p)
- return;
- p->vlv_online = 0;
- p->vlv_enabled = 0;
- p->vlv_indexlength = 0;
- p->vlv_attrinfo->ai_indexmask |= INDEX_OFFLINE;
- dblayer_erase_index_file_nolock(be, p->vlv_attrinfo, 1 /* chkpt if not busy */);
- }
- void vlvIndex_go_online(struct vlvIndex *p, backend *be)
- {
- if (NULL == p)
- return;
- p->vlv_attrinfo->ai_indexmask &= ~INDEX_OFFLINE;
- p->vlv_online = 1;
- vlvIndex_checkforindex(p, be);
- }
- /*
- * Access Control Check to see if the client is allowed to use this VLV Index.
- */
- int
- vlvIndex_accessallowed(struct vlvIndex *p, Slapi_PBlock *pb)
- {
- if (NULL == p)
- return 0;
- return vlvSearch_accessallowed(p->vlv_search, pb);
- }
- const Slapi_DN *vlvIndex_getBase(struct vlvIndex* p)
- {
- if (NULL == p)
- return NULL;
- return vlvSearch_getBase(p->vlv_search);
- }
- int vlvIndex_getScope(struct vlvIndex* p)
- {
- if (NULL == p)
- return 0;
- return vlvSearch_getScope(p->vlv_search);
- }
- Slapi_Filter *vlvIndex_getFilter(struct vlvIndex* p)
- {
- if (NULL == p)
- return NULL;
- return vlvSearch_getFilter(p->vlv_search);
- }
- const char *vlvIndex_getName(struct vlvIndex* p)
- {
- if (NULL == p)
- return NULL;
- return p->vlv_name;
- }
- /*
- * JCM: Could also match reverse sense of index and use in reverse.
- */
- static int
- vlvIndex_equal(const struct vlvIndex* p1, const sort_spec* sort_control)
- {
- int r= 1;
- const sort_spec *t1= sort_control;
- LDAPsortkey *t2= p1->vlv_sortkey[0];
- int n= 1;
- for(;t1!=NULL && t2!=NULL && r;t1= t1->next,t2=p1->vlv_sortkey[n],n++)
- {
- r= (t1->order && t2->sk_reverseorder) || (!t1->order && !t2->sk_reverseorder);
- if(r) r= (strcasecmp(t1->type, t2->sk_attrtype)==0);
- if(r)
- {
- if(t1->matchrule==NULL && t2->sk_matchruleoid==NULL)
- {
- r= 1;
- }
- else if(t1->matchrule!=NULL && t2->sk_matchruleoid!=NULL)
- {
- r= (strcasecmp(t1->matchrule, t2->sk_matchruleoid)==0);
- }
- else
- {
- r= 0;
- }
- }
- }
- if(r) r= (t1==NULL && t2==NULL);
- return r;
- }
- /*
- * Check if the index file actually exists,
- * and set vlv_enabled appropriately
- */
- static void
- vlvIndex_checkforindex(struct vlvIndex* p, backend *be)
- {
- DB *db = NULL;
- /* if the vlv index is offline (being generated), don't even look */
- if (! p->vlv_online)
- return;
- if (dblayer_get_index_file(be, p->vlv_attrinfo, &db, 0) == 0) {
- p->vlv_enabled = 1;
- dblayer_release_index_file( be, p->vlv_attrinfo, db );
- } else {
- p->vlv_enabled = 0;
- }
- }
- int vlvIndex_isVlvIndexEntry(Slapi_Entry *e)
- {
- return slapi_entry_attr_hasvalue(e, "objectclass", "vlvindex");
- }
- /*
- * Create the filename for the index.
- * Extract all the alphanumeric characters from the descriptive name.
- * Convert to all lower case.
- */
- static int
- vlvIndex_createfilename(struct vlvIndex* pIndex, char **ppc)
- {
- int filenameValid= 1;
- unsigned int i;
- char *p, *filename;
- filename= slapi_ch_malloc(strlen(pIndex->vlv_name) + 1);
- p= filename;
- for(i=0;i<strlen(pIndex->vlv_name);i++)
- {
- if(isalnum(pIndex->vlv_name[i]))
- {
- *p= TOLOWER( pIndex->vlv_name[i] );
- p++;
- }
- }
- *p= '\0';
- if(strlen(filename)==0)
- {
- LDAPDebug( LDAP_DEBUG_ANY, "Couldn't generate valid filename from Virtual List View Index Name (%s). Need some alphabetical characters.\n", pIndex->vlv_name, 0, 0);
- filenameValid= 0;
- }
- /* JCM: Check if this file clashes with another VLV Index filename */
- *ppc= filename;
- return filenameValid;
- }
- int
- vlv_isvlv(char *filename)
- {
- if (0 == strncmp(filename, file_prefix, 4))
- return 1;
- return 0;
- }
- void
- internal_ldap_free_sort_keylist(LDAPsortkey **sortKeyList)
- {
- #if defined(USE_OPENLDAP)
- ldap_free_sort_keylist((LDAPSortKey **)sortKeyList);
- #else
- ldap_free_sort_keylist(sortKeyList);
- #endif
- }
- int
- internal_ldap_create_sort_keylist(LDAPsortkey ***sortKeyList, const char *string_rep)
- {
- #if defined(USE_OPENLDAP)
- return ldap_create_sort_keylist((LDAPSortKey ***)sortKeyList, (char *)string_rep);
- #else
- return ldap_create_sort_keylist(sortKeyList, string_rep);
- #endif
- }
|