banshee r4967 - in trunk/banshee: . src/Core/Banshee.Services/Banshee.Collection src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Database src/Core/Banshee.Services/Banshee.Playlist src/Extensions/Banshee.Daap/Banshee.Daap src/Libraries/Hyena/Hyena.Data.Sqlite
- From: gburt svn gnome org
- To: svn-commits-list gnome org
- Subject: banshee r4967 - in trunk/banshee: . src/Core/Banshee.Services/Banshee.Collection src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Database src/Core/Banshee.Services/Banshee.Playlist src/Extensions/Banshee.Daap/Banshee.Daap src/Libraries/Hyena/Hyena.Data.Sqlite
- Date: Mon, 26 Jan 2009 04:24:37 +0000 (UTC)
Author: gburt
Date: Mon Jan 26 04:24:37 2009
New Revision: 4967
URL: http://svn.gnome.org/viewvc/banshee?rev=4967&view=rev
Log:
2009-01-25 Gabriel Burt <gabriel burt gmail com>
* Core/Banshee.Services/Banshee.Collection.Database/DatabaseFilterListModel.cs:
* Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs:
* Core/Banshee.Services/Banshee.Collection/FilterListModel.cs:
* Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs:
* Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs:
* Extensions/Banshee.Daap/Banshee.Daap/DaapSource.cs:
* Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs:
* Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteConnection.cs:
* Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs: Fix the
Begin/Commit/RollbackTransaction methods in HyenaSqliteConnection. Use
transactions when importing media, loading DAAP shares, and reloading
filter models.
Modified:
trunk/banshee/ChangeLog
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseFilterListModel.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection/FilterListModel.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapSource.cs
trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs
trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteConnection.cs
trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseFilterListModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseFilterListModel.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseFilterListModel.cs Mon Jan 26 04:24:37 2009
@@ -49,7 +49,7 @@
private long count;
private string reload_fragment;
-
+
private string reload_fragment_format;
protected string ReloadFragmentFormat {
get { return reload_fragment_format; }
@@ -57,6 +57,7 @@
}
protected readonly U select_all_item;
+ private HyenaSqliteConnection connection;
public DatabaseFilterListModel (string name, string label, Banshee.Sources.DatabaseSource source,
DatabaseTrackListModel trackModel, HyenaSqliteConnection connection, SqliteModelProvider<T> provider, U selectAllItem, string uuid)
@@ -67,6 +68,7 @@
FilterLabel = label;
select_all_item = selectAllItem;
+ this.connection = connection;
cache = new BansheeModelCache <T> (connection, uuid, this, provider);
cache.HasSelectAllItem = true;
}
@@ -148,12 +150,16 @@
{
GenerateReloadFragment ();
- cache.SaveSelection ();
- cache.Reload ();
- cache.UpdateAggregates ();
- cache.RestoreSelection ();
+ lock (cache) {
+ connection.BeginTransaction ();
+ cache.SaveSelection ();
+ cache.Reload ();
+ cache.UpdateAggregates ();
+ cache.RestoreSelection ();
+ connection.CommitTransaction ();
- count = cache.Count + 1;
+ count = cache.Count + 1;
+ }
UpdateSelectAllItem (count - 1);
@@ -166,7 +172,9 @@
if (index == 0)
return select_all_item;
- return cache.GetValue (index - 1);
+ lock (cache) {
+ return cache.GetValue (index - 1);
+ }
}
}
@@ -187,7 +195,11 @@
}
public int CacheId {
- get { return (int) cache.CacheId; }
+ get {
+ lock (cache) {
+ return (int) cache.CacheId;
+ }
+ }
}
public IEnumerable<object> GetSelectedObjects ()
@@ -199,7 +211,9 @@
public override void InvalidateCache (bool notify)
{
- cache.Clear ();
+ lock (cache) {
+ cache.Clear ();
+ }
if (notify) {
OnReloaded ();
}
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs Mon Jan 26 04:24:37 2009
@@ -169,7 +169,7 @@
// TODO note, there is deadlock potential here b/c of locking of shared commands and blocking
// because of transactions. Needs to be fixed in HyenaDatabaseConnection.
- //ServiceManager.DbConnection.BeginTransaction ();
+ ServiceManager.DbConnection.BeginTransaction ();
try {
track = new DatabaseTrackInfo ();
track.Uri = uri;
@@ -183,9 +183,9 @@
track.Save (false);
- //ServiceManager.DbConnection.CommitTransaction ();
+ ServiceManager.DbConnection.CommitTransaction ();
} catch (Exception) {
- //ServiceManager.DbConnection.RollbackTransaction ();
+ ServiceManager.DbConnection.RollbackTransaction ();
throw;
}
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection/FilterListModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection/FilterListModel.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection/FilterListModel.cs Mon Jan 26 04:24:37 2009
@@ -70,6 +70,11 @@
private void HandleSelectionChanged (object sender, EventArgs args)
{
+ Banshee.Base.ThreadAssist.SpawnFromMain (ReloadBrowsingModel);
+ }
+
+ private void ReloadBrowsingModel ()
+ {
browsing_model.Reload (this);
}
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs Mon Jan 26 04:24:37 2009
@@ -62,6 +62,7 @@
if (Banshee.Base.ApplicationContext.CommandLine.Contains ("debug-sql")) {
Hyena.Data.Sqlite.HyenaSqliteCommand.LogAll = true;
+ WarnIfCalledFromThread = Banshee.Base.ThreadAssist.MainThread;
}
}
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs Mon Jan 26 04:24:37 2009
@@ -277,12 +277,13 @@
HyenaSqliteCommand select_command = new HyenaSqliteCommand (String.Format ("SELECT ItemID FROM CoreCache WHERE ModelID = {0} LIMIT ?, ?", DatabaseTrackModel.CacheId));
// Reorder the selected items
- // TODO put in transaction
+ ServiceManager.DbConnection.BeginTransaction ();
foreach (RangeCollection.Range range in TrackModel.Selection.Ranges) {
foreach (long entry_id in ServiceManager.DbConnection.QueryEnumerable<long> (select_command, range.Start, range.Count)) {
ServiceManager.DbConnection.Execute (update_command, order++, entry_id);
}
}
+ ServiceManager.DbConnection.CommitTransaction ();
Reload ();
}
@@ -360,12 +361,12 @@
{
if (!temps_cleared) {
temps_cleared = true;
+ ServiceManager.DbConnection.BeginTransaction ();
ServiceManager.DbConnection.Execute (@"
- BEGIN TRANSACTION;
- DELETE FROM CorePlaylistEntries WHERE PlaylistID IN (SELECT PlaylistID FROM CorePlaylists WHERE IsTemporary = 1);
- DELETE FROM CorePlaylists WHERE IsTemporary = 1;
- COMMIT TRANSACTION"
+ DELETE FROM CorePlaylistEntries WHERE PlaylistID IN (SELECT PlaylistID FROM CorePlaylists WHERE IsTemporary = 1);
+ DELETE FROM CorePlaylists WHERE IsTemporary = 1;"
);
+ ServiceManager.DbConnection.CommitTransaction ();
}
}
Modified: trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapSource.cs (original)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapSource.cs Mon Jan 26 04:24:37 2009
@@ -31,6 +31,7 @@
using Mono.Unix;
using Hyena;
+using Hyena.Data.Sqlite;
using Banshee.Base;
using Banshee.Collection;
@@ -243,14 +244,23 @@
notify_every -= notify_every % 250;
int count = 0;
- // TODO use transactions when fixed
DaapTrackInfo daap_track = null;
+
+ HyenaSqliteConnection conn = ServiceManager.DbConnection;
+ conn.BeginTransaction ();
foreach (DAAP.Track track in database.Tracks) {
daap_track = new DaapTrackInfo (track, this);
// Only notify once in a while because otherwise the source Reloading slows things way down
- daap_track.Save (++count % notify_every == 0);
+ if (++count % notify_every == 0) {
+ conn.CommitTransaction ();
+ daap_track.Save (true);
+ conn.BeginTransaction ();
+ } else {
+ daap_track.Save (false);
+ }
}
+ conn.CommitTransaction ();
// Save the last track once more to trigger the NotifyTrackAdded
if (daap_track != null) {
Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs (original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs Mon Jan 26 04:24:37 2009
@@ -58,10 +58,11 @@
public class HyenaSqliteCommand
{
- protected object result = null;
+ private object result = null;
private Exception execution_exception = null;
private bool finished = false;
+ private ManualResetEvent finished_event = new ManualResetEvent (true);
private string command;
private string command_format = null;
private string command_formatted = null;
@@ -149,6 +150,7 @@
execution_exception = e;
}
+ finished_event.Reset ();
finished = true;
}
@@ -164,6 +166,7 @@
finished = false;
conn.ClaimResult ();
+ finished_event.Set ();
if (execution_exception != null) {
throw execution_exception;
@@ -172,6 +175,11 @@
return ret;
}
+ internal void WaitIfNotFinished ()
+ {
+ finished_event.WaitOne ();
+ }
+
internal HyenaSqliteCommand ApplyValues (params object [] param_values)
{
if (command_format == null) {
@@ -201,7 +209,7 @@
return this;
}
- protected static object SqlifyObject (object o)
+ private static object SqlifyObject (object o)
{
if (o is string) {
return String.Format ("'{0}'", (o as string).Replace ("'", "''"));
Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteConnection.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteConnection.cs (original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteConnection.cs Mon Jan 26 04:24:37 2009
@@ -90,7 +90,12 @@
private SqliteConnection connection;
private string dbpath;
+ // These are 'parallel' queues; that is, when a value is pushed or popped to
+ // one, a value is pushed or popped to all three.
private Queue<HyenaSqliteCommand> command_queue = new Queue<HyenaSqliteCommand>();
+ private Queue<object[]> args_queue = new Queue<object[]>();
+ private Queue<object> arg_queue = new Queue<object>();
+
private Thread queue_thread;
private volatile bool dispose_requested = false;
private volatile int results_ready = 0;
@@ -100,6 +105,12 @@
private volatile Thread transaction_thread = null;
private ManualResetEvent transaction_signal = new ManualResetEvent (true);
+ private Thread warn_if_called_from_thread;
+ public Thread WarnIfCalledFromThread {
+ get { return warn_if_called_from_thread; }
+ set { warn_if_called_from_thread = value; }
+ }
+
internal ManualResetEvent ResultReadySignal {
get { return result_ready_signal; }
}
@@ -110,6 +121,7 @@
{
this.dbpath = dbpath;
queue_thread = new Thread(ProcessQueue);
+ queue_thread.Name = String.Format ("HyenaSqliteConnection ({0})", dbpath);
queue_thread.IsBackground = true;
queue_thread.Start();
}
@@ -121,18 +133,16 @@
// SELECT multiple column queries
public IDataReader Query (HyenaSqliteCommand command)
{
- lock (command) {
- command.CommandType = HyenaCommandType.Reader;
- QueueCommand (command);
- return command.WaitForResult (this) as SqliteDataReader;
- }
+ command.CommandType = HyenaCommandType.Reader;
+ QueueCommand (command, null);
+ return command.WaitForResult (this) as SqliteDataReader;
}
public IDataReader Query (HyenaSqliteCommand command, params object [] param_values)
{
- lock (command) {
- return Query (command.ApplyValues (param_values));
- }
+ command.CommandType = HyenaCommandType.Reader;
+ QueueCommand (command, param_values);
+ return command.WaitForResult (this) as SqliteDataReader;
}
public IDataReader Query (string command_str, params object [] param_values)
@@ -158,8 +168,11 @@
public IEnumerable<T> QueryEnumerable<T> (HyenaSqliteCommand command, params object [] param_values)
{
- lock (command) {
- return QueryEnumerable<T> (command.ApplyValues (param_values));
+ Type type = typeof (T);
+ using (IDataReader reader = Query (command, param_values)) {
+ while (reader.Read ()) {
+ yield return (T) SqliteUtils.FromDbFormat (type, reader[0]);
+ }
}
}
@@ -176,21 +189,18 @@
// SELECT single column, single row queries
public T Query<T> (HyenaSqliteCommand command)
{
- object result = null;
- lock (command) {
- command.CommandType = HyenaCommandType.Scalar;
- QueueCommand (command);
- result = command.WaitForResult (this);
- }
-
+ command.CommandType = HyenaCommandType.Scalar;
+ QueueCommand (command, null);
+ object result = command.WaitForResult (this);
return (T)SqliteUtils.FromDbFormat (typeof (T), result);
}
public T Query<T> (HyenaSqliteCommand command, params object [] param_values)
{
- lock (command) {
- return Query<T> (command.ApplyValues (param_values));
- }
+ command.CommandType = HyenaCommandType.Scalar;
+ QueueCommand (command, param_values);
+ object result = command.WaitForResult (this);
+ return (T)SqliteUtils.FromDbFormat (typeof (T), result);
}
public T Query<T> (string command_str, params object [] param_values)
@@ -206,18 +216,16 @@
// INSERT, UPDATE, DELETE queries
public int Execute (HyenaSqliteCommand command)
{
- lock (command) {
- command.CommandType = HyenaCommandType.Execute;;
- QueueCommand(command);
- return (int) command.WaitForResult (this);
- }
+ command.CommandType = HyenaCommandType.Execute;;
+ QueueCommand(command, null);
+ return (int) command.WaitForResult (this);
}
public int Execute (HyenaSqliteCommand command, params object [] param_values)
{
- lock (command) {
- return Execute (command.ApplyValues (param_values));
- }
+ command.CommandType = HyenaCommandType.Execute;;
+ QueueCommand(command, param_values);
+ return (int) command.WaitForResult (this);
}
public int Execute (string command_str, params object [] param_values)
@@ -245,7 +253,7 @@
// the command locking and values applied only when we know the calling thread is not blocking by a
// transaction thread.
//
- /*public void BeginTransaction ()
+ public void BeginTransaction ()
{
if (transaction_thread == Thread.CurrentThread) {
throw new Exception ("Can't start a recursive transaction");
@@ -297,7 +305,7 @@
// Let any other threads continue
transaction_signal.Set ();
}
- }*/
+ }
public bool TableExists (string tableName)
{
@@ -365,12 +373,28 @@
#region Private Queue Methods
- private void QueueCommand(HyenaSqliteCommand command)
+ private void QueueCommand(HyenaSqliteCommand command, object [] args)
{
+ QueueCommand (command, null, args);
+ }
+
+ private void QueueCommand(HyenaSqliteCommand command, object arg)
+ {
+ QueueCommand (command, arg, null);
+ }
+
+ private void QueueCommand(HyenaSqliteCommand command, object arg, object [] args)
+ {
+ if (warn_if_called_from_thread != null && Thread.CurrentThread == warn_if_called_from_thread) {
+ Hyena.Log.Warning ("HyenaSqliteConnection command issued from the main thread");
+ }
+
while (true) {
lock (command_queue) {
if (transaction_thread == null || Thread.CurrentThread == transaction_thread) {
command_queue.Enqueue (command);
+ args_queue.Enqueue (args);
+ arg_queue.Enqueue (arg);
break;
}
}
@@ -401,11 +425,26 @@
while (!dispose_requested) {
while (command_queue.Count > 0) {
HyenaSqliteCommand command;
+ object [] args;
+ object arg;
lock (command_queue) {
command = command_queue.Dequeue ();
+ args = args_queue.Dequeue ();
+ arg = arg_queue.Dequeue ();
+ }
+
+ // Ensure the command is not altered while applying values or executing
+ lock (command) {
+ command.WaitIfNotFinished ();
+
+ if (arg != null) {
+ command.ApplyValues (arg);
+ } else if (args != null) {
+ command.ApplyValues (args);
+ }
+
+ command.Execute (this, connection);
}
-
- command.Execute (this, connection);
lock (command_queue) {
results_ready++;
Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs (original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs Mon Jan 26 04:24:37 2009
@@ -283,7 +283,7 @@
lock (this) {
if (last_reload_fragment != model.ReloadFragment || last_reload_command == null) {
last_reload_fragment = model.ReloadFragment;
- last_reload_command = new HyenaSqliteCommand (String.Format ("BEGIN; {0}{1}; COMMIT", reload_sql, last_reload_fragment));
+ last_reload_command = new HyenaSqliteCommand (String.Format ("{0}{1}", reload_sql, last_reload_fragment));
}
Clear ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]