/// <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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.DBriize_RESOURCES_CONCERNING, "in Remove", ex); } finally { _sync.ExitWriteLock(); } }
/// <summary> /// Checks validity of the user table name /// </summary> /// <param name="tableName"></param> public static void UserTableNameIsOk(string tableName) { if (tableName == String.Empty) { throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.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 DBriize case '^': //reserved by DBriize case '~': //reserved by DBriize case '´': //reserved by DBriize throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.TABLE_NAMES_TABLENAMECANT_CONTAINRESERVEDSYMBOLS); } } return; }
/// <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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); } throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); }
/// <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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.RESTORE_ROLLBACK_DATA_FAILED, this._fileName, ex); } }
/// <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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.TABLE_PATTERN_SYMBOLS_AFTER_SHARP); } if (tableName[i + 1] != '/') { throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.TABLE_PATTERN_SYMBOLS_AFTER_SHARP); } break; } } return(tableName); }
private void InitFiles() { //Creates filestreams and rollbacks, restores rollback to the initial file, if necessary try { RIC.OpenRemoteTable(this._fileName); //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); //!!!!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) if (RIC.DataFileLength == 0) { //Writing initial root data RIC.DataFilePosition = 0; RIC.DataFileWrite(new byte[this._trieSettings.ROOT_SIZE], 0, this._trieSettings.ROOT_SIZE, false); //_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 = RIC.DataFileLength; //eofData = this._fsData.Length; //Check is .rhp is empty add 0 pointer //if (this._fsRollbackHelper.Length == 0) if (RIC.RollbackHelperFileLength == 0) { //no sense to write here } else { InitRollback(); } _storageFixTime = DateTime.UtcNow; } catch (Exception ex) { IsOperable = false; throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.DB_IS_NOT_OPERABLE, "RISR INIT 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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.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) { DBriizeException.Throw(DBriizeException.eDBriizeExceptions.SCHEME_TABLE_DELETE_FAILED, userTableName, ex); } finally { _sync_openTablesHolder.ExitWriteLock(); } }
/// <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 (Environment.CurrentManagedThreadId != transactionThreadId) { this.UnregisterTransaction(transactionThreadId); throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.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.DBriizeSchema.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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.TRANSACTION_DOESNT_EXIST); } }
/// <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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.CUSTOM_SERIALIZATION_ERROR, ex); } }
/// <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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.CUSTOM_DESERIALIZATION_ERROR, ex); } }
/// <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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.TRANSACTION_GETTING_TRANSACTION_FAILED, ex); } finally { _sync_transactions.ExitWriteLock(); } return(transactionUnit.Transaction); }
/// <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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.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> /// 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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); } if (CustomSerializator.ByteArrayDeSerializator != null) { return((TData)CustomSerializator.ByteArrayDeSerializator(dt, td)); } throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); }
/// <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 == DBriizeConfiguration.eStorage.DISK) { DirectoryInfo di = new DirectoryInfo(MainFolder); if (!di.Exists) { di.Create(); } } //trying to open schema file DBriizeSchema = 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); } } catch (Exception ex) { DBisOperable = false; DBisOperableReason = "InitDb"; throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.CREATE_DB_FOLDER_FAILED, ex); } }
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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); } if (td.GetTypeInfo().IsEnum) { var enumtype = Enum.GetUnderlyingType(td); if (dce.TryGetValue(enumtype, out f)) { return(f(data)); } throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.UNSUPPORTED_DATATYPE, td.ToString(), null); }
/// <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 (!ignoreThreadIdCheck && Environment.CurrentManagedThreadId != transactionThreadId) { this.UnregisterTransaction(transactionThreadId); throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.TRANSACTION_CANBEUSED_FROM_ONE_THREAD); } LTrie tbl = null; try { if (!this._engine.DBriizeSchema.IfUserTableExists(tableName)) { return(null); } tbl = this._engine.DBriizeSchema.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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.TRANSACTION_DOESNT_EXIST); } }
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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.ROLLBACK_FAILED, this.Tree.TableName, 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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.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, "DBriizeBM.mg1"), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, _bufferSize); IsActive = true; } catch (Exception ex) { IsActive = false; throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.DBriize_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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.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 //DBriize.Diagnostic.SpeedStatistic.StartCounter("Commit"); //this.Tree.Cache.Commit(this.EmptyPointer, ref me, ref oldRoot); this.Tree.Cache.Commit(ref me, ref oldRoot); //DBriize.Diagnostic.SpeedStatistic.StopCounter("Commit"); } catch (Exception ex) { ////rollbak will be done on the level of the tree //////////////////////////////////////// throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.COMMIT_FAILED, this.Tree.TableName, ex); } }
private void RestoreNotFinishedTransactions() { //TODO Trie settings from the table must be taken from schema (when they will differ) //STORE FILE NAME of rollback not table name try { byte[] btCommittedTablesNames = null; List <string> committedTablesNames = new List <string>(); if (LTrie.Count(false) == 0) //All ok { LTrie.RemoveAll(true); return; } string physicalPathToTheUserTable = String.Empty; //Settigns and storage for Committed tables !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MUST BE TAKEN FROM SCHEMA, FOR NOW DEFAULT TrieSettings ltrSet = null; IStorage storage = null; DBriize.LianaTrie.LTrie ltrie = null; foreach (var row in LTrie.IterateForward(true, false)) { btCommittedTablesNames = row.GetFullValue(true); committedTablesNames = System.Text.Encoding.UTF8.GetString(btCommittedTablesNames).DeserializeXml <List <string> >(); foreach (var fn in committedTablesNames) { //Trying to get path from the Schema, there is universal function for getting table physical TABLE FULL PATH /NAME physicalPathToTheUserTable = Engine.DBriizeSchema.GetPhysicalPathToTheUserTable(fn); //Returned path can be empty, if no more such table if (physicalPathToTheUserTable == String.Empty) { continue; } //We don't restore in-memory tables if (physicalPathToTheUserTable == "MEMORY") { continue; } //we open ltrie, and it automatically restores rollback ltrSet = new TrieSettings(); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MUST BE TAKEN FROM SCHEMA, FOR NOW DEFAULT //storage = new TrieDiskStorage(physicalPathToTheUserTable, ltrSet, Engine.Configuration); storage = new StorageLayer(physicalPathToTheUserTable, ltrSet, Engine.Configuration); ltrie = new LTrie(storage); //closing trie, that Schema could open it again ltrie.Dispose(); ////Deleting rollback file for such table //physicalPathToTheUserTable += ".rol"; //System.IO.File.Delete(physicalPathToTheUserTable); } committedTablesNames.Clear(); } //If all ok, recreate file LTrie.RemoveAll(true); } catch (OperationCanceledException ex) { throw ex; } //catch (System.Threading.ThreadAbortException ex) //{ // //We don'T make DBisOperable = false; // throw ex; //} catch (Exception) { //BRINGS TO DB NOT OPERATABLE this.Engine.DBisOperable = false; this.Engine.DBisOperableReason = "TransactionsCoordinator.RestoreNotFinishedTransaction"; //NOT CASCADE ADD EXCEPTION throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.CLEAN_ROLLBACK_FILES_FOR_FINISHED_TRANSACTIONS_FAILED); } }
/// <summary> /// Gets resource from memory or database (if not yet loaded) /// Value instance, when byte[], must stay immutable, please use DBriize.Utils.CloneArray /// </summary> /// <typeparam name="TValue"></typeparam> /// <param name="resourceName"></param> /// <param name="resourceSettings">resource extra behaviour</param> /// <returns></returns> public TValue Select <TValue>(string resourceName, Settings resourceSettings = null) { if (String.IsNullOrEmpty(resourceName)) { return(default(TValue)); } if (resourceSettings == null) { resourceSettings = _defaultSetting; } byte[] val = null; string rn = _urp + resourceName; _sync.EnterUpgradeableReadLock(); try { if (!_d.TryGetValue(rn, out val)) { //Value is not found _sync.EnterWriteLock(); try { //At this moment value appeared if (_d.TryGetValue(rn, out val)) { return(val == null ? default(TValue) : DataTypesConvertor.ConvertBack <TValue>(val)); } //trying to get from database byte[] btKey = DataTypesConvertor.ConvertKey <string>(rn); var row = LTrie.GetKey(btKey, false, false); if (row.Exists) { val = row.GetFullValue(false); if (val == null) { if (resourceSettings.HoldInMemory) { _d[rn] = null; } return(default(TValue)); } else { if (resourceSettings.HoldInMemory) { _d[rn] = val; } return(DataTypesConvertor.ConvertBack <TValue>(val)); } } else { if (resourceSettings.HoldInMemory) { _d[rn] = null; } return(default(TValue)); } } catch (Exception ex) { throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.DBriize_RESOURCES_CONCERNING, "in Select 1", ex); } finally { _sync.ExitWriteLock(); } } else { return(val == null ? default(TValue) : DataTypesConvertor.ConvertBack <TValue>(val)); } } catch (System.Exception ex) { throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.DBriize_RESOURCES_CONCERNING, "in Select 2", ex); } finally { _sync.ExitUpgradeableReadLock(); } }
/// <summary> /// Gets resources of the same type as a batch from memory or database (if not yet loaded). /// Value instance, when byte[], must stay immutable, please use DBriize.Utils.CloneArray /// </summary> /// <typeparam name="TValue"></typeparam> /// <param name="resourcesNames"></param> /// <param name="resourceSettings">resource extra behaviour</param> /// <returns></returns> public IDictionary <string, TValue> Select <TValue>(IList <string> resourcesNames, Settings resourceSettings = null) { Dictionary <string, TValue> ret = new Dictionary <string, TValue>(); if (resourcesNames == null || resourcesNames.Count < 1) { return(ret); } if (resourceSettings == null) { resourceSettings = _defaultSetting; } byte[] val = null; string rn = String.Empty; //bool ba = typeof(TValue) == typeof(byte[]); _sync.EnterUpgradeableReadLock(); try { foreach (var rsn in resourcesNames.OrderBy(r => r)) { if (String.IsNullOrEmpty(rsn)) { continue; } rn = _urp + rsn; if (!_d.TryGetValue(rn, out val)) { //Value is not found _sync.EnterWriteLock(); try { //At this moment value appeared if (_d.TryGetValue(rn, out val)) { if (val != null) { ret[rsn] = DataTypesConvertor.ConvertBack <TValue>(val); } else { ret[rsn] = default(TValue); } continue; } //trying to get from database byte[] btKey = DataTypesConvertor.ConvertKey <string>(rn); var row = LTrie.GetKey(btKey, false, false); if (row.Exists) { val = row.GetFullValue(false); if (val == null) { if (resourceSettings.HoldInMemory) { _d[rn] = null; } ret[rsn] = default(TValue); } else { if (resourceSettings.HoldInMemory) { _d[rn] = val; } ret[rsn] = DataTypesConvertor.ConvertBack <TValue>(val); } } else { if (resourceSettings.HoldInMemory) { _d[rn] = null; } ret[rsn] = default(TValue); } } catch (Exception ex) { throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.DBriize_RESOURCES_CONCERNING, "in Select 1", ex); } finally { _sync.ExitWriteLock(); } } else { if (val == null) { ret[rsn] = default(TValue); } else { ret[rsn] = DataTypesConvertor.ConvertBack <TValue>(val); } } }//eo foreach } catch (System.Exception ex) { throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.DBriize_RESOURCES_CONCERNING, "in Select 2", ex); } finally { _sync.ExitUpgradeableReadLock(); } return(ret); }
/// <summary> /// Batch insert of resources where value is a byte[] /// </summary> /// <param name="resources"></param> /// <param name="resourceSettings">resource extra behaviour</param> public void Insert(IDictionary <string, byte[]> resources, Settings resourceSettings = null) { if (resources == null || resources.Count < 1) { return; } if (resourceSettings == null) { resourceSettings = _defaultSetting; } byte[] btKey = null; byte[] btExVal = null; string rn = String.Empty; _sync.EnterWriteLock(); try { bool cov = LTrie.OverWriteIsAllowed; if (resourceSettings.HoldOnDisk && resourceSettings.FastUpdates) { LTrie.OverWriteIsAllowed = false; } foreach (var rs in resources.OrderBy(r => r.Key)) { if (String.IsNullOrEmpty(rs.Key)) { continue; } rn = _urp + rs.Key; //------- Verification, to prevent storing of the identical value if (resourceSettings.InsertWithVerification) { if (_d.TryGetValue(rn, out btExVal)) { if (btExVal._ByteArrayEquals(rs.Value)) { continue; } } else { //Grabbing from disk if (resourceSettings.HoldOnDisk) { var row = LTrie.GetKey(btKey, false, false); if (row.Exists) { btExVal = row.GetFullValue(false); if (btExVal._ByteArrayEquals(rs.Value)) { if (resourceSettings.HoldInMemory) { _d[rn] = rs.Value; } continue; } } } } } //------- if (resourceSettings.HoldInMemory) { _d[rn] = rs.Value; } if (resourceSettings.HoldOnDisk) { btKey = DataTypesConvertor.ConvertKey <string>(rn); LTrie.Add(btKey, rs.Value); } } if (resourceSettings.HoldOnDisk) { if (resourceSettings.FastUpdates) { LTrie.OverWriteIsAllowed = cov; } LTrie.Commit(); } } catch (Exception ex) { throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.DBriize_RESOURCES_CONCERNING, "in Insert batch", ex); } finally { _sync.ExitWriteLock(); } }
/// <summary> /// Insert resource /// </summary> /// <typeparam name="TValue"></typeparam> /// <param name="resourceName"></param> /// <param name="resourceObject"></param> /// <param name="resourceSettings">resource extra behaviour</param> public void Insert <TValue>(string resourceName, TValue resourceObject, Settings resourceSettings = null) { if (String.IsNullOrEmpty(resourceName)) { return; } if (resourceSettings == null) { resourceSettings = _defaultSetting; } string rn = _urp + resourceName; byte[] btKey = DataTypesConvertor.ConvertKey <string>(rn); byte[] btValue = DataTypesConvertor.ConvertValue <TValue>(resourceObject); _sync.EnterWriteLock(); try { //------- Verification, to prevent storing of the identical value if (resourceSettings.InsertWithVerification) { byte[] btExVal = null; if (_d.TryGetValue(rn, out btExVal)) { if (btExVal._ByteArrayEquals(btValue)) { return; } } else { //Grabbing from disk if (resourceSettings.HoldOnDisk) { var row = LTrie.GetKey(btKey, false, false); if (row.Exists) { btExVal = row.GetFullValue(false); if (btExVal._ByteArrayEquals(btValue)) { if (resourceSettings.HoldInMemory) { _d[rn] = btValue; } return; } } } } } //------- if (resourceSettings.HoldOnDisk) { bool cov = LTrie.OverWriteIsAllowed; if (resourceSettings.FastUpdates) { LTrie.OverWriteIsAllowed = false; } LTrie.Add(btKey, btValue); LTrie.Commit(); if (resourceSettings.FastUpdates) { LTrie.OverWriteIsAllowed = cov; } } if (resourceSettings.HoldInMemory) { _d[rn] = btValue; } } catch (Exception ex) { throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.DBriize_RESOURCES_CONCERNING, "in Insert", ex); } finally { _sync.ExitWriteLock(); } #region "remark" // if (holdInMemory) // { // _sync.EnterWriteLock(); // try // { // _d[resourceName] = btValue; // } // catch (Exception ex) // { // throw ex; // } // finally // { // _sync.ExitWriteLock(); // } // } // Action a = () => // { // _sync.EnterWriteLock(); // try // { // LTrie.Add(btKey, btValue); // LTrie.Commit(); // } // catch (Exception ex) // { // throw ex; // } // finally // { // _sync.ExitWriteLock(); // } // }; //#if NET35 || NETr40 //The same must be use for .NET 4.0 // new System.Threading.Thread(new System.Threading.ThreadStart(() => // { // a(); // })).Start(); //#else // System.Threading.Tasks.Task.Run(() => { // a(); // }); //#endif #endregion }
public void Commit(int transactionThreadId) { if (!this._engine.DBisOperable) { throw DBriizeException.Throw(DBriizeException.eDBriizeExceptions.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 (OperationCanceledException ex) { throw ex; } //catch (System.Threading.ThreadAbortException ex) // { // //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 (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 (OperationCanceledException ex1) { throw ex1; } //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.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 (OperationCanceledException ex) { throw ex; } //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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.TRANSACTION_DOESNT_EXIST); } }
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 (OperationCanceledException ex) { throw ex; } //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 (OperationCanceledException ex) { throw ex; } //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 DBriizeException.Throw(DBriizeException.eDBriizeExceptions.TRANSACTION_DOESNT_EXIST); } }