[dovecot-cvs] dovecot/src/lib file-cache.c,1.9,1.10

cras at dovecot.org cras at dovecot.org
Sat May 14 15:05:53 EEST 2005


Update of /var/lib/cvs/dovecot/src/lib
In directory talvi:/tmp/cvs-serv7539/lib

Modified Files:
	file-cache.c 
Log Message:
Optimizations



Index: file-cache.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/file-cache.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- file-cache.c	14 May 2005 11:35:08 -0000	1.9
+++ file-cache.c	14 May 2005 12:05:50 -0000	1.10
@@ -42,10 +42,50 @@
 	file_cache_invalidate(cache, 0, cache->mmap_length);
 }
 
+static int file_cache_set_size(struct file_cache *cache, uoff_t size)
+{
+	size_t page_size = mmap_get_page_size();
+	uoff_t diff = size % page_size;
+
+	if (diff != 0)
+		size += page_size - diff;
+
+	i_assert((size % page_size) == 0);
+	if (size <= cache->mmap_length)
+		return 0;
+
+	if (size > (size_t)-1) {
+		i_error("file_cache_set_size(%"PRIuUOFF_T"): size too large",
+			size);
+		return -1;
+	}
+
+	/* grow mmaping */
+	if (cache->mmap_base == NULL) {
+		cache->mmap_base = mmap_anon(size);
+		if (cache->mmap_base == MAP_FAILED) {
+			i_error("mmap_anon(%"PRIuUOFF_T") failed: %m", size);
+			cache->mmap_length = 0;
+			return -1;
+		}
+	} else {
+		cache->mmap_base = mremap_anon(cache->mmap_base,
+					       cache->mmap_length,
+					       size, MREMAP_MAYMOVE);
+		if (cache->mmap_base == MAP_FAILED) {
+			i_error("mremap_anon(%"PRIuUOFF_T") failed: %m", size);
+			cache->mmap_length = 0;
+			return -1;
+		}
+	}
+	cache->mmap_length = size;
+	return 0;
+}
+
 ssize_t file_cache_read(struct file_cache *cache, uoff_t offset, size_t size)
 {
 	size_t page_size = mmap_get_page_size();
-	size_t poffset, psize, mmap_needed, dest_offset, dest_size;
+	size_t poffset, psize, dest_offset, dest_size;
 	unsigned char *bits, *dest;
 	ssize_t ret;
 
@@ -75,34 +115,13 @@
 		}
 	}
 
+	if (file_cache_set_size(cache, offset + size) < 0)
+		return -1;
+
 	poffset = offset / page_size;
 	psize = (offset + size + page_size-1) / page_size - poffset;
 	i_assert(psize > 0);
 
-	mmap_needed = (poffset + psize) * page_size;
-	if (mmap_needed > cache->mmap_length) {
-		/* grow mmaping */
-		if (cache->mmap_base == NULL) {
-			cache->mmap_base = mmap_anon(mmap_needed);
-			if (cache->mmap_base == MAP_FAILED) {
-				i_error("mmap_anon(%"PRIuSIZE_T") failed: %m",
-					mmap_needed);
-				return -1;
-			}
-		} else {
-			cache->mmap_base = mremap_anon(cache->mmap_base,
-						       cache->mmap_length,
-						       mmap_needed,
-						       MREMAP_MAYMOVE);
-			if (cache->mmap_base == MAP_FAILED) {
-				i_error("mremap_anon(%"PRIuSIZE_T") failed: %m",
-					mmap_needed);
-				return -1;
-			}
-		}
-		cache->mmap_length = mmap_needed;
-	}
-
 	bits = buffer_get_space_unsafe(cache->page_bitmask, 0,
 				       poffset / CHAR_BIT +
 				       (psize + CHAR_BIT - 1) / CHAR_BIT);
@@ -114,10 +133,26 @@
 	while (psize > 0) {
 		if (bits[poffset / CHAR_BIT] & (1 << (poffset % CHAR_BIT))) {
 			/* page is already in cache */
-			psize--; poffset++;
-			dest += page_size;
 			dest_offset += page_size;
-			continue;
+			if (dest_offset <= cache->read_highwater) {
+				psize--; poffset++;
+				dest += page_size;
+				continue;
+			}
+
+			/* this is the last partially cached block.
+			   use the caching only if we don't want to
+			   read past read_highwater */
+			if (offset + size <= cache->read_highwater) {
+				i_assert(psize == 1);
+				break;
+			}
+
+			/* mark the block noncached again and
+			   read it */
+			bits[poffset / CHAR_BIT] &=
+				~(1 << (poffset % CHAR_BIT));
+			dest_offset -= page_size;
 		}
 
 		ret = pread(cache->fd, dest, dest_size, dest_offset);
@@ -125,10 +160,10 @@
 			if (ret < 0)
 				return -1;
 
-			/* EOF */
-			/* FIXME: we should mark the last block cached and
-			   invalidate it only when trying to read past the
-			   file */
+			/* EOF. mark the last block as cached even if it
+			   isn't completely. read_highwater tells us how far
+			   we've actually made. */
+			bits[poffset / CHAR_BIT] |= 1 << (poffset % CHAR_BIT);
 			return dest_offset <= offset ? 0 :
 				dest_offset - offset < size ?
 				dest_offset - offset : size;
@@ -164,18 +199,27 @@
 		      uoff_t offset)
 {
 	size_t page_size = mmap_get_page_size();
-	size_t max_size;
 	unsigned char *bits;
 	unsigned int first_page, last_page;
 
-	if (offset >= cache->mmap_length)
+	if (file_cache_set_size(cache, offset + size) < 0) {
+		/* couldn't grow mapping. just make sure the written memory
+		   area is invalidated then. */
+		file_cache_invalidate(cache, offset, size);
 		return;
+	}
 
-	max_size = cache->mmap_length - offset;
-	if (max_size < size)
-		size = max_size;
 	memcpy(PTR_OFFSET(cache->mmap_base, offset), data, size);
 
+	if (cache->read_highwater < offset + size) {
+		unsigned int page = cache->read_highwater / page_size;
+
+		bits = buffer_get_space_unsafe(cache->page_bitmask,
+					       page / CHAR_BIT, 1);
+		*bits &= ~(1 << (page % CHAR_BIT));
+		cache->read_highwater = offset + size;
+	}
+
 	/* mark fully written pages cached */
 	if (size >= page_size) {
 		first_page = offset / page_size;



More information about the dovecot-cvs mailing list