private static int PAGERID(Pager p) { return p.GetHashCode(); }
// was:sqlite3PagerOpen public static RC Open(VirtualFileSystem pVfs, out Pager ppPager, string zFilename, int nExtra, PAGEROPEN flags, VFSOPEN vfsFlags, Action<PgHdr> xReinit, Func<object> memPageBuilder) { Pager pPager = null; // Pager object to allocate and return byte memDb = 0; // True if this is an in-memory file bool readOnly = false; // True if this is a read-only file string zPathname = null; // Full path to database file //int nPathname = 0; // Number of bytes in zPathname bool useJournal = (flags & PAGEROPEN.OMIT_JOURNAL) == 0; // False to omit journal bool noReadlock = (flags & PAGEROPEN.NO_READLOCK) != 0; // True to omit read-lock int pcacheSize = PCache.sqlite3PcacheSize(); // Bytes to allocate for PCache uint szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; // Default page size string zUri = null; // URI args to copy int nUri = 0; // Number of bytes of URI args at *zUri // Figure out how much space is required for each journal file-handle (there are two of them, the main journal and the sub-journal). This // is the maximum space required for an in-memory journal file handle and a regular journal file-handle. Note that a "regular journal-handle" // may be a wrapper capable of caching the first portion of the journal file in memory to implement the atomic-write optimization (see // source file journal.c). int journalFileSize = SysEx.ROUND8(sqlite3JournalSize(pVfs) > MemJournalFile.sqlite3MemJournalSize() ? sqlite3JournalSize(pVfs) : MemJournalFile.sqlite3MemJournalSize()); // Bytes to allocate for each journal fd // Set the output variable to NULL in case an error occurs. ppPager = null; #if !SQLITE_OMIT_MEMORYDB if ((flags & PAGEROPEN.MEMORY) != 0) { memDb = 1; zFilename = null; } #endif // Compute and store the full pathname in an allocated buffer pointed to by zPathname, length nPathname. Or, if this is a temporary file, // leave both nPathname and zPathname set to 0. var rc = RC.OK; if (!string.IsNullOrEmpty(zFilename)) { rc = pVfs.xFullPathname(zFilename, out zPathname); var z = zUri = zFilename; nUri = zUri.Length; if (rc == RC.OK && zPathname.Length + 8 > pVfs.mxPathname) // This branch is taken when the journal path required by the database being opened will be more than pVfs.mxPathname // bytes in length. This means the database cannot be opened, as it will not be possible to open the journal file or even // check for a hot-journal before reading. rc = SysEx.SQLITE_CANTOPEN_BKPT(); if (rc != RC.OK) return rc; } // Allocate memory for the Pager structure, PCache object, the three file descriptors, the database file name and the journal // file name. The layout in memory is as follows: // Pager object (sizeof(Pager) bytes) // PCache object (sqlite3PcacheSize() bytes) // Database file handle (pVfs.szOsFile bytes) // Sub-journal file handle (journalFileSize bytes) // Main journal file handle (journalFileSize bytes) // Database file name (nPathname+1 bytes) // Journal file name (nPathname+8+1 bytes) pPager = new Pager(memPageBuilder); pPager.pPCache = new PCache(); pPager.fd = new VirtualFile(); pPager.sjfd = new VirtualFile(); pPager.jfd = new VirtualFile(); // Fill in the Pager.zFilename and Pager.zJournal buffers, if required. if (zPathname != null) { Debug.Assert(zPathname.Length > 0); pPager.zFilename = zPathname.ToString(); zUri = pPager.zFilename; pPager.zJournal = pPager.zFilename + "-journal"; #if !SQLITE_OMIT_WAL pPager.zWal = &pPager.zJournal[nPathname + 8 + 1]; memcpy(pPager.zWal, zPathname, nPathname); memcpy(&pPager.zWal[nPathname], "-wal", 4); #endif } else pPager.zFilename = string.Empty; pPager.pVfs = pVfs; pPager.vfsFlags = vfsFlags; // Open the pager file. var tempFile = LOCKINGMODE.NORMAL; // True for temp files (incl. in-memory files) if (!string.IsNullOrEmpty(zFilename)) { VFSOPEN fout = 0; // VFS flags returned by xOpen() rc = FileEx.sqlite3OsOpen(pVfs, zFilename, pPager.fd, vfsFlags, ref fout); Debug.Assert(0 == memDb); readOnly = (fout & VFSOPEN.READONLY) != 0; // If the file was successfully opened for read/write access, choose a default page size in case we have to create the // database file. The default page size is the maximum of: // + SQLITE_DEFAULT_PAGE_SIZE, // + The value returned by sqlite3OsSectorSize() // + The largest page size that can be written atomically. if (rc == RC.OK && !readOnly) { pPager.setSectorSize(); Debug.Assert(SQLITE_DEFAULT_PAGE_SIZE <= SQLITE_MAX_DEFAULT_PAGE_SIZE); if (szPageDflt < pPager.sectorSize) szPageDflt = (pPager.sectorSize > SQLITE_MAX_DEFAULT_PAGE_SIZE ? SQLITE_MAX_DEFAULT_PAGE_SIZE : (uint)pPager.sectorSize); #if SQLITE_ENABLE_ATOMIC_WRITE int iDc = sqlite3OsDeviceCharacteristics(pPager.fd); Debug.Assert(SQLITE_IOCAP_ATOMIC512 == (512 >> 8)); Debug.Assert(SQLITE_IOCAP_ATOMIC64K == (65536 >> 8)); Debug.Assert(SQLITE_MAX_DEFAULT_PAGE_SIZE <= 65536); for (var ii = szPageDflt; ii <= SQLITE_MAX_DEFAULT_PAGE_SIZE; ii = ii * 2) if (iDc & (SQLITE_IOCAP_ATOMIC | (ii >> 8))) szPageDflt = ii; #endif } } else { // If a temporary file is requested, it is not opened immediately. In this case we accept the default page size and delay actually // opening the file until the first call to OsWrite(). // This branch is also run for an in-memory database. An in-memory database is the same as a temp-file that is never written out to // disk and uses an in-memory rollback journal. tempFile = LOCKINGMODE.EXCLUSIVE; pPager.eState = PAGER.READER; pPager.eLock = VFSLOCK.EXCLUSIVE; readOnly = (vfsFlags & VFSOPEN.READONLY) != 0; } // The following call to PagerSetPagesize() serves to set the value of Pager.pageSize and to allocate the Pager.pTmpSpace buffer. if (rc == RC.OK) { Debug.Assert(pPager.memDb == 0); rc = pPager.SetPageSize(ref szPageDflt, -1); } // If an error occurred in either of the blocks above, free the Pager structure and close the file. if (rc != RC.OK) { Debug.Assert(null == pPager.pTmpSpace); FileEx.sqlite3OsClose(pPager.fd); return rc; } // Initialize the PCache object. Debug.Assert(nExtra < 1000); nExtra = SysEx.ROUND8(nExtra); PCache.Open((int)szPageDflt, nExtra, (memDb == 0), (memDb == 0 ? (Func<object, PgHdr, RC>)pagerStress : null), pPager, pPager.pPCache); PAGERTRACE("OPEN {0} {1}", FILEHANDLEID(pPager.fd), pPager.zFilename); SysEx.IOTRACE("OPEN {0:x} {1}", pPager.GetHashCode(), pPager.zFilename); pPager.useJournal = (byte)(useJournal ? 1 : 0); pPager.noReadlock = (byte)(noReadlock && readOnly ? 1 : 0); pPager.mxPgno = SQLITE_MAX_PAGE_COUNT; #if false Debug.Assert(pPager.state == (tempFile != 0 ? PAGER.EXCLUSIVE : PAGER.UNLOCK)); #endif pPager.tempFile = tempFile != 0; Debug.Assert(tempFile == LOCKINGMODE.NORMAL || tempFile == LOCKINGMODE.EXCLUSIVE); pPager.exclusiveMode = tempFile != 0; pPager.changeCountDone = pPager.tempFile; pPager.memDb = memDb; pPager.readOnly = readOnly; Debug.Assert(useJournal || pPager.tempFile); pPager.noSync = pPager.tempFile; pPager.fullSync = pPager.noSync; pPager.syncFlags = (pPager.noSync ? 0 : VirtualFile.SYNC.NORMAL); pPager.ckptSyncFlags = pPager.syncFlags; pPager.nExtra = (ushort)nExtra; pPager.journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; Debug.Assert(pPager.fd.IsOpen || tempFile != 0); pPager.setSectorSize(); if (!useJournal) pPager.journalMode = JOURNALMODE.OFF; else if (memDb != 0) pPager.journalMode = JOURNALMODE.MEMORY; pPager.xReiniter = xReinit; ppPager = pPager; return RC.OK; }
private static int PAGERID(Pager p) { return(p.GetHashCode()); }