private void AvoidDirtyRead() { // if disk are exclusive don't need check dirty read if (_disk.IsExclusive) { return; } _log.Write(Logger.CACHE, "checking disk to avoid dirty read"); // empty cache? just exit if (_cache.CleanUsed == 0) { return; } // get ChangeID from cache var header = _cache.GetPage(0) as HeaderPage; var changeID = header == null ? 0 : header.ChangeID; // and get header from disk var disk = BasePage.ReadPage(_disk.ReadPage(0)) as HeaderPage; // if header change, clear cache and add new header to cache if (disk.ChangeID != changeID) { _log.Write(Logger.CACHE, "file changed from another process, cleaning all cache pages"); _cache.ClearPages(); _cache.AddPage(disk); } }
/// <summary> /// Get a page from cache or from disk (get from cache or from disk) /// </summary> public T GetPage <T>(uint pageID) where T : BasePage { lock (_disk) { var page = _cache.GetPage(pageID); // is not on cache? load from disk if (page == null) { var buffer = _disk.ReadPage(pageID); // if datafile are encrypted, decrypt buffer (header are not encrypted) if (_crypto != null && pageID > 0) { buffer = _crypto.Decrypt(buffer); } page = BasePage.ReadPage(buffer); _cache.AddPage(page); } return((T)page); } }
/// <summary> /// Get a page from cache or from disk (and put on cache) /// </summary> public T GetPage <T>(uint pageID) where T : BasePage, new() { var page = _cache.GetPage <T>(pageID); if (page == null) { page = _disk.ReadPage <T>(pageID); _cache.AddPage(page); } return(page); }
/// <summary> /// Get a page from cache or from disk (and put on cache) /// </summary> public T GetPage <T>(uint pageID, bool setDirty = false) where T : BasePage { var page = _cache.GetPage(pageID); // is not on cache? load from disk if (page == null) { var buffer = _disk.ReadPage(pageID); page = BasePage.ReadPage(buffer); _cache.AddPage(page); } #if DEBUG // if page is empty, convert to T if (page.PageType == PageType.Empty && typeof(T) != typeof(BasePage)) { throw new Exception("Pager.GetPage<T>() never shuld happend"); } #endif // set page as dirty if passing by param if (setDirty) { this.SetDirty((T)page); } return((T)page); }
/// <summary> /// Test if cache still valid (if datafile was changed by another process reset cache) /// Returns true if file was changed /// [Thread Safe] /// </summary> private bool DetectDatabaseChanges() { // if disk are exclusive don't need check dirty read if (_disk.IsExclusive) { return(false); } // empty cache? just exit if (_cache.CleanUsed == 0) { return(false); } _log.Write(Logger.CACHE, "checking disk to detect database changes from another process"); // get ChangeID from cache var header = _cache.GetPage(0) as HeaderPage; var changeID = header == null ? 0 : header.ChangeID; // and get header from disk var disk = BasePage.ReadPage(_disk.ReadPage(0)) as HeaderPage; // if disk header are in recovery mode, throw exception to datafile re-open and recovery pages if (disk.Recovery) { _log.Write(Logger.ERROR, "datafile in recovery mode, need re-open database"); throw LiteException.NeedRecover(); } // if header change, clear cache and add new header to cache if (disk.ChangeID != changeID) { _log.Write(Logger.CACHE, "file changed from another process, cleaning all cache pages"); _cache.ClearPages(); _cache.AddPage(disk); return(true); } return(false); }