* Committing Ahzz's patch number 620.

* Description SQLITE Inventory Table locks. *Provided by Openlfiegrid.com 
* Provides missing inventory table locks in SQLite.
ThreadPoolClientBranch
Teravus Ovares 2008-02-19 00:08:28 +00:00
parent 75fe826d57
commit 01cf9d8b7e
1 changed files with 177 additions and 135 deletions

View File

@ -47,6 +47,11 @@ namespace OpenSim.Framework.Data.SQLite
private SqliteDataAdapter invItemsDa; private SqliteDataAdapter invItemsDa;
private SqliteDataAdapter invFoldersDa; private SqliteDataAdapter invFoldersDa;
/// <summary>
/// used to manage concurrent access tothe sqlite database files. Only one thread may open, read, write at a time.
/// </summary>
private object InventoryLock = new object();
/// <summary> /// <summary>
/// Initialises the interface /// Initialises the interface
/// </summary> /// </summary>
@ -126,58 +131,67 @@ namespace OpenSim.Framework.Data.SQLite
private void addFolder(InventoryFolderBase folder) private void addFolder(InventoryFolderBase folder)
{ {
DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; lock (InventoryLock)
DataRow inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folder.folderID));
if (inventoryRow == null)
{ {
inventoryRow = inventoryFolderTable.NewRow(); DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
fillFolderRow(inventoryRow, folder);
inventoryFolderTable.Rows.Add(inventoryRow);
}
else
{
fillFolderRow(inventoryRow, folder);
}
invFoldersDa.Update(ds, "inventoryfolders"); DataRow inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folder.folderID));
if (inventoryRow == null)
{
inventoryRow = inventoryFolderTable.NewRow();
fillFolderRow(inventoryRow, folder);
inventoryFolderTable.Rows.Add(inventoryRow);
}
else
{
fillFolderRow(inventoryRow, folder);
}
invFoldersDa.Update(ds, "inventoryfolders");
}
} }
private void moveFolder(InventoryFolderBase folder) private void moveFolder(InventoryFolderBase folder)
{ {
DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; lock (InventoryLock)
DataRow inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folder.folderID));
if (inventoryRow == null)
{ {
inventoryRow = inventoryFolderTable.NewRow(); DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
fillFolderRow(inventoryRow, folder);
inventoryFolderTable.Rows.Add(inventoryRow);
}
else
{
moveFolderRow(inventoryRow, folder);
}
invFoldersDa.Update(ds, "inventoryfolders"); DataRow inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folder.folderID));
if (inventoryRow == null)
{
inventoryRow = inventoryFolderTable.NewRow();
fillFolderRow(inventoryRow, folder);
inventoryFolderTable.Rows.Add(inventoryRow);
}
else
{
moveFolderRow(inventoryRow, folder);
}
invFoldersDa.Update(ds, "inventoryfolders");
}
} }
private void addItem(InventoryItemBase item) private void addItem(InventoryItemBase item)
{ {
DataTable inventoryItemTable = ds.Tables["inventoryitems"]; lock (InventoryLock)
{
DataTable inventoryItemTable = ds.Tables["inventoryitems"];
DataRow inventoryRow = inventoryItemTable.Rows.Find(Util.ToRawUuidString(item.inventoryID)); DataRow inventoryRow = inventoryItemTable.Rows.Find(Util.ToRawUuidString(item.inventoryID));
if (inventoryRow == null) if (inventoryRow == null)
{ {
inventoryRow = inventoryItemTable.NewRow(); inventoryRow = inventoryItemTable.NewRow();
fillItemRow(inventoryRow, item); fillItemRow(inventoryRow, item);
inventoryItemTable.Rows.Add(inventoryRow); inventoryItemTable.Rows.Add(inventoryRow);
}
else
{
fillItemRow(inventoryRow, item);
}
invItemsDa.Update(ds, "inventoryitems");
} }
else
{
fillItemRow(inventoryRow, item);
}
invItemsDa.Update(ds, "inventoryitems");
} }
public void Shutdown() public void Shutdown()
@ -224,16 +238,19 @@ namespace OpenSim.Framework.Data.SQLite
/// <returns>A List of InventoryItemBase items</returns> /// <returns>A List of InventoryItemBase items</returns>
public List<InventoryItemBase> getInventoryInFolder(LLUUID folderID) public List<InventoryItemBase> getInventoryInFolder(LLUUID folderID)
{ {
List<InventoryItemBase> retval = new List<InventoryItemBase>(); lock (InventoryLock)
DataTable inventoryItemTable = ds.Tables["inventoryitems"];
string selectExp = "parentFolderID = '" + Util.ToRawUuidString(folderID) + "'";
DataRow[] rows = inventoryItemTable.Select(selectExp);
foreach (DataRow row in rows)
{ {
retval.Add(buildItem(row)); List<InventoryItemBase> retval = new List<InventoryItemBase>();
} DataTable inventoryItemTable = ds.Tables["inventoryitems"];
string selectExp = "parentFolderID = '" + Util.ToRawUuidString(folderID) + "'";
DataRow[] rows = inventoryItemTable.Select(selectExp);
foreach (DataRow row in rows)
{
retval.Add(buildItem(row));
}
return retval; return retval;
}
} }
/// <summary> /// <summary>
@ -249,27 +266,30 @@ namespace OpenSim.Framework.Data.SQLite
// see InventoryItemBase.getUserRootFolder // see InventoryItemBase.getUserRootFolder
public InventoryFolderBase getUserRootFolder(LLUUID user) public InventoryFolderBase getUserRootFolder(LLUUID user)
{ {
List<InventoryFolderBase> folders = new List<InventoryFolderBase>(); lock (InventoryLock)
DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
string selectExp = "agentID = '" + Util.ToRawUuidString(user) + "' AND parentID = '" +
Util.ToRawUuidString(LLUUID.Zero) + "'";
DataRow[] rows = inventoryFolderTable.Select(selectExp);
foreach (DataRow row in rows)
{ {
folders.Add(buildFolder(row)); List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
} DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
string selectExp = "agentID = '" + Util.ToRawUuidString(user) + "' AND parentID = '" +
Util.ToRawUuidString(LLUUID.Zero) + "'";
DataRow[] rows = inventoryFolderTable.Select(selectExp);
foreach (DataRow row in rows)
{
folders.Add(buildFolder(row));
}
// There should only ever be one root folder for a user. However, if there's more // There should only ever be one root folder for a user. However, if there's more
// than one we'll simply use the first one rather than failing. It would be even // than one we'll simply use the first one rather than failing. It would be even
// nicer to print some message to this effect, but this feels like it's too low a // nicer to print some message to this effect, but this feels like it's too low a
// to put such a message out, and it's too minor right now to spare the time to // to put such a message out, and it's too minor right now to spare the time to
// suitably refactor. // suitably refactor.
if (folders.Count > 0) if (folders.Count > 0)
{ {
return folders[0]; return folders[0];
} }
return null; return null;
}
} }
/// <summary> /// <summary>
@ -279,12 +299,15 @@ namespace OpenSim.Framework.Data.SQLite
/// <param name="parentID">ID of parent</param> /// <param name="parentID">ID of parent</param>
protected void getInventoryFolders(ref List<InventoryFolderBase> folders, LLUUID parentID) protected void getInventoryFolders(ref List<InventoryFolderBase> folders, LLUUID parentID)
{ {
DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; lock (InventoryLock)
string selectExp = "parentID = '" + Util.ToRawUuidString(parentID) + "'";
DataRow[] rows = inventoryFolderTable.Select(selectExp);
foreach (DataRow row in rows)
{ {
folders.Add(buildFolder(row)); DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
string selectExp = "parentID = '" + Util.ToRawUuidString(parentID) + "'";
DataRow[] rows = inventoryFolderTable.Select(selectExp);
foreach (DataRow row in rows)
{
folders.Add(buildFolder(row));
}
} }
} }
@ -323,14 +346,17 @@ namespace OpenSim.Framework.Data.SQLite
/// <returns>A class containing item information</returns> /// <returns>A class containing item information</returns>
public InventoryItemBase getInventoryItem(LLUUID item) public InventoryItemBase getInventoryItem(LLUUID item)
{ {
DataRow row = ds.Tables["inventoryitems"].Rows.Find(Util.ToRawUuidString(item)); lock (InventoryLock)
if (row != null)
{ {
return buildItem(row); DataRow row = ds.Tables["inventoryitems"].Rows.Find(Util.ToRawUuidString(item));
} if (row != null)
else {
{ return buildItem(row);
return null; }
else
{
return null;
}
} }
} }
@ -346,15 +372,17 @@ namespace OpenSim.Framework.Data.SQLite
// better to leave multi region at this point. It does mean // better to leave multi region at this point. It does mean
// that you don't get to see system textures why creating // that you don't get to see system textures why creating
// clothes and the like. :( // clothes and the like. :(
lock (InventoryLock)
DataRow row = ds.Tables["inventoryfolders"].Rows.Find(Util.ToRawUuidString(folder));
if (row != null)
{ {
return buildFolder(row); DataRow row = ds.Tables["inventoryfolders"].Rows.Find(Util.ToRawUuidString(folder));
} if (row != null)
else {
{ return buildFolder(row);
return null; }
else
{
return null;
}
} }
} }
@ -382,18 +410,20 @@ namespace OpenSim.Framework.Data.SQLite
/// <param name="item"></param> /// <param name="item"></param>
public void deleteInventoryItem(LLUUID itemID) public void deleteInventoryItem(LLUUID itemID)
{ {
DataTable inventoryItemTable = ds.Tables["inventoryitems"]; lock (InventoryLock)
DataRow inventoryRow = inventoryItemTable.Rows.Find(Util.ToRawUuidString(itemID));
if (inventoryRow != null)
{ {
inventoryRow.Delete(); DataTable inventoryItemTable = ds.Tables["inventoryitems"];
DataRow inventoryRow = inventoryItemTable.Rows.Find(Util.ToRawUuidString(itemID));
if (inventoryRow != null)
{
inventoryRow.Delete();
}
invItemsDa.Update(ds, "inventoryitems");
} }
invItemsDa.Update(ds, "inventoryitems");
} }
/// <summary> /// <summary>
/// Delete all items in the specified folder /// Delete all items in the specified folder
/// </summary> /// </summary>
@ -443,31 +473,34 @@ namespace OpenSim.Framework.Data.SQLite
/// <param name="item"></param> /// <param name="item"></param>
public void deleteInventoryFolder(LLUUID folderID) public void deleteInventoryFolder(LLUUID folderID)
{ {
List<InventoryFolderBase> subFolders = getFolderHierarchy(Util.ToRawUuidString(folderID)); lock (InventoryLock)
DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
DataRow inventoryRow;
//Delete all sub-folders
foreach (InventoryFolderBase f in subFolders)
{ {
inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(f.folderID)); List<InventoryFolderBase> subFolders = getFolderHierarchy(Util.ToRawUuidString(folderID));
DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
DataRow inventoryRow;
//Delete all sub-folders
foreach (InventoryFolderBase f in subFolders)
{
inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(f.folderID));
if (inventoryRow != null)
{
deleteItemsInFolder(Util.ToRawUuidString(f.folderID));
inventoryRow.Delete();
}
}
//Delete the actual row
inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folderID));
if (inventoryRow != null) if (inventoryRow != null)
{ {
deleteItemsInFolder(Util.ToRawUuidString(f.folderID)); deleteItemsInFolder(Util.ToRawUuidString(folderID));
inventoryRow.Delete(); inventoryRow.Delete();
} }
}
//Delete the actual row invFoldersDa.Update(ds, "inventoryfolders");
inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folderID));
if (inventoryRow != null)
{
deleteItemsInFolder(Util.ToRawUuidString(folderID));
inventoryRow.Delete();
} }
invFoldersDa.Update(ds, "inventoryfolders");
} }
/*********************************************************************** /***********************************************************************
@ -517,30 +550,36 @@ namespace OpenSim.Framework.Data.SQLite
private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn)
{ {
da.InsertCommand = createInsertCommand("inventoryitems", ds.Tables["inventoryitems"]); lock (InventoryLock)
da.InsertCommand.Connection = conn; {
da.InsertCommand = createInsertCommand("inventoryitems", ds.Tables["inventoryitems"]);
da.InsertCommand.Connection = conn;
da.UpdateCommand = createUpdateCommand("inventoryitems", "UUID=:UUID", ds.Tables["inventoryitems"]); da.UpdateCommand = createUpdateCommand("inventoryitems", "UUID=:UUID", ds.Tables["inventoryitems"]);
da.UpdateCommand.Connection = conn; da.UpdateCommand.Connection = conn;
SqliteCommand delete = new SqliteCommand("delete from inventoryitems where UUID = :UUID"); SqliteCommand delete = new SqliteCommand("delete from inventoryitems where UUID = :UUID");
delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); delete.Parameters.Add(createSqliteParameter("UUID", typeof(String)));
delete.Connection = conn; delete.Connection = conn;
da.DeleteCommand = delete; da.DeleteCommand = delete;
}
} }
private void setupFoldersCommands(SqliteDataAdapter da, SqliteConnection conn) private void setupFoldersCommands(SqliteDataAdapter da, SqliteConnection conn)
{ {
da.InsertCommand = createInsertCommand("inventoryfolders", ds.Tables["inventoryfolders"]); lock (InventoryLock)
da.InsertCommand.Connection = conn; {
da.InsertCommand = createInsertCommand("inventoryfolders", ds.Tables["inventoryfolders"]);
da.InsertCommand.Connection = conn;
da.UpdateCommand = createUpdateCommand("inventoryfolders", "UUID=:UUID", ds.Tables["inventoryfolders"]); da.UpdateCommand = createUpdateCommand("inventoryfolders", "UUID=:UUID", ds.Tables["inventoryfolders"]);
da.UpdateCommand.Connection = conn; da.UpdateCommand.Connection = conn;
SqliteCommand delete = new SqliteCommand("delete from inventoryfolders where UUID = :UUID"); SqliteCommand delete = new SqliteCommand("delete from inventoryfolders where UUID = :UUID");
delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); delete.Parameters.Add(createSqliteParameter("UUID", typeof(String)));
delete.Connection = conn; delete.Connection = conn;
da.DeleteCommand = delete; da.DeleteCommand = delete;
}
} }
private InventoryFolderBase buildFolder(DataRow row) private InventoryFolderBase buildFolder(DataRow row)
@ -579,15 +618,18 @@ namespace OpenSim.Framework.Data.SQLite
private void InitDB(SqliteConnection conn) private void InitDB(SqliteConnection conn)
{ {
string createInventoryItems = defineTable(createInventoryItemsTable()); lock (InventoryLock)
string createInventoryFolders = defineTable(createInventoryFoldersTable()); {
string createInventoryItems = defineTable(createInventoryItemsTable());
string createInventoryFolders = defineTable(createInventoryFoldersTable());
SqliteCommand pcmd = new SqliteCommand(createInventoryItems, conn); SqliteCommand pcmd = new SqliteCommand(createInventoryItems, conn);
SqliteCommand scmd = new SqliteCommand(createInventoryFolders, conn); SqliteCommand scmd = new SqliteCommand(createInventoryFolders, conn);
conn.Open(); conn.Open();
pcmd.ExecuteNonQuery(); pcmd.ExecuteNonQuery();
scmd.ExecuteNonQuery(); scmd.ExecuteNonQuery();
conn.Close(); conn.Close();
}
} }
private bool TestTables(SqliteConnection conn) private bool TestTables(SqliteConnection conn)
@ -631,4 +673,4 @@ namespace OpenSim.Framework.Data.SQLite
return true; return true;
} }
} }
} }