banshee r3332 - in trunk/banshee: . build src/Core/Banshee.Core/Banshee.IO src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Configuration src/Core/Banshee.Services/Banshee.Database src/Core/Banshee.Services/Banshee.Library src/Core/Banshee.Services/Banshee.MediaEngine src/Core/Banshee.Services/Banshee.PlayerMigration src/Core/Banshee.Services/Banshee.Playlist src/Core/Banshee.Services/Banshee.ServiceStack src/Core/Banshee.Services/Banshee.SmartPlaylist src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient/Banshee.SmartPlaylist.Gui src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue src/Libraries/Hyena/Hyena.Data.Sqlite
- From: gburt svn gnome org
- To: svn-commits-list gnome org
- Subject: banshee r3332 - in trunk/banshee: . build src/Core/Banshee.Core/Banshee.IO src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Configuration src/Core/Banshee.Services/Banshee.Database src/Core/Banshee.Services/Banshee.Library src/Core/Banshee.Services/Banshee.MediaEngine src/Core/Banshee.Services/Banshee.PlayerMigration src/Core/Banshee.Services/Banshee.Playlist src/Core/Banshee.Services/Banshee.ServiceStack src/Core/Banshee.Services/Banshee.SmartPlaylist src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient/Banshee.SmartPlaylist.Gui src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue src/Libraries/Hyena/Hyena.Data.Sqlite
- Date: Wed, 27 Feb 2008 05:44:08 +0000 (GMT)
Author: gburt
Date: Wed Feb 27 05:44:07 2008
New Revision: 3332
URL: http://svn.gnome.org/viewvc/banshee?rev=3332&view=rev
Log:
2008-02-26 Gabriel Burt <gabriel burt gmail com>
This commit brings back a thread-safe database layer. Unfortunately, that
currently means switching back to the deprecated Mono.Data.SqliteClient
library. Mono.Data.Sqlite does not allow executing a command in one
thread and reading it in another, where M.D.SqliteClient does.
* Makefile.am: Add BANSHEE_DEV_MONO_OPTIONS env var to enable setting
--profile=default:stat for example to run with make run.
* build/build.environment.mk: Depend on Mono.Data.SqliteClient again.
Mono.Data.Sqlite requires that even reading the results of a query must be
done in the same thread that ran the query/owns the connection.
* src/Core/Banshee.Core/Banshee.IO/Provider.cs: Clean up.
* src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs:
* src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs:
* src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs:
* src/Core/Banshee.Services/Banshee.SmartPlaylist/Migrator.cs:
* src/Core/Banshee.Services/Banshee.Configuration/DatabaseConfigurationClient.cs:
* src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs:
* src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs:
* src/Core/Banshee.Services/Banshee.Collection.Database/TrackListDatabaseModel.cs:
* src/Core/Banshee.Services/Banshee.Collection.Database/LibraryAlbumInfo.cs:
* src/Core/Banshee.Services/Banshee.Collection.Database/LibraryArtistInfo.cs:
* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs:
New HyenaSqliteConnection API.
* src/Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs:
Get rid of unused ctor and execute useful performance-related PRAGMAs.
* src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs:
Use HyenaSqliteConnection's utility methods, new API. Add UserJob to
rescan a user's songs when migrating over in order to get fields we now
store in the database - like Disc, etc.
* src/Core/Banshee.Services/Banshee.Library/LibraryImportManager.cs: Get
rid of ProxyToMain call.
* src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs:
Add null check.
* src/Core/Banshee.Services/Banshee.ServiceStack/Application.cs: Reorder
loading of Library, Library playlists.
* src/Core/Banshee.Services/Banshee.PlayerMigration/AmarokPlayerImportSource.cs:
Use Mono.Data.SqliteClient.
* src/Core/Banshee.Services/Banshee.ServiceStack/UserJob.cs: Avoid
duplication in ctors.
* src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs: Increase the
delay betwen refreshes.
* src/Core/Banshee.ThickClient/Banshee.SmartPlaylist.Gui/Editor.cs: Get
rid of ProxyToMain calls.
* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs:
* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs: Do
not login to Last.fm radio until a source is activated.
* src/Libraries/Hyena/Hyena.Data.Sqlite/DatabaseColumn.cs: Convert longs
in a different way that M.D.SqliteClient likes.
* src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs: Combined
with QueuedSqliteCommand code, meant to be called by threaded/queued
HyenaSqliteConnection.
* src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteConnection.cs: Combined
with QueuedSqliteDatabase code (from F-Spot's copy). Supports blocking
other threads during transactions and has no busy-waits.
Modified:
trunk/banshee/ChangeLog
trunk/banshee/Makefile.am
trunk/banshee/build/build.environment.mk
trunk/banshee/src/Core/Banshee.Core/Banshee.IO/Provider.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/LibraryAlbumInfo.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/LibraryArtistInfo.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/TrackListDatabaseModel.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Configuration/DatabaseConfigurationClient.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibraryImportManager.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.PlayerMigration/AmarokPlayerImportSource.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/Application.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/UserJob.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/Migrator.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
trunk/banshee/src/Core/Banshee.ThickClient/Banshee.SmartPlaylist.Gui/Editor.cs
trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs
trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs
trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/DatabaseColumn.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
trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs
Modified: trunk/banshee/Makefile.am
==============================================================================
--- trunk/banshee/Makefile.am (original)
+++ trunk/banshee/Makefile.am Wed Feb 27 05:44:07 2008
@@ -61,7 +61,7 @@
run:
@pushd bin; \
- $(MONO) --debug Nereid.exe --debug --uninstalled $(BANSHEE_DEV_OPTIONS); \
+ $(MONO) --debug $(BANSHEE_DEV_MONO_OPTIONS) Nereid.exe --debug --uninstalled $(BANSHEE_DEV_OPTIONS); \
popd;
clean-local:
Modified: trunk/banshee/build/build.environment.mk
==============================================================================
--- trunk/banshee/build/build.environment.mk (original)
+++ trunk/banshee/build/build.environment.mk Wed Feb 27 05:44:07 2008
@@ -9,7 +9,7 @@
# External libraries to link against, generated from configure
LINK_SYSTEM = -r:System
LINK_SYSTEM_WEB = -r:System.Web
-LINK_SQLITE = -r:System.Data -r:Mono.Data.Sqlite
+LINK_SQLITE = -r:System.Data -r:Mono.Data.SqliteClient
LINK_CAIRO = -r:Mono.Cairo
LINK_MONO_POSIX = -r:Mono.Posix
LINK_ICSHARP_ZIP_LIB = -r:ICSharpCode.SharpZipLib
Modified: trunk/banshee/src/Core/Banshee.Core/Banshee.IO/Provider.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Core/Banshee.IO/Provider.cs (original)
+++ trunk/banshee/src/Core/Banshee.Core/Banshee.IO/Provider.cs Wed Feb 27 05:44:07 2008
@@ -42,8 +42,7 @@
private static IDirectory directory;
private static IFile file;
- private static void LoadProvider ()
- {
+ static Provider () {
lock (typeof (Provider)) {
if (provider != null) {
return;
@@ -71,11 +70,11 @@
}
public static IDirectory Directory {
- get { LoadProvider (); return directory; }
+ get { return directory; }
}
public static IFile File {
- get { LoadProvider (); return file; }
+ get { return file; }
}
public static IDemuxVfs CreateDemuxVfs (string file)
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs Wed Feb 27 05:44:07 2008
@@ -284,8 +284,8 @@
public static bool ContainsUri (SafeUri uri)
{
string relative_path = Paths.MakePathRelativeToLibrary (uri.AbsolutePath) ?? uri.AbsoluteUri;
- return Convert.ToInt32 (ServiceManager.DbConnection.ExecuteScalar (
- check_command.ApplyValues (relative_path, uri.AbsoluteUri))) > 0;
+ return ServiceManager.DbConnection.Query<int> (
+ check_command.ApplyValues (relative_path, uri.AbsoluteUri)) > 0;
}
public SafeUri CopyToLibrary ()
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/LibraryAlbumInfo.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/LibraryAlbumInfo.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/LibraryAlbumInfo.cs Wed Feb 27 05:44:07 2008
@@ -67,7 +67,7 @@
if (title == null || title.Trim () == String.Empty)
title = Catalog.GetString ("Unknown Album");
- using (IDataReader reader = ServiceManager.DbConnection.ExecuteReader (select_command.ApplyValues (artist.DbId, title))) {
+ using (IDataReader reader = ServiceManager.DbConnection.Query (select_command.ApplyValues (artist.DbId, title))) {
if (reader.Read ()) {
dbid = Convert.ToInt32 (reader[(int) Column.AlbumID]);
Title = reader[(int) Column.Title] as string;
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/LibraryArtistInfo.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/LibraryArtistInfo.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/LibraryArtistInfo.cs Wed Feb 27 05:44:07 2008
@@ -66,7 +66,7 @@
if (artistName == null || artistName.Trim () == String.Empty)
artistName = Catalog.GetString ("Unknown Artist");
- using (IDataReader reader = ServiceManager.DbConnection.ExecuteReader (select_command.ApplyValues (artistName))) {
+ using (IDataReader reader = ServiceManager.DbConnection.Query (select_command.ApplyValues (artistName))) {
if (reader.Read ()) {
LoadFromReader (reader);
} else {
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/TrackListDatabaseModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/TrackListDatabaseModel.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/TrackListDatabaseModel.cs Wed Feb 27 05:44:07 2008
@@ -169,12 +169,14 @@
provider.From, JoinFragment, provider.Where, ConditionFragment
);
- using (IDataReader reader = connection.ExecuteReader (String.Format (
+ using (IDataReader reader = connection.Query (String.Format (
"SELECT COUNT(*), {0} {1}", SelectAggregates, unfiltered_query)))
{
- count = Convert.ToInt32 (reader[0]);
- duration = TimeSpan.FromMilliseconds (reader.IsDBNull (1) ? 0 : Convert.ToInt64 (reader[1]));
- filesize = reader.IsDBNull (2) ? 0 : Convert.ToInt64 (reader[2]);
+ if (reader.Read ()) {
+ count = Convert.ToInt32 (reader[0]);
+ duration = TimeSpan.FromMilliseconds (reader.IsDBNull (1) ? 0 : Convert.ToInt64 (reader[1]));
+ filesize = reader.IsDBNull (2) ? 0 : Convert.ToInt64 (reader[2]);
+ }
}
StringBuilder qb = new StringBuilder ();
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Configuration/DatabaseConfigurationClient.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Configuration/DatabaseConfigurationClient.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Configuration/DatabaseConfigurationClient.cs Wed Feb 27 05:44:07 2008
@@ -95,7 +95,7 @@
private IDataReader Get (string namespce, string key)
{
- return connection.ExecuteReader (
+ return connection.Query (
select_value_command.ApplyValues (MakeKey (namespce, key)));
}
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 Wed Feb 27 05:44:07 2008
@@ -29,8 +29,9 @@
using System;
using System.IO;
using System.Data;
-using Mono.Data.Sqlite;
+using System.Threading;
+using Hyena;
using Hyena.Data;
using Hyena.Data.Sqlite;
@@ -41,22 +42,18 @@
{
public sealed class BansheeDbConnection : HyenaSqliteConnection, IService
{
- public BansheeDbConnection () : this (true)
+ public BansheeDbConnection () : base (DatabaseFile)
{
- }
+ Execute ("PRAGMA synchronous = OFF;");
+ Execute ("PRAGMA cache_size = 32768;");
- public BansheeDbConnection (bool connect)
- : base(connect)
- {
- if (connect) {
- BansheeDbFormatMigrator migrator = new BansheeDbFormatMigrator (Connection);
- migrator.SlowStarted += OnMigrationSlowStarted;
- migrator.SlowPulse += OnMigrationSlowPulse;
- migrator.SlowFinished += OnMigrationSlowFinished;
- migrator.Migrate ();
- }
+ BansheeDbFormatMigrator migrator = new BansheeDbFormatMigrator (this);
+ migrator.SlowStarted += OnMigrationSlowStarted;
+ migrator.SlowPulse += OnMigrationSlowPulse;
+ migrator.SlowFinished += OnMigrationSlowFinished;
+ migrator.Migrate ();
}
-
+
//private Gtk.Window slow_window;
//private Gtk.ProgressBar slow_progress;
@@ -125,7 +122,7 @@
}*/
}
- public override string DatabaseFile {
+ public static string DatabaseFile {
get {
if (ApplicationContext.CommandLine.Contains ("db"))
return ApplicationContext.CommandLine["db"];
@@ -150,7 +147,7 @@
return dbfile;
}
}
-
+
string IService.ServiceName {
get { return "DbConnection"; }
}
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs Wed Feb 27 05:44:07 2008
@@ -31,8 +31,15 @@
using System.Reflection;
using System.Threading;
+using Hyena;
+using Hyena.Data.Sqlite;
using Timer=Hyena.Timer;
+using Banshee.ServiceStack;
+using Banshee.Sources;
+using Banshee.Collection.Database;
+using Banshee.Streaming;
+
namespace Banshee.Database
{
public class BansheeDbFormatMigrator
@@ -65,9 +72,9 @@
}
}
- private IDbConnection connection;
+ private HyenaSqliteConnection connection;
- public BansheeDbFormatMigrator(IDbConnection connection)
+ public BansheeDbFormatMigrator (HyenaSqliteConnection connection)
{
this.connection = connection;
}
@@ -134,26 +141,12 @@
protected bool TableExists(string tableName)
{
- IDbCommand command = connection.CreateCommand();
- command.CommandText = @"
- SELECT COUNT(*)
- FROM sqlite_master
- WHERE Type='table' AND Name=:table_name";
-
- IDbDataParameter table_param = command.CreateParameter();
- table_param.ParameterName = "table_name";
- table_param.Value = tableName;
-
- command.Parameters.Add(table_param);
-
- return Convert.ToInt32(command.ExecuteScalar()) > 0;
+ return connection.TableExists (tableName);
}
protected void Execute(string query)
{
- IDbCommand command = connection.CreateCommand();
- command.CommandText = query;
- command.ExecuteNonQuery();
+ connection.Execute (query);
}
protected int DatabaseVersion {
@@ -162,14 +155,13 @@
return 0;
}
- IDbCommand command = connection.CreateCommand();
- command.CommandText = @"
+ string select_query = @"
SELECT Value
FROM CoreConfiguration
WHERE Key = 'DatabaseVersion'
";
- return Convert.ToInt32(command.ExecuteScalar());
+ return Convert.ToInt32 (connection.Query<int> (select_query));
}
}
@@ -449,9 +441,64 @@
INSERT INTO CoreSmartPlaylists (SmartPlaylistID, Name, Condition, OrderBy, LimitNumber, LimitCriterion)
SELECT * FROM SmartPlaylists
");
-
+
// TODO: Kick off some kind of scanner to find the file size of all the files
// since that information was never in the old Banshee
+ ServiceManager.ServiceStarted += OnServiceStarted;
+ }
+
+ private void OnServiceStarted (ServiceStartedArgs args)
+ {
+ if (args.Service is UserJobManager) {
+ ServiceManager.ServiceStarted -= OnServiceStarted;
+ if (ServiceManager.SourceManager.Library != null) {
+ new RefreshMetadataJob ();
+ } else {
+ ServiceManager.SourceManager.SourceAdded += OnSourceAdded;
+ }
+ }
+ }
+
+ private void OnSourceAdded (SourceAddedArgs args)
+ {
+ if (args.Source is Banshee.Library.LibrarySource) {
+ ServiceManager.SourceManager.SourceAdded -= OnSourceAdded;
+ new RefreshMetadataJob ();
+ }
+ }
+
+ private class RefreshMetadataJob : UserJob
+ {
+ public RefreshMetadataJob () : base ("Refreshing Metadata", "Refreshing Metadata", "Preparing...")
+ {
+ Register ();
+ CanCancel = false;
+
+ Banshee.Library.LibrarySource library = ServiceManager.SourceManager.Library;
+ int total = ServiceManager.DbConnection.Query<int> ("SELECT count(*) FROM CoreTracks WHERE SourceID = 1");
+ long now = DateTimeUtil.FromDateTime (DateTime.Now);
+
+ HyenaSqliteCommand select_command = new HyenaSqliteCommand (
+ String.Format (
+ "SELECT {0} FROM {1} WHERE {2} AND CoreTracks.SourceID = 1",
+ DatabaseTrackInfo.Provider.Select,
+ DatabaseTrackInfo.Provider.From,
+ DatabaseTrackInfo.Provider.Where
+ )
+ );
+
+ int count = 0;
+ using (System.Data.IDataReader reader = ServiceManager.DbConnection.Query (select_command)) {
+ while (reader.Read ()) {
+ Progress = ++count / total;
+ DatabaseTrackInfo track = DatabaseTrackInfo.Provider.Load (reader, 0);
+ Status = String.Format ("Updating {0} - {1}", track.ArtistName, track.TrackTitle);
+ TagLib.File file = StreamTagger.ProcessUri (track.Uri);
+ StreamTagger.TrackInfoMerge (track, file);
+ track.Save ();
+ }
+ }
+ }
}
#endregion
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibraryImportManager.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibraryImportManager.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibraryImportManager.cs Wed Feb 27 05:44:07 2008
@@ -32,6 +32,8 @@
using Mono.Unix;
using Hyena;
+using Hyena.Data.Sqlite;
+
using Banshee.Base;
using Banshee.Sources;
using Banshee.ServiceStack;
@@ -116,19 +118,20 @@
/*if (DatabaseTrackInfo.ContainsUri (uri)) {
IncrementProcessedCount (null);
- return;
+ return null;
}*/
- TagLib.File file = StreamTagger.ProcessUri (uri);
- track = new DatabaseTrackInfo ();
- StreamTagger.TrackInfoMerge (track, file);
-
- SafeUri newpath = track.CopyToLibrary ();
- if (newpath != null) {
- track.Uri = newpath;
- }
+ //ServiceManager.DbConnection.BeginTransaction ();
+ //try {
+ TagLib.File file = StreamTagger.ProcessUri (uri);
+ track = new DatabaseTrackInfo ();
+ StreamTagger.TrackInfoMerge (track, file);
+
+ SafeUri newpath = track.CopyToLibrary ();
+ if (newpath != null) {
+ track.Uri = newpath;
+ }
- ThreadAssist.ProxyToMain (delegate {
track.DateAdded = DateTime.Now;
LibraryArtistInfo artist = new LibraryArtistInfo (track.ArtistName);
track.ArtistId = artist.DbId;
@@ -137,8 +140,13 @@
artist.Save ();
track.Source = ServiceManager.SourceManager.Library;
+
track.Save ();
- });
+ //ServiceManager.DbConnection.CommitTransaction ();
+ /*} catch (Exception) {
+ ServiceManager.DbConnection.RollbackTransaction ();
+ throw;
+ }*/
return track;
}
@@ -146,6 +154,10 @@
private void LogError (string path, Exception e)
{
LogError (path, e.Message);
+
+ if (!(e is TagLib.CorruptFileException) && !(e is TagLib.UnsupportedFormatException)) {
+ Log.DebugFormat ("Full import exception: {0}", e.ToString ());
+ }
}
private void LogError (string path, string msg)
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs Wed Feb 27 05:44:07 2008
@@ -357,7 +357,7 @@
public bool IsPlaying (TrackInfo track)
{
- return CurrentState != PlayerEngineState.Idle && track.AudiblyEqual (CurrentTrack);
+ return CurrentState != PlayerEngineState.Idle && track != null && track.AudiblyEqual (CurrentTrack);
}
private void CheckPending ()
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.PlayerMigration/AmarokPlayerImportSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.PlayerMigration/AmarokPlayerImportSource.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.PlayerMigration/AmarokPlayerImportSource.cs Wed Feb 27 05:44:07 2008
@@ -31,7 +31,7 @@
using System.Data;
using System.IO;
-using Mono.Data.Sqlite;
+using Mono.Data.SqliteClient;
using Mono.Unix;
using Banshee.Base;
@@ -222,4 +222,4 @@
get { return new string [] { "system-search" }; }
}
}
-}
\ No newline at end of file
+}
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 Wed Feb 27 05:44:07 2008
@@ -257,7 +257,7 @@
public static IEnumerable<PlaylistSource> LoadAll ()
{
- using (IDataReader reader = ServiceManager.DbConnection.ExecuteReader (
+ using (IDataReader reader = ServiceManager.DbConnection.Query (
"SELECT PlaylistID, Name, SortColumn, SortType FROM CorePlaylists WHERE Special = 0")) {
while (reader.Read ()) {
yield return new PlaylistSource (
@@ -270,14 +270,9 @@
public static int GetPlaylistId (string name)
{
- object result = ServiceManager.DbConnection.ExecuteScalar (new HyenaSqliteCommand (
- "SELECT PlaylistID FROM Playlists WHERE Name = ? LIMIT 1", name));
-
- if (result != null) {
- return Convert.ToInt32 (result);
- }
-
- return 0;
+ return ServiceManager.DbConnection.Query<int> (
+ "SELECT PlaylistID FROM Playlists WHERE Name = ? LIMIT 1", name
+ );
}
public static bool PlaylistExists (string name)
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/Application.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/Application.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/Application.cs Wed Feb 27 05:44:07 2008
@@ -57,12 +57,13 @@
ServiceManager.Run ();
if (ServiceManager.SourceManager != null) {
- ServiceManager.SourceManager.LoadExtensionSources ();
ServiceManager.SourceManager.AddSource (new LibrarySource (), true);
foreach (PlaylistSource pl in PlaylistSource.LoadAll ()) {
- ServiceManager.SourceManager.DefaultSource.AddChildSource (pl);
+ ServiceManager.SourceManager.Library.AddChildSource (pl);
}
+
+ ServiceManager.SourceManager.LoadExtensionSources ();
}
Banshee.Base.PlatformHacks.RestoreMonoJitSegv ();
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/UserJob.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/UserJob.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/UserJob.cs Wed Feb 27 05:44:07 2008
@@ -52,26 +52,16 @@
public event EventHandler Updated;
public event EventHandler CancelRequested;
- public UserJob (string name, string title, string status)
+ public UserJob (string name, string title, string status) : this (name, title, status, null)
{
- FreezeUpdate ();
- Name = name;
- Title = title;
- Status = status;
- ThawUpdate (true);
}
- public UserJob (string name, string title, string status, string iconName)
+ /*public UserJob (string name, string title, string status, string iconName)
+ : this (name, title, status, new string [] { iconName })
{
- FreezeUpdate ();
- Name = name;
- Title = title;
- Status = status;
- IconNames = new string [] { iconName };
- ThawUpdate (true);
- }
+ }*/
- public UserJob (string name, string title, string status, string [] iconNames)
+ public UserJob (string name, string title, string status, params string [] iconNames)
{
FreezeUpdate ();
Name = name;
@@ -173,9 +163,11 @@
public virtual string [] IconNames {
get { return icon_names; }
- set {
- icon_names = value;
- OnUpdated ();
+ set {
+ if (value != null) {
+ icon_names = value;
+ OnUpdated ();
+ }
}
}
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/Migrator.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/Migrator.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/Migrator.cs Wed Feb 27 05:44:07 2008
@@ -59,7 +59,7 @@
try {
ServiceManager.DbConnection.Execute ("BEGIN");
Migrator m = new Migrator ();
- using (IDataReader reader = ServiceManager.DbConnection.ExecuteReader (
+ using (IDataReader reader = ServiceManager.DbConnection.Query (
"SELECT SmartPlaylistID, Name, Condition, OrderBy, LimitNumber, LimitCriterion FROM CoreSmartPlaylists")) {
while (reader.Read ()) {
m.Migrate (
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs Wed Feb 27 05:44:07 2008
@@ -338,7 +338,7 @@
public static IEnumerable<SmartPlaylistSource> LoadAll ()
{
- using (IDataReader reader = ServiceManager.DbConnection.ExecuteReader (
+ using (IDataReader reader = ServiceManager.DbConnection.Query (
"SELECT SmartPlaylistID, Name, Condition, OrderBy, LimitNumber, LimitCriterion FROM CoreSmartPlaylists")) {
while (reader.Read ()) {
SmartPlaylistSource playlist = null;
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs Wed Feb 27 05:44:07 2008
@@ -90,11 +90,11 @@
source_id = ServiceManager.DbConnection.Execute ("INSERT INTO CorePrimarySources (StringID) VALUES (?)", id);
}
- track_model.Condition = String.Format ("CoreTracks.SourceID = {0}", source_id);;
+ track_model.Condition = String.Format ("CoreTracks.SourceID = {0}", source_id);
error_source.Updated += OnErrorSourceUpdated;
OnErrorSourceUpdated (null, null);
- tracks_updated_limiter = new RateLimiter (10.0, 50.0, RateLimitedOnTracksUpdated);
+ tracks_updated_limiter = new RateLimiter (50.0, 500.0, RateLimitedOnTracksUpdated);
primary_sources[source_id] = this;
}
Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.SmartPlaylist.Gui/Editor.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.SmartPlaylist.Gui/Editor.cs (original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.SmartPlaylist.Gui/Editor.cs Wed Feb 27 05:44:07 2008
@@ -232,8 +232,8 @@
playlist.Limit = limit;
playlist.LimitValue = limit_value;
+ playlist.Save ();
ThreadAssist.ProxyToMain (delegate {
- playlist.Save ();
ServiceManager.SourceManager.DefaultSource.AddChildSource (playlist);
});
//SmartPlaylistCore.Instance.StartTimer (playlist);
@@ -243,11 +243,9 @@
playlist.LimitValue = limit_value;
playlist.Limit = limit;
- ThreadAssist.ProxyToMain (delegate {
- playlist.Rename (name);
- playlist.Save ();
- playlist.Reload ();
- });
+ playlist.Rename (name);
+ playlist.Save ();
+ playlist.Reload ();
/*if (playlist.TimeDependent)
SmartPlaylistCore.Instance.StartTimer (playlist);
Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs (original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs Wed Feb 27 05:44:07 2008
@@ -107,9 +107,9 @@
{
Connection.StateChanged += HandleConnectionStateChanged;
- if (Account.UserName != null && Account.CryptedPassword != null) {
+ /*if (Account.UserName != null && Account.CryptedPassword != null) {
Connection.Connect ();
- }
+ }*/
UpdateUI ();
}
@@ -234,10 +234,13 @@
}
}
- /*public override void Activate ()
+ public override void Activate ()
{
- InterfaceElements.ActionButtonBox.PackStart (add_button, false, false, 0);
- }*/
+ //InterfaceElements.ActionButtonBox.PackStart (add_button, false, false, 0);
+ if (Connection.State == ConnectionState.Disconnected) {
+ Connection.Connect ();
+ }
+ }
public override bool CanSearch {
get { return false; }
Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs (original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs Wed Feb 27 05:44:07 2008
@@ -521,7 +521,7 @@
creator
);
- using (IDataReader reader = ServiceManager.DbConnection.ExecuteReader (command)) {
+ using (IDataReader reader = ServiceManager.DbConnection.Query (command)) {
while (reader.Read ()) {
try {
stations.Add (new StationSource (lastfm,
Modified: trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs (original)
+++ trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs Wed Feb 27 05:44:07 2008
@@ -114,18 +114,17 @@
private void BindToDatabase ()
{
- object result = ServiceManager.DbConnection.ExecuteScalar (new HyenaSqliteCommand (@"
- SELECT PlaylistID FROM CorePlaylists
- WHERE Special = 1 AND Name = ?
- LIMIT 1", special_playlist_name));
+ int result = ServiceManager.DbConnection.Query<int> (
+ "SELECT PlaylistID FROM CorePlaylists WHERE Special = 1 AND Name = ? LIMIT 1",
+ special_playlist_name
+ );
- if (result != null) {
- DbId = Convert.ToInt32 (result);
+ if (result != 0) {
+ DbId = result;
} else {
- ServiceManager.DbConnection.Execute (new HyenaSqliteCommand (@"
- INSERT INTO CorePlaylists VALUES (0, ?, -1, 0, 1)
+ DbId = ServiceManager.DbConnection.Execute (new HyenaSqliteCommand (@"
+ INSERT INTO CorePlaylists (PlaylistID, Name, SortColumn, SortType, Special) VALUES (NULL, ?, -1, 0, 1)
", special_playlist_name));
- DbId = ServiceManager.DbConnection.LastInsertRowId;
}
}
Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/DatabaseColumn.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/DatabaseColumn.cs (original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/DatabaseColumn.cs Wed Feb 27 05:44:07 2008
@@ -95,7 +95,7 @@
: 0;
} else {
result = !reader.IsDBNull (column)
- ? (long) reader.GetValue (column)
+ ? Convert.ToInt64 (reader.GetValue (column))
: 0;
}
result = SqliteUtils.FromDbFormat (type, result);
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 Wed Feb 27 05:44:07 2008
@@ -1,11 +1,11 @@
//
// HyenaSqliteCommand.cs
//
-// Author:
+// Authors:
// Aaron Bockover <abockover novell com>
// Gabriel Burt <gburt novell com>
//
-// Copyright (C) 2007 Novell, Inc.
+// Copyright (C) 2007-2008 Novell, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@@ -30,120 +30,154 @@
using System;
using System.IO;
using System.Data;
-using Mono.Data.Sqlite;
+using System.Text;
+using System.Threading;
+
+// NOTE: Mono.Data.Sqlite has serious threading issues. You cannot access
+// its results from any thread but the one the SqliteConnection belongs to.
+// That is why we still use Mono.Data.SqliteClient.
+using Mono.Data.SqliteClient;
namespace Hyena.Data.Sqlite
{
public class HyenaSqliteCommand
{
- private SqliteCommand command;
+ protected object result = null;
+ private Exception execution_exception = null;
+ private bool finished = false;
+
+ private string command;
+ private string command_format = null;
+ private string command_formatted = null;
+ private int parameter_count = 0;
+ private object [] current_values;
#region Properties
- public SqliteCommand Command {
+ public string Text {
get { return command; }
}
- public SqliteParameterCollection Parameters {
- get { return command.Parameters; }
- }
-
- public string CommandText {
- get { return command.CommandText; }
+ private HyenaCommandType command_type;
+ public HyenaCommandType CommandType {
+ get { return command_type; }
+ set { command_type = value; }
}
#endregion
- public HyenaSqliteCommand (string command_str)
+ public HyenaSqliteCommand (string command)
+ {
+ this.command = command;
+ }
+
+ public HyenaSqliteCommand (string command, params object [] param_values)
{
- this.command = new SqliteCommand (command_str);
+ this.command = command;
+ ApplyValues (param_values);
+ }
- int num_params = 0;
- for (int i = 0; i < command_str.Length; i++) {
- if (command_str [i] == '?') {
- num_params++;
+ public void Execute (SqliteConnection connection)
+ {
+ finished = false;
+ execution_exception = null;
+ result = null;
+
+ SqliteCommand sql_command = new SqliteCommand (CurrentSqlText ());
+ sql_command.Connection = connection;
+ //Log.Debug ("Executing {0}", sql_command.CommandText);
+
+ try {
+ switch (command_type) {
+ case HyenaCommandType.Reader:
+ result = sql_command.ExecuteReader ();
+ break;
+
+ case HyenaCommandType.Scalar:
+ result = sql_command.ExecuteScalar ();
+ break;
+
+ case HyenaCommandType.Execute:
+ default:
+ sql_command.ExecuteNonQuery ();
+ result = sql_command.LastInsertRowID ();
+ break;
}
+ } catch (Exception e) {
+ Log.DebugFormat (String.Format ("Exception executing command: {0}", Text), e.ToString ());
+ execution_exception = e;
}
- CreateParameters (num_params);
+ finished = true;
}
- public HyenaSqliteCommand (string command_str, params object [] param_values)
+ internal object WaitForResult (HyenaSqliteConnection conn)
{
- this.command = new SqliteCommand (command_str);
- CreateParameters (param_values.Length);
- ApplyValues (param_values);
- }
+ while (!finished) {
+ conn.ResultReadySignal.WaitOne ();
+ }
- protected void CreateParameters (int num_params)
- {
- for (int i = 0; i < num_params; i++) {
- Parameters.Add (new SqliteParameter ());
+ conn.ClaimResult ();
+
+ if (execution_exception != null) {
+ throw execution_exception;
}
+
+ return result;
}
public HyenaSqliteCommand ApplyValues (params object [] param_values)
{
- if (param_values.Length != Parameters.Count) {
+ finished = false;
+ if (command_format == null) {
+ CreateParameters ();
+ }
+
+ if (param_values.Length != parameter_count) {
throw new ArgumentException (String.Format (
- "Command has {0} parameters, but {1} values given.", Parameters.Count, param_values.Length
+ "Command has {0} parameters, but {1} values given.", parameter_count, param_values.Length
));
}
- for (int i = 0; i < param_values.Length; i++) {
- Parameters[i].Value = param_values[i];
+ for (int i = 0; i < parameter_count; i++) {
+ if (param_values[i] is string) {
+ param_values[i] = String.Format ("'{0}'", (param_values[i] as string).Replace ("'", "''"));
+ } else if (param_values[i] == null) {
+ param_values[i] = "NULL";
+ }
}
+ current_values = param_values;
+ command_formatted = null;
return this;
}
-
- public void AddNamedParameter (string name, object value)
+
+ private string CurrentSqlText ()
{
- SqliteParameter param = new SqliteParameter (name, DbType.String);
- param.Value = value;
- Parameters.Add (param);
- }
-
- /*public DbCommand(string command, params object [] parameters) : this(command)
- {
- for(int i = 0; i < parameters.Length;) {
- SqliteParameter param;
-
- if(parameters[i] is SqliteParameter) {
- param = (SqliteParameter)parameters[i];
- if(i < parameters.Length - 1 && !(parameters[i + 1] is SqliteParameter)) {
- param.Value = parameters[i + 1];
- i += 2;
- } else {
- i++;
- }
- } else {
- param = new SqliteParameter();
- param.ParameterName = (string)parameters[i];
- param.Value = parameters[i + 1];
- i += 2;
- }
-
- Parameters.Add(param);
+ if (command_format == null) {
+ return command;
}
+
+ if (command_formatted == null) {
+ command_formatted = String.Format (command_format, current_values);
+ }
+
+ return command_formatted;
}
-
- public void AddParameter (object value)
- {
- SqliteParameter param = new SqliteParameter ();
- param.Value = value;
- Parameters.Add (param);
- }
-
- public void AddParameter<T>(string name, T value)
+
+ private void CreateParameters ()
{
- AddParameter<T>(new DbParameter<T>(name), value);
+ StringBuilder sb = new StringBuilder ();
+ foreach (char c in command) {
+ if (c == '?') {
+ sb.Append ('{');
+ sb.Append (parameter_count++);
+ sb.Append ('}');
+ } else {
+ sb.Append (c);
+ }
+ }
+ command_format = sb.ToString ();
}
-
- public void AddParameter<T>(DbParameter<T> param, T value)
- {
- param.Value = value;
- Parameters.Add(param);
- }*/
}
}
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 Wed Feb 27 05:44:07 2008
@@ -1,10 +1,11 @@
//
// HyenaSqliteConnection.cs
//
-// Author:
+// Authors:
// Aaron Bockover <abockover novell com>
+// Gabriel Burt <gburt novell com>
//
-// Copyright (C) 2007 Novell, Inc.
+// Copyright (C) 2005-2008 Novell, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@@ -25,74 +26,170 @@
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-
+
using System;
-using System.IO;
-using System.Collections.Generic;
using System.Data;
using System.Threading;
-using Mono.Data.Sqlite;
+using System.Collections.Generic;
+
+// NOTE: Mono.Data.Sqlite has serious threading issues. You cannot access
+// its results from any thread but the one the SqliteConnection belongs to.
+// That is why we still use Mono.Data.SqliteClient.
+using Mono.Data.SqliteClient;
namespace Hyena.Data.Sqlite
{
- public abstract class HyenaSqliteConnection : IDisposable
+ public enum HyenaCommandType {
+ Reader,
+ Scalar,
+ Execute,
+ }
+
+ public class HyenaSqliteConnection : IDisposable
{
private SqliteConnection connection;
+ private string dbpath;
+
+ private Queue<HyenaSqliteCommand> command_queue = new Queue<HyenaSqliteCommand>();
+ private Thread queue_thread;
+ private bool processing_queue = false;
+ private volatile bool dispose_requested = false;
+ private volatile int results_ready = 0;
+ private AutoResetEvent queue_signal = new AutoResetEvent (false);
+ private ManualResetEvent result_ready_signal = new ManualResetEvent (false);
+
+ private volatile Thread transaction_thread = null;
+ private ManualResetEvent transaction_signal = new ManualResetEvent (true);
- private static Thread main_thread;
- static HyenaSqliteConnection () {
- main_thread = Thread.CurrentThread;
+ internal ManualResetEvent ResultReadySignal {
+ get { return result_ready_signal; }
+ }
+
+ public HyenaSqliteConnection(string dbpath)
+ {
+ this.dbpath = dbpath;
+ queue_thread = new Thread(ProcessQueue);
+ queue_thread.IsBackground = true;
+ queue_thread.Start();
}
- private static bool InMainThread {
- get { return main_thread.Equals (Thread.CurrentThread); }
+#region Public Query Methods
+
+ // SELECT multiple column queries
+ public IDataReader Query (HyenaSqliteCommand command)
+ {
+ command.CommandType = HyenaCommandType.Reader;
+ QueueCommand(command);
+ return command.WaitForResult (this) as SqliteDataReader;
}
- public HyenaSqliteConnection () : this (true)
+ public IDataReader Query (string command_str, params object [] param_values)
+ {
+ return Query (new HyenaSqliteCommand (command_str, param_values));
+ }
+
+ public IDataReader Query (object command)
{
+ return Query (new HyenaSqliteCommand (command.ToString ()));
+ }
+
+ // SELECT single column queries
+ public T Query<T> (HyenaSqliteCommand command)
+ {
+ command.CommandType = HyenaCommandType.Scalar;
+ QueueCommand(command);
+ object result = command.WaitForResult (this);
+
+ return result == null
+ ? default (T)
+ : (T) SqliteUtils.FromDbFormat (typeof (T), Convert.ChangeType (result, typeof (T)));
}
- public HyenaSqliteConnection (bool connect)
+ public T Query<T> (string command_str, params object [] param_values)
{
- if (connect) {
- Open ();
- }
+ return Query<T> (new HyenaSqliteCommand (command_str, param_values));
}
- public void Dispose ()
+ public T Query<T> (object command)
{
- Close ();
+ return Query<T> (new HyenaSqliteCommand (command.ToString ()));
}
- public void Open ()
+ // INSERT, UPDATE, DELETE queries
+ public int Execute (HyenaSqliteCommand command)
{
- lock (this) {
- if (connection != null) {
- return;
- }
+ command.CommandType = HyenaCommandType.Execute;;
+ QueueCommand(command);
+ return (int) command.WaitForResult (this);
+ }
- string dbfile = DatabaseFile;
- connection = new SqliteConnection (String.Format ("Version=3,URI=file:{0}", dbfile));
- connection.Open ();
+ public int Execute (string command_str, params object [] param_values)
+ {
+ return Execute (new HyenaSqliteCommand (command_str, param_values));
+ }
- Execute (@"
- PRAGMA synchronous = OFF;
- PRAGMA cache_size = 32768;
- ");
- }
+ public int Execute (object command)
+ {
+ return Execute (new HyenaSqliteCommand (command.ToString ()));
}
- public void Close ()
+#endregion
+
+#region Public Utility Methods
+
+ public void BeginTransaction ()
{
- lock (this) {
- if (connection != null) {
- connection.Close ();
- connection = null;
+ if (transaction_thread == Thread.CurrentThread) {
+ throw new Exception ("Can't start a recursive transaction");
+ }
+
+ while (transaction_thread != Thread.CurrentThread) {
+ if (transaction_thread != null) {
+ // Wait for the existing transaction to finish before this thread proceeds
+ transaction_signal.WaitOne ();
+ }
+
+ lock (command_queue) {
+ if (transaction_thread == null) {
+ transaction_thread = Thread.CurrentThread;
+ transaction_signal.Reset ();
+ }
}
}
+
+ Execute ("BEGIN TRANSACTION");
}
-#region Convenience methods
+ public void CommitTransaction ()
+ {
+ if (transaction_thread != Thread.CurrentThread) {
+ throw new Exception ("Can't commit from outside a transaction");
+ }
+
+ Execute ("COMMIT TRANSACTION");
+
+ lock (command_queue) {
+ transaction_thread = null;
+ // Let any other threads continue
+ transaction_signal.Set ();
+ }
+ }
+
+ public void RollbackTransaction ()
+ {
+ if (transaction_thread != Thread.CurrentThread) {
+ throw new Exception ("Can't rollback from outside a transaction");
+ }
+
+ Execute ("ROLLBACK");
+
+ lock (command_queue) {
+ transaction_thread = null;
+
+ // Let any other threads continue
+ transaction_signal.Set ();
+ }
+ }
public bool TableExists (string tableName)
{
@@ -115,7 +212,7 @@
type, name)
) > 0;
}
-
+
private delegate void SchemaHandler (string column);
private void SchemaClosure (string table_name, SchemaHandler code)
@@ -156,136 +253,73 @@
return schema;
}
- public IDataReader ExecuteReader (SqliteCommand command)
- {
- if (command.Connection == null)
- command.Connection = connection;
-
- if (!InMainThread) {
- Console.WriteLine ("About to execute command not in main thread: {0}", command.CommandText);
- }
-
- try {
- return command.ExecuteReader ();
- } catch (Exception e) {
- Console.WriteLine ("Caught exception trying to execute {0}", command.CommandText);
- throw e;
- }
- }
-
- public IDataReader ExecuteReader (HyenaSqliteCommand command)
- {
- return ExecuteReader (command.Command);
- }
-
- public IDataReader ExecuteReader (string command_str, params object [] param_values)
- {
- return ExecuteReader (new HyenaSqliteCommand (command_str, param_values));
- }
+#endregion
- public IDataReader ExecuteReader (object command)
- {
- return ExecuteReader (new SqliteCommand (command.ToString ()));
- }
+#region Private Queue Methods
- public object ExecuteScalar (SqliteCommand command)
+ private void QueueCommand(HyenaSqliteCommand command)
{
- if (command.Connection == null)
- command.Connection = connection;
-
- if (!InMainThread) {
- Console.WriteLine ("About to execute command not in main thread: {0}", command.CommandText);
- }
+ bool queued = false;
+ while (true) {
+ lock (command_queue) {
+ if (transaction_thread == null || Thread.CurrentThread == transaction_thread) {
+ command_queue.Enqueue (command);
+ break;
+ }
+ }
- try {
- return command.ExecuteScalar ();
- } catch (Exception e) {
- Console.WriteLine ("Caught exception trying to execute {0}", command.CommandText);
- throw e;
+ transaction_signal.WaitOne ();
}
+ queue_signal.Set ();
}
- public object ExecuteScalar (HyenaSqliteCommand command)
- {
- return ExecuteScalar (command.Command);
- }
-
- public object ExecuteScalar (string command_str, params object [] param_values)
- {
- return ExecuteScalar (new HyenaSqliteCommand (command_str, param_values));
- }
-
- public object ExecuteScalar (object command)
- {
- return ExecuteScalar (new SqliteCommand (command.ToString ()));
- }
-
- public T Query<T> (SqliteCommand command)
- {
- object result = ExecuteScalar (command);
- return result == null
- ? default (T)
- : (T)SqliteUtils.FromDbFormat (typeof (T), Convert.ChangeType (result, typeof (T)));
- }
-
- public T Query<T> (HyenaSqliteCommand command)
+ internal void ClaimResult ()
{
- return Query<T> (command.Command);
- }
-
- public T Query<T> (string command_str, params object [] param_values)
- {
- return Query<T> (new HyenaSqliteCommand (command_str, param_values));
- }
-
- public T Query<T> (object command)
- {
- return Query<T> (new SqliteCommand (command.ToString ()));
+ lock (command_queue) {
+ results_ready++;
+ if (results_ready == 0) {
+ result_ready_signal.Reset ();
+ }
+ }
}
- public int Execute (SqliteCommand command)
- {
- if (command.Connection == null)
- command.Connection = connection;
-
- if (!InMainThread) {
- Console.WriteLine ("About to execute command not in main thread: {0}", command.CommandText);
+ private void ProcessQueue()
+ {
+ if (connection == null) {
+ connection = new SqliteConnection (String.Format ("Version=3,URI=file:{0}", dbpath));
+ connection.Open ();
}
+
+ // Keep handling queries
+ while (!dispose_requested) {
+ while (command_queue.Count > 0) {
+ HyenaSqliteCommand command;
+ lock (command_queue) {
+ command = command_queue.Dequeue ();
+ }
+
+ command.Execute (connection);
+
+ lock (command_queue) {
+ results_ready++;
+ result_ready_signal.Set ();
+ }
+ }
- try {
- command.ExecuteNonQuery ();
- } catch (Exception e) {
- Console.WriteLine ("Caught exception trying to execute {0}", command.CommandText);
- throw e;
+ queue_signal.WaitOne ();
}
- return command.LastInsertRowID ();
- }
- public int Execute (HyenaSqliteCommand command)
- {
- return Execute (command.Command);
- }
-
- public int Execute (string command_str, params object [] param_values)
- {
- return Execute (new HyenaSqliteCommand (command_str, param_values));
- }
-
- public int Execute (object command)
- {
- return Execute (new SqliteCommand (command.ToString ()));
- }
-
- public int LastInsertRowId {
- get { return connection.LastInsertRowId; }
+ // Finish
+ connection.Close ();
}
#endregion
- public abstract string DatabaseFile { get; }
-
- public IDbConnection Connection {
- get { return connection; }
+ public void Dispose()
+ {
+ dispose_requested = true;
+ queue_signal.Set ();
+ queue_thread.Join ();
}
}
}
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 Wed Feb 27 05:44:07 2008
@@ -169,7 +169,7 @@
{
//using (new Timer (String.Format ("Fetching set for {0}", model))) {
select_range_command.ApplyValues (offset, limit);
- using (IDataReader reader = connection.ExecuteReader (select_range_command)) {
+ using (IDataReader reader = connection.Query (select_range_command)) {
while (reader.Read ()) {
if (!ContainsKey (offset)) {
Add (offset, provider.Load (reader, offset));
@@ -182,12 +182,14 @@
protected void UpdateAggregates ()
{
- using (IDataReader reader = connection.ExecuteReader (count_command.ApplyValues (uid))) {
- rows = Convert.ToInt32 (reader[0]);
+ using (IDataReader reader = connection.Query (count_command.ApplyValues (uid))) {
+ if (reader.Read ()) {
+ rows = Convert.ToInt32 (reader[0]);
- AggregatesUpdatedEventHandler handler = AggregatesUpdated;
- if (handler != null) {
- handler (reader);
+ AggregatesUpdatedEventHandler handler = AggregatesUpdated;
+ if (handler != null) {
+ handler (reader);
+ }
}
}
}
Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs (original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs Wed Feb 27 05:44:07 2008
@@ -48,7 +48,6 @@
private HyenaSqliteCommand select_command;
private HyenaSqliteCommand select_range_command;
private HyenaSqliteCommand select_single_command;
-
private string primary_key;
private string select;
@@ -102,7 +101,7 @@
protected virtual void CheckVersion ()
{
if (connection.TableExists (HyenaTableName)) {
- using (IDataReader reader = connection.ExecuteReader (SelectVersionSql (TableName))) {
+ using (IDataReader reader = connection.Query (SelectVersionSql (TableName))) {
if (reader.Read ()) {
int table_version = reader.GetInt32 (0);
if (table_version < ModelVersion) {
@@ -243,14 +242,16 @@
protected virtual void PrepareInsertCommand (T target)
{
+ object [] values = new object [columns.Count];
for (int i = 0; i < columns.Count; i++) {
if (columns[i] != key) {
- InsertCommand.Parameters[i].Value = columns[i].GetValue (target);
+ values[i] = columns[i].GetValue (target);
} else {
// On insert, the key needs to be NULL to be automatically set by Sqlite
- InsertCommand.Parameters[i].Value = null;
+ values[i] = null;
}
}
+ InsertCommand.ApplyValues (values);
}
protected int Insert (T target)
@@ -261,10 +262,12 @@
protected virtual void PrepareUpdateCommand (T target)
{
+ object [] values = new object [columns.Count + 1];
for (int i = 0; i < columns.Count; i++) {
- UpdateCommand.Parameters[i].Value = columns[i].GetValue (target);
+ values [i] = columns[i].GetValue (target);
}
- UpdateCommand.Parameters[columns.Count].Value = key.GetValue (target);
+ values[columns.Count] = key.GetValue (target);
+ UpdateCommand.ApplyValues (values);
}
protected void Update (T target)
@@ -311,7 +314,7 @@
{
PrepareSelectCommand ();
int i = 1;
- using (IDataReader reader = connection.ExecuteReader (SelectCommand)) {
+ using (IDataReader reader = connection.Query (SelectCommand)) {
while (reader.Read ()) {
yield return Load (reader, i++);
}
@@ -326,7 +329,7 @@
public IEnumerable<T> FetchRange (int offset, int limit)
{
PrepareSelectRangeCommand (offset, limit);
- using (IDataReader reader = connection.ExecuteReader (SelectRangeCommand)) {
+ using (IDataReader reader = connection.Query (SelectRangeCommand)) {
while (reader.Read ()) {
yield return Load (reader, offset++);
}
@@ -341,7 +344,7 @@
public T FetchSingle (int id)
{
PrepareSelectSingleCommand (id);
- using (IDataReader reader = connection.ExecuteReader (SelectSingleCommand)) {
+ using (IDataReader reader = connection.Query (SelectSingleCommand)) {
if (reader.Read ()) {
return Load (reader, id);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]