Asterisk - The Open Source Telephony Project  18.5.0
Macros | Functions
mpool.c File Reference
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "../include/db.h"
#include <mpool.h>
Include dependency graph for mpool.c:

Go to the source code of this file.

Macros

#define __APPLE__
 
#define __MPOOLINTERFACE_PRIVATE
 
#define mpool_close   __mpool_close
 
#define mpool_filter   __mpool_filter
 
#define mpool_get   __mpool_get
 
#define mpool_new   __mpool_new
 
#define mpool_open   __mpool_open
 
#define mpool_put   __mpool_put
 
#define mpool_sync   __mpool_sync
 

Functions

static BKT *mpool_bkt __P ((MPOOL *))
 
static BKT *mpool_look __P ((MPOOL *, pgno_t))
 
static int mpool_write __P ((MPOOL *, BKT *))
 
static BKTmpool_bkt (MPOOL *mp)
 
int mpool_close (MPOOL *mp)
 
void mpool_filter (MPOOL *mp, void *pgin, void *pgout, void *pgcookie)
 
void * mpool_get (MPOOL *mp, pgno_t pgno, u_int flags)
 
static BKTmpool_look (MPOOL *mp, pgno_t pgno)
 
void * mpool_new (MPOOL *mp, pgno_t *pgnoaddr)
 
MPOOLmpool_open (void *key, int fd, pgno_t pagesize, pgno_t maxcache)
 
int mpool_put (MPOOL *mp, void *page, u_int flags)
 
int mpool_sync (MPOOL *mp)
 
static int mpool_write (MPOOL *mp, BKT *bp)
 

Macro Definition Documentation

◆ __APPLE__

#define __APPLE__

Definition at line 316 of file mpool.c.

Referenced by handle_cli_test_locales().

◆ __MPOOLINTERFACE_PRIVATE

#define __MPOOLINTERFACE_PRIVATE

Definition at line 50 of file mpool.c.

◆ mpool_close

#define mpool_close   __mpool_close

Definition at line 62 of file mpool.c.

◆ mpool_filter

#define mpool_filter   __mpool_filter

Definition at line 57 of file mpool.c.

◆ mpool_get

#define mpool_get   __mpool_get

Definition at line 59 of file mpool.c.

◆ mpool_new

#define mpool_new   __mpool_new

Definition at line 58 of file mpool.c.

◆ mpool_open

#define mpool_open   __mpool_open

Definition at line 56 of file mpool.c.

◆ mpool_put

#define mpool_put   __mpool_put

Definition at line 60 of file mpool.c.

◆ mpool_sync

#define mpool_sync   __mpool_sync

Definition at line 61 of file mpool.c.

Function Documentation

◆ __P() [1/3]

static BKT* mpool_bkt __P ( (MPOOL *)  )
static

◆ __P() [2/3]

static BKT* mpool_look __P ( (MPOOL *, pgno_t )
static

◆ __P() [3/3]

static int mpool_write __P ( (MPOOL *, BKT *)  )
static

◆ mpool_bkt()

static BKT* mpool_bkt ( MPOOL mp)
static

Definition at line 343 of file mpool.c.

References calloc, CIRCLEQ_REMOVE, MPOOL::curcache, _bkt::flags, HASHKEY, MPOOL::maxcache, MPOOL_DIRTY, MPOOL_PINNED, mpool_write(), NULL, _bkt::page, MPOOL::pagesize, _bkt::pgno, and RET_ERROR.

Referenced by mpool_get(), and mpool_new().

345 {
346  struct _hqh *head;
347  BKT *bp;
348 
349  /* If under the max cached, always create a new page. */
350  if (mp->curcache < mp->maxcache)
351  goto new;
352 
353  /*
354  * If the cache is max'd out, walk the lru list for a buffer we
355  * can flush. If we find one, write it (if necessary) and take it
356  * off any lists. If we don't find anything we grow the cache anyway.
357  * The cache never shrinks.
358  */
359  for (bp = mp->lqh.cqh_first;
360  bp != (void *)&mp->lqh; bp = bp->q.cqe_next)
361  if (!(bp->flags & MPOOL_PINNED)) {
362  /* Flush if dirty. */
363  if (bp->flags & MPOOL_DIRTY &&
364  mpool_write(mp, bp) == RET_ERROR)
365  return (NULL);
366 #ifdef STATISTICS
367  ++mp->pageflush;
368 #endif
369  /* Remove from the hash and lru queues. */
370  head = &mp->hqh[HASHKEY(bp->pgno)];
371  CIRCLEQ_REMOVE(head, bp, hq);
372  CIRCLEQ_REMOVE(&mp->lqh, bp, q);
373 #ifdef DEBUG
374  { void *spage;
375  spage = bp->page;
376  memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
377  bp->page = spage;
378  }
379 #endif
380  return (bp);
381  }
382 
383 new: if ((bp = (BKT *) calloc(1, sizeof(BKT) + mp->pagesize)) == NULL)
384  return (NULL);
385 #ifdef STATISTICS
386  ++mp->pagealloc;
387 #endif
388 #if defined(DEBUG) || defined(PURIFY)
389  memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
390 #endif
391  bp->page = (char *)bp + sizeof(BKT);
392  ++mp->curcache;
393  return (bp);
394 }
#define RET_ERROR
Definition: db.h:51
#define MPOOL_PINNED
Definition: mpool.h:62
#define NULL
Definition: resample.c:96
void * page
Definition: mpool.h:58
#define calloc(a, b)
Definition: astmm.h:157
#define MPOOL_DIRTY
Definition: mpool.h:61
static int mpool_write(MPOOL *mp, BKT *bp)
Definition: mpool.c:401
pgno_t pgno
Definition: mpool.h:59
pgno_t maxcache
Definition: mpool.h:71
#define CIRCLEQ_REMOVE(head, elm, field)
Definition: queue.h:482
u_long pagesize
Definition: mpool.h:73
#define HASHKEY(pgno)
Definition: mpool.h:52
Definition: mpool.h:55
u_int8_t flags
Definition: mpool.h:63
pgno_t curcache
Definition: mpool.h:70

◆ mpool_close()

int mpool_close ( MPOOL mp)

Definition at line 279 of file mpool.c.

References CIRCLEQ_REMOVE, free(), and RET_SUCCESS.

Referenced by __bt_close().

281 {
282  BKT *bp;
283 
284  /* Free up any space allocated to the lru pages. */
285  while ((bp = mp->lqh.cqh_first) != (void *)&mp->lqh) {
286  CIRCLEQ_REMOVE(&mp->lqh, mp->lqh.cqh_first, q);
287  free(bp);
288  }
289 
290  /* Free the MPOOL cookie. */
291  free(mp);
292  return (RET_SUCCESS);
293 }
void free()
#define RET_SUCCESS
Definition: db.h:52
#define CIRCLEQ_REMOVE(head, elm, field)
Definition: queue.h:482
Definition: mpool.h:55

◆ mpool_filter()

void mpool_filter ( MPOOL mp,
void *  pgin,
void *  pgout,
void *  pgcookie 
)

Definition at line 114 of file mpool.c.

Referenced by __bt_open().

119 {
120  mp->pgin = pgin;
121  mp->pgout = pgout;
122  mp->pgcookie = pgcookie;
123 }
void * pgcookie
Definition: mpool.h:79

◆ mpool_get()

void* mpool_get ( MPOOL mp,
pgno_t  pgno,
u_int  flags 
)

Definition at line 165 of file mpool.c.

References CIRCLEQ_INSERT_HEAD, CIRCLEQ_INSERT_TAIL, CIRCLEQ_REMOVE, EFTYPE, errno, MPOOL::fd, _bkt::flags, HASHKEY, mpool_bkt(), mpool_look(), MPOOL_PINNED, MPOOL::npages, NULL, _bkt::page, MPOOL::pagesize, MPOOL::pgcookie, and _bkt::pgno.

Referenced by __bt_curdel(), __bt_delete(), __bt_first(), __bt_new(), __bt_pdelete(), __bt_put(), __bt_relink(), __bt_search(), __bt_seqadv(), __bt_seqset(), __bt_snext(), __bt_split(), __bt_sprev(), __bt_stkacq(), __ovfl_delete(), __ovfl_get(), __rec_open(), __rec_search(), bt_fast(), bt_meta(), bt_page(), bt_preserve(), and nroot().

169 {
170  struct _hqh *head;
171  BKT *bp;
172  off_t off;
173  int nr;
174 
175  /* Check for attempt to retrieve a non-existent page. */
176  if (pgno >= mp->npages) {
177  errno = EINVAL;
178  return (NULL);
179  }
180 
181 #ifdef STATISTICS
182  ++mp->pageget;
183 #endif
184 
185  /* Check for a page that is cached. */
186  if ((bp = mpool_look(mp, pgno)) != NULL) {
187 #ifdef DEBUG
188  if (bp->flags & MPOOL_PINNED) {
189  (void)fprintf(stderr,
190  "mpool_get: page %d already pinned\n", bp->pgno);
191  abort();
192  }
193 #endif
194  /*
195  * Move the page to the head of the hash chain and the tail
196  * of the lru chain.
197  */
198  head = &mp->hqh[HASHKEY(bp->pgno)];
199  CIRCLEQ_REMOVE(head, bp, hq);
200  CIRCLEQ_INSERT_HEAD(head, bp, hq);
201  CIRCLEQ_REMOVE(&mp->lqh, bp, q);
202  CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
203 
204  /* Return a pinned page. */
205  bp->flags |= MPOOL_PINNED;
206  return (bp->page);
207  }
208 
209  /* Get a page from the cache. */
210  if ((bp = mpool_bkt(mp)) == NULL)
211  return (NULL);
212 
213  /* Read in the contents. */
214 #ifdef STATISTICS
215  ++mp->pageread;
216 #endif
217  off = mp->pagesize * pgno;
218  if (lseek(mp->fd, off, SEEK_SET) != off)
219  return (NULL);
220  if ((u_long) (nr = read(mp->fd, bp->page, mp->pagesize))
221  != mp->pagesize) {
222  if (nr >= 0)
223  errno = EFTYPE;
224  return (NULL);
225  }
226 
227  /* Set the page number, pin the page. */
228  bp->pgno = pgno;
229  bp->flags = MPOOL_PINNED;
230 
231  /*
232  * Add the page to the head of the hash chain and the tail
233  * of the lru chain.
234  */
235  head = &mp->hqh[HASHKEY(bp->pgno)];
236  CIRCLEQ_INSERT_HEAD(head, bp, hq);
237  CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
238 
239  /* Run through the user's filter. */
240  if (mp->pgin != NULL)
241  (mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
242 
243  return (bp->page);
244 }
pgno_t npages
Definition: mpool.h:72
#define MPOOL_PINNED
Definition: mpool.h:62
void * pgcookie
Definition: mpool.h:79
#define NULL
Definition: resample.c:96
void * page
Definition: mpool.h:58
pgno_t pgno
Definition: mpool.h:59
static BKT * mpool_look(MPOOL *mp, pgno_t pgno)
Definition: mpool.c:430
int fd
Definition: mpool.h:74
int errno
#define CIRCLEQ_REMOVE(head, elm, field)
Definition: queue.h:482
u_long pagesize
Definition: mpool.h:73
#define EFTYPE
#define CIRCLEQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:456
#define HASHKEY(pgno)
Definition: mpool.h:52
Definition: mpool.h:55
#define CIRCLEQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:466
u_int8_t flags
Definition: mpool.h:63
static BKT * mpool_bkt(MPOOL *mp)
Definition: mpool.c:343

◆ mpool_look()

static BKT* mpool_look ( MPOOL mp,
pgno_t  pgno 
)
static

Definition at line 430 of file mpool.c.

References _bkt::flags, HASHKEY, MPOOL_DIRTY, MPOOL_PINNED, NULL, and _bkt::pgno.

Referenced by mpool_get().

433 {
434  struct _hqh *head;
435  BKT *bp;
436 
437  head = &mp->hqh[HASHKEY(pgno)];
438  for (bp = head->cqh_first; bp != (void *)head; bp = bp->hq.cqe_next)
439  if (bp->pgno == pgno) {
440 #ifdef STATISTICS
441  ++mp->cachehit;
442 #endif
443  return (bp);
444  }
445 #ifdef STATISTICS
446  ++mp->cachemiss;
447 #endif
448  return (NULL);
449 }
#define NULL
Definition: resample.c:96
pgno_t pgno
Definition: mpool.h:59
#define HASHKEY(pgno)
Definition: mpool.h:52
Definition: mpool.h:55

◆ mpool_new()

void* mpool_new ( MPOOL mp,
pgno_t pgnoaddr 
)

Definition at line 130 of file mpool.c.

References CIRCLEQ_INSERT_HEAD, CIRCLEQ_INSERT_TAIL, _bkt::flags, HASHKEY, MAX_PAGE_NUMBER, mpool_bkt(), MPOOL_PINNED, MPOOL::npages, NULL, _bkt::page, and _bkt::pgno.

Referenced by __bt_new(), and nroot().

133 {
134  struct _hqh *head;
135  BKT *bp;
136 
137  if (mp->npages == MAX_PAGE_NUMBER) {
138  (void)fprintf(stderr, "mpool_new: page allocation overflow.\n");
139  abort();
140  }
141 #ifdef STATISTICS
142  ++mp->pagenew;
143 #endif
144  /*
145  * Get a BKT from the cache. Assign a new page number, attach
146  * it to the head of the hash chain, the tail of the lru chain,
147  * and return.
148  */
149  if ((bp = mpool_bkt(mp)) == NULL)
150  return (NULL);
151  *pgnoaddr = bp->pgno = mp->npages++;
152  bp->flags = MPOOL_PINNED;
153 
154  head = &mp->hqh[HASHKEY(bp->pgno)];
155  CIRCLEQ_INSERT_HEAD(head, bp, hq);
156  CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
157  return (bp->page);
158 }
pgno_t npages
Definition: mpool.h:72
#define MPOOL_PINNED
Definition: mpool.h:62
#define NULL
Definition: resample.c:96
void * page
Definition: mpool.h:58
#define MAX_PAGE_NUMBER
Definition: db.h:77
pgno_t pgno
Definition: mpool.h:59
#define CIRCLEQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:456
#define HASHKEY(pgno)
Definition: mpool.h:52
Definition: mpool.h:55
#define CIRCLEQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:466
u_int8_t flags
Definition: mpool.h:63
static BKT * mpool_bkt(MPOOL *mp)
Definition: mpool.c:343

◆ mpool_open()

MPOOL* mpool_open ( void *  key,
int  fd,
pgno_t  pagesize,
pgno_t  maxcache 
)

Definition at line 74 of file mpool.c.

References calloc, CIRCLEQ_INIT, errno, HASHSIZE, and NULL.

Referenced by __bt_open().

78 {
79  struct stat sb;
80  MPOOL *mp;
81  int entry;
82 
83  /*
84  * Get information about the file.
85  *
86  * XXX
87  * We don't currently handle pipes, although we should.
88  */
89  if (fstat(fd, &sb))
90  return (NULL);
91  if (!S_ISREG(sb.st_mode)) {
92  errno = ESPIPE;
93  return (NULL);
94  }
95 
96  /* Allocate and initialize the MPOOL cookie. */
97  if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL)
98  return (NULL);
99  CIRCLEQ_INIT(&mp->lqh);
100  for (entry = 0; entry < HASHSIZE; ++entry)
101  CIRCLEQ_INIT(&mp->hqh[entry]);
102  mp->maxcache = maxcache;
103  mp->npages = sb.st_size / pagesize;
104  mp->pagesize = pagesize;
105  mp->fd = fd;
106  return (mp);
107 }
Definition: mpool.h:66
#define HASHSIZE
Definition: mpool.h:51
#define NULL
Definition: resample.c:96
#define calloc(a, b)
Definition: astmm.h:157
int errno
Definition: search.h:40
#define CIRCLEQ_INIT(head)
Definition: queue.h:431

◆ mpool_put()

int mpool_put ( MPOOL mp,
void *  page,
u_int  flags 
)

Definition at line 251 of file mpool.c.

References _bkt::flags, MPOOL_DIRTY, MPOOL_PINNED, _bkt::pgno, and RET_SUCCESS.

Referenced by __bt_bdelete(), __bt_close(), __bt_curdel(), __bt_delete(), __bt_fd(), __bt_first(), __bt_free(), __bt_get(), __bt_pdelete(), __bt_put(), __bt_relink(), __bt_search(), __bt_seq(), __bt_seqadv(), __bt_seqset(), __bt_snext(), __bt_split(), __bt_sprev(), __bt_stkacq(), __bt_sync(), __ovfl_delete(), __ovfl_get(), __ovfl_put(), __rec_close(), __rec_delete(), __rec_fd(), __rec_get(), __rec_iput(), __rec_open(), __rec_put(), __rec_search(), __rec_seq(), __rec_sync(), bt_broot(), bt_fast(), bt_meta(), bt_page(), bt_preserve(), bt_rroot(), nroot(), and rec_rdelete().

255 {
256  BKT *bp;
257 
258 #ifdef STATISTICS
259  ++mp->pageput;
260 #endif
261  bp = (BKT *)((char *)page - sizeof(BKT));
262 #ifdef DEBUG
263  if (!(bp->flags & MPOOL_PINNED)) {
264  (void)fprintf(stderr,
265  "mpool_put: page %d not pinned\n", bp->pgno);
266  abort();
267  }
268 #endif
269  bp->flags &= ~MPOOL_PINNED;
270  bp->flags |= flags & MPOOL_DIRTY;
271  return (RET_SUCCESS);
272 }
#define MPOOL_PINNED
Definition: mpool.h:62
#define MPOOL_DIRTY
Definition: mpool.h:61
pgno_t pgno
Definition: mpool.h:59
#define RET_SUCCESS
Definition: db.h:52
Definition: mpool.h:55
u_int8_t flags
Definition: mpool.h:63
struct _bkt BKT

◆ mpool_sync()

int mpool_sync ( MPOOL mp)

Definition at line 300 of file mpool.c.

References MPOOL::fd, _bkt::flags, MPOOL_DIRTY, mpool_write(), RET_ERROR, and RET_SUCCESS.

Referenced by __bt_sync().

302 {
303  BKT *bp;
304 
305  /* Walk the lru chain, flushing any dirty pages to disk. */
306  for (bp = mp->lqh.cqh_first;
307  bp != (void *)&mp->lqh; bp = bp->q.cqe_next)
308  if (bp->flags & MPOOL_DIRTY &&
309  mpool_write(mp, bp) == RET_ERROR)
310  return (RET_ERROR);
311 
312  /* Sync the file descriptor. */
313  return (fsync(mp->fd) ? RET_ERROR : RET_SUCCESS);
314 }
#define RET_ERROR
Definition: db.h:51
#define MPOOL_DIRTY
Definition: mpool.h:61
static int mpool_write(MPOOL *mp, BKT *bp)
Definition: mpool.c:401
#define RET_SUCCESS
Definition: db.h:52
int fd
Definition: mpool.h:74
Definition: mpool.h:55
u_int8_t flags
Definition: mpool.h:63

◆ mpool_write()

static int mpool_write ( MPOOL mp,
BKT bp 
)
static

Definition at line 401 of file mpool.c.

References MPOOL::fd, _bkt::flags, MPOOL_DIRTY, _bkt::page, MPOOL::pagesize, MPOOL::pgcookie, _bkt::pgno, RET_ERROR, and RET_SUCCESS.

Referenced by mpool_bkt(), and mpool_sync().

404 {
405  off_t off;
406 
407 #ifdef STATISTICS
408  ++mp->pagewrite;
409 #endif
410 
411  /* Run through the user's filter. */
412  if (mp->pgout)
413  (mp->pgout)(mp->pgcookie, bp->pgno, bp->page);
414 
415  off = mp->pagesize * bp->pgno;
416  if (lseek(mp->fd, off, SEEK_SET) != off)
417  return (RET_ERROR);
418  if ((u_long) write(mp->fd, bp->page, mp->pagesize) != mp->pagesize)
419  return (RET_ERROR);
420 
421  bp->flags &= ~MPOOL_DIRTY;
422  return (RET_SUCCESS);
423 }
#define RET_ERROR
Definition: db.h:51
void * pgcookie
Definition: mpool.h:79
void * page
Definition: mpool.h:58
#define MPOOL_DIRTY
Definition: mpool.h:61
pgno_t pgno
Definition: mpool.h:59
#define RET_SUCCESS
Definition: db.h:52
int fd
Definition: mpool.h:74
u_long pagesize
Definition: mpool.h:73
u_int8_t flags
Definition: mpool.h:63