/// <summary> /// Converts key type to a byte[] /// </summary> /// <typeparam name="TData"></typeparam> /// <param name="data"></param> /// <returns></returns> public static byte[] ConvertKey <TData>(TData data) { if (data == null) { return(null); } Type td = typeof(TData); Func <object, byte[]> f = null; if (dck.TryGetValue(td, out f)) { return(f(data)); } if (td.GetTypeInfo().IsEnum) { var enumtype = Enum.GetUnderlyingType(td); if (dce.TryGetValue(enumtype, out f)) { return(f(data)); } throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); } throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); }
internal static byte[] ConvertValue(object data, Type td) { if (data == null) return null; //Type td = typeof(TData); Func<object, byte[]> f = null; if (dcv.TryGetValue(td, out f)) return f(data); if (td.Name == "DbMJSON`1" || td.Name == "DbCustomSerializer`1" || td.Name == "DbXML`1") return ((IDBConvertable)((object)data)).GetBytes(); if (td == TYPE_OBJECT) throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); if (td.GetTypeInfo().IsEnum) { var enumtype = Enum.GetUnderlyingType(td); if (dce.TryGetValue(enumtype, out f)) return f(data); throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); } //Trying byte serialization for unknown object, in case if byte serializer is set if (CustomSerializator.ByteArraySerializator != null) return CustomSerializator.ByteArraySerializator(data); throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); }
/// <summary> /// Checks validity of the user table name /// </summary> /// <param name="tableName"></param> public static void UserTableNameIsOk(string tableName) { if (tableName == String.Empty) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TABLE_NAMES_TABLENAMECANTBEEMPTY); } for (int i = 0; i < tableName.Length; i++) { switch (tableName[i]) { case '*': //used as pattern mask case '#': //used as pattern mask case '$': //used as pattern mask case '@': //used for system tables case '\\': //reserved by dbreeze case '^': //reserved by dbreeze case '~': //reserved by dbreeze case '´': //reserved by dbreeze throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TABLE_NAMES_TABLENAMECANT_CONTAINRESERVEDSYMBOLS); } } return; }
/// <summary> /// Removes resource from database and /// </summary> public void Remove(string resourceName) { if (String.IsNullOrEmpty(resourceName)) { return; } string rn = _urp + resourceName; byte[] btKey = DataTypesConvertor.ConvertKey <string>(rn); _sync.EnterWriteLock(); try { _d.Remove(rn); LTrie.Remove(ref btKey); LTrie.Commit(); } catch (Exception ex) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.DBREEZE_RESOURCES_CONCERNING, "in Remove", ex); } finally { _sync.ExitWriteLock(); } }
private void InitFiles() { //Creates filestreams and rollbacks, restores rollback to the initial file, if necessary try { //this._fsData = new FileStream(this._fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, _fileStreamBufferSize, FileOptions.WriteThrough); //this._fsRollback = new FileStream(this._fileName + ".rol", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, _fileStreamBufferSize, FileOptions.WriteThrough); //this._fsRollbackHelper = new FileStream(this._fileName + ".rhp", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, _fileStreamBufferSize, FileOptions.WriteThrough); this._fsData = this._configuration.FSFactory.CreateType1(this._fileName, _fileStreamBufferSize); this._fsRollback = this._configuration.FSFactory.CreateType1(this._fileName + ".rol", _fileStreamBufferSize); this._fsRollbackHelper = this._configuration.FSFactory.CreateType1(this._fileName + ".rhp", _fileStreamBufferSize); //!!!!We dont have this value in root yet, could have and economize tail of the file in case if rollback occured if (this._fsData.Length == 0) { //Writing initial root data _fsData.Position = 0; _fsData.Write(new byte[this._trieSettings.ROOT_SIZE], 0, this._trieSettings.ROOT_SIZE); if (_backupIsActive) { this._configuration.Backup.WriteBackupElement(ulFileName, 0, 0, new byte[this._trieSettings.ROOT_SIZE]); } //no flush here } eofData = this._fsData.Length; fsLength = this._fsData.Length; //Check is .rhp is empty add 0 pointer if (this._fsRollbackHelper.Length == 0) { //no sense to write here //_fsRollbackHelper.Position = 0; //_fsRollbackHelper.Write(eofRollback.To_8_bytes_array_BigEndian(), 0, 8); //NET_Flush(_fsRollbackHelper); } else { InitRollback(); } _storageFixTime = DateTime.UtcNow; } catch (Exception ex) { IsOperable = false; throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.DB_IS_NOT_OPERABLE, "FSR INIT FAILED: " + this._fileName, ex); } }
/// <summary> /// Can return NULL (if DbIsNotOperatable) /// </summary> /// <param name="tableName"></param> /// <param name="transactionThreadId"></param> /// <returns></returns> public LTrie GetTable_WRITE(string tableName, int transactionThreadId) { if (!this._engine.DBisOperable) { return(null); } TransactionUnit transactionUnit = this.GetTransactionUnit(transactionThreadId); if (transactionUnit != null) { #if NET35 || NETr40 if (System.Threading.Thread.CurrentThread.ManagedThreadId != transactionThreadId) #else if (Environment.CurrentManagedThreadId != transactionThreadId) #endif { this.UnregisterTransaction(transactionThreadId); throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TRANSACTION_CANBEUSED_FROM_ONE_THREAD); } //We must put Get_Table_Write through the same bottleneck as RegisterWriteTablesForTransaction this.RegisterWriteTablesForTransaction(transactionThreadId, new List <string> { tableName }, false); //it will wait here till table for writing, reserved by other thread is released LTrie tbl = null; try { tbl = this._engine.DBreezeSchema.GetTable(tableName); //Adding table to transaction unit with the ITransactable interface transactionUnit.AddTransactionWriteTable(tableName, tbl); //added together with ITransactable //TODO - THIS TABLE LTrie must be Interfaced //Telling to the table that transactionThreadId Thread will modify it tbl.ModificationThreadId(transactionThreadId); } catch (Exception ex) { //Exception must come from Schema, by in-ability to get the table this.UnregisterTransaction(transactionThreadId); //CIRCULAR PARTLY throw ex; } return(tbl); } else { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TRANSACTION_DOESNT_EXIST); } }
/// <summary> /// Throws exception if smth. happened. /// Returns either original table name or cutted if * is found /// </summary> /// <param name="tableName"></param> /// <returns></returns> public static string UserTablePatternIsOk(string tableName) { //RULES: // tableName should not be empty // * means all following characters -> .+ <- what means must 1 or more any characters // $ means all following characters without slash, after $ should be no more characters // # means must be 1 or more characters, except slash, and followed by slash and another symbol // after slash must come something else // all what is after * will be cutted (for patterns storage) //Cars# - NOT acceptable (no trailing slash) - may be add slash automatic? //Cars#/ - NOT acceptable (no symbol after slash) //Cars#/Items# - NOT acceptable (no trailing slash) //Cars#/I - acceptable //Cars#/* - acceptable //Cars*/Items -> converts into Cars* - and acceptable //Cars* - acceptable //Cars#/Items123 - acceptable //Cars#/Items#/ - acceptable //Cars#/Items* - acceptable if (tableName == String.Empty) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TABLE_PATTERN_CANTBEEMPTY); } for (int i = 0; i < tableName.Length; i++) { switch (tableName[i]) { case '*': //Substring till * and return return(tableName.Substring(0, i + 1)); case '$': //Substring till $ and return return(tableName.Substring(0, i + 1)); case '#': if ((i + 2) > (tableName.Length - 1)) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TABLE_PATTERN_SYMBOLS_AFTER_SHARP); } if (tableName[i + 1] != '/') { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TABLE_PATTERN_SYMBOLS_AFTER_SHARP); } break; } } return(tableName); }
/// <summary> /// Standard and transactional rollback /// </summary> public void Rollback() { try { lock (lock_fs) { //Clearing random buffer if (_randBuf.Count() != 0) { usedBufferSize = 0; _randBuf.Clear(); } //Restoring Rollback records byte[] btWork = null; if (_rollbackCache.Count() > 0) { foreach (var rb in _rollbackCache) { btWork = new byte[rb.Value.l]; btWork = _fsRollback.Read((int)rb.Value.o, btWork.Length); //_fsRollback.Position = rb.Value.o; //_fsRollback.Read(btWork, 0, btWork.Length); _fsData.Write_ByOffset((int)rb.Key, btWork); //_fsData.Position = rb.Key; //_fsData.Write(btWork, 0, btWork.Length); } //NET_Flush(_fsData); //Restoring rhp eofRollback = 0; btWork = eofRollback.To_8_bytes_array_BigEndian(); _fsRollbackHelper.Write_ByOffset(0, btWork); //_fsRollbackHelper.Position = 0; //_fsRollbackHelper.Write(eofRollback.To_8_bytes_array_BigEndian(), 0, 8); //NET_Flush(_fsRollbackHelper); //Clearing rollbackCache _rollbackCache.Clear(); } //we dont move eofData, space can be re-used up to next restart (may be root can have this info in next protocols) //eofData = this._fsData.Length; } } catch (Exception ex) { IsOperable = false; throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.RESTORE_ROLLBACK_DATA_FAILED, this._fileName, ex); } }
/// <summary> /// Returns transaction object. /// </summary> /// <param name="tablesLockType"> /// <para>SHARED: threads can use listed tables in parallel. Must be used together with tran.SynchronizeTables command, if necessary.</para> /// <para>EXCLUSIVE: if other threads use listed tables for reading or writing, current thread will be in a waiting queue.</para> /// </param> /// <param name="tables"></param> /// <returns>Returns transaction object</returns> public Transaction GetTransaction(eTransactionTablesLockTypes tablesLockType, params string[] tables) { if (!DBisOperable) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.DB_IS_NOT_OPERABLE, DBisOperableReason, new Exception()); } //User receives new transaction from the engine return(this._transactionsCoordinator.GetTransaction(1, tablesLockType, tables)); }
/// <summary> /// Deletes user table /// </summary> /// <param name="userTableName"></param> public void DeleteTable(string userTableName) { string tableName = GetUserTableNameAsString(userTableName); this.cachedTableNames.Remove(tableName); //Blocking Schema _sync_openTablesHolder.EnterWriteLock(); try { if (_openTablesHolder.ContainsKey(tableName)) { //Someone can use this table //We dispose table, what will cause disposing DBstorage and RollbackStorage //In this moment parallel reading table threads inside of Iterations, can get Exceptions - What is acceptable for now. _openTablesHolder[tableName].Dispose(); _openTablesHolder[tableName] = null; //Deleting table from the holder _openTablesHolder.Remove(tableName); } //Trying to get full file name, via globilzed function which will also support mapping outside the DB main directory string physicalDbFileName = GetPhysicalPathToTheUserTable(userTableName); if (physicalDbFileName == String.Empty) { return; //fake } //Removing record from the schema byte[] btTableName = GetUserTableNameAsByte(userTableName); //ulong cc = LTrie.Count(); LTrie.Remove(ref btTableName); LTrie.Commit(); //cc = LTrie.Count(); //Deleting file physically if (physicalDbFileName != "MEMORY") { DeleteAllReleatedTableFiles(physicalDbFileName); } } catch (System.Exception ex) { DBreezeException.Throw(DBreezeException.eDBreezeExceptions.SCHEME_TABLE_DELETE_FAILED, userTableName, ex); } finally { _sync_openTablesHolder.ExitWriteLock(); } }
/// <summary> /// Deserializes object from Microsoft JSON string /// </summary> /// <typeparam name="T"></typeparam> /// <param name="str"></param> /// <returns></returns> public static T DeserializeCustom <T>(this string str) { try { return((T)Deserializator(str, typeof(T))); } catch (Exception ex) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.CUSTOM_DESERIALIZATION_ERROR, ex); } }
/// <summary> /// Serializes object to JSON from Microsoft /// </summary> /// <param name="objectForSerialization"></param> /// <returns></returns> public static string SerializeCustom(this object objectForSerialization) { try { return(Serializator(objectForSerialization)); } catch (Exception ex) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.CUSTOM_SERIALIZATION_ERROR, ex); } }
/// <summary> /// Returns physical path to the table file, if table doesn't exists in the Scheme returns String.Empty /// </summary> /// <param name="userTableName"></param> /// <returns></returns> public string GetTablePathFromTableName(string userTableName) { //For user usage _sync_openTablesHolder.EnterReadLock(); try { byte[] btTableName = GetUserTableNameAsByte(userTableName); LTrieRow row = LTrie.GetKey(btTableName, true, false); if (!row.Exists) { return(String.Empty); } byte[] fullValue = row.GetFullValue(true); //Can be parsed different. First protocol version is 1 ushort schemeProtocol = fullValue.Substring(0, 2).To_UInt16_BigEndian(); ulong fileName = 0; switch (schemeProtocol) { case 1: fileName = fullValue.Substring(2, 8).To_UInt64_BigEndian(); break; default: throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.SCHEME_FILE_PROTOCOL_IS_UNKNOWN); } string alternativeTableLocation = String.Empty; if (CheckAlternativeTableLocationsIntersections(userTableName, out alternativeTableLocation)) { if (alternativeTableLocation == String.Empty) { return("MEMORY"); } else { return(Path.Combine(alternativeTableLocation, fileName.ToString())); } } else { return(Path.Combine(Engine.MainFolder, fileName.ToString())); } } finally { _sync_openTablesHolder.ExitReadLock(); } }
/// <summary> /// /// </summary> /// <param name="transactionType">0 = standard transaction, 1 - locked transaction</param> /// <param name="lockType"></param> /// <param name="tables"></param> /// <returns></returns> public Transaction GetTransaction(int transactionType, eTransactionTablesLockTypes lockType, params string[] tables) { //this check is done on upper level //if (!this.DbIsOperatable) // return null; //Transaction must have 2 classes one class is for the user, with appropriate methods, second for technical purposes TransactionDetails, where we store different transaction information //both classes must be bound into one class TransactionUnit TransactionUnit transactionUnit = new TransactionUnit(transactionType, this, lockType, tables); //Checking if the same transaction already exists in the list of Transactions. //It could happen in case of abnormal termination of parallel thread, without disposing of the transaction. //So we delete pending transaction first, then create new one. bool reRun = false; _sync_transactions.EnterReadLock(); try { if (this._transactions.ContainsKey(transactionUnit.TransactionThreadId)) { reRun = true; } } finally { _sync_transactions.ExitReadLock(); } if (reRun) { UnregisterTransaction(transactionUnit.TransactionThreadId); return(GetTransaction(transactionType, lockType, tables)); } //Adding transaction to the list _sync_transactions.EnterWriteLock(); try { this._transactions.Add(transactionUnit.TransactionThreadId, transactionUnit); } catch (System.Exception ex) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TRANSACTION_GETTING_TRANSACTION_FAILED, ex); } finally { _sync_transactions.ExitWriteLock(); } return(transactionUnit.Transaction); }
/// <summary> /// Can return NULL if table doesn't exist /// Can return NULL (if DbIsNotOperatable) /// /// Differs from GetTable_Write: /// 1. table is not registered for Write; /// 2. Table is not created, if doesn't exist. /// </summary> /// <param name="tableName"></param> /// <param name="transactionThreadId"></param> /// <param name="ignoreThreadIdCheck"></param> /// <returns></returns> public LTrie GetTable_READ(string tableName, int transactionThreadId, bool ignoreThreadIdCheck = false) { if (!this._engine.DBisOperable) { return(null); } TransactionUnit transactionUnit = this.GetTransactionUnit(transactionThreadId); if (transactionUnit != null) { #if NET35 || NETr40 if (!ignoreThreadIdCheck && System.Threading.Thread.CurrentThread.ManagedThreadId != transactionThreadId) #else if (!ignoreThreadIdCheck && Environment.CurrentManagedThreadId != transactionThreadId) #endif { this.UnregisterTransaction(transactionThreadId); throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TRANSACTION_CANBEUSED_FROM_ONE_THREAD); } LTrie tbl = null; try { if (!this._engine.DBreezeSchema.IfUserTableExists(tableName)) { return(null); } tbl = this._engine.DBreezeSchema.GetTable(tableName); } catch (Exception ex) { //Exception must come from Schema, by in-ability to get the table this.UnregisterTransaction(transactionThreadId); //CIRCULAR PARTLY throw ex; } return(tbl); } else { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TRANSACTION_DOESNT_EXIST); } }
/// <summary> /// InitDb /// </summary> private void InitDb() { //trying to check and create folder try { lock (lock_initDb) { //Init type converter DataTypes.DataTypesConvertor.InitDict(); if (Configuration.Storage == DBreezeConfiguration.eStorage.DISK) { DirectoryInfo di = new DirectoryInfo(MainFolder); if (!di.Exists) { di.Create(); } } //trying to open schema file DBreezeSchema = new Scheme(this); //Initializing Transactions Coordinator _transactionsCoordinator = new TransactionsCoordinator(this); //Initializing transactions Journal, may be later move journal into transactionsCoordinator //We must create journal after Schema, for getting path to rollback files _transactionsJournal = new TransactionsJournal(this); //Initializes transaction locker, who can help block tables of writing and reading threads _transactionTablesLocker = new TransactionTablesLocker(); //Initializing DeferredIndexer = new TextDeferredIndexer(this); //Init DBreezeResources Resources = new DBreezeResources(this); } } catch (Exception ex) { DBisOperable = false; DBisOperableReason = "InitDb"; throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.CREATE_DB_FOLDER_FAILED, ex); } }
/// <summary> /// CONVERTING FROM byte[] to the generic type /// </summary> /// <typeparam name="TData"></typeparam> /// <param name="dt"></param> /// <returns></returns> public static TData ConvertBack <TData>(byte[] dt) { if (dt == null) { return(default(TData)); } Type td = typeof(TData); Func <byte[], object> f = null; if (dcb.TryGetValue(td, out f)) { return((TData)f(dt)); } if (td.Name.Equals("DbMJSON`1") || td.Name.Equals("DbCustomSerializer`1") || td.Name.Equals("DbXML`1")) { object o = Activator.CreateInstance(td); ((IDBConvertable)o).SetBytes(dt); return((TData)o); } if (td == TYPE_OBJECT) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); } if (td.GetTypeInfo().IsEnum) { var enumtype = Enum.GetUnderlyingType(td); if (dcbe.TryGetValue(enumtype, out f)) { return((TData)f(dt)); } throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); } if (CustomSerializator.ByteArrayDeSerializator != null) { return((TData)CustomSerializator.ByteArrayDeSerializator(dt, td)); } throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); }
/// <summary> /// Deserializes object from XML string /// </summary> /// <typeparam name="T"></typeparam> /// <param name="str"></param> /// <returns></returns> public static T DeserializeXml <T>(this string str) { try { System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T)); object r = null; using (System.IO.StringReader sr = new System.IO.StringReader(str)) { r = xs.Deserialize(new System.IO.StringReader(str)); } return((T)r); } catch (Exception ex) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.XML_DESERIALIZATION_ERROR, ex); } }
/// <summary> /// Deserializes object from Microsoft JSON string /// </summary> /// <typeparam name="T"></typeparam> /// <param name="str"></param> /// <returns></returns> public static T DeserializeMJSON <T>(this string str) { try { //DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(T)); //using (MemoryStream stream1 = new MemoryStream(Encoding.UTF8.GetBytes(str))) //{ // T obj = (T)s.ReadObject(stream1); // return obj; //} System.Web.Script.Serialization.JavaScriptSerializer s = new System.Web.Script.Serialization.JavaScriptSerializer(); return(s.Deserialize <T>(str)); } catch (Exception ex) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.MJSON_DESERIALIZATION_ERROR, ex); } }
public void RollBack() { try { this.Tree.Cache.RollBack(); //Important, Better to re-read all generation nodes for safety reasons, de bene esse this._generationMap.Clear(); //And re-Read RootNode ReadRootNode(); } catch (Exception ex) { //HERE DB MUST BECOMES NOT-OPERABLE !!!!!!!!!!!!!!!!!!!!!!!!! //PARTIALLY CASCADE this.Tree.Cache.RollBack(); has wrap, others not throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.ROLLBACK_FAILED, this.Tree.TableName, ex); } }
/// <summary> /// Serializes object to JSON from Microsoft /// </summary> /// <param name="objectForSerialization"></param> /// <returns></returns> public static string SerializeMJSON(this object objectForSerialization) { try { System.Web.Script.Serialization.JavaScriptSerializer s = new System.Web.Script.Serialization.JavaScriptSerializer(); return(s.Serialize(objectForSerialization)); //DataContractJsonSerializer s = new DataContractJsonSerializer(objectForSerialization.GetType()); //using (MemoryStream stream1 = new MemoryStream()) //{ // s.WriteObject(stream1, objectForSerialization); // return Encoding.UTF8.GetString(stream1.GetBuffer()); //} } catch (Exception ex) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.MJSON_SERIALIZATION_ERROR, ex); } }
/// <summary> /// Serializes object to XML string /// </summary> /// <param name="objectForSerialization"></param> /// <returns></returns> public static string SerializeXml(this object objectForSerialization) { try { System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(objectForSerialization.GetType()); string r = String.Empty; using (System.IO.StringWriter wr = new System.IO.StringWriter()) { xs.Serialize(wr, objectForSerialization); r = wr.GetStringBuilder().ToString(); } return(r); } catch (Exception ex) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.XML_SERIALIZATION_ERROR, ex); } }
public void TransactionalCommit() { try { ////rollbak will be done on the level of the tree this.Save_GM_nodes_Starting_From(0); byte[] oldRoot = me; //Gettign new root for save me = this.SerializeRootNode(); //Synchronized inside //this.Tree.Cache.TransactionalCommit(this.EmptyPointer, ref me, ref oldRoot); this.Tree.Cache.TransactionalCommit(ref me, ref oldRoot); } catch (Exception ex) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TRANSACTIONAL_COMMIT_FAILED, this.Tree.TableName, ex); } }
private void InitBackupFolder() { try { DirectoryInfo di = new DirectoryInfo(this._backupFolderName); if (!di.Exists) { di.Create(); } //bmFs = new FileStream(Path.Combine(this._backupFolderName, "DBreezeBM.mg1"), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, _bufferSize); IsActive = true; } catch (Exception ex) { IsActive = false; throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.BACKUP_FOLDER_CREATE_FAILED, ex); } }
/// <summary> /// Removes resources from database and In-Memory dictionary /// </summary> public void Remove(IList <string> resourcesNames) { if (resourcesNames == null || resourcesNames.Count == 0) { return; } byte[] btKey; string rn = String.Empty; _sync.EnterWriteLock(); try { foreach (var rs in resourcesNames) { if (String.IsNullOrEmpty(rs)) { continue; } rn = _urp + rs; _d.Remove(rn); btKey = DataTypesConvertor.ConvertKey <string>(rn); LTrie.Remove(ref btKey); } LTrie.Commit(); } catch (Exception ex) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.DBREEZE_RESOURCES_CONCERNING, "in Remove batch", ex); } finally { _sync.ExitWriteLock(); } }
private void InitFiles() { //Creates filestreams and rollbacks, restores rollback to the initial file, if necessary try { this._fsData = new MemoryStorage(1024 * 16, 1024 * 500, MemoryStorage.eMemoryExpandStartegy.FIXED_LENGTH_INCREASE); this._fsRollback = new MemoryStorage(1024 * 16, 1024 * 128, MemoryStorage.eMemoryExpandStartegy.FIXED_LENGTH_INCREASE); this._fsRollbackHelper = new MemoryStorage(8, 10, MemoryStorage.eMemoryExpandStartegy.FIXED_LENGTH_INCREASE); //Writing root this._fsData.Write_ToTheEnd(new byte[64]); eofData = this._fsData.EOF; _storageFixTime = DateTime.UtcNow; } catch (Exception ex) { IsOperable = false; throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.DB_IS_NOT_OPERABLE, "MSR INIT FAILED: " + this._fileName, ex); } }
public void Commit() { try { this.Save_GM_nodes_Starting_From(0); byte[] oldRoot = me; me = this.SerializeRootNode(); //Synchronized inside //DBreeze.Diagnostic.SpeedStatistic.StartCounter("Commit"); //this.Tree.Cache.Commit(this.EmptyPointer, ref me, ref oldRoot); this.Tree.Cache.Commit(ref me, ref oldRoot); //DBreeze.Diagnostic.SpeedStatistic.StopCounter("Commit"); } catch (Exception ex) { ////rollbak will be done on the level of the tree //////////////////////////////////////// throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.COMMIT_FAILED, this.Tree.TableName, ex); } }
public void Rollback(int transactionThreadId) { if (!this._engine.DBisOperable) { return; } TransactionUnit transactionUnit = this.GetTransactionUnit(transactionThreadId); if (transactionUnit != null) { List <ITransactable> tablesForTransaction = transactionUnit.GetTransactionWriteTables(); if (tablesForTransaction.Count() == 0) { //DO NOTHING } else if (tablesForTransaction.Count() == 1) { try { tablesForTransaction[0].SingleRollback(); } //catch (System.Threading.ThreadAbortException ex) //{ // //We don'T make DBisOperable = false; // throw ex; //} catch (Exception ex) { this._engine.DBisOperable = false; this._engine.DBisOperableReason = "TransactionsCoordinator.Rollback tablesForTransaction.Count = 1"; //CASCADE, WHICH MUST BRING TO DB is not opearatbale state throw ex; } } else { //Rollback MANY AT ONCE try { foreach (var tt1 in tablesForTransaction) { tt1.SingleRollback(); } } //catch (System.Threading.ThreadAbortException ex1) //{ // //We don'T make DBisOperable = false; // throw ex1; //} catch (Exception ex1) { //CASCADE, WHICH MUST BRING TO DB is not opearatbale state this._engine.DBisOperable = false; this._engine.DBisOperableReason = "TransactionsCoordinator.Rollback tablesForTransaction.Count > 1"; throw ex1; } } } else { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TRANSACTION_DOESNT_EXIST); } }
/// <summary> /// Commit /// </summary> /// <param name="transactionThreadId"></param> public void Commit(int transactionThreadId) { if (!this._engine.DBisOperable) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.DB_IS_NOT_OPERABLE, this._engine.DBisOperableReason, new Exception()); } TransactionUnit transactionUnit = this.GetTransactionUnit(transactionThreadId); if (transactionUnit != null) { List <ITransactable> tablesForTransaction = transactionUnit.GetTransactionWriteTables(); if (tablesForTransaction.Count() == 0) { //DO NOTHING } else if (tablesForTransaction.Count() == 1) { try { tablesForTransaction[0].SingleCommit(); } catch (System.Threading.ThreadAbortException ex) { //Rollback was ok, so we just return mistake, why commit failed //We don'T make DBisOperable = false; throw ex; } catch (TableNotOperableException ex1) { this._engine.DBisOperable = false; this._engine.DBisOperableReason = "TransactionsCoordinator.Commit tablesForTransaction.Count = 1"; //CASCADE, WHICH MUST BRING TO DB is not opearatbale state throw ex1; } catch (System.Exception ex) { //Rollback was ok, so we just return mistake, why commit failed //CASCADE throw ex; } } else { //Gettign new TransactionJournalId ulong tranNumber = this._engine._transactionsJournal.GetTransactionNumber(); foreach (var tt in tablesForTransaction) { try { //Adding table this._engine._transactionsJournal.AddTableForTransaction(tranNumber, tt); tt.ITRCommit(); } //catch (System.Threading.ThreadAbortException ex) //{ // //We don'T make DBisOperable = false; // throw ex; //} catch (Exception ex) { //SMTH HAPPENED INSIDE OF COMMIT Trying to rollBack tables try { foreach (var tt1 in tablesForTransaction) { tt1.ITRRollBack(); } this._engine._transactionsJournal.RemoveTransactionFromDictionary(tranNumber); } //catch (System.Threading.ThreadAbortException ex1) //{ // //We don'T make DBisOperable = false; // throw ex1; //} catch (Exception ex1) { //CASCADE, WHICH MUST BRING TO DB is not opearable state this._engine.DBisOperable = false; this._engine.DBisOperableReason = "TransactionsCoordinator.Commit tablesForTransaction.Count > 1"; throw new Exception(ex.ToString() + " --> " + ex1.ToString()); } //In case if rollback succeeded we throw exception brough by bad commit //CASCADE from LTrieRootNode.TransactionalCommit throw ex; } }//end of foreach //Here we appear if all tables were succesfully commited (but it's not visible still for READING THREDS and all tables still have their rollback files active) //We have to finish the transaction try { this._engine._transactionsJournal.FinishTransaction(tranNumber); } //catch (System.Threading.ThreadAbortException ex) //{ // //We don'T make DBisOperable = false; // throw ex; //} catch (Exception ex) { this._engine.DBisOperable = false; this._engine.DBisOperableReason = "TransactionsCoordinator.Commit FinishTransaction"; throw ex; } } } else { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TRANSACTION_DOESNT_EXIST); } }
/// <summary> /// Access synchronizer. /// All calls of the WRITE LOCATOR come over this function. /// </summary> /// <param name="transactionThreadId"></param> /// <param name="tablesNames"></param> /// <param name="calledBySynchronizer"></param> public void RegisterWriteTablesForTransaction(int transactionThreadId, List <string> tablesNames, bool calledBySynchronizer) { //in every transaction unit we got a list of reserved for WRITING tables //if we have in tablesNames one of the tables which is in this list we have to stop the thread with mre bool toWaitTillTransactionIsFinished = false; bool breakOuterLoop = false; TransactionUnit transactionUnit = null; bool deadlock = false; //When SyncTables is called //Console.WriteLine(DateTime.UtcNow.ToString("dd.MM.yyyy HH:mm:ss") + "> SYNC IN Thread: " + transactionThreadId); while (true) //loop till thread will get full access to write tables { toWaitTillTransactionIsFinished = false; breakOuterLoop = false; deadlock = false; //Console.WriteLine(DateTime.UtcNow.ToString("dd.MM.yyyy HH:mm:ss") + "> " + "Thread: " + transactionThreadId + "WHILE "); //only tables required for writing or read-commited will have to go over this fast bottleneck lock (_sync_dl) { _sync_transactions.EnterReadLock(); try { this._transactions.TryGetValue(transactionThreadId, out transactionUnit); if (transactionUnit == null) { return; //transaction doesn't exist anymore, gracefully goes out } if (!calledBySynchronizer) { //Here we are in case if Registrator is called by WriteTableCall, so we check intersections //Between reserved Write tables and current table using patterns intersections technique. //If they intersect we let the thread to proceed if (DbUserTables.TableNamesIntersect(transactionUnit.GetTransactionWriteTablesNames(), tablesNames)) { return; } } //iterating over all open transactions except self, finding out if desired tables are locked by other threads. foreach (var tu in this._transactions.Where(r => r.Value.TransactionThreadId != transactionThreadId)) { foreach (string tableName in tu.Value.GetTransactionWriteTablesNames()) { //if (tablesNames.Contains(tableName)) if (DbUserTables.TableNamesContains(tablesNames, tableName)) { // //++++++++++++++ here we can register all tables which are waiting for write lock release transactionUnit.AddTransactionWriteTablesAwaitingReservation(tablesNames); //++++++++++++++ if thread, who has locked this table has another table in a "waiting for reservation" blocked by this thread - it's a deadlock //if (transactionUnit.GetTransactionWriteTablesNames().Intersect(tu.Value.GetTransactionWriteTablesAwaitingReservation()).Count() > 0) if (DbUserTables.TableNamesIntersect(transactionUnit.GetTransactionWriteTablesNames(), tu.Value.GetTransactionWriteTablesAwaitingReservation())) { //we got deadlock, we will stop this transaction with an exception deadlock = true; } //other thread has reserved table for the transaction we have to wait toWaitTillTransactionIsFinished = true; breakOuterLoop = true; if (!deadlock) { //Console.WriteLine(DateTime.UtcNow.ToString("dd.MM.yyyy HH:mm:ss") + "> " + "Thread: " + transactionThreadId + " GATE IS CLOSED "); ThreadsGator.CloseGate(); //closing gate only if no deadlock situation //mreWriteTransactionLock.Reset(); //setting to signalled only in non-deadlock case } break; } } if (breakOuterLoop) { break; } } } catch (System.Exception ex) { this.UnregisterTransaction(transactionThreadId); throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TRANSACTION_TABLE_WRITE_REGISTRATION_FAILED, ex); } finally { _sync_transactions.ExitReadLock(); } //if(true) this thread owns all table for modification lock if (!toWaitTillTransactionIsFinished) { //+++++++++++ Here we can clear all table names in the waiting reservation queue transactionUnit.ClearTransactionWriteTablesAwaitingReservation(tablesNames); //we have to reserve for our transaction all tables foreach (var tbn in tablesNames) { transactionUnit.AddTransactionWriteTable(tbn, null); } //Console.WriteLine(DateTime.UtcNow.ToString("dd.MM.yyyy HH:mm:ss") + "> SYNC OUT Thread: " + transactionThreadId + " Sync stop: " + transactionUnit.udtSyncStop.ToString("dd.MM.yyyy HH:mm:ss")); return; } }//end of lock if (deadlock) { this.UnregisterTransaction(transactionThreadId); throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.TRANSACTION_IN_DEADLOCK); } if (toWaitTillTransactionIsFinished) { //Console.WriteLine(DateTime.UtcNow.ToString("dd.MM.yyyy HH:mm:ss") + "> " + "Thread: " + transactionThreadId + " GATE IS PUT "); //blocking thread which requires busy tables for writing, till they are released //ThreadsGator.PutGateHere(20000); //every 20 second (or by Gate open we give a chance to re-try, for safety reasons of hanged threads, if programmer didn't dispose DBreeze process after the programm end) //#if ASYNC // await ThreadsGator.PutGateHere().ConfigureAwait(false); //#else // ThreadsGator.PutGateHere(); //#endif ThreadsGator.PutGateHere(); //mreWriteTransactionLock.WaitOne(); } }//eo while }