cdb_next_item() now returns both key and value
authorArt Cancro <ajc@citadel.org>
Wed, 23 Aug 2023 14:17:28 +0000 (05:17 -0900)
committerArt Cancro <ajc@citadel.org>
Wed, 23 Aug 2023 14:17:28 +0000 (05:17 -0900)
citadel/server/backends/berkeley_db/berkeley_db.c
citadel/server/control.c
citadel/server/database.c
citadel/server/database.h
citadel/server/modules/ctdlproto/serv_rooms.c
citadel/server/modules/ctdlproto/serv_user.c
citadel/server/modules/expire/serv_expire.c
citadel/server/modules/imap/imap_acl.c
citadel/server/room_ops.c
citadel/server/server.h
citadel/server/user_ops.c

index 2c118ce2ba00cf57e872d4ec9645823fee41fcc2..a55c6113a2df523a69ccaf8be1edc855e98f53cb 100644 (file)
@@ -599,11 +599,11 @@ void bdb_rewind(int cdb) {
 
 // Fetch the next item in a sequential search.  Returns a pointer to a 
 // cdbdata structure, or NULL if we've hit the end.
-struct cdbdata bdb_next_item(int cdb) {
-       struct cdbdata cdbret;
+struct cdbkeyval bdb_next_item(int cdb) {
+       struct cdbkeyval kv;
        int ret = 0;
 
-       memset(&cdbret, 0, sizeof(struct cdbdata));
+       memset(&kv, 0, sizeof(struct cdbkeyval));
 
        // reuse memory from the previous call.
        TSD->dbkey[cdb].flags = DB_DBT_MALLOC;
@@ -617,15 +617,16 @@ struct cdbdata bdb_next_item(int cdb) {
                        bdb_abort();
                }
                bdb_close_cursor(cdb);
-               return(cdbret);         // presumably, we are at the end
+               return(kv);             // presumably, we are at the end
        }
 
        bdb_decompress_if_necessary(&TSD->dbdata[cdb]);
 
-       cdbret.len = TSD->dbdata[cdb].size;
-       cdbret.ptr = TSD->dbdata[cdb].data;
-
-       return (cdbret);
+       kv.key.len = TSD->dbkey[cdb].size;
+       kv.key.ptr = TSD->dbkey[cdb].data;
+       kv.val.len = TSD->dbdata[cdb].size;
+       kv.val.ptr = TSD->dbdata[cdb].data;
+       return (kv);
 }
 
 
index ff3cccaa0de11fcc7584760186a04f07dc6ea409..b6e4d88bea0757699e4d774de376ef1e19f77f60 100644 (file)
@@ -639,18 +639,18 @@ void cmd_conf(char *argbuf) {
 
        // CONF LISTVAL - list configuration variables in the database and their values
        else if (!strcasecmp(cmd, "LISTVAL")) {
-               struct cdbdata cdbcfg;
+               struct cdbkeyval cdbcfg;
                int keylen = 0;
                char *key = NULL;
                char *value = NULL;
        
                cprintf("%d all configuration variables\n", LISTING_FOLLOWS);
                cdb_rewind(CDB_CONFIG);
-               while (cdbcfg = cdb_next_item(CDB_CONFIG), cdbcfg.ptr!=NULL) {
-                       if (cdbcfg.len < 1020) {
-                               keylen = strlen(cdbcfg.ptr);
-                               key = cdbcfg.ptr;
-                               value = cdbcfg.ptr + keylen + 1;
+               while (cdbcfg = cdb_next_item(CDB_CONFIG), cdbcfg.val.ptr!=NULL) {
+                       if (cdbcfg.val.len < 1020) {
+                               keylen = strlen(cdbcfg.val.ptr);
+                               key = cdbcfg.val.ptr;
+                               value = cdbcfg.val.ptr + keylen + 1;
                                cprintf("%s|%s\n", key, value);
                        }
                }
index 9f31ad074f7bb0892daf341f9f98e0c04bbb0c4a..2e7717d039e3a17576087f171197367dd549c496 100644 (file)
@@ -27,7 +27,7 @@ void                  (*cdb_close_databases)(void)                            = NULL;
 struct cdbdata                 (*cdb_fetch)(int, const void *, int)                    = NULL;
 int                    (*cdb_store)(int, const void *, int, void *, int)       = NULL;
 int                    (*cdb_delete)(int, void *, int)                         = NULL;
-struct cdbdata         (*cdb_next_item)(int)                                   = NULL;
+struct cdbkeyval       (*cdb_next_item)(int)                                   = NULL;
 void                   (*cdb_close_cursor)(int)                                = NULL;
 void                   (*cdb_begin_transaction)(void)                          = NULL;
 void                   (*cdb_end_transaction)(void)                            = NULL;
index bcf3da5bafec4228e53bae87d05582a0511f47c5..ed72f55d131c3be66fc8200b831bc8927e0a7862 100644 (file)
@@ -13,7 +13,7 @@ extern void           (*cdb_open_databases)(void);
 extern void            (*cdb_close_databases)(void);
 extern int             (*cdb_store)(int, const void *, int, void *, int);
 extern int             (*cdb_delete)(int, void *, int);
-extern struct cdbdata  (*cdb_next_item)(int);
+extern struct cdbkeyval        (*cdb_next_item)(int);
 extern void            (*cdb_close_cursor)(int);
 extern void            (*cdb_begin_transaction)(void);
 extern void            (*cdb_end_transaction)(void);
index c57395a78252806bb63d29f229d47dec20428be8..29f57c8883241bd84e6d0ae71c22ae4a2efaa266 100644 (file)
@@ -322,21 +322,18 @@ void cmd_goto(char *gargs) {
 
 void cmd_whok(char *cmdbuf) {
        struct ctdluser temp;
-       struct cdbdata cdbus;
+       struct cdbkeyval cdbus;
        int ra;
 
        cprintf("%d Who knows room:\n", LISTING_FOLLOWS);
        cdb_rewind(CDB_USERS);
-       while (cdbus = cdb_next_item(CDB_USERS), cdbus.ptr!=NULL) {
+       while (cdbus = cdb_next_item(CDB_USERS), cdbus.val.ptr!=NULL) {
                memset(&temp, 0, sizeof temp);
-               memcpy(&temp, cdbus.ptr, sizeof temp);
-
+               memcpy(&temp, cdbus.val.ptr, sizeof temp);
                CtdlRoomAccess(&CC->room, &temp, &ra, NULL);
-               if ((!IsEmptyStr(temp.fullname)) && 
-                   (CC->room.QRflags & QR_INUSE) &&
-                   (ra & UA_KNOWN)
-                       )
+               if ((!IsEmptyStr(temp.fullname)) && (CC->room.QRflags & QR_INUSE) && (ra & UA_KNOWN)) {
                        cprintf("%s\n", temp.fullname);
+               }
        }
        cprintf("000\n");
 }
index 3b356ed4c6498ab07671d61fb079373a42b1d8d7..65e2bd47f744045671eea6e1576be0eca63c8a77 100644 (file)
@@ -381,7 +381,7 @@ void cmd_forg(char *argbuf) {
 
 // Get Next Unregistered User
 void cmd_gnur(char *argbuf) {
-       struct cdbdata cdbus;
+       struct cdbkeyval cdbus;
        struct ctdluser usbuf;
 
        if (CtdlAccessCheck(ac_aide)) {
@@ -395,9 +395,9 @@ void cmd_gnur(char *argbuf) {
 
        // There are unvalidated users.  Traverse the user database, and return the first user we find that needs validation.
        cdb_rewind(CDB_USERS);
-       while (cdbus = cdb_next_item(CDB_USERS), cdbus.ptr!=NULL) {
+       while (cdbus = cdb_next_item(CDB_USERS), cdbus.val.ptr!=NULL) {
                memset(&usbuf, 0, sizeof(struct ctdluser));
-               memcpy(&usbuf, cdbus.ptr, ((cdbus.len > sizeof(struct ctdluser)) ?  sizeof(struct ctdluser) : cdbus.len));
+               memcpy(&usbuf, cdbus.val.ptr, ((cdbus.val.len > sizeof(struct ctdluser)) ? sizeof(struct ctdluser) : cdbus.val.len));
                if ((usbuf.flags & US_NEEDVALID) && (usbuf.axlevel > AxDeleted)) {
                        cprintf("%d %s\n", MORE_DATA, usbuf.fullname);
                        cdb_close_cursor(CDB_USERS);
index 20ac197ddd9c4a33fc712256eab4235d0a694c85..876edc9fa4c8b167ee1960be256ce246a2d2e390 100644 (file)
@@ -486,7 +486,7 @@ int PurgeUsers(void) {
 // record is useless and should be removed.)
 //
 int PurgeVisits(void) {
-       struct cdbdata cdbvisit;
+       struct cdbkeyval cdbvisit;
        struct visit vbuf;
        struct VPurgeList *VisitPurgeList = NULL;
        struct VPurgeList *vptr;
@@ -505,32 +505,29 @@ int PurgeVisits(void) {
 
        // Now traverse through the visits, purging irrelevant records...
        cdb_rewind(CDB_VISIT);
-       while(cdbvisit = cdb_next_item(CDB_VISIT), cdbvisit.ptr!=NULL) {
+       while(cdbvisit = cdb_next_item(CDB_VISIT), cdbvisit.val.ptr!=NULL) {
                memset(&vbuf, 0, sizeof(struct visit));
-               memcpy(&vbuf, cdbvisit.ptr,
-                       ( (cdbvisit.len > sizeof(struct visit)) ?
-                         sizeof(struct visit) : cdbvisit.len) );
-
+               memcpy(&vbuf, cdbvisit.val.ptr, ((cdbvisit.val.len > sizeof(struct visit)) ? sizeof(struct visit) : cdbvisit.val.len));
                RoomIsValid = 0;
                UserIsValid = 0;
 
                // Check to see if the room exists
                for (vrptr=ValidRoomList; vrptr!=NULL; vrptr=vrptr->next) {
-                       if ( (vrptr->vr_roomnum==vbuf.v_roomnum)
-                            && (vrptr->vr_roomgen==vbuf.v_roomgen))
+                       if ( (vrptr->vr_roomnum==vbuf.v_roomnum) && (vrptr->vr_roomgen==vbuf.v_roomgen)) {
                                RoomIsValid = 1;
+                       }
                }
 
                // Check to see if the user exists
                for (vuptr=ValidUserList; vuptr!=NULL; vuptr=vuptr->next) {
-                       if (vuptr->vu_usernum == vbuf.v_usernum)
+                       if (vuptr->vu_usernum == vbuf.v_usernum) {
                                UserIsValid = 1;
+                       }
                }
 
                // Put the record on the purge list if it's dead
                if ((RoomIsValid==0) || (UserIsValid==0)) {
-                       vptr = (struct VPurgeList *)
-                               malloc(sizeof(struct VPurgeList));
+                       vptr = (struct VPurgeList *) malloc(sizeof(struct VPurgeList));
                        vptr->next = VisitPurgeList;
                        vptr->vp_roomnum = vbuf.v_roomnum;
                        vptr->vp_roomgen = vbuf.v_roomgen;
@@ -576,7 +573,7 @@ int PurgeVisits(void) {
 int PurgeUseTable(StrBuf *ErrMsg) {
        int purged = 0;
        int total = 0;
-       struct cdbdata cdbut;
+       struct cdbkeyval cdbut;
        struct UseTable ut;
        Array *purge_list = array_new(sizeof(int));
 
@@ -584,13 +581,13 @@ int PurgeUseTable(StrBuf *ErrMsg) {
 
        syslog(LOG_DEBUG, "Purge use table: phase 1");
        cdb_rewind(CDB_USETABLE);
-       while(cdbut = cdb_next_item(CDB_USETABLE), cdbut.ptr!=NULL) {
+       while(cdbut = cdb_next_item(CDB_USETABLE), cdbut.val.ptr!=NULL) {
                ++total;
-               if (cdbut.len > sizeof(struct UseTable))
-                       memcpy(&ut, cdbut.ptr, sizeof(struct UseTable));
+               if (cdbut.val.len > sizeof(struct UseTable))
+                       memcpy(&ut, cdbut.val.ptr, sizeof(struct UseTable));
                else {
                        memset(&ut, 0, sizeof(struct UseTable));
-                       memcpy(&ut, cdbut.ptr, cdbut.len);
+                       memcpy(&ut, cdbut.val.ptr, cdbut.val.len);
                }
 
                if ( (time(NULL) - ut.timestamp) > USETABLE_RETAIN ) {
@@ -616,7 +613,7 @@ int PurgeUseTable(StrBuf *ErrMsg) {
 // Purge the EUID Index of old records.
 int PurgeEuidIndexTable(void) {
        int purged = 0;
-       struct cdbdata cdbei;
+       struct cdbkeyval cdbei;
        struct EPurgeList *el = NULL;
        struct EPurgeList *eptr; 
        long msgnum;
@@ -625,9 +622,9 @@ int PurgeEuidIndexTable(void) {
        // Phase 1: traverse through the table, discovering old records...
        syslog(LOG_DEBUG, "Purge EUID index: phase 1");
        cdb_rewind(CDB_EUIDINDEX);
-       while(cdbei = cdb_next_item(CDB_EUIDINDEX), cdbei.ptr!=NULL) {
+       while(cdbei = cdb_next_item(CDB_EUIDINDEX), cdbei.val.ptr!=NULL) {
 
-               memcpy(&msgnum, cdbei.ptr, sizeof(long));
+               memcpy(&msgnum, cdbei.val.ptr, sizeof(long));
 
                msg = CtdlFetchMessage(msgnum, 0);
                if (msg != NULL) {
@@ -637,9 +634,9 @@ int PurgeEuidIndexTable(void) {
                        eptr = (struct EPurgeList *) malloc(sizeof(struct EPurgeList));
                        if (eptr != NULL) {
                                eptr->next = el;
-                               eptr->ep_keylen = cdbei.len - sizeof(long);
-                               eptr->ep_key = malloc(cdbei.len);
-                               memcpy(eptr->ep_key, &cdbei.ptr[sizeof(long)], eptr->ep_keylen);
+                               eptr->ep_keylen = cdbei.val.len - sizeof(long);
+                               eptr->ep_key = malloc(cdbei.val.len);
+                               memcpy(eptr->ep_key, &cdbei.val.ptr[sizeof(long)], eptr->ep_keylen);
                                el = eptr;
                        }
                        ++purged;
index da1ff39bdee553a583ec056a8a1a2bffbcd40d29..fbc5460af268b22c107e09ec9eb34809f7619aac 100644 (file)
@@ -107,7 +107,7 @@ void imap_getacl(int num_parms, ConstStr *Params) {
        int msgs, new;
        int ret;
        struct ctdluser temp;
-       struct cdbdata cdbus;
+       struct cdbkeyval cdbus;
        int ra;
        StrBuf *rights;
 
@@ -136,9 +136,9 @@ void imap_getacl(int num_parms, ConstStr *Params) {
        // Traverse the userlist
        rights = NewStrBuf();
        cdb_rewind(CDB_USERS);
-       while (cdbus = cdb_next_item(CDB_USERS), cdbus.ptr!=NULL) {
+       while (cdbus = cdb_next_item(CDB_USERS), cdbus.val.ptr!=NULL) {
                memset(&temp, 0, sizeof temp);
-               memcpy(&temp, cdbus.ptr, sizeof temp);
+               memcpy(&temp, cdbus.val.ptr, sizeof temp);
 
                CtdlRoomAccess(&CC->room, &temp, &ra, NULL);
                if (!IsEmptyStr(temp.fullname)) {
index 7c48922f3a6654ffb257153834cea0c2037769a5..804eb3bb62e2628e111d6c88a3aba188ed75e812 100644 (file)
@@ -523,13 +523,13 @@ void lputfloor(struct floor *flbuf, int floor_num) {
 // Iterate through the room table, performing a callback for each room.
 void CtdlForEachRoom(ForEachRoomCallBack callback_func, void *in_data) {
        struct ctdlroom qrbuf;
-       struct cdbdata cdbqr;
+       struct cdbkeyval cdbqr;
 
        cdb_rewind(CDB_ROOMS);
 
-       while (cdbqr = cdb_next_item(CDB_ROOMS), cdbqr.ptr!=NULL) {
+       while (cdbqr = cdb_next_item(CDB_ROOMS), cdbqr.val.ptr!=NULL) {
                memset(&qrbuf, 0, sizeof(struct ctdlroom));
-               memcpy(&qrbuf, cdbqr.ptr, ((cdbqr.len > sizeof(struct ctdlroom)) ?  sizeof(struct ctdlroom) : cdbqr.len) );
+               memcpy(&qrbuf, cdbqr.val.ptr, ((cdbqr.val.len > sizeof(struct ctdlroom)) ?  sizeof(struct ctdlroom) : cdbqr.val.len) );
                room_sanity_check(&qrbuf);
                if (qrbuf.QRflags & QR_INUSE) {
                        callback_func(&qrbuf, in_data);
index c628df2a18e09e49cf28a8685c6e4278a847ede5..f58a9c3f1d7715ec6eebb070dab51eca07bb6a3d 100644 (file)
@@ -73,6 +73,13 @@ struct cdbdata {
 };
 
 
+// Row being fetched from the database, both key and value are returned
+struct cdbkeyval {
+       struct cdbdata key;             // size and pointer to key
+       struct cdbdata val;             // size and pointer to value
+};
+
+
 // Defines the relationship of a user to a particular room
 // NOTE: if you add fields to this, you have to also write export/import code in server/modules/migrate/serv_migrate.c
 // NOTE: if you add fields to this, you have to also write conversion code in utils/ctdl3264/*
index d05d0ef3dad8e544330894ceb17ee0a6ad4dd469..7c85b011893b76daa02311e668d234e05de4d9c7 100644 (file)
@@ -391,16 +391,15 @@ void rebuild_usersbynumber(void) {
 //                     Returns 0 if user was found
 int getuserbyuid(struct ctdluser *usbuf, uid_t number) {
 
-       struct cdbdata cdbus;
+       struct cdbkeyval cdbus;
        struct ctdluser *usptr;
        int return_value = (-1);
 
-       // Yes, we do this the long way.
+       // Yes, we do this the long way.  Someday we might want to try an index.
        // No, we don't use CtdlForEachUser() because that requires multiple reads for each record
-       // TODO: make an index
        cdb_rewind(CDB_USERS);
-       while (cdbus = cdb_next_item(CDB_USERS), cdbus.ptr!=NULL) {
-               usptr = (struct ctdluser *) cdbus.ptr;
+       while (cdbus = cdb_next_item(CDB_USERS), cdbus.val.ptr!=NULL) {
+               usptr = (struct ctdluser *) cdbus.val.ptr;
 
                if (usptr->uid == number) {
                        syslog(LOG_DEBUG, "user_ops: found uid=%d username=%s", usptr->uid, usptr->fullname);
@@ -1031,7 +1030,7 @@ int CtdlForgetThisRoom(void) {
 // Traverse the user file and perform a callback for each user record.
 // (New improved version that runs in two phases so that callbacks can perform writes without having a r/o cursor open)
 void ForEachUser(void (*CallBack) (char *, void *out_data), void *in_data) {
-       struct cdbdata cdbus;
+       struct cdbkeyval cdbus;
        struct ctdluser *usptr;
 
        Array *all_users = array_new(USERNAME_SIZE);
@@ -1044,8 +1043,8 @@ void ForEachUser(void (*CallBack) (char *, void *out_data), void *in_data) {
        cdb_rewind(CDB_USERS);
 
        // Phase 1 : build an array of all our user account names
-       while (cdbus = cdb_next_item(CDB_USERS), cdbus.ptr!=NULL) {
-               usptr = (struct ctdluser *) cdbus.ptr;
+       while (cdbus = cdb_next_item(CDB_USERS), cdbus.val.ptr!=NULL) {
+               usptr = (struct ctdluser *) cdbus.val.ptr;
                if (strlen(usptr->fullname) > 0) {
                        array_append(all_users, usptr->fullname);
                }