sync uid database after every message. this is accompanied by a dbm ->
db4 migration. patch by theodore, with some final polishing by me.
This commit is contained in:
		
							parent
							
								
									052195c982
								
							
						
					
					
						commit
						180f5fa201
					
				
					 4 changed files with 56 additions and 57 deletions
				
			
		
							
								
								
									
										24
									
								
								configure.in
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								configure.in
									
										
									
									
									
								
							|  | @ -33,28 +33,8 @@ if test "x$ob_cv_with_ssl" != xno; then | ||||||
|       ]) |       ]) | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| AC_CACHE_CHECK(for dbm_open, ac_cv_dbmopen, | AC_CHECK_LIB(db, db_create, [LIBS="$LIBS -ldb"], [AC_MSG_ERROR([Berkley DB not found.])]) | ||||||
| 	[ac_cv_dbmopen=no | AC_CHECK_HEADER(db.h, , [AC_MSG_ERROR([Berkley DB header file not found.])]) | ||||||
| 	AC_TRY_LINK([#include <ndbm.h>], |  | ||||||
| 		[dbm_open(0,0,0);],[ac_cv_dbmopen=yes])]) |  | ||||||
| if test $ac_cv_dbmopen = no; then |  | ||||||
| 	AC_CACHE_CHECK([for dbm_open in -ldb], ac_cv_libdb, |  | ||||||
| 		[save_LIBS="$LIBS" |  | ||||||
| 		LIBS="$LIBS -ldb" |  | ||||||
| 		ac_cv_libdb=no |  | ||||||
| 		AC_TRY_LINK([#define DB_DBM_HSEARCH 1 |  | ||||||
| #include <db.h>], |  | ||||||
| 			[dbm_open(0,0,0);], |  | ||||||
| 			[ac_cv_libdb=yes]) |  | ||||||
| 		LIBS="$save_LIBS"]) |  | ||||||
| 
 |  | ||||||
| 	if test $ac_cv_libdb = yes; then |  | ||||||
| 		LIBS="$LIBS -ldb" |  | ||||||
| 		AC_DEFINE(HAVE_LIBDB, 1, [Define if you have libdb]) |  | ||||||
| 	else |  | ||||||
| 		AC_MSG_ERROR([Could not find dbm_open(), you must install libdb]) |  | ||||||
| 	fi |  | ||||||
| fi |  | ||||||
| 
 | 
 | ||||||
| AC_OUTPUT(Makefile src/Makefile debian/Makefile isync.spec) | AC_OUTPUT(Makefile src/Makefile debian/Makefile isync.spec) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -26,12 +26,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| 
 | 
 | ||||||
| #if HAVE_LIBDB | #include <db.h> | ||||||
| # define DB_DBM_HSEARCH 1 |  | ||||||
| # include <db.h> |  | ||||||
| #else |  | ||||||
| # include <ndbm.h> |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| #if HAVE_LIBSSL | #if HAVE_LIBSSL | ||||||
| # include <openssl/ssl.h> | # include <openssl/ssl.h> | ||||||
|  | @ -94,7 +89,7 @@ struct config | ||||||
| /* struct representing local mailbox file */ | /* struct representing local mailbox file */ | ||||||
| struct mailbox | struct mailbox | ||||||
| { | { | ||||||
|     DBM *db; |     DB *db; | ||||||
|     char *path; |     char *path; | ||||||
|     message_t *msgs; |     message_t *msgs; | ||||||
|     int lockfd; |     int lockfd; | ||||||
|  |  | ||||||
|  | @ -125,8 +125,8 @@ maildir_open (const char *path, int flags) | ||||||
|     int count = 0; |     int count = 0; | ||||||
|     struct stat sb; |     struct stat sb; | ||||||
|     const char *subdirs[] = { "cur", "new", "tmp" }; |     const char *subdirs[] = { "cur", "new", "tmp" }; | ||||||
|     int i; |     int i, ret; | ||||||
|     datum key; |     DBT key, value; | ||||||
| 
 | 
 | ||||||
|     m = calloc (1, sizeof (mailbox_t)); |     m = calloc (1, sizeof (mailbox_t)); | ||||||
|     m->lockfd = -1; |     m->lockfd = -1; | ||||||
|  | @ -200,8 +200,18 @@ maildir_open (const char *path, int flags) | ||||||
|     if (read_uid (m->path, "isyncmaxuid", &m->maxuid) == -1) |     if (read_uid (m->path, "isyncmaxuid", &m->maxuid) == -1) | ||||||
| 	goto err; | 	goto err; | ||||||
| 
 | 
 | ||||||
|     snprintf (buf, sizeof (buf), "%s/isyncuidmap", m->path); |     snprintf (buf, sizeof (buf), "%s/isyncuidmap.db", m->path); | ||||||
|     m->db = dbm_open (buf, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); |     if (db_create (&m->db, 0, 0)) { | ||||||
|  | 	    fputs ("dbcreate failed\n", stderr); | ||||||
|  | 	    goto err; | ||||||
|  |     } | ||||||
|  |     if ((ret = m->db->set_pagesize (m->db, 4096)) != 0 || | ||||||
|  | 	(ret = m->db->set_h_ffactor (m->db, 40)) != 0 || | ||||||
|  | 	(ret = m->db->set_h_nelem (m->db, 1)) != 0) { | ||||||
|  | 	    fputs ("Error configuring database\n", stderr); | ||||||
|  | 	    goto err; | ||||||
|  |     } | ||||||
|  |     m->db->open (m->db, buf, 0, DB_HASH, DB_CREATE, S_IRUSR | S_IWUSR); | ||||||
|     if (m->db == NULL) |     if (m->db == NULL) | ||||||
|     { |     { | ||||||
| 	fputs ("ERROR: unable to open UID db\n", stderr); | 	fputs ("ERROR: unable to open UID db\n", stderr); | ||||||
|  | @ -237,19 +247,24 @@ maildir_open (const char *path, int flags) | ||||||
| 	    /* determine the UID for this message.  The basename (sans
 | 	    /* determine the UID for this message.  The basename (sans
 | ||||||
| 	     * flags) is used as the key in the db | 	     * flags) is used as the key in the db | ||||||
| 	     */ | 	     */ | ||||||
| 	    key.dptr = p->file; | 	    memset (&key, 0, sizeof(key)); | ||||||
| 	    s = strchr (key.dptr, ':'); | 	    memset (&value, 0, sizeof(value)); | ||||||
| 	    key.dsize = s ? (size_t) (s - key.dptr) : strlen (key.dptr); | 	    key.data = p->file; | ||||||
| 	    key = dbm_fetch (m->db, key); | 	    s = strchr (p->file, ':'); | ||||||
| 	    if (key.dptr) | 	    key.size = s ? (size_t) (s - p->file) : strlen (p->file); | ||||||
| 	    { | 	    ret = m->db->get (m->db, 0, &key, &value, 0); | ||||||
| 		p->uid = *(int *) key.dptr; | 	    if (ret == DB_NOTFOUND) { | ||||||
|  | 		/* Every locally generated message triggers this ... */ | ||||||
|  | 		/*printf ("Warning, no UID for message %.*s\n",
 | ||||||
|  | 			key.size, p->file);*/ | ||||||
|  | 	    } else if (ret) { | ||||||
|  | 		fprintf (stderr, "Unexpected error (%d) from db_get(%.*s)\n",  | ||||||
|  | 			 ret, key.size, p->file); | ||||||
|  | 	    } else if (ret == 0) { | ||||||
|  | 		p->uid = *((int *) value.data); | ||||||
| 		if (p->uid > m->maxuid) | 		if (p->uid > m->maxuid) | ||||||
| 		    m->maxuid = p->uid; | 		    m->maxuid = p->uid; | ||||||
| 	    } | 	    } | ||||||
| 	    else /* XXX remove. every locally generated message triggers this */ |  | ||||||
| 		puts ("Warning, no UID for message"); |  | ||||||
| 
 |  | ||||||
| 	    if (s) | 	    if (s) | ||||||
| 		parse_info (p, s + 1); | 		parse_info (p, s + 1); | ||||||
| 	    if (p->flags & D_DELETED) | 	    if (p->flags & D_DELETED) | ||||||
|  | @ -262,7 +277,7 @@ maildir_open (const char *path, int flags) | ||||||
| 
 | 
 | ||||||
|   err: |   err: | ||||||
|     if (m->db) |     if (m->db) | ||||||
| 	dbm_close (m->db); | 	m->db->close (m->db, 0); | ||||||
|     dotlock_unlock (&m->lockfd); |     dotlock_unlock (&m->lockfd); | ||||||
|     free (m->path); |     free (m->path); | ||||||
|     free (m); |     free (m); | ||||||
|  | @ -278,7 +293,7 @@ maildir_expunge (mailbox_t * mbox, int dead) | ||||||
|     message_t **cur = &mbox->msgs; |     message_t **cur = &mbox->msgs; | ||||||
|     message_t *tmp; |     message_t *tmp; | ||||||
|     char *s; |     char *s; | ||||||
|     datum key; |     DBT key; | ||||||
|     char path[_POSIX_PATH_MAX]; |     char path[_POSIX_PATH_MAX]; | ||||||
| 
 | 
 | ||||||
|     while (*cur) |     while (*cur) | ||||||
|  | @ -292,10 +307,12 @@ maildir_expunge (mailbox_t * mbox, int dead) | ||||||
| 	    if (unlink (path)) | 	    if (unlink (path)) | ||||||
| 		perror (path); | 		perror (path); | ||||||
| 	    /* remove the message from the UID map */ | 	    /* remove the message from the UID map */ | ||||||
| 	    key.dptr = tmp->file; | 	    memset (&key, 0, sizeof(key)); | ||||||
| 	    s = strchr (key.dptr, ':'); | 	    key.data = tmp->file; | ||||||
| 	    key.dsize = s ? (size_t) (s - key.dptr) : strlen (key.dptr); | 	    s = strchr (tmp->file, ':'); | ||||||
| 	    dbm_delete (mbox->db, key); | 	    key.size = s ? (size_t) (s - tmp->file) : strlen (key.data); | ||||||
|  | 	    mbox->db->del (mbox->db, 0, &key, 0); | ||||||
|  | 	    mbox->db->sync (mbox->db, 0); | ||||||
| 	    *cur = (*cur)->next; | 	    *cur = (*cur)->next; | ||||||
| 	    free (tmp->file); | 	    free (tmp->file); | ||||||
| 	    free (tmp); | 	    free (tmp); | ||||||
|  | @ -386,7 +403,7 @@ void | ||||||
| maildir_close (mailbox_t * mbox) | maildir_close (mailbox_t * mbox) | ||||||
| { | { | ||||||
|     if (mbox->db) |     if (mbox->db) | ||||||
| 	dbm_close (mbox->db); | 	mbox->db->close (mbox->db, 0); | ||||||
| 
 | 
 | ||||||
|     /* release the mutex on the mailbox */ |     /* release the mutex on the mailbox */ | ||||||
|     dotlock_unlock (&mbox->lockfd); |     dotlock_unlock (&mbox->lockfd); | ||||||
|  |  | ||||||
							
								
								
									
										21
									
								
								src/sync.c
									
										
									
									
									
								
							
							
						
						
									
										21
									
								
								src/sync.c
									
										
									
									
									
								
							|  | @ -46,17 +46,24 @@ find_msg (message_t * list, unsigned int uid) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| set_uid (DBM * db, const char *f, unsigned int uid) | set_uid (DB * db, const char *f, unsigned int uid) | ||||||
| { | { | ||||||
|     char *s; |     char *s; | ||||||
|     datum key, val; |     DBT key, val; | ||||||
|  |     int ret; | ||||||
| 
 | 
 | ||||||
|     key.dptr = (void *) f; |     memset (&key, 0, sizeof(key)); | ||||||
|  |     memset (&val, 0, sizeof(val)); | ||||||
|  |     key.data = (void *) f; | ||||||
|     s = strchr (f, ':'); |     s = strchr (f, ':'); | ||||||
|     key.dsize = s ? (size_t) (s - key.dptr) : strlen (f); |     key.size = s ? (size_t) (s - f) : strlen (f); | ||||||
|     val.dptr = (void *) &uid; |     val.data = (void *) &uid; | ||||||
|     val.dsize = sizeof (uid); |     val.size = sizeof (uid); | ||||||
|     dbm_store (db, key, val, DBM_REPLACE); |     ret = db->put (db, 0, &key, &val, 0); | ||||||
|  |     if (ret < 0) | ||||||
|  | 	fprintf (stderr, "Unexpected error (%d) from db_put(%.*s, %d)\n",  | ||||||
|  | 		 ret, key.size, f, uid); | ||||||
|  |     db->sync(db, 0); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue