public void Initialize(Logger log, string password) { // get log instance to disk _log = log; // if stream are empty, create header page and save to stream if (_stream.Length == 0) { _log.Write(Logger.DISK, "initialize new datafile"); // create a new header page in bytes var header = new HeaderPage(); if (password != null) { _log.Write(Logger.DISK, "datafile encrypted"); header.Password = AesEncryption.HashSHA1(password); header.Salt = AesEncryption.Salt(); } // write bytes on page this.WritePage(0, header.WritePage()); } }
/// <summary> /// Initialize new datafile with header page + lock reserved area zone /// </summary> public static void CreateDatabase(Stream stream, string password = null) { // create a new header page in bytes (keep second page empty) var header = new HeaderPage() { LastPageID = 1 }; if (password != null) { header.Password = AesEncryption.HashSHA1(password); header.Salt = AesEncryption.Salt(); } // point to begin file stream.Seek(0, SeekOrigin.Begin); // get header page in bytes var buffer = header.WritePage(); stream.Write(buffer, 0, BasePage.PAGE_SIZE); // write second page empty just to use as lock control stream.Write(new byte[BasePage.PAGE_SIZE], 0, BasePage.PAGE_SIZE); }
/// <summary> /// Initialize LiteEngine using custom disk service implementation and full engine options /// </summary> public LiteEngine(IDiskService disk, string password = null, TimeSpan?timeout = null, int cacheSize = 5000, Logger log = null, bool utcDate = false) { if (disk == null) { throw new ArgumentNullException("disk"); } _timeout = timeout ?? TimeSpan.FromMinutes(1); _cacheSize = cacheSize; _disk = disk; _log = log ?? new Logger(); _bsonReader = new BsonReader(utcDate); try { // initialize datafile (create) and set log instance _disk.Initialize(_log, password); // lock disk (read mode) before read header var position = _disk.Lock(LockState.Read, _timeout); var buffer = _disk.ReadPage(0); _disk.Unlock(LockState.Read, position); // create header instance from array bytes var header = BasePage.ReadPage(buffer) as HeaderPage; // hash password with sha1 or keep as empty byte[20] var sha1 = password == null ? new byte[20] : AesEncryption.HashSHA1(password); // compare header password with user password even if not passed password (datafile can have password) if (sha1.BinaryCompareTo(header.Password) != 0) { throw LiteException.DatabaseWrongPassword(); } // initialize AES encryptor if (password != null) { _crypto = new AesEncryption(password, header.Salt); } // initialize all services this.InitializeServices(); // if header are marked with recovery, do it now if (header.Recovery) { _trans.Recovery(); } } catch (Exception) { // explicit dispose this.Dispose(); throw; } }
public void Initialize(Logger log, string password) { // get log instance to disk _log = log; // if is readonly, journal must be disabled if (_options.FileMode == FileMode.ReadOnly) { _options.Journal = false; } // open/create file using readonly/exclusive options _stream = new FileStream(_filename, _options.FileMode == FileMode.ReadOnly ? System.IO.FileMode.Open : System.IO.FileMode.OpenOrCreate, _options.FileMode == FileMode.ReadOnly ? FileAccess.Read : FileAccess.ReadWrite, _options.FileMode == FileMode.Exclusive ? FileShare.None : FileShare.ReadWrite, BasePage.PAGE_SIZE); // if file is new, initialize if (_stream.Length == 0) { _log.Write(Logger.DISK, "initialize new datafile"); // set datafile initial size _stream.SetLength(_options.InitialSize); // create a new header page in bytes (keep second page empty) var header = new HeaderPage() { LastPageID = 1 }; if (password != null) { _log.Write(Logger.DISK, "datafile encrypted"); header.Password = AesEncryption.HashSHA1(password); header.Salt = AesEncryption.Salt(); } // write bytes on page this.WritePage(0, header.WritePage()); // write second page empty just to use as lock control this.WritePage(1, new byte[BasePage.PAGE_SIZE]); } #if !NET35 // there is no Lock in NetStandard (1.x) - no shared mode if (_options.FileMode == FileMode.Shared) { _options.FileMode = FileMode.Exclusive; } #endif }
/// <summary> /// Initialize new datafile with header page + lock reserved area zone /// </summary> public static void CreateDatabase(Stream stream, string password = null, long initialSize = 0) { // calculate how many empty pages will be added on disk var emptyPages = initialSize == 0 ? 0 : (initialSize - (2 * BasePage.PAGE_SIZE)) / BasePage.PAGE_SIZE; // if too small size (less than 2 pages), assume no initial size if (emptyPages < 0) { emptyPages = 0; } // create a new header page in bytes (keep second page empty) var header = new HeaderPage { LastPageID = initialSize == 0 ? 1 : (uint)emptyPages + 1, FreeEmptyPageID = initialSize == 0 ? uint.MaxValue : 2 }; if (password != null) { header.Password = AesEncryption.HashSHA1(password); header.Salt = AesEncryption.Salt(); } // point to begin file stream.Seek(0, SeekOrigin.Begin); // get header page in bytes var buffer = header.WritePage(); stream.Write(buffer, 0, BasePage.PAGE_SIZE); // write second page as an empty AREA (it's not a page) just to use as lock control stream.Write(new byte[BasePage.PAGE_SIZE], 0, BasePage.PAGE_SIZE); // if initial size is defined, lets create empty pages in a linked list if (emptyPages > 0) { stream.SetLength(initialSize); var pageID = 1u; while (++pageID < (emptyPages + 2)) { var empty = new EmptyPage(pageID) { PrevPageID = pageID == 2 ? 0 : pageID - 1, NextPageID = pageID == emptyPages + 1 ? uint.MaxValue : pageID + 1 }; stream.Write(empty.WritePage(), 0, BasePage.PAGE_SIZE); } } }
public void Initialize(Logger log, string password) { // get log instance to disk _log = log; // if file not exists, just create empty file if (!File.Exists(_filename)) { // readonly if (_options.ReadOnly) { throw LiteException.ReadOnlyDatabase(); } // open file as create mode _stream = new FileStream(_filename, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Read, BasePage.PAGE_SIZE); _log.Write(Logger.DISK, "initialize new datafile"); // set datafile initial size _stream.SetLength(_options.InitialSize); // create a new header page in bytes var header = new HeaderPage(); if (password != null) { _log.Write(Logger.DISK, "datafile encrypted"); header.Password = AesEncryption.HashSHA1(password); header.Salt = AesEncryption.Salt(); } // write bytes on page this.WritePage(0, header.WritePage()); } else { // try open file in exclusive mode TryExec(() => { _stream = new FileStream(_filename, FileMode.Open, _options.ReadOnly ? FileAccess.Read : FileAccess.ReadWrite, _options.ReadOnly ? FileShare.ReadWrite : FileShare.Read, BasePage.PAGE_SIZE); }); } }
/// <summary> /// Initialize LiteEngine using custom disk service implementation and full engine options /// </summary> public LiteEngine(IDiskService disk, string password = null, TimeSpan?timeout = null, int cacheSize = 5000, Logger log = null) { if (disk == null) { throw new ArgumentNullException("disk"); } _timeout = timeout ?? TimeSpan.FromMinutes(1); _cacheSize = cacheSize; _disk = disk; _log = log ?? new Logger(); try { // initialize datafile (create) and set log instance _disk.Initialize(_log, password); // read header page var header = BasePage.ReadPage(_disk.ReadPage(0)) as HeaderPage; // hash password with sha1 or keep as empty byte[20] var sha1 = password == null ? new byte[20] : AesEncryption.HashSHA1(password); // compare header password with user password even if not passed password (datafile can have password) if (sha1.BinaryCompareTo(header.Password) != 0) { throw LiteException.DatabaseWrongPassword(); } // initialize AES encryptor if (password != null) { _crypto = new AesEncryption(password, header.Salt); } // initialize all services this.InitializeServices(); // try recovery if has journal file _trans.Recovery(); } catch (Exception) { // explicit dispose this.Dispose(); throw; } }