int db_file_mread(struct db_file *f, void **data, const uint32_t len, const uint32_t pos) { ssize_t n; if (pos + len > f->len) return -1; if (!cached(f, len, pos)) { if (grow_cache(f, len)) return -1; #ifdef HAVE_PREAD n = pread(f->fd, f->cache, len, pos); #else if (pos != f->pos && lseek(f->fd, pos, SEEK_SET) != pos) return -1; n = read(f->fd, f->cache, len); #endif if (n >= 0) f->pos = pos + n; if (n != len) return -1; f->cache_pos = pos; f->cache_len = len; } *data = (char *)f->cache + (pos - f->cache_pos); return 0; }
int db_file_write(struct db_file *f, void *data, uint32_t len) { ssize_t n; uint32_t blob; if (!len) return 0; if (grow_cache(f, PAGESIZE)) return -1; /* first fill the rest of the page */ blob = len < (PAGESIZE - f->pending) ? len : PAGESIZE - f->pending; memcpy((char *)f->cache + f->pending, data, blob); f->pending += blob; data = (char *)data + blob; len -= blob; f->pos += blob; /* flush full pages */ if (f->pending == PAGESIZE) { n = write(f->fd, f->cache, PAGESIZE); if (n == -1) return -1; f->pending = 0; } /* flush rest of the data, when it is a lot */ blob = len & ~(PAGESIZE - 1); if (blob) { n = write(f->fd, data, blob); if (n == -1) return -1; data = (char *)data + blob; len -= blob; f->pos += blob; } /* start filling the next page with the leftovers */ if (len) { memcpy(f->cache, data, len); f->pending += len; f->pos += len; } if (f->pos > f->len) f->len = f->pos; return 0; }
void build_cache() { if (cached_ng == ng && cached_absfirst == absfirst && time((time_t*)NULL) < cached_time + 6*60*60L) { grow_cache(lastart); rc_to_bits(); if (sel_mode == SM_ARTICLE) set_selector(sel_mode, sel_artsort); else set_selector(sel_threadmode, sel_threadsort); thread_grow(); return; } close_cache(); cached_ng = ng; cached_absfirst = absfirst; cached_time = time((time_t*)NULL); cached_cnt = lastart-absfirst+2 + 5; article_list = (ARTICLE*) safemalloc((MEM_SIZE)(cached_cnt * sizeof (ARTICLE))); bzero((char*)article_list, cached_cnt * sizeof (ARTICLE)); subj_hash = hashcreate(201, subject_cmp); /*TODO: pick a better size */ rc_to_bits(); /* sets firstart */ first_cached = thread_always? absfirst : firstart; last_cached = first_cached-1; cached_all_in_range = FALSE; #ifdef PENDING subj_to_get = xref_to_get = firstart; #endif #ifndef USE_NNTP setmissingbits(); #endif /* Cache as much data in advance as possible, possibly threading ** articles as we go. */ thread_open(); }