file-cache.c revision 72767afd6cd99439a4d93fcba1621bfcac5e791c
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen/* Copyright (c) 2004 Timo Sirainen */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->page_bitmask = buffer_create_dynamic(default_pool, 128);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (munmap_anon(cache->mmap_base, cache->mmap_length) < 0)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenvoid file_cache_set_fd(struct file_cache *cache, int fd)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen file_cache_invalidate(cache, 0, cache->mmap_length);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenssize_t file_cache_read(struct file_cache *cache, uoff_t offset, size_t size)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen size_t poffset, psize, mmap_needed, dest_offset, dest_size;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen offset + size - cache->mmap_length > 1024*1024) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* growing more than a megabyte, make sure that the
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen file is large enough so we don't allocate memory
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen more than needed */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen psize = (offset + size + page_size-1) / page_size - poffset;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* grow mmaping */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen i_error("mmap_anon(%"PRIuSIZE_T") failed: %m",
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->mmap_base = mremap_anon(cache->mmap_base,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen i_error("mremap_anon(%"PRIuSIZE_T") failed: %m",
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen bits = buffer_get_space_unsafe(cache->page_bitmask, poffset / CHAR_BIT,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen dest = PTR_OFFSET(cache->mmap_base, dest_offset);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen while (psize > 0) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (bits[poffset / CHAR_BIT] & (1 << (poffset % CHAR_BIT))) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* page is already in cache */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen ret = pread(cache->fd, dest, dest_size, dest_offset);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* FIXME: we should mark the last block cached and
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen invalidate it only when trying to read past the
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* partial read - probably EOF but make sure. */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen bits[poffset / CHAR_BIT] |= 1 << (poffset % CHAR_BIT);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenconst void *file_cache_get_map(struct file_cache *cache, size_t *size_r)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenvoid file_cache_invalidate(struct file_cache *cache, uoff_t offset, size_t size)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen unsigned int i;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen size = (offset + size + page_size-1) / page_size;
72767afd6cd99439a4d93fcba1621bfcac5e791cTimo Sirainen /* tell operating system that we don't need the memory anymore
72767afd6cd99439a4d93fcba1621bfcac5e791cTimo Sirainen and it may free it. don't bother to do it for single pages,
72767afd6cd99439a4d93fcba1621bfcac5e791cTimo Sirainen there's a good chance that they get re-read back
72767afd6cd99439a4d93fcba1621bfcac5e791cTimo Sirainen immediately. */
72767afd6cd99439a4d93fcba1621bfcac5e791cTimo Sirainen (void)madvise(PTR_OFFSET(cache->mmap_base, offset * page_size),
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen bits = buffer_get_space_unsafe(cache->page_bitmask, offset / CHAR_BIT,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* set the first byte */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen for (i = offset % CHAR_BIT, mask = 0; i < CHAR_BIT && size > 0; i++) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* set the middle bytes */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* set the last byte */