1N/A * See the file LICENSE for redistribution information. 1N/A * Copyright (c) 1996, 1997, 1998 1N/A * Sleepycat Software. All rights reserved. 1N/A#
endif /* not lint */ 1N/A * Open a backing file for the memory pool. 1N/A /* Validate arguments. */ 1N/A /* Require a non-zero pagesize. */ 1N/A * Open a backing file for the memory pool; internal version. 1N/A * PUBLIC: int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *, 1N/A * PUBLIC: u_int32_t, int, size_t, int, DB_MPOOL_FINFO *, DB_MPOOLFILE **)); 1N/A * If mfp is provided, we take the DB_MPOOL_FINFO information from 1N/A * the mfp. We don't bother initializing everything, because some 1N/A * of them are expensive to acquire. If no mfp is provided and the 1N/A * finfop argument is NULL, we default the values. 1N/A /* Allocate and initialize the per-process structure. */ 1N/A "memp_fopen: temporary files can't be readonly");
1N/A /* Get the real name for this file and open it. */ 1N/A * Don't permit files that aren't a multiple of the pagesize, 1N/A * and find the number of the last page in the file, all the 1N/A * time being careful not to overflow 32 bits. 1N/A * We can't use off_t's here, or in any code in the mainline 1N/A * library for that matter. (We have to use them in the os 1N/A * stubs, of course, as there are system calls that take them 1N/A * as arguments.) The reason is that some customers build in 1N/A * environments where an off_t is 32-bits, but still run where 1N/A * offsets are 64-bits, and they pay us a lot of money. 1N/A /* Page sizes have to be a power-of-two, ignore mbytes. */ 1N/A "%s: file size not a multiple of the pagesize",
1N/A /* Correction: page numbers are zero-based, not 1-based. */ 1N/A * Get the file id if we weren't given one. Generated file id's 1N/A * don't use timestamps, otherwise there'd be no chance of any 1N/A * other process joining the party. 1N/A * If we weren't provided an underlying shared object to join with, 1N/A * for the per-process thread lock. 1N/A * + the DB_NOMMAP flag wasn't set 1N/A * + and is less than mp_mmapsize bytes in size 1N/A * checking based on the mmap call failure. We want to do normal I/O 1N/A * on the file if the reason we failed was because the file was on an 1N/A * NFS mounted partition, and we can fail in buffer I/O just as easily 1N/A * We'd like to test to see if the file is too big to mmap. Since we 1N/A * don't know what size or type off_t's or size_t's are, or the largest 1N/A * unsigned integral type is, or what random insanity the local C 1N/A * compiler will perpetrate, doing the comparison in a portable way is 1N/A * flatly impossible. Hope that mmap fails if the file is too large. 1N/A * Note that we do not have to free the thread mutex, because we 1N/A * never get to here after we have successfully allocated it. 1N/A * Open an MPOOLFILE. 1N/A * Walk the list of MPOOLFILE's, looking for a matching file. 1N/A * Temporary files can't match previous files. 1N/A "%s: ftype, clear length or pagesize changed",
1N/A /* Found it: increment the reference count. */ 1N/A /* Allocate a new MPOOLFILE. */ 1N/A /* Initialize the structure. */ 1N/A * If the user specifies DB_MPOOL_LAST or DB_MPOOL_NEW on a memp_fget, 1N/A * we have to know the last page in the file. Figure it out and save 1N/A /* Copy the file path into shared memory. */ 1N/A /* Copy the file identification string into shared memory. */ 1N/A /* Copy the page cookie into shared memory. */ 1N/A /* Prepend the MPOOLFILE to the list of MPOOLFILE's. */ 1N/A * Close a backing file for the memory pool. 1N/A * We have to reference count DB_MPOOLFILE structures as other 1N/A * threads may be using them. The problem only happens if the 1N/A * application makes a bad design choice. Here's the path: 1N/A * Thread A opens a database. 1N/A * Thread B uses thread A's DB_MPOOLFILE to write a buffer 1N/A * in order to free up memory in the mpool cache. 1N/A * Thread A closes the database while thread B is using the 1N/A * DB_MPOOLFILE structure. 1N/A * By opening all databases before creating the threads, and 1N/A * closing them after the threads have exited, applications 1N/A * get better performance and avoid the problem path entirely. 1N/A * Regardless, holding the DB_MPOOLFILE to flush a dirty buffer 1N/A * is a short-term lock, even in worst case, since we better be 1N/A * the only thread of control using the DB_MPOOLFILE structure 1N/A * to read pages *into* the cache. Wait until we're the only 1N/A * reference holder and remove the DB_MPOOLFILE structure from 1N/A * the list, so nobody else can even find it. 1N/A /* Complain if pinned blocks never returned. */ 1N/A /* Close the underlying MPOOLFILE. */ 1N/A /* Discard any mmap information. */ 1N/A /* Close the file; temporary files may not yet have been created. */ 1N/A /* Discard the DB_MPOOLFILE structure. */ 1N/A * __memp_mf_close -- 1N/A * Close down an MPOOLFILE. 1N/A /* If more than a single reference, simply decrement. */ 1N/A * Move any BH's held by the file to the free list. We don't free the 1N/A * memory itself because we may be discarding the memory pool, and it's 1N/A * fairly expensive to reintegrate the buffers back into the region for 1N/A /* Complain if we find any blocks that were left dirty. */ 1N/A "%s: close: pgno %lu left dirty; ref %lu",
1N/A /* Delete from the list of MPOOLFILEs. */ 1N/A /* Free the space. */