internal LTrie GetTable(string userTableName)
{
string tableName = GetUserTableNameAsString(userTableName);
//TODO pattern based mapping If table doesn't exist we create it with properties which could be supplied after db init as regex theme.
//Schema protocol: 2 bytes - protocol version, other data
//For protocol 1: first 8 bytes will be TheFileName, starting from db10000-dbN (0-N ulong). up to 10000 are reserved for dbreeze.
//Table names are UTF-8 based, no limits
ulong fileName = 0;
OpenTable otl = null;
_sync_openTablesHolder.EnterUpgradeableReadLock();
try
{
_openTablesHolder.TryGetValue(tableName, out otl);
if (otl != null)
{
//Try to increase usage and return LTrie
otl.Add();
return otl.Trie;
}
//Probably table Exists in db but not in openTablesHolder
_sync_openTablesHolder.EnterWriteLock();
try
{
//UpgradeableRead recheck
_openTablesHolder.TryGetValue(tableName, out otl);
if (otl != null)
{
//Try to increase usage and return LTrie
otl.Add();
return otl.Trie;
}
byte[] btTableName = GetUserTableNameAsByte(userTableName);
//Trying to get fileName from cache
fileName = this.cachedTableNames.GetFileName(tableName);
// LTrieRow row = null;
bool tableExists = false;
if (fileName == 0)
{
LTrieRow row = LTrie.GetKey(btTableName, false);
if (row.Exists)
{
tableExists = true;
byte[] fullValue = row.GetFullValue(false);
//Can be parsed different. First protocol version is 1
ushort schemeProtocol = fullValue.Substring(0, 2).To_UInt16_BigEndian();
switch (schemeProtocol)
{
case 1:
fileName = fullValue.Substring(2, 8).To_UInt64_BigEndian();
break;
default:
throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.SCHEME_FILE_PROTOCOL_IS_UNKNOWN);
}
}
else
{
tableExists = false;
//Creating new table.
//Checking table name validity
//this will throw exception, if not valid
DbUserTables.UserTableNameIsOk(userTableName);
//Creating such table and renewing LastFileNumber counter
//Adding to LastFileNumber
LastFileNumber++;
////Deleting physical files related to the table, if they existed - normally they should not
//DeleteAllReleatedTableFiles(Path.Combine(Engine.MainFolder, LastFileNumber.ToString()));
byte[] lft = LastFileNumber.To_8_bytes_array_BigEndian();
//Writing this number to Schema file
LTrie.Add(Encoding.UTF8.GetBytes(LastFileNumberKeyName), lft);
//Creating table self and writing to Schema file
LTrie.Add(btTableName,
new byte[] { 0, 1 } //Protocol version 1
.Concat(lft)); //Number of the file
//Committing both records
LTrie.Commit();
fileName = LastFileNumber;
this.cachedTableNames.Add(tableName, fileName);
}
}
else
tableExists = true;
//Creating LTrie, adding it to _openTablesHolder
//Seeting up Trie TableName, OTHER SETTINGS
TrieSettings ts = new TrieSettings();
IStorage storage = null;
////Checking if default Flusg Disk behaviour was overriden
//ts.DiskFlushBehaviour = Engine.Configuration.DiskFlushBehaviour;
////Checking if we have alternative DiskFlush behaviour
//foreach (var pattern in Engine.Configuration.AlternativeDiskFlushBehaviour)
//{
// //pattern.Key
// if (DbUserTables.PatternsIntersect(pattern.Key, userTableName))
// {
// ts.DiskFlushBehaviour = pattern.Value;
// break;
// }
//}
string alternativeTableLocation = String.Empty;
if (CheckAlternativeTableLocationsIntersections(userTableName, out alternativeTableLocation))
{
ts.StorageWasOverriden = true;
if (alternativeTableLocation == String.Empty)
{
ts.AlternativeTableStorageType = DBreezeConfiguration.eStorage.MEMORY;
storage = new StorageLayer(Path.Combine(Engine.MainFolder, fileName.ToString()), ts, Engine.Configuration);
}
else
{
ts.AlternativeTableStorageType = DBreezeConfiguration.eStorage.DISK;
ts.AlternativeTableStorageFolder = alternativeTableLocation;
DirectoryInfo diAlt = new DirectoryInfo(alternativeTableLocation);
if (!diAlt.Exists)
diAlt.Create();
if (!tableExists)
{
//Deleting physical files related to the table, if they existed - normally they should not
DeleteAllReleatedTableFiles(Path.Combine(ts.AlternativeTableStorageFolder, LastFileNumber.ToString()));
}
storage = new StorageLayer(Path.Combine(ts.AlternativeTableStorageFolder, fileName.ToString()), ts, Engine.Configuration);
}
}
else
{
if (!tableExists)
{
//Deleting physical files related to the table, if they existed - normally they should not
DeleteAllReleatedTableFiles(Path.Combine(Engine.MainFolder, LastFileNumber.ToString()));
}
storage = new StorageLayer(Path.Combine(Engine.MainFolder, fileName.ToString()), ts, Engine.Configuration);
}
//storage = new StorageLayer(Path.Combine(Engine.MainFolder, fileName.ToString()), ts, Engine.Configuration);
LTrie trie = new LTrie(storage);
//Setting LTrie user table name
trie.TableName = userTableName;
//_openTablesHolder.Add(tableName, trie);
//Automatically increased usage in OpenTable constructor
_openTablesHolder.Add(tableName, new OpenTable(trie));
return trie;
}
catch (System.Exception ex)
{
//CASCADE
throw ex;
}
finally
{
_sync_openTablesHolder.ExitWriteLock();
}
}
catch (Exception ex)
{
throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.SCHEME_GET_TABLE_WRITE_FAILED, tableName, ex);
}
finally
{
_sync_openTablesHolder.ExitUpgradeableReadLock();
}
}