Summary: | crash searching in local collection (SqlQueryMaker::handleResult) | ||
---|---|---|---|
Product: | [Applications] amarok | Reporter: | Marc Puig Pasarrius <modcube> |
Component: | Collection Browser | Assignee: | Amarok Developers <amarok-bugs-dist> |
Status: | RESOLVED FIXED | ||
Severity: | crash | CC: | a.m.p.boelens, andresbajotierra, christopherheiny, kde, maximilian.kossick, mikko.cal, operative.terminus, shaunehunter, ubuntu |
Priority: | HI | Keywords: | release_blocker |
Version: | 2.3-GIT | ||
Target Milestone: | 2.2.2 | ||
Platform: | Gentoo Packages | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | |||
Attachments: | Captured traffic |
Description
Marc Puig Pasarrius
2009-11-22 15:37:27 UTC
*** Bug 215857 has been marked as a duplicate of this bug. *** Confirmed by duplicate. *** Bug 216334 has been marked as a duplicate of this bug. *** Setting keyword. got the exact same crash with git master of today. bt: Thread 9 (Thread 0x7fd7cd821910 (LWP 20864)): [KCrash Handler] #5 0x00007fd7d0a0a15c in SqlQueryMaker::handleResult (this=0x5d38080, result=...) at /home/mikko/amarok/src/collection/sqlcollection/SqlQueryMaker.cpp:765 #6 0x00007fd7d0a0d932 in SqlWorkerThread::run (this=0x477b820) at /home/mikko/amarok/src/collection/sqlcollection/SqlQueryMaker.cpp:56 #7 0x00007fd7e4023363 in ThreadWeaver::JobRunHelper::runTheJob (this=0x7fd7cd820f90, th=0x22d8c80, job=0x477b820) at /var/tmp/paludis/kde-base-kdelibs-9999/work/kdelibs-9999/threadweaver/Weaver/Job.cpp:106 #8 0x00007fd7e4023522 in ThreadWeaver::Job::execute (this=0x477b820, th=0x22d8c80) at /var/tmp/paludis/kde-base-kdelibs-9999/work/kdelibs-9999/threadweaver/Weaver/Job.cpp:135 #9 0x00007fd7e402293f in ThreadWeaver::ThreadRunHelper::run (this=0x7fd7cd821030, parent=0x229b200, th=0x22d8c80) at /var/tmp/paludis/kde-base-kdelibs-9999/work/kdelibs-9999/threadweaver/Weaver/Thread.cpp:95 #10 0x00007fd7e4022a94 in ThreadWeaver::Thread::run (this=0x22d8c80) at /var/tmp/paludis/kde-base-kdelibs-9999/work/kdelibs-9999/threadweaver/Weaver/Thread.cpp:142 #11 0x00007fd7e851c5ba in QThreadPrivate::start (arg=0x22d8c80) at thread/qthread_unix.cpp:244 #12 0x00007fd7e6b8d664 in start_thread () from /lib/libpthread.so.0 #13 0x00007fd7e70c3d9d in clone () from /lib/libc.so.6 #14 0x0000000000000000 in ?? () Created attachment 38938 [details]
Captured traffic
Sorry, but your attachment is not usable, it is labeled as a binary file. Please select the appropriate file type when adding an attachement, if it is a text file, please paste it inline, it makes searches easier. Comment on attachment 38938 [details]
Captured traffic
This is the captured traffic of the mysql transaction between amarok and the mysql server before amarok crashes. You can open it with wireshark.
I am using: KDE Version 2.2.1 (KDE 4.3.4 (KDE 4.3.4), Chakra KDE) Application Audio Player Operating System Linux (x86_64) release 2.6.31-ARCH Compiler gcc (that beeing Arch Linux) I seem to have the same issue. I search for "Metall" and everythings is fine. When I go on with "Metalls" amarok crashes. Things to note: I am using external MySQL. I can search for other strings that yield no result fine. If I am slow, typing every letter and see what it finds I get the crash. If I start amarok and type "Metalls" fast, the problem is gone. Sometimes while testing I could also type "Metalls" slow and then backspace again to "Metall" and then put an "s", back and forth 2-3 times, and then it crashes when I put the "s" again. This looks like some type of timing/communication problem or something similar. I get differing results in the output of amarok --debug, but these two lines are in there sometimes (!) amarok: NOTE: MySQL server had gone away, ping reconnected it amarok: [SqlQueryMaker] Warning: queryResult with queryType == NONE My MySQL server is running fine all the time. I also can't find any errors in the error files there. my backtrace: Application: Amarok (amarok), signal: Segmentation fault [Current thread is 1 (Thread 0x7fe336ff97a0 (LWP 6655))] Thread 14 (Thread 0x7fe31f813710 (LWP 6658)): #0 pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:211 #1 0x00007fe324d1aa71 in metronom_sync_loop () from /usr/lib/libxine.so.1 #2 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #3 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #4 0x0000000000000000 in ?? () Thread 13 (Thread 0x7fe31e9d8710 (LWP 6659)): #0 0x00007fe333d1f37e in __pthread_mutex_unlock_usercnt (mutex=0x233ead8, decr=<value optimized out>) at pthread_mutex_unlock.c:52 #1 0x00007fe32d1b2cfe in g_main_context_query () from /usr/lib/libglib-2.0.so.0 #2 0x00007fe32d1b7871 in g_main_context_iterate () from /usr/lib/libglib-2.0.so.0 #3 0x00007fe32d1b7ce0 in g_main_context_iteration () from /usr/lib/libglib-2.0.so.0 #4 0x00007fe3357208b6 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/libQtCore.so.4 #5 0x00007fe3356f6c72 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/libQtCore.so.4 #6 0x00007fe3356f7044 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/libQtCore.so.4 #7 0x00007fe33561058b in QThread::exec() () from /usr/lib/libQtCore.so.4 #8 0x00007fe324f737e4 in Phonon::Xine::XineThread::run() () from /usr/lib/kde4/plugins/phonon_backend/phonon_xine.so #9 0x00007fe3356132e5 in ?? () from /usr/lib/libQtCore.so.4 #10 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #11 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #12 0x0000000000000000 in ?? () The current source language is "auto; currently asm". Thread 12 (Thread 0x7fe31dfce710 (LWP 6662)): #0 0x00007fe33424e0d3 in *__GI___poll (fds=<value optimized out>, nfds=<value optimized out>, timeout=333) at ../sysdeps/unix/sysv/linux/poll.c:87 #1 0x00007fe31dfd47ae in ao_alsa_handle_event_thread () from /usr/lib/xine/plugins/1.27/xineplug_ao_out_alsa.so #2 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #3 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #4 0x0000000000000000 in ?? () The current source language is "auto; currently c". Thread 11 (Thread 0x7fe31d7cd710 (LWP 6663)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162 #1 0x00007fe324d2b52b in ao_loop () from /usr/lib/libxine.so.1 #2 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #3 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #4 0x0000000000000000 in ?? () Thread 10 (Thread 0x7fe31cbc3710 (LWP 6664)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162 #1 0x00007fe324d2b52b in ao_loop () from /usr/lib/libxine.so.1 #2 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #3 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #4 0x0000000000000000 in ?? () The current source language is "auto; currently asm". Thread 9 (Thread 0x7fe31c3c2710 (LWP 6665)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162 #1 0x00007fe324d2b52b in ao_loop () from /usr/lib/libxine.so.1 #2 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #3 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #4 0x0000000000000000 in ?? () Thread 8 (Thread 0x7fe31bbc1710 (LWP 6666)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162 #1 0x00007fe324d2b52b in ao_loop () from /usr/lib/libxine.so.1 #2 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #3 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #4 0x0000000000000000 in ?? () Thread 7 (Thread 0x7fe31429d710 (LWP 6668)): [KCrash Handler] #5 0x0000000000000040 in ?? () #6 0x00007fe31aca3485 in SqlQueryMaker::handleResult(QStringList const&) () from /usr/lib/kde4/amarok_collection-mysqlservercollection.so #7 0x00007fe31aca4abb in SqlWorkerThread::run() () from /usr/lib/kde4/amarok_collection-mysqlservercollection.so #8 0x00007fe33130f6bd in ThreadWeaver::JobRunHelper::runTheJob(ThreadWeaver::Thread*, ThreadWeaver::Job*) () from /usr/lib/libthreadweaver.so.4 #9 0x00007fe33130f9be in ThreadWeaver::Job::execute(ThreadWeaver::Thread*) () from /usr/lib/libthreadweaver.so.4 #10 0x00007fe33130e98f in ThreadWeaver::ThreadRunHelper::run(ThreadWeaver::WeaverImpl*, ThreadWeaver::Thread*) () from /usr/lib/libthreadweaver.so.4 #11 0x00007fe33130ee18 in ThreadWeaver::Thread::run() () from /usr/lib/libthreadweaver.so.4 #12 0x00007fe3356132e5 in ?? () from /usr/lib/libQtCore.so.4 #13 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #14 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #15 0x0000000000000000 in ?? () Thread 6 (Thread 0x7fe313a9c710 (LWP 6669)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162 #1 0x00007fe3356143ab in QWaitCondition::wait(QMutex*, unsigned long) () from /usr/lib/libQtCore.so.4 #2 0x00007fe33130e286 in ThreadWeaver::WeaverImpl::blockThreadUntilJobsAreBeingAssigned(ThreadWeaver::Thread*) () from /usr/lib/libthreadweaver.so.4 #3 0x00007fe3313103bb in ThreadWeaver::WorkingHardState::applyForWork(ThreadWeaver::Thread*, ThreadWeaver::Job*) () from /usr/lib/libthreadweaver.so.4 #4 0x00007fe33130e9bf in ThreadWeaver::ThreadRunHelper::run(ThreadWeaver::WeaverImpl*, ThreadWeaver::Thread*) () from /usr/lib/libthreadweaver.so.4 #5 0x00007fe33130ee18 in ThreadWeaver::Thread::run() () from /usr/lib/libthreadweaver.so.4 #6 0x00007fe3356132e5 in ?? () from /usr/lib/libQtCore.so.4 #7 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #8 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #9 0x0000000000000000 in ?? () Thread 5 (Thread 0x7fe31329b710 (LWP 6670)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162 #1 0x00007fe3356143ab in QWaitCondition::wait(QMutex*, unsigned long) () from /usr/lib/libQtCore.so.4 #2 0x00007fe33130e286 in ThreadWeaver::WeaverImpl::blockThreadUntilJobsAreBeingAssigned(ThreadWeaver::Thread*) () from /usr/lib/libthreadweaver.so.4 #3 0x00007fe3313103bb in ThreadWeaver::WorkingHardState::applyForWork(ThreadWeaver::Thread*, ThreadWeaver::Job*) () from /usr/lib/libthreadweaver.so.4 #4 0x00007fe33130e9bf in ThreadWeaver::ThreadRunHelper::run(ThreadWeaver::WeaverImpl*, ThreadWeaver::Thread*) () from /usr/lib/libthreadweaver.so.4 #5 0x00007fe33130ee18 in ThreadWeaver::Thread::run() () from /usr/lib/libthreadweaver.so.4 #6 0x00007fe3356132e5 in ?? () from /usr/lib/libQtCore.so.4 #7 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #8 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #9 0x0000000000000000 in ?? () Thread 4 (Thread 0x7fe312a9a710 (LWP 6671)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162 #1 0x00007fe3356143ab in QWaitCondition::wait(QMutex*, unsigned long) () from /usr/lib/libQtCore.so.4 #2 0x00007fe33130e286 in ThreadWeaver::WeaverImpl::blockThreadUntilJobsAreBeingAssigned(ThreadWeaver::Thread*) () from /usr/lib/libthreadweaver.so.4 #3 0x00007fe3313103bb in ThreadWeaver::WorkingHardState::applyForWork(ThreadWeaver::Thread*, ThreadWeaver::Job*) () from /usr/lib/libthreadweaver.so.4 #4 0x00007fe33130e9bf in ThreadWeaver::ThreadRunHelper::run(ThreadWeaver::WeaverImpl*, ThreadWeaver::Thread*) () from /usr/lib/libthreadweaver.so.4 #5 0x00007fe33130ee18 in ThreadWeaver::Thread::run() () from /usr/lib/libthreadweaver.so.4 #6 0x00007fe3356132e5 in ?? () from /usr/lib/libQtCore.so.4 #7 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #8 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #9 0x0000000000000000 in ?? () Thread 3 (Thread 0x7fe311579710 (LWP 6681)): #0 pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:211 #1 0x00007fe335614312 in QWaitCondition::wait(QMutex*, unsigned long) () from /usr/lib/libQtCore.so.4 #2 0x00007fe33560a472 in ?? () from /usr/lib/libQtCore.so.4 #3 0x00007fe3356132e5 in ?? () from /usr/lib/libQtCore.so.4 #4 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #5 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #6 0x0000000000000000 in ?? () Thread 2 (Thread 0x7fe310d78710 (LWP 6682)): #0 pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:211 #1 0x00007fe335614312 in QWaitCondition::wait(QMutex*, unsigned long) () from /usr/lib/libQtCore.so.4 #2 0x00007fe33560a472 in ?? () from /usr/lib/libQtCore.so.4 #3 0x00007fe3356132e5 in ?? () from /usr/lib/libQtCore.so.4 #4 0x00007fe333d1b81a in start_thread (arg=<value optimized out>) at pthread_create.c:297 #5 0x00007fe3342568cd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #6 0x0000000000000000 in ?? () Thread 1 (Thread 0x7fe336ff97a0 (LWP 6655)): #0 0x00007fe33424e0d3 in *__GI___poll (fds=<value optimized out>, nfds=<value optimized out>, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:87 #1 0x00007fe32c01989a in _xcb_conn_wait () from /usr/lib/libxcb.so.1 #2 0x00007fe32c019e37 in _xcb_out_send () from /usr/lib/libxcb.so.1 #3 0x00007fe32c01a0e5 in xcb_writev () from /usr/lib/libxcb.so.1 #4 0x00007fe333605d5a in _XSend () from /usr/lib/libX11.so.6 #5 0x00007fe333605e99 in _XReply () from /usr/lib/libX11.so.6 #6 0x00007fe3335f3780 in XQueryPointer () from /usr/lib/libX11.so.6 #7 0x00007fe334c1bc6d in QCursor::pos() () from /usr/lib/libQtGui.so.4 #8 0x00007fe336059fe0 in CollectionTreeItemDelegate::paint(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const () from /usr/lib/libamaroklib.so.1 #9 0x00007fe3350aea09 in QTreeView::drawRow(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const () from /usr/lib/libQtGui.so.4 #10 0x00007fe3364c49c0 in Amarok::PrettyTreeView::drawRow(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const () from /usr/lib/libamaroklib.so.1 #11 0x00007fe3350b65c4 in QTreeView::drawTree(QPainter*, QRegion const&) const () from /usr/lib/libQtGui.so.4 #12 0x00007fe3350b7073 in QTreeView::paintEvent(QPaintEvent*) () from /usr/lib/libQtGui.so.4 #13 0x00007fe334bf2e40 in QWidget::event(QEvent*) () from /usr/lib/libQtGui.so.4 #14 0x00007fe334f4c2b6 in QFrame::event(QEvent*) () from /usr/lib/libQtGui.so.4 #15 0x00007fe33507e5cb in QAbstractItemView::viewportEvent(QEvent*) () from /usr/lib/libQtGui.so.4 #16 0x00007fe3350b5710 in QTreeView::viewportEvent(QEvent*) () from /usr/lib/libQtGui.so.4 #17 0x00007fe3356f7687 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) () from /usr/lib/libQtCore.so.4 #18 0x00007fe334ba45dc in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4 #19 0x00007fe334bab8de in QApplication::notify(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4 #20 0x00007fe336b29926 in KApplication::notify(QObject*, QEvent*) () from /usr/lib/libkdeui.so.5 #21 0x00007fe3356f833c in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/libQtCore.so.4 #22 0x00007fe334bfa233 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #23 0x00007fe334bfa990 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #24 0x00007fe334bf9ea3 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #25 0x00007fe334bfa990 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #26 0x00007fe334bf9ea3 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #27 0x00007fe334bfa990 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #28 0x00007fe334bf9ea3 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #29 0x00007fe334bfa990 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #30 0x00007fe334bf9ea3 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #31 0x00007fe334bfa990 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #32 0x00007fe334bf9ea3 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #33 0x00007fe334bfa990 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #34 0x00007fe334bf9ea3 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #35 0x00007fe334bfa990 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #36 0x00007fe334bf9ea3 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4 #37 0x00007fe334d69e1e in ?? () from /usr/lib/libQtGui.so.4 #38 0x00007fe334bec670 in QWidgetPrivate::syncBackingStore() () from /usr/lib/libQtGui.so.4 #39 0x00007fe334bf2c58 in QWidget::event(QEvent*) () from /usr/lib/libQtGui.so.4 #40 0x00007fe334f6688b in QMainWindow::event(QEvent*) () from /usr/lib/libQtGui.so.4 #41 0x00007fe334ba460c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4 #42 0x00007fe334bab8de in QApplication::notify(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4 #43 0x00007fe336b29926 in KApplication::notify(QObject*, QEvent*) () from /usr/lib/libkdeui.so.5 #44 0x00007fe3356f833c in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/libQtCore.so.4 #45 0x00007fe3356f8f4a in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /usr/lib/libQtCore.so.4 #46 0x00007fe335720cc3 in ?? () from /usr/lib/libQtCore.so.4 #47 0x00007fe32d1b41fe in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0 #48 0x00007fe32d1b7bb8 in g_main_context_iterate () from /usr/lib/libglib-2.0.so.0 #49 0x00007fe32d1b7ce0 in g_main_context_iteration () from /usr/lib/libglib-2.0.so.0 #50 0x00007fe335720863 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/libQtCore.so.4 #51 0x00007fe334c376de in ?? () from /usr/lib/libQtGui.so.4 #52 0x00007fe3356f6c72 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/libQtCore.so.4 #53 0x00007fe3356f7044 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/libQtCore.so.4 #54 0x00007fe3356f91f9 in QCoreApplication::exec() () from /usr/lib/libQtCore.so.4 #55 0x0000000000409d74 in _start () The current source language is "auto; currently c". From bug 219307: --- What I was doing when the application crashed: amarok crashed while I was typing in the local collection search box. It is possible that the collection was being updated at the time. *** Bug 219307 has been marked as a duplicate of this bug. *** It was not updating for me. I was also not using "watch dir", like mentioned in one duplicate. Probably still the same bug, but not dependent on these things. *** Bug 219463 has been marked as a duplicate of this bug. *** Another backtrace, from today: Application: Amarok (amarok), signal: Segmentation fault The current source language is "auto; currently c". [Current thread is 1 (Thread 0x7f3b8c8367a0 (LWP 2709))] Thread 15 (Thread 0x7f3b719c9910 (LWP 2712)): #0 pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:220 #1 0x00007f3b7767ec91 in ?? () from /usr/lib/libxine.so.1 #2 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #3 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #4 0x0000000000000000 in ?? () Thread 14 (Thread 0x7f3b70480910 (LWP 2713)): #0 0xffffffffff60017b in ?? () #1 0x00007f3b7047fce0 in ?? () #2 0x00007fff90fff782 in ?? () Backtrace stopped: previous frame identical to this frame (corrupt stack?) The current source language is "auto; currently asm". Thread 13 (Thread 0x7f3b6b86d910 (LWP 2719)): #0 0x00007f3b88fa0373 in *__GI___poll (fds=<value optimized out>, nfds=<value optimized out>, timeout=333) at ../sysdeps/unix/sysv/linux/poll.c:87 #1 0x00007f3b6fa7bcbe in ?? () from /usr/lib/xine/plugins/1.26/xineplug_ao_out_alsa.so #2 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #3 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #4 0x0000000000000000 in ?? () Thread 12 (Thread 0x7f3b6f668910 (LWP 2720)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:261 #1 0x00007f3b7768f983 in ?? () from /usr/lib/libxine.so.1 #2 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #3 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #4 0x0000000000000000 in ?? () The current source language is "auto; currently c". Thread 11 (Thread 0x7f3b6ee67910 (LWP 2721)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:261 #1 0x00007f3b7768f983 in ?? () from /usr/lib/libxine.so.1 #2 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #3 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #4 0x0000000000000000 in ?? () The current source language is "auto; currently asm". Thread 10 (Thread 0x7f3b6d147910 (LWP 2723)): #0 0x00007f3b88fa53c2 in select () from /lib/libc.so.6 #1 0x00007f3b776a7725 in xine_usec_sleep () from /usr/lib/libxine.so.1 #2 0x00007f3b7768c7e9 in ?? () from /usr/lib/libxine.so.1 #3 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #4 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #5 0x0000000000000000 in ?? () Thread 9 (Thread 0x7f3b6788a910 (LWP 2724)): [KCrash Handler] #5 QMutex::lock (this=0x88) at thread/qmutex.cpp:152 #6 0x00007f3b89b41075 in QMutexLocker::relock (sender=0x88c83d0, from_signal_index=10, to_signal_index=<value optimized out>, argv=0x7f3b67889c50) at ../../include/QtCore/../../src/corelib/thread/qmutex.h:120 #7 QMutexLocker (sender=0x88c83d0, from_signal_index=10, to_signal_index=<value optimized out>, argv=0x7f3b67889c50) at ../../include/QtCore/../../src/corelib/thread/qmutex.h:102 #8 QMetaObject::activate (sender=0x88c83d0, from_signal_index=10, to_signal_index=<value optimized out>, argv=0x7f3b67889c50) at kernel/qobject.cpp:3052 #9 0x00007f3b8bac49c5 in QueryMaker::newResultReady (this=0x88c83d0, _t1=..., _t2=...) at /home/mark/kde/build/amarok/src/QueryMaker.moc:145 #10 0x00007f3b6d99aa19 in SqlQueryMaker::handleTracks (this=0x88c83d0, result=...) at /home/mark/kde/src/amarok/src/collection/sqlcollection/SqlQueryMaker.cpp:1051 #11 0x00007f3b6d998c40 in SqlQueryMaker::handleResult (this=0x88c83d0, result=...) at /home/mark/kde/src/amarok/src/collection/sqlcollection/SqlQueryMaker.cpp:741 #12 0x00007f3b6d99c484 in SqlWorkerThread::run (this=0x8570a60) at /home/mark/kde/src/amarok/src/collection/sqlcollection/SqlQueryMaker.cpp:56 #13 0x00007f3b869ac75d in ThreadWeaver::JobRunHelper::runTheJob (this=0x7f3b67889f70, th=0x2cac640, job=0x8570a60) at ../../../threadweaver/Weaver/Job.cpp:106 #14 0x00007f3b869aca5e in ThreadWeaver::Job::execute (this=0x8570a60, th=0x2cac640) at ../../../threadweaver/Weaver/Job.cpp:135 #15 0x00007f3b869aba2f in ThreadWeaver::ThreadRunHelper::run (this=0x7f3b6788a000, parent=0x2cab510, th=0x2cac640) at ../../../threadweaver/Weaver/Thread.cpp:95 #16 0x00007f3b869abeb8 in ThreadWeaver::Thread::run (this=0x2cac640) at ../../../threadweaver/Weaver/Thread.cpp:142 #17 0x00007f3b89a45445 in QThreadPrivate::start (arg=0x2cac640) at thread/qthread_unix.cpp:188 #18 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #19 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #20 0x0000000000000000 in ?? () The current source language is "auto; currently c". Thread 8 (Thread 0x7f3b66c39910 (LWP 2725)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:261 #1 0x00007f3b89a464fb in QWaitConditionPrivate::wait (this=<value optimized out>, mutex=0x2cac100, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:87 #2 QWaitCondition::wait (this=<value optimized out>, mutex=0x2cac100, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:159 #3 0x00007f3b869ab326 in ThreadWeaver::WeaverImpl::blockThreadUntilJobsAreBeingAssigned (this=0x2cab510, th=0x2184f40) at ../../../threadweaver/Weaver/WeaverImpl.cpp:365 #4 0x00007f3b869ad45b in ThreadWeaver::WorkingHardState::applyForWork (this=0x24e4da0, th=0x2184f40) at ../../../threadweaver/Weaver/WorkingHardState.cpp:71 #5 0x00007f3b869ad474 in ThreadWeaver::WorkingHardState::applyForWork (this=0x24e4da0, th=0x2184f40) at ../../../threadweaver/Weaver/WorkingHardState.cpp:74 #6 0x00007f3b869ad474 in ThreadWeaver::WorkingHardState::applyForWork (this=0x24e4da0, th=0x2184f40) at ../../../threadweaver/Weaver/WorkingHardState.cpp:74 #7 0x00007f3b869ad474 in ThreadWeaver::WorkingHardState::applyForWork (this=0x24e4da0, th=0x2184f40) at ../../../threadweaver/Weaver/WorkingHardState.cpp:74 #8 0x00007f3b869ad474 in ThreadWeaver::WorkingHardState::applyForWork (this=0x24e4da0, th=0x2184f40) at ../../../threadweaver/Weaver/WorkingHardState.cpp:74 #9 0x00007f3b869aba5f in ThreadWeaver::ThreadRunHelper::run (this=0x7f3b66c39000, parent=0x2cab510, th=0x2184f40) at ../../../threadweaver/Weaver/Thread.cpp:87 #10 0x00007f3b869abeb8 in ThreadWeaver::Thread::run (this=0x2184f40) at ../../../threadweaver/Weaver/Thread.cpp:142 #11 0x00007f3b89a45445 in QThreadPrivate::start (arg=0x2184f40) at thread/qthread_unix.cpp:188 #12 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #13 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #14 0x0000000000000000 in ?? () Thread 7 (Thread 0x7f3b66438910 (LWP 2726)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:261 #1 0x00007f3b89a464fb in QWaitConditionPrivate::wait (this=<value optimized out>, mutex=0x2cac100, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:87 #2 QWaitCondition::wait (this=<value optimized out>, mutex=0x2cac100, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:159 #3 0x00007f3b869ab326 in ThreadWeaver::WeaverImpl::blockThreadUntilJobsAreBeingAssigned (this=0x2cab510, th=0x7f3b601671d0) at ../../../threadweaver/Weaver/WeaverImpl.cpp:365 #4 0x00007f3b869ad45b in ThreadWeaver::WorkingHardState::applyForWork (this=0x24e4da0, th=0x7f3b601671d0) at ../../../threadweaver/Weaver/WorkingHardState.cpp:71 #5 0x00007f3b869ad474 in ThreadWeaver::WorkingHardState::applyForWork (this=0x24e4da0, th=0x7f3b601671d0) at ../../../threadweaver/Weaver/WorkingHardState.cpp:74 #6 0x00007f3b869aba5f in ThreadWeaver::ThreadRunHelper::run (this=0x7f3b66438000, parent=0x2cab510, th=0x7f3b601671d0) at ../../../threadweaver/Weaver/Thread.cpp:87 #7 0x00007f3b869abeb8 in ThreadWeaver::Thread::run (this=0x7f3b601671d0) at ../../../threadweaver/Weaver/Thread.cpp:142 #8 0x00007f3b89a45445 in QThreadPrivate::start (arg=0x7f3b601671d0) at thread/qthread_unix.cpp:188 #9 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #10 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #11 0x0000000000000000 in ?? () The current source language is "auto; currently asm". Thread 6 (Thread 0x7f3b65c37910 (LWP 2727)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:261 #1 0x00007f3b89a464fb in QWaitConditionPrivate::wait (this=<value optimized out>, mutex=0x2cac100, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:87 #2 QWaitCondition::wait (this=<value optimized out>, mutex=0x2cac100, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:159 #3 0x00007f3b869ab326 in ThreadWeaver::WeaverImpl::blockThreadUntilJobsAreBeingAssigned (this=0x2cab510, th=0x2395440) at ../../../threadweaver/Weaver/WeaverImpl.cpp:365 #4 0x00007f3b869ad45b in ThreadWeaver::WorkingHardState::applyForWork (this=0x24e4da0, th=0x2395440) at ../../../threadweaver/Weaver/WorkingHardState.cpp:71 #5 0x00007f3b869ad474 in ThreadWeaver::WorkingHardState::applyForWork (this=0x24e4da0, th=0x2395440) at ../../../threadweaver/Weaver/WorkingHardState.cpp:74 #6 0x00007f3b869ad474 in ThreadWeaver::WorkingHardState::applyForWork (this=0x24e4da0, th=0x2395440) at ../../../threadweaver/Weaver/WorkingHardState.cpp:74 #7 0x00007f3b869aba5f in ThreadWeaver::ThreadRunHelper::run (this=0x7f3b65c37000, parent=0x2cab510, th=0x2395440) at ../../../threadweaver/Weaver/Thread.cpp:87 #8 0x00007f3b869abeb8 in ThreadWeaver::Thread::run (this=0x2395440) at ../../../threadweaver/Weaver/Thread.cpp:142 #9 0x00007f3b89a45445 in QThreadPrivate::start (arg=0x2395440) at thread/qthread_unix.cpp:188 #10 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #11 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #12 0x0000000000000000 in ?? () Thread 5 (Thread 0x7f3b4df9c910 (LWP 3440)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:261 #1 0x00007f3b89a464fb in QWaitConditionPrivate::wait (this=<value optimized out>, mutex=0x8a40410, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:87 #2 QWaitCondition::wait (this=<value optimized out>, mutex=0x8a40410, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:159 #3 0x00007f3b8ab7743e in QFileInfoGatherer::run (this=<value optimized out>) at dialogs/qfileinfogatherer.cpp:207 #4 0x00007f3b89a45445 in QThreadPrivate::start (arg=0x8a40400) at thread/qthread_unix.cpp:188 #5 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #6 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #7 0x0000000000000000 in ?? () Thread 4 (Thread 0x7f3b48e91910 (LWP 3441)): #0 0x00007f3b88fa0373 in *__GI___poll (fds=<value optimized out>, nfds=<value optimized out>, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:87 #1 0x00007f3b820e737c in ?? () from /lib/libglib-2.0.so.0 #2 0x00007f3b820e76c0 in g_main_context_iteration () from /lib/libglib-2.0.so.0 #3 0x00007f3b89b541fe in QEventDispatcherGlib::processEvents (this=0x33bb540, flags=<value optimized out>) at kernel/qeventdispatcher_glib.cpp:329 #4 0x00007f3b89b2a532 in QEventLoop::processEvents (this=<value optimized out>, flags=) at kernel/qeventloop.cpp:149 #5 0x00007f3b89b2a904 in QEventLoop::exec (this=0x7f3b48e90fc0, flags=) at kernel/qeventloop.cpp:201 #6 0x00007f3b89a426cb in QThread::exec (this=<value optimized out>) at thread/qthread.cpp:487 #7 0x00007f3b89b0db78 in QInotifyFileSystemWatcherEngine::run (this=0x80400f0) at io/qfilesystemwatcher_inotify.cpp:214 #8 0x00007f3b89a45445 in QThreadPrivate::start (arg=0x80400f0) at thread/qthread_unix.cpp:188 #9 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #10 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #11 0x0000000000000000 in ?? () Thread 3 (Thread 0x7f3b47e8f910 (LWP 3466)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:261 #1 0x00007f3b89a464fb in QWaitConditionPrivate::wait (this=<value optimized out>, mutex=0x83869b0, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:87 #2 QWaitCondition::wait (this=<value optimized out>, mutex=0x83869b0, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:159 #3 0x00007f3b8ab7743e in QFileInfoGatherer::run (this=<value optimized out>) at dialogs/qfileinfogatherer.cpp:207 #4 0x00007f3b89a45445 in QThreadPrivate::start (arg=0x83869a0) at thread/qthread_unix.cpp:188 #5 0x00007f3b83ee6a04 in start_thread (arg=<value optimized out>) at pthread_create.c:300 #6 0x00007f3b88fac7bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #7 0x0000000000000000 in ?? () The current source language is "auto; currently c". Thread 2 (Thread 0x7f3b4768e910 (LWP 3467)): #0 0xffffffffff60017b in ?? () #1 0x00007f3b4768dcf0 in ?? () #2 0x00007fff90fff782 in ?? () Backtrace stopped: previous frame identical to this frame (corrupt stack?) The current source language is "auto; currently asm". Thread 1 (Thread 0x7f3b8c8367a0 (LWP 2709)): #0 0x00007f3b83eea6dd in __pthread_mutex_unlock_usercnt (mutex=0x1a89178) at pthread_mutex_unlock.c:52 #1 __pthread_mutex_unlock (mutex=0x1a89178) at pthread_mutex_unlock.c:289 #2 0x00007f3b8100d284 in ?? () from /usr/lib/libxcb.so.1 #3 0x00007f3b8100d7d7 in ?? () from /usr/lib/libxcb.so.1 #4 0x00007f3b8100da85 in xcb_writev () from /usr/lib/libxcb.so.1 #5 0x00007f3b887bcd4a in _XSend () from /usr/lib/libX11.so.6 #6 0x00007f3b887bce89 in _XReply () from /usr/lib/libX11.so.6 #7 0x00007f3b887997f5 in XGetImage () from /usr/lib/libX11.so.6 #8 0x00007f3b8a7905ee in QX11PixmapData::toImage (this=0x8af0fc0) at image/qpixmap_x11.cpp:1428 #9 0x00007f3b8a78038d in QPixmap::toImage (this=0x7fff90f81fc0) at image/qpixmap.cpp:447 #10 0x00007f3b8c37e4bd in KIconEffect::apply (this=0x7fff90f82010, pixmap=<value optimized out>, effect=1, value=<value optimized out>, col=..., col2=<value optimized out>, trans=false) at ../../kdeui/icons/kiconeffect.cpp:287 #11 0x00007f3b8c37e861 in KIconEffect::apply (this=<value optimized out>, pixmap=..., effect=1, value=<value optimized out>, col=<value optimized out>, trans=false) at ../../kdeui/icons/kiconeffect.cpp:266 #12 0x00007f3b8bceda3d in KRatingPainter::paint (this=0x245ad20, painter=0x7fff90f83250, rect=..., rating=0, hoverRating=0) at /home/mark/kde/src/amarok/src/widgets/kratingpainter.cpp:197 #13 0x00007f3b8b857005 in RatingWidget::paint (this=0x24595a0, painter=0x7fff90f83250, option=0x23b41d0, widget=0x2416bb0) at /home/mark/kde/src/amarok/src/context/widgets/RatingWidget.cpp:266 #14 0x00007f3b8ac64e05 in _q_paintItem (item=<value optimized out>, painter=0x7fff90f83250, option=0x23b41d0, widget=0x2416bb0, useWindowOpacity=<value optimized out>, painterStateProtection=<value optimized out>) at graphicsview/qgraphicsscene.cpp:4630 #15 0x00007f3b8ac773cc in QGraphicsScenePrivate::drawItemHelper (this=<value optimized out>, item=0x24595b0, painter=0x7fff90f83250, option=0x23b41d0, widget=0x2416bb0, painterStateProtection=true) at graphicsview/qgraphicsscene.cpp:4699 #16 0x00007f3b8ac7966c in QGraphicsScene::drawItems (this=<value optimized out>, painter=0x7fff90f83250, numItems=<value optimized out>, items=<value optimized out>, options=0x23b3f90, widget=<value optimized out>) at graphicsview/qgraphicsscene.cpp:5102 #17 0x00007f3b8ac8abbe in QGraphicsView::paintEvent (this=0x23683a0, event=<value optimized out>) at graphicsview/qgraphicsview.cpp:3528 #18 0x00007f3b8a70f7a0 in QWidget::event (this=0x23683a0, event=0x7fff90f83970) at kernel/qwidget.cpp:7687 #19 0x00007f3b8aa6b2a6 in QFrame::event (this=0x23683a0, e=0x7fff90f83970) at widgets/qframe.cpp:559 #20 0x00007f3b8ac8892b in QGraphicsView::viewportEvent (this=0x23683a0, event=0x7fff90f83970) at graphicsview/qgraphicsview.cpp:2919 #21 0x00007f3b89b2af47 in QCoreApplicationPrivate::sendThroughObjectEventFilters (this=<value optimized out>, receiver=0x2416bb0, event=0x7fff90f83970) at kernel/qcoreapplication.cpp:726 #22 0x00007f3b8a6c0ecc in QApplicationPrivate::notify_helper (this=0x1a85ab0, receiver=0x2416bb0, e=0x7fff90f83970) at kernel/qapplication.cpp:4052 #23 0x00007f3b8a6c81ce in QApplication::notify (this=0x7fff90f85570, receiver=0x2416bb0, e=0x7fff90f83970) at kernel/qapplication.cpp:4021 #24 0x00007f3b8bbf2fee in App::notify (this=0x7fff90f85570, receiver=0x2416bb0, event=0x7fff90f83970) at /home/mark/kde/src/amarok/src/App.cpp:845 #25 0x00007f3b89b2bc2c in QCoreApplication::notifyInternal (this=0x7fff90f85570, receiver=0x2416bb0, event=0x7fff90f83970) at kernel/qcoreapplication.cpp:610 #26 0x00007f3b8a716b93 in QCoreApplication::sendSpontaneousEvent (this=0x2364360, pdev=0x1a838b8, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=<value optimized out>, backingStore=0x1a836f0) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:216 #27 QWidgetPrivate::drawWidget (this=0x2364360, pdev=0x1a838b8, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=<value optimized out>, backingStore=0x1a836f0) at kernel/qwidget.cpp:5079 #28 0x00007f3b8a7172f0 in QWidgetPrivate::paintSiblingsRecursive (this=<value optimized out>, pdev=<value optimized out>, siblings=..., index=2, rgn=<value optimized out>, offset=<value optimized out>, flags=4, sharedPainter=0x0, backingStore=0x1a836f0) at kernel/qwidget.cpp:5189 #29 0x00007f3b8a717204 in QWidgetPrivate::paintSiblingsRecursive (this=<value optimized out>, pdev=<value optimized out>, siblings=..., index=7, rgn=<value optimized out>, offset=<value optimized out>, flags=4, sharedPainter=0x0, backingStore=0x1a836f0) at kernel/qwidget.cpp:5180 #30 0x00007f3b8a716803 in QWidgetPrivate::drawWidget (this=0x2362440, pdev=0x1a838b8, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=<value optimized out>, backingStore=0x1a836f0) at kernel/qwidget.cpp:5128 #31 0x00007f3b8a7172f0 in QWidgetPrivate::paintSiblingsRecursive (this=<value optimized out>, pdev=<value optimized out>, siblings=..., index=1, rgn=<value optimized out>, offset=<value optimized out>, flags=4, sharedPainter=0x0, backingStore=0x1a836f0) at kernel/qwidget.cpp:5189 #32 0x00007f3b8a716803 in QWidgetPrivate::drawWidget (this=0x22c9de0, pdev=0x1a838b8, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=<value optimized out>, backingStore=0x1a836f0) at kernel/qwidget.cpp:5128 #33 0x00007f3b8a7172f0 in QWidgetPrivate::paintSiblingsRecursive (this=<value optimized out>, pdev=<value optimized out>, siblings=..., index=5, rgn=<value optimized out>, offset=<value optimized out>, flags=4, sharedPainter=0x0, backingStore=0x1a836f0) at kernel/qwidget.cpp:5189 #34 0x00007f3b8a716803 in QWidgetPrivate::drawWidget (this=0x2308c40, pdev=0x1a838b8, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=<value optimized out>, backingStore=0x1a836f0) at kernel/qwidget.cpp:5128 #35 0x00007f3b8a7172f0 in QWidgetPrivate::paintSiblingsRecursive (this=<value optimized out>, pdev=<value optimized out>, siblings=..., index=61, rgn=<value optimized out>, offset=<value optimized out>, flags=4, sharedPainter=0x0, backingStore=0x1a836f0) at kernel/qwidget.cpp:5189 #36 0x00007f3b8a716803 in QWidgetPrivate::drawWidget (this=0x1a839d0, pdev=0x1a838b8, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=<value optimized out>, backingStore=0x1a836f0) at kernel/qwidget.cpp:5128 #37 0x00007f3b8a888e1e in QWidgetBackingStore::sync (this=0x1a836f0) at painting/qbackingstore.cpp:1269 #38 0x00007f3b8a708fa0 in QWidgetPrivate::syncBackingStore (this=0x1a839d0) at kernel/qwidget.cpp:1603 #39 0x00007f3b8a70f5b8 in QWidget::event (this=0x1a82bf0, event=0x87d7930) at kernel/qwidget.cpp:7827 #40 0x00007f3b8aa859db in QMainWindow::event (this=0x1a82bf0, event=0x87d7930) at widgets/qmainwindow.cpp:1399 #41 0x00007f3b8a6c0efc in QApplicationPrivate::notify_helper (this=0x1a85ab0, receiver=0x1a82bf0, e=0x87d7930) at kernel/qapplication.cpp:4056 #42 0x00007f3b8a6c81ce in QApplication::notify (this=0x7fff90f85570, receiver=0x1a82bf0, e=0x87d7930) at kernel/qapplication.cpp:4021 #43 0x00007f3b8bbf2fee in App::notify (this=0x7fff90f85570, receiver=0x1a82bf0, event=0x87d7930) at /home/mark/kde/src/amarok/src/App.cpp:845 #44 0x00007f3b89b2bc2c in QCoreApplication::notifyInternal (this=0x7fff90f85570, receiver=0x1a82bf0, event=0x87d7930) at kernel/qcoreapplication.cpp:610 #45 0x00007f3b89b2c80a in QCoreApplication::sendEvent (receiver=0x0, event_type=<value optimized out>, data=0x1938f30) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:213 #46 QCoreApplicationPrivate::sendPostedEvents (receiver=0x0, event_type=<value optimized out>, data=0x1938f30) at kernel/qcoreapplication.cpp:1247 #47 0x00007f3b89b54533 in QCoreApplication::sendPostedEvents (s=<value optimized out>) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:218 #48 postEventSourceDispatch (s=<value optimized out>) at kernel/qeventdispatcher_glib.cpp:210 #49 0x00007f3b820e3bce in g_main_context_dispatch () from /lib/libglib-2.0.so.0 #50 0x00007f3b820e7598 in ?? () from /lib/libglib-2.0.so.0 #51 0x00007f3b820e76c0 in g_main_context_iteration () from /lib/libglib-2.0.so.0 #52 0x00007f3b89b541a6 in QEventDispatcherGlib::processEvents (this=0x1938770, flags=<value optimized out>) at kernel/qeventdispatcher_glib.cpp:327 #53 0x00007f3b8a7554be in QGuiEventDispatcherGlib::processEvents (this=0x1a89178, flags=<value optimized out>) at kernel/qguieventdispatcher_glib.cpp:202 #54 0x00007f3b89b2a532 in QEventLoop::processEvents (this=<value optimized out>, flags=) at kernel/qeventloop.cpp:149 #55 0x00007f3b89b2a904 in QEventLoop::exec (this=0x7fff90f85510, flags=) at kernel/qeventloop.cpp:201 #56 0x00007f3b89b2cab9 in QCoreApplication::exec () at kernel/qcoreapplication.cpp:888 #57 0x00000000004098af in main (argc=4, argv=0x7fff90f87478) at /home/mark/kde/src/amarok/src/main.cpp:235 The current source language is "auto; currently c". Raising priority Committed a patch (from Max Kossick), please test: commit 2a24f8d7d1484741aa0732d3f7e696c1e2e05496 Author: Mark Kretschmann <kretschmann@kde.org> Date: Mon Dec 28 08:03:25 2009 +0100 Fix random crashes with SqlQueryMaker. Many thanks to Maximilian Kossick for making this patch. @Max: I had to modify this slightly to make it compile. Please check for correctness. @All: More testing for this is very welcome. BUG: 215684 CCMAIL: amarok-devel@kde.org The bug is fixed! No more crashes in local collection search! Thanks to Maximilian Kossick! commit 2a24f8d7d1484741aa0732d3f7e696c1e2e05496 Author: Mark Kretschmann <kretschmann@kde.org> Date: Mon Dec 28 08:03:25 2009 +0100 Fix random crashes with SqlQueryMaker. Many thanks to Maximilian Kossick for making this patch. @Max: I had to modify this slightly to make it compile. Please check for correctness. @All: More testing for this is very welcome. BUG: 215684 CCMAIL: amarok-devel@kde.org diff --git a/src/collection/mysqlecollection/CMakeLists.txt b/src/collection/mysqlecollection/CMakeLists.txt index 0193a5a..3d28353 100755 --- a/src/collection/mysqlecollection/CMakeLists.txt +++ b/src/collection/mysqlecollection/CMakeLists.txt @@ -36,6 +36,7 @@ set(amarok_collection-mysqlecollection_PART_SRCS ../sqlcollection/SqlCollectionDBusHandler.cpp ../sqlcollection/SqlCollectionLocation.cpp ../sqlcollection/SqlQueryMaker.cpp + ../sqlcollection/SqlQueryMakerInternal.cpp ../sqlcollection/SqlReadLabelCapability.cpp ../sqlcollection/SqlRegistry.cpp ../sqlcollection/SqlMeta.cpp diff --git a/src/collection/mysqlservercollection/CMakeLists.txt b/src/collection/mysqlservercollection/CMakeLists.txt index 940bf6d..525204b 100755 --- a/src/collection/mysqlservercollection/CMakeLists.txt +++ b/src/collection/mysqlservercollection/CMakeLists.txt @@ -36,6 +36,8 @@ set(amarok_collection-mysqlservercollection_PART_SRCS ../sqlcollection/SqlCollectionDBusHandler.cpp ../sqlcollection/SqlCollectionLocation.cpp ../sqlcollection/SqlQueryMaker.cpp + ../sqlcollection/SqlQueryMakerInternal.cpp + ../sqlcollection/SqlReadLabelCapability.cpp ../sqlcollection/SqlReadLabelCapability.cpp ../sqlcollection/SqlRegistry.cpp ../sqlcollection/SqlMeta.cpp diff --git a/src/collection/sqlcollection/SqlQueryMaker.cpp b/src/collection/sqlcollection/SqlQueryMaker.cpp index c027b3c..ecef045 100644 --- a/src/collection/sqlcollection/SqlQueryMaker.cpp +++ b/src/collection/sqlcollection/SqlQueryMaker.cpp @@ -23,7 +23,10 @@ #include "MountPointManager.h" #include "SqlCollection.h" +#include "SqlQueryMakerInternal.h" +#include "collection/SqlStorage.h" +#include <QPointer> #include <QStack> #include <threadweaver/Job.h> @@ -34,30 +37,37 @@ using namespace Meta; class SqlWorkerThread : public ThreadWeaver::Job { public: - SqlWorkerThread( SqlQueryMaker *queryMaker ) + SqlWorkerThread( SqlQueryMakerInternal *queryMakerInternal ) : ThreadWeaver::Job() - , m_queryMaker( queryMaker ) + , m_queryMakerInternal( queryMakerInternal ) , m_aborted( false ) { //nothing to do } + virtual ~SqlWorkerThread() + { + delete m_queryMakerInternal; + } + virtual void requestAbort() { m_aborted = true; } + SqlQueryMakerInternal* queryMakerInternal() const + { + return m_queryMakerInternal; + } + protected: virtual void run() { - QString query = m_queryMaker->query(); - QStringList result = m_queryMaker->runQuery( query ); - if( !m_aborted ) - m_queryMaker->handleResult( result ); + m_queryMakerInternal->run(); setFinished( !m_aborted ); } private: - SqlQueryMaker *m_queryMaker; + SqlQueryMakerInternal *m_queryMakerInternal; bool m_aborted; }; @@ -83,7 +93,14 @@ struct SqlQueryMaker::Private QStack<bool> andStack; - Meta::DataList data; + QStringList blockingCustomData; + Meta::DataList blockingData; + Meta::TrackList blockingTracks; + Meta::AlbumList blockingAlbums; + Meta::ArtistList blockingArtists; + Meta::GenreList blockingGenres; + Meta::ComposerList blockingComposers; + Meta::YearList blockingYears; bool blocking; bool used; }; @@ -101,6 +118,8 @@ SqlQueryMaker::SqlQueryMaker( SqlCollection* collection ) SqlQueryMaker::~SqlQueryMaker() { + disconnect(); + abortQuery(); delete d; } @@ -125,7 +144,15 @@ SqlQueryMaker::reset() d->andStack.push( true ); //and is default d->blocking = false; d->used = false; - d->data.clear(); + d->blockingCustomData.clear(); + d->blockingData.clear(); + d->blockingAlbums.clear(); + d->blockingArtists.clear(); + d->blockingComposers.clear(); + d->blockingGenres.clear(); + d->blockingTracks.clear(); + d->blockingYears.clear(); + return this; } @@ -133,7 +160,12 @@ void SqlQueryMaker::abortQuery() { if( d->worker ) + { d->worker->requestAbort(); + d->worker->disconnect( this ); + if( d->worker->queryMakerInternal() ) + d->worker->queryMakerInternal()->disconnect( this ); + } } QueryMaker* @@ -162,18 +194,41 @@ SqlQueryMaker::run() //TODO: wait or job to complete } - else if ( ! d->blocking ) - { - //debug() << "Query is " << query(); - d->worker = new SqlWorkerThread( this ); - connect( d->worker, SIGNAL( done( ThreadWeaver::Job* ) ), SLOT( done( ThreadWeaver::Job* ) ) ); - ThreadWeaver::Weaver::instance()->enqueue( d->worker ); - } - else //use it blocking + else { - QString query = this->query(); - QStringList result = runQuery( query ); - handleResult( result ); + SqlQueryMakerInternal *qmi = new SqlQueryMakerInternal( m_collection ); + qmi->setQuery( query() ); + qmi->setQueryType( d->queryType ); + qmi->setResultAsDataPtrs( d->resultAsDataPtrs ); + + + if ( !d->blocking ) + { + connect( qmi, SIGNAL(newResultReady(QString,Meta::AlbumList)), SIGNAL(newResultReady(QString,Meta::AlbumList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::ArtistList)), SIGNAL(newResultReady(QString,Meta::ArtistList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::GenreList)), SIGNAL(newResultReady(QString,Meta::GenreList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::ComposerList)), SIGNAL(newResultReady(QString,Meta::ComposerList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::YearList)), SIGNAL(newResultReady(QString,Meta::YearList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::TrackList)), SIGNAL(newResultReady(QString,Meta::TrackList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::DataList)), SIGNAL(newResultReady(QString,Meta::DataList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,QStringList)), SIGNAL(newResultReady(QString,QStringList)), Qt::DirectConnection ); + d->worker = new SqlWorkerThread( qmi ); + connect( d->worker, SIGNAL( done( ThreadWeaver::Job* ) ), SLOT( done( ThreadWeaver::Job* ) ) ); + ThreadWeaver::Weaver::instance()->enqueue( d->worker ); + } + else //use it blocking + { + connect( qmi, SIGNAL(newResultReady(QString,Meta::AlbumList)), SLOT(blockingNewResultReady(QString,Meta::AlbumList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::ArtistList)), SLOT(blockingNewResultReady(QString,Meta::ArtistList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::GenreList)), SLOT(blockingNewResultReady(QString,Meta::GenreList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::ComposerList)), SLOT(blockingNewResultReady(QString,Meta::ComposerList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::YearList)), SLOT(blockingNewResultReady(QString,Meta::YearList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::TrackList)), SLOT(blockingNewResultReady(QString,Meta::TrackList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::DataList)), SLOT(blockingNewResultReady(QString,Meta::DataList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,QStringList)), SLOT(blockingNewResultReady(QString,QStringList)), Qt::DirectConnection ); + qmi->run(); + delete qmi; + } } d->used = true; } @@ -535,7 +590,7 @@ SqlQueryMaker::orderBy( qint64 value, bool descending ) QueryMaker* SqlQueryMaker::orderByRandom() { - d->queryOrderBy = " ORDER BY " + m_collection->randomFunc(); + d->queryOrderBy = " ORDER BY " + CollectionManager::instance()->sqlStorage()->randomFunc(); return this; } @@ -725,80 +780,10 @@ SqlQueryMaker::query() QStringList SqlQueryMaker::runQuery( const QString &query ) { - return m_collection->query( query ); + return CollectionManager::instance()->sqlStorage()->query( query ); } -void -SqlQueryMaker::handleResult( const QStringList &result ) -{ - if( !result.isEmpty() ) - { - switch( d->queryType ) { - case QueryMaker::Custom: - emit newResultReady( m_collection->collectionId(), result ); - break; - case QueryMaker::Track: - handleTracks( result ); - break; - case QueryMaker::Artist: - handleArtists( result ); - break; - case QueryMaker::Album: - handleAlbums( result ); - break; - case QueryMaker::Genre: - handleGenres( result ); - break; - case QueryMaker::Composer: - handleComposers( result ); - break; - case QueryMaker::Year: - handleYears( result ); - break; - - case QueryMaker::None: - debug() << "Warning: queryResult with queryType == NONE"; - } - } - else - { - if( d->resultAsDataPtrs ) - { - emit newResultReady( m_collection->collectionId(), Meta::DataList() ); - } - else - { - switch( d->queryType ) { - case QueryMaker::Custom: - emit newResultReady( m_collection->collectionId(), QStringList() ); - break; - case QueryMaker::Track: - emit newResultReady( m_collection->collectionId(), Meta::TrackList() ); - break; - case QueryMaker::Artist: - emit newResultReady( m_collection->collectionId(), Meta::ArtistList() ); - break; - case QueryMaker::Album: - emit newResultReady( m_collection->collectionId(), Meta::AlbumList() ); - break; - case QueryMaker::Genre: - emit newResultReady( m_collection->collectionId(), Meta::GenreList() ); - break; - case QueryMaker::Composer: - emit newResultReady( m_collection->collectionId(), Meta::ComposerList() ); - break; - case QueryMaker::Year: - emit newResultReady( m_collection->collectionId(), Meta::YearList() ); - break; - - case QueryMaker::None: - debug() << "Warning: queryResult with queryType == NONE"; - } - } - } - //queryDone will be emitted in done(Job*) -} void SqlQueryMaker::setBlocking( bool enabled ) @@ -817,115 +802,57 @@ SqlQueryMaker::collectionIds() const Meta::DataList SqlQueryMaker::data( const QString &id ) const { - if ( d->blocking && d->used && d->resultAsDataPtrs && m_collection->collectionId() == id ) - return d->data; - else - return Meta::DataList(); + Q_UNUSED( id ); + return d->blockingData; } Meta::TrackList SqlQueryMaker::tracks( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Track && m_collection->collectionId() == id ) - { - Meta::TrackList list; - foreach( DataPtr p, d->data ) - { - list << Meta::TrackPtr::staticCast( p ); - } - return list; - } - else - return Meta::TrackList(); + Q_UNUSED( id ); + return d->blockingTracks; } Meta::AlbumList SqlQueryMaker::albums( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Album && m_collection->collectionId() == id ) - { - Meta::AlbumList list; - foreach( DataPtr p, d->data ) - { - list << Meta::AlbumPtr::staticCast( p ); - } - return list; - } - else - return Meta::AlbumList(); + Q_UNUSED( id ); + return d->blockingAlbums; } Meta::ArtistList SqlQueryMaker::artists( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Artist && m_collection->collectionId() == id ) - { - Meta::ArtistList list; - foreach( DataPtr p, d->data ) - { - list << Meta::ArtistPtr::staticCast( p ); - } - return list; - } - else - return Meta::ArtistList(); + Q_UNUSED( id ); + return d->blockingArtists; } Meta::GenreList SqlQueryMaker::genres( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Genre && m_collection->collectionId() == id ) - { - Meta::GenreList list; - foreach( DataPtr p, d->data ) - { - list << Meta::GenrePtr::staticCast( p ); - } - return list; - } - else - return Meta::GenreList(); + Q_UNUSED( id ); + return d->blockingGenres; } Meta::ComposerList SqlQueryMaker::composers( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Composer && m_collection->collectionId() == id ) - { - Meta::ComposerList list; - foreach( DataPtr p, d->data ) - { - list << Meta::ComposerPtr::staticCast( p ); - } - return list; - } - else - return Meta::ComposerList(); + Q_UNUSED( id ); + return d->blockingComposers; } Meta::YearList SqlQueryMaker::years( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Year && m_collection->collectionId() == id ) - { - Meta::YearList list; - foreach( DataPtr p, d->data ) - { - list << Meta::YearPtr::staticCast( p ); - } - return list; - } - else - return Meta::YearList(); + Q_UNUSED( id ); + return d->blockingYears; } QStringList SqlQueryMaker::customData( const QString &id ) const { - AMAROK_NOTIMPLEMENTED - Q_UNUSED( id ) - // not implemented yet - return QStringList(); + Q_UNUSED( id ); + return d->blockingCustomData; } QString @@ -1016,116 +943,10 @@ SqlQueryMaker::andOr() const return d->andStack.top() ? " AND " : " OR "; } -// What's worse, a bunch of almost identical repeated code, or a not so obvious macro? :-) -// The macro below will emit the proper result signal. If m_resultAsDataPtrs is true, -// it'll emit the signal that takes a list of DataPtrs. Otherwise, it'll call the -// signal that takes the list of the specific class. -// If qm is used blocking it only stores the result ptrs into data as DataPtrs - -#define emitOrStoreProperResult( PointerType, list ) { \ - if ( d->resultAsDataPtrs || d->blocking ) { \ - foreach( PointerType p, list ) { \ - d->data << DataPtr::staticCast( p ); \ - } \ - if ( !d->blocking ) \ - emit newResultReady( m_collection->collectionId(), d->data ); \ - } \ - else { \ - emit newResultReady( m_collection->collectionId(), list ); \ - } \ - } - -void -SqlQueryMaker::handleTracks( const QStringList &result ) -{ - TrackList tracks; - SqlRegistry* reg = m_collection->registry(); - //there are 29 columns in the result set as generated by startTrackQuery() - int returnCount = SqlTrack::getTrackReturnValueCount(); - int resultRows = result.size() / returnCount; - for( int i = 0; i < resultRows; i++ ) - { - QStringList row = result.mid( i*returnCount, returnCount ); - tracks.append( reg->getTrack( row ) ); - } - emitOrStoreProperResult( TrackPtr, tracks ); -} - -void -SqlQueryMaker::handleArtists( const QStringList &result ) -{ - ArtistList artists; - SqlRegistry* reg = m_collection->registry(); - for( QStringListIterator iter( result ); iter.hasNext(); ) - { - QString name = iter.next(); - QString id = iter.next(); - artists.append( reg->getArtist( name, id.toInt() ) ); - } - emitOrStoreProperResult( ArtistPtr, artists ); -} - -void -SqlQueryMaker::handleAlbums( const QStringList &result ) -{ - AlbumList albums; - SqlRegistry* reg = m_collection->registry(); - for( QStringListIterator iter( result ); iter.hasNext(); ) - { - QString name = iter.next(); - QString id = iter.next(); - QString artist = iter.next(); - albums.append( reg->getAlbum( name, id.toInt(), artist.toInt() ) ); - } - emitOrStoreProperResult( AlbumPtr, albums ); -} - -void -SqlQueryMaker::handleGenres( const QStringList &result ) -{ - GenreList genres; - SqlRegistry* reg = m_collection->registry(); - for( QStringListIterator iter( result ); iter.hasNext(); ) - { - QString name = iter.next(); - QString id = iter.next(); - genres.append( reg->getGenre( name, id.toInt() ) ); - } - emitOrStoreProperResult( GenrePtr, genres ); -} - -void -SqlQueryMaker::handleComposers( const QStringList &result ) -{ - ComposerList composers; - SqlRegistry* reg = m_collection->registry(); - for( QStringListIterator iter( result ); iter.hasNext(); ) - { - QString name = iter.next(); - QString id = iter.next(); - composers.append( reg->getComposer( name, id.toInt() ) ); - } - emitOrStoreProperResult( ComposerPtr, composers ); -} - -void -SqlQueryMaker::handleYears( const QStringList &result ) -{ - YearList years; - SqlRegistry* reg = m_collection->registry(); - for( QStringListIterator iter( result ); iter.hasNext(); ) - { - QString name = iter.next(); - QString id = iter.next(); - years.append( reg->getYear( name, id.toInt() ) ); - } - emitOrStoreProperResult( YearPtr, years ); -} - QString SqlQueryMaker::escape( QString text ) const //krazy:exclude=constref { - return m_collection->escape( text ); + return CollectionManager::instance()->sqlStorage()->escape( text ); } QString @@ -1167,5 +988,61 @@ SqlQueryMaker::likeCondition( const QString &text, bool anyBegin, bool anyEnd ) } } +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::AlbumList &albums) +{ + Q_UNUSED( id ); + d->blockingAlbums = albums; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::ArtistList &artists) +{ + Q_UNUSED( id ); + d->blockingArtists = artists; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::GenreList &genres) +{ + Q_UNUSED( id ); + d->blockingGenres = genres; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::ComposerList &composers) +{ + Q_UNUSED( id ); + d->blockingComposers = composers; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::YearList &years) +{ + Q_UNUSED( id ); + d->blockingYears = years; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::TrackList &tracks) +{ + Q_UNUSED( id ); + d->blockingTracks = tracks; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::DataList &data) +{ + Q_UNUSED( id ); + d->blockingData = data; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const QStringList &customData) +{ + Q_UNUSED( id ); + d->blockingCustomData = customData; +} + #include "SqlQueryMaker.moc" diff --git a/src/collection/sqlcollection/SqlQueryMaker.h b/src/collection/sqlcollection/SqlQueryMaker.h index c20766e..b58b86c 100644 --- a/src/collection/sqlcollection/SqlQueryMaker.h +++ b/src/collection/sqlcollection/SqlQueryMaker.h @@ -17,7 +17,7 @@ #ifndef AMAROK_COLLECTION_SQLQUERYMAKER_H #define AMAROK_COLLECTION_SQLQUERYMAKER_H -#include "QueryMaker.h" +#include "collection/QueryMaker.h" #include "amarok_export.h" @@ -103,6 +103,14 @@ class /*AMAROK_EXPORT*/ SqlQueryMaker : public QueryMaker public slots: void done( ThreadWeaver::Job * job ); + void blockingNewResultReady( const QString &id, const QStringList &customData ); + void blockingNewResultReady( const QString &id, const Meta::AlbumList &albums ); + void blockingNewResultReady( const QString &id, const Meta::ArtistList &artists ); + void blockingNewResultReady( const QString &id, const Meta::GenreList &genres ); + void blockingNewResultReady( const QString &id, const Meta::ComposerList &composers ); + void blockingNewResultReady( const QString &id, const Meta::YearList &years ); + void blockingNewResultReady( const QString &id, const Meta::TrackList &tracks ); + void blockingNewResultReady( const QString &id, const Meta::DataList &data ); private: @@ -112,13 +120,6 @@ class /*AMAROK_EXPORT*/ SqlQueryMaker : public QueryMaker QString nameForValue( qint64 value ); QString andOr() const; - void handleTracks( const QStringList &result ); - void handleArtists( const QStringList &result ); - void handleAlbums( const QStringList &result ); - void handleGenres( const QStringList &result ); - void handleComposers( const QStringList &result ); - void handleYears( const QStringList &result ); - SqlCollection *m_collection; struct Private; @@ -126,4 +127,10 @@ class /*AMAROK_EXPORT*/ SqlQueryMaker : public QueryMaker }; +class SqlQueryMakerFactory +{ +public: + virtual SqlQueryMaker* createQueryMaker() const = 0; +}; + #endif /* AMAROK_COLLECTION_SQLQUERYMAKER_H */ diff --git a/src/collection/sqlcollection/SqlQueryMakerInternal.cpp b/src/collection/sqlcollection/SqlQueryMakerInternal.cpp new file mode 100644 index 0000000..db999d1 --- /dev/null +++ b/src/collection/sqlcollection/SqlQueryMakerInternal.cpp @@ -0,0 +1,250 @@ +/**************************************************************************************** + * Copyright (c) 2009 Maximilian Kossick <maximilian.kossick@googlemail.com> * + * * + * This program is free software; you can redistribute it and/or modify it under * + * the terms of the GNU General Public License as published by the Free Software * + * Foundation; either version 2 of the License, or (at your option) any later * + * version. * + * * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY * + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * + * PARTICULAR PURPOSE. See the GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License along with * + * this program. If not, see <http://www.gnu.org/licenses/>. * + ****************************************************************************************/ + +#include "SqlQueryMakerInternal.h" + +#include "collection/SqlStorage.h" +#include "Debug.h" +#include "SqlCollection.h" +#include "SqlMeta.h" +#include "SqlRegistry.h" + +#include <QStringList> + +SqlQueryMakerInternal::SqlQueryMakerInternal( SqlCollection *collection ) + : QObject() + , m_collection( collection ) + , m_resultAsDataPtrs( false ) + , m_queryType( QueryMaker::None ) +{ +} + +SqlQueryMakerInternal::~ SqlQueryMakerInternal() +{ + disconnect(); +} + +void +SqlQueryMakerInternal::run() +{ + Q_ASSERT( !m_query.isEmpty() ); + if( m_collection ) + { + QStringList result = m_collection->query( m_query ); + handleResult( result ); + } + else + { + deleteLater(); + } + +} + +void +SqlQueryMakerInternal::setQuery( const QString &query ) +{ + m_query = query; +} + +void +SqlQueryMakerInternal::setResultAsDataPtrs( bool value ) +{ + m_resultAsDataPtrs = value; +} + +void +SqlQueryMakerInternal::setQueryType( QueryMaker::QueryType type ) +{ + m_queryType = type; +} + +void +SqlQueryMakerInternal::handleResult( const QStringList &result ) +{ + if( !result.isEmpty() ) + { + switch( m_queryType ) { + case QueryMaker::Custom: + emit newResultReady( m_collection->collectionId(), result ); + break; + case QueryMaker::Track: + handleTracks( result ); + break; + case QueryMaker::Artist: + handleArtists( result ); + break; + case QueryMaker::Album: + handleAlbums( result ); + break; + case QueryMaker::Genre: + handleGenres( result ); + break; + case QueryMaker::Composer: + handleComposers( result ); + break; + case QueryMaker::Year: + handleYears( result ); + break; + + case QueryMaker::None: + debug() << "Warning: queryResult with queryType == NONE"; + } + } + else + { + if( m_resultAsDataPtrs ) + { + emit newResultReady( m_collection->collectionId(), Meta::DataList() ); + } + else + { + switch( m_queryType ) { + case QueryMaker::Custom: + emit newResultReady( m_collection->collectionId(), QStringList() ); + break; + case QueryMaker::Track: + emit newResultReady( m_collection->collectionId(), Meta::TrackList() ); + break; + case QueryMaker::Artist: + emit newResultReady( m_collection->collectionId(), Meta::ArtistList() ); + break; + case QueryMaker::Album: + emit newResultReady( m_collection->collectionId(), Meta::AlbumList() ); + break; + case QueryMaker::Genre: + emit newResultReady( m_collection->collectionId(), Meta::GenreList() ); + break; + case QueryMaker::Composer: + emit newResultReady( m_collection->collectionId(), Meta::ComposerList() ); + break; + case QueryMaker::Year: + emit newResultReady( m_collection->collectionId(), Meta::YearList() ); + break; + + case QueryMaker::None: + debug() << "Warning: queryResult with queryType == NONE"; + } + } + } + + //queryDone will be emitted in done(Job*) +} + +// What's worse, a bunch of almost identical repeated code, or a not so obvious macro? :-) +// The macro below will emit the proper result signal. If m_resultAsDataPtrs is true, +// it'll emit the signal that takes a list of DataPtrs. Otherwise, it'll call the +// signal that takes the list of the specific class. +// If qm is used blocking it only stores the result ptrs into data as DataPtrs + +#define emitOrStoreProperResult( PointerType, list ) { \ + if ( m_resultAsDataPtrs ) { \ + Meta::DataList data; \ + foreach( PointerType p, list ) { \ + data << Meta::DataPtr::staticCast( p ); \ + } \ + emit newResultReady( m_collection->collectionId(), data ); \ + } \ + else { \ + emit newResultReady( m_collection->collectionId(), list ); \ + } \ + } + +void +SqlQueryMakerInternal::handleTracks( const QStringList &result ) +{ + Meta::TrackList tracks; + SqlRegistry* reg = m_collection->registry(); + //there are 29 columns in the result set as generated by startTrackQuery() + int returnCount = Meta::SqlTrack::getTrackReturnValueCount(); + int resultRows = result.size() / returnCount; + for( int i = 0; i < resultRows; i++ ) + { + QStringList row = result.mid( i*returnCount, returnCount ); + tracks.append( reg->getTrack( row ) ); + } + emitOrStoreProperResult( Meta::TrackPtr, tracks ); +} + +void +SqlQueryMakerInternal::handleArtists( const QStringList &result ) +{ + Meta::ArtistList artists; + SqlRegistry* reg = m_collection->registry(); + for( QStringListIterator iter( result ); iter.hasNext(); ) + { + QString name = iter.next(); + QString id = iter.next(); + artists.append( reg->getArtist( name, id.toInt() ) ); + } + emitOrStoreProperResult( Meta::ArtistPtr, artists ); +} + +void +SqlQueryMakerInternal::handleAlbums( const QStringList &result ) +{ + Meta::AlbumList albums; + SqlRegistry* reg = m_collection->registry(); + for( QStringListIterator iter( result ); iter.hasNext(); ) + { + QString name = iter.next(); + QString id = iter.next(); + QString artist = iter.next(); + albums.append( reg->getAlbum( name, id.toInt(), artist.toInt() ) ); + } + emitOrStoreProperResult( Meta::AlbumPtr, albums ); +} + +void +SqlQueryMakerInternal::handleGenres( const QStringList &result ) +{ + Meta::GenreList genres; + SqlRegistry* reg = m_collection->registry(); + for( QStringListIterator iter( result ); iter.hasNext(); ) + { + QString name = iter.next(); + QString id = iter.next(); + genres.append( reg->getGenre( name, id.toInt() ) ); + } + emitOrStoreProperResult( Meta::GenrePtr, genres ); +} + +void +SqlQueryMakerInternal::handleComposers( const QStringList &result ) +{ + Meta::ComposerList composers; + SqlRegistry* reg = m_collection->registry(); + for( QStringListIterator iter( result ); iter.hasNext(); ) + { + QString name = iter.next(); + QString id = iter.next(); + composers.append( reg->getComposer( name, id.toInt() ) ); + } + emitOrStoreProperResult( Meta::ComposerPtr, composers ); +} + +void +SqlQueryMakerInternal::handleYears( const QStringList &result ) +{ + Meta::YearList years; + SqlRegistry* reg = m_collection->registry(); + for( QStringListIterator iter( result ); iter.hasNext(); ) + { + QString name = iter.next(); + QString id = iter.next(); + years.append( reg->getYear( name, id.toInt() ) ); + } + emitOrStoreProperResult( Meta::YearPtr, years ); +} diff --git a/src/collection/sqlcollection/SqlQueryMakerInternal.h b/src/collection/sqlcollection/SqlQueryMakerInternal.h new file mode 100644 index 0000000..b8ecda4 --- /dev/null +++ b/src/collection/sqlcollection/SqlQueryMakerInternal.h @@ -0,0 +1,68 @@ +/**************************************************************************************** + * Copyright (c) 2009 Maximilian Kossick <maximilian.kossick@googlemail.com> * + * * + * This program is free software; you can redistribute it and/or modify it under * + * the terms of the GNU General Public License as published by the Free Software * + * Foundation; either version 2 of the License, or (at your option) any later * + * version. * + * * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY * + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * + * PARTICULAR PURPOSE. See the GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License along with * + * this program. If not, see <http://www.gnu.org/licenses/>. * + ****************************************************************************************/ + +#ifndef SQLQUERYMAKERINTERNAL_H +#define SQLQUERYMAKERINTERNAL_H + +#include "collection/QueryMaker.h" +#include "meta/Meta.h" + +#include <QObject> +#include <QPointer> +#include <QString> + +class SqlCollection; + +class SqlQueryMakerInternal : public QObject +{ +Q_OBJECT +public: + explicit SqlQueryMakerInternal( SqlCollection *collection ); + virtual ~ SqlQueryMakerInternal(); + + void run(); + void setQuery( const QString &query ); + void setQueryType( QueryMaker::QueryType type ); + void setResultAsDataPtrs( bool value ); + +signals: + void newResultReady( QString collectionId, Meta::TrackList ); + void newResultReady( QString collectionId, Meta::ArtistList ); + void newResultReady( QString collectionId, Meta::AlbumList ); + void newResultReady( QString collectionId, Meta::GenreList ); + void newResultReady( QString collectionId, Meta::ComposerList ); + void newResultReady( QString collectionId, Meta::YearList ); + void newResultReady( QString collectionId, Meta::DataList ); + void newResultReady( QString collectionId, QStringList ); + +private: + void handleResult( const QStringList &result ); + void handleTracks( const QStringList &result ); + void handleArtists( const QStringList &result ); + void handleAlbums( const QStringList &result ); + void handleGenres( const QStringList &result ); + void handleComposers( const QStringList &result ); + void handleYears( const QStringList &result ); + +private: + QPointer<SqlCollection> m_collection; + bool m_resultAsDataPtrs; + QueryMaker::QueryType m_queryType; + QString m_query; + +}; + +#endif // SQLQUERYMAKERINTERNAL_H commit 2a24f8d7d1484741aa0732d3f7e696c1e2e05496 Author: Mark Kretschmann <kretschmann@kde.org> Date: Mon Dec 28 08:03:25 2009 +0100 Fix random crashes with SqlQueryMaker. Many thanks to Maximilian Kossick for making this patch. @Max: I had to modify this slightly to make it compile. Please check for correctness. @All: More testing for this is very welcome. BUG: 215684 CCMAIL: amarok-devel@kde.org diff --git a/src/collection/mysqlecollection/CMakeLists.txt b/src/collection/mysqlecollection/CMakeLists.txt index 0193a5a..3d28353 100755 --- a/src/collection/mysqlecollection/CMakeLists.txt +++ b/src/collection/mysqlecollection/CMakeLists.txt @@ -36,6 +36,7 @@ set(amarok_collection-mysqlecollection_PART_SRCS ../sqlcollection/SqlCollectionDBusHandler.cpp ../sqlcollection/SqlCollectionLocation.cpp ../sqlcollection/SqlQueryMaker.cpp + ../sqlcollection/SqlQueryMakerInternal.cpp ../sqlcollection/SqlReadLabelCapability.cpp ../sqlcollection/SqlRegistry.cpp ../sqlcollection/SqlMeta.cpp diff --git a/src/collection/mysqlservercollection/CMakeLists.txt b/src/collection/mysqlservercollection/CMakeLists.txt index 940bf6d..525204b 100755 --- a/src/collection/mysqlservercollection/CMakeLists.txt +++ b/src/collection/mysqlservercollection/CMakeLists.txt @@ -36,6 +36,8 @@ set(amarok_collection-mysqlservercollection_PART_SRCS ../sqlcollection/SqlCollectionDBusHandler.cpp ../sqlcollection/SqlCollectionLocation.cpp ../sqlcollection/SqlQueryMaker.cpp + ../sqlcollection/SqlQueryMakerInternal.cpp + ../sqlcollection/SqlReadLabelCapability.cpp ../sqlcollection/SqlReadLabelCapability.cpp ../sqlcollection/SqlRegistry.cpp ../sqlcollection/SqlMeta.cpp diff --git a/src/collection/sqlcollection/SqlQueryMaker.cpp b/src/collection/sqlcollection/SqlQueryMaker.cpp index c027b3c..ecef045 100644 --- a/src/collection/sqlcollection/SqlQueryMaker.cpp +++ b/src/collection/sqlcollection/SqlQueryMaker.cpp @@ -23,7 +23,10 @@ #include "MountPointManager.h" #include "SqlCollection.h" +#include "SqlQueryMakerInternal.h" +#include "collection/SqlStorage.h" +#include <QPointer> #include <QStack> #include <threadweaver/Job.h> @@ -34,30 +37,37 @@ using namespace Meta; class SqlWorkerThread : public ThreadWeaver::Job { public: - SqlWorkerThread( SqlQueryMaker *queryMaker ) + SqlWorkerThread( SqlQueryMakerInternal *queryMakerInternal ) : ThreadWeaver::Job() - , m_queryMaker( queryMaker ) + , m_queryMakerInternal( queryMakerInternal ) , m_aborted( false ) { //nothing to do } + virtual ~SqlWorkerThread() + { + delete m_queryMakerInternal; + } + virtual void requestAbort() { m_aborted = true; } + SqlQueryMakerInternal* queryMakerInternal() const + { + return m_queryMakerInternal; + } + protected: virtual void run() { - QString query = m_queryMaker->query(); - QStringList result = m_queryMaker->runQuery( query ); - if( !m_aborted ) - m_queryMaker->handleResult( result ); + m_queryMakerInternal->run(); setFinished( !m_aborted ); } private: - SqlQueryMaker *m_queryMaker; + SqlQueryMakerInternal *m_queryMakerInternal; bool m_aborted; }; @@ -83,7 +93,14 @@ struct SqlQueryMaker::Private QStack<bool> andStack; - Meta::DataList data; + QStringList blockingCustomData; + Meta::DataList blockingData; + Meta::TrackList blockingTracks; + Meta::AlbumList blockingAlbums; + Meta::ArtistList blockingArtists; + Meta::GenreList blockingGenres; + Meta::ComposerList blockingComposers; + Meta::YearList blockingYears; bool blocking; bool used; }; @@ -101,6 +118,8 @@ SqlQueryMaker::SqlQueryMaker( SqlCollection* collection ) SqlQueryMaker::~SqlQueryMaker() { + disconnect(); + abortQuery(); delete d; } @@ -125,7 +144,15 @@ SqlQueryMaker::reset() d->andStack.push( true ); //and is default d->blocking = false; d->used = false; - d->data.clear(); + d->blockingCustomData.clear(); + d->blockingData.clear(); + d->blockingAlbums.clear(); + d->blockingArtists.clear(); + d->blockingComposers.clear(); + d->blockingGenres.clear(); + d->blockingTracks.clear(); + d->blockingYears.clear(); + return this; } @@ -133,7 +160,12 @@ void SqlQueryMaker::abortQuery() { if( d->worker ) + { d->worker->requestAbort(); + d->worker->disconnect( this ); + if( d->worker->queryMakerInternal() ) + d->worker->queryMakerInternal()->disconnect( this ); + } } QueryMaker* @@ -162,18 +194,41 @@ SqlQueryMaker::run() //TODO: wait or job to complete } - else if ( ! d->blocking ) - { - //debug() << "Query is " << query(); - d->worker = new SqlWorkerThread( this ); - connect( d->worker, SIGNAL( done( ThreadWeaver::Job* ) ), SLOT( done( ThreadWeaver::Job* ) ) ); - ThreadWeaver::Weaver::instance()->enqueue( d->worker ); - } - else //use it blocking + else { - QString query = this->query(); - QStringList result = runQuery( query ); - handleResult( result ); + SqlQueryMakerInternal *qmi = new SqlQueryMakerInternal( m_collection ); + qmi->setQuery( query() ); + qmi->setQueryType( d->queryType ); + qmi->setResultAsDataPtrs( d->resultAsDataPtrs ); + + + if ( !d->blocking ) + { + connect( qmi, SIGNAL(newResultReady(QString,Meta::AlbumList)), SIGNAL(newResultReady(QString,Meta::AlbumList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::ArtistList)), SIGNAL(newResultReady(QString,Meta::ArtistList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::GenreList)), SIGNAL(newResultReady(QString,Meta::GenreList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::ComposerList)), SIGNAL(newResultReady(QString,Meta::ComposerList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::YearList)), SIGNAL(newResultReady(QString,Meta::YearList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::TrackList)), SIGNAL(newResultReady(QString,Meta::TrackList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::DataList)), SIGNAL(newResultReady(QString,Meta::DataList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,QStringList)), SIGNAL(newResultReady(QString,QStringList)), Qt::DirectConnection ); + d->worker = new SqlWorkerThread( qmi ); + connect( d->worker, SIGNAL( done( ThreadWeaver::Job* ) ), SLOT( done( ThreadWeaver::Job* ) ) ); + ThreadWeaver::Weaver::instance()->enqueue( d->worker ); + } + else //use it blocking + { + connect( qmi, SIGNAL(newResultReady(QString,Meta::AlbumList)), SLOT(blockingNewResultReady(QString,Meta::AlbumList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::ArtistList)), SLOT(blockingNewResultReady(QString,Meta::ArtistList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::GenreList)), SLOT(blockingNewResultReady(QString,Meta::GenreList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::ComposerList)), SLOT(blockingNewResultReady(QString,Meta::ComposerList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::YearList)), SLOT(blockingNewResultReady(QString,Meta::YearList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::TrackList)), SLOT(blockingNewResultReady(QString,Meta::TrackList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,Meta::DataList)), SLOT(blockingNewResultReady(QString,Meta::DataList)), Qt::DirectConnection ); + connect( qmi, SIGNAL(newResultReady(QString,QStringList)), SLOT(blockingNewResultReady(QString,QStringList)), Qt::DirectConnection ); + qmi->run(); + delete qmi; + } } d->used = true; } @@ -535,7 +590,7 @@ SqlQueryMaker::orderBy( qint64 value, bool descending ) QueryMaker* SqlQueryMaker::orderByRandom() { - d->queryOrderBy = " ORDER BY " + m_collection->randomFunc(); + d->queryOrderBy = " ORDER BY " + CollectionManager::instance()->sqlStorage()->randomFunc(); return this; } @@ -725,80 +780,10 @@ SqlQueryMaker::query() QStringList SqlQueryMaker::runQuery( const QString &query ) { - return m_collection->query( query ); + return CollectionManager::instance()->sqlStorage()->query( query ); } -void -SqlQueryMaker::handleResult( const QStringList &result ) -{ - if( !result.isEmpty() ) - { - switch( d->queryType ) { - case QueryMaker::Custom: - emit newResultReady( m_collection->collectionId(), result ); - break; - case QueryMaker::Track: - handleTracks( result ); - break; - case QueryMaker::Artist: - handleArtists( result ); - break; - case QueryMaker::Album: - handleAlbums( result ); - break; - case QueryMaker::Genre: - handleGenres( result ); - break; - case QueryMaker::Composer: - handleComposers( result ); - break; - case QueryMaker::Year: - handleYears( result ); - break; - - case QueryMaker::None: - debug() << "Warning: queryResult with queryType == NONE"; - } - } - else - { - if( d->resultAsDataPtrs ) - { - emit newResultReady( m_collection->collectionId(), Meta::DataList() ); - } - else - { - switch( d->queryType ) { - case QueryMaker::Custom: - emit newResultReady( m_collection->collectionId(), QStringList() ); - break; - case QueryMaker::Track: - emit newResultReady( m_collection->collectionId(), Meta::TrackList() ); - break; - case QueryMaker::Artist: - emit newResultReady( m_collection->collectionId(), Meta::ArtistList() ); - break; - case QueryMaker::Album: - emit newResultReady( m_collection->collectionId(), Meta::AlbumList() ); - break; - case QueryMaker::Genre: - emit newResultReady( m_collection->collectionId(), Meta::GenreList() ); - break; - case QueryMaker::Composer: - emit newResultReady( m_collection->collectionId(), Meta::ComposerList() ); - break; - case QueryMaker::Year: - emit newResultReady( m_collection->collectionId(), Meta::YearList() ); - break; - - case QueryMaker::None: - debug() << "Warning: queryResult with queryType == NONE"; - } - } - } - //queryDone will be emitted in done(Job*) -} void SqlQueryMaker::setBlocking( bool enabled ) @@ -817,115 +802,57 @@ SqlQueryMaker::collectionIds() const Meta::DataList SqlQueryMaker::data( const QString &id ) const { - if ( d->blocking && d->used && d->resultAsDataPtrs && m_collection->collectionId() == id ) - return d->data; - else - return Meta::DataList(); + Q_UNUSED( id ); + return d->blockingData; } Meta::TrackList SqlQueryMaker::tracks( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Track && m_collection->collectionId() == id ) - { - Meta::TrackList list; - foreach( DataPtr p, d->data ) - { - list << Meta::TrackPtr::staticCast( p ); - } - return list; - } - else - return Meta::TrackList(); + Q_UNUSED( id ); + return d->blockingTracks; } Meta::AlbumList SqlQueryMaker::albums( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Album && m_collection->collectionId() == id ) - { - Meta::AlbumList list; - foreach( DataPtr p, d->data ) - { - list << Meta::AlbumPtr::staticCast( p ); - } - return list; - } - else - return Meta::AlbumList(); + Q_UNUSED( id ); + return d->blockingAlbums; } Meta::ArtistList SqlQueryMaker::artists( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Artist && m_collection->collectionId() == id ) - { - Meta::ArtistList list; - foreach( DataPtr p, d->data ) - { - list << Meta::ArtistPtr::staticCast( p ); - } - return list; - } - else - return Meta::ArtistList(); + Q_UNUSED( id ); + return d->blockingArtists; } Meta::GenreList SqlQueryMaker::genres( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Genre && m_collection->collectionId() == id ) - { - Meta::GenreList list; - foreach( DataPtr p, d->data ) - { - list << Meta::GenrePtr::staticCast( p ); - } - return list; - } - else - return Meta::GenreList(); + Q_UNUSED( id ); + return d->blockingGenres; } Meta::ComposerList SqlQueryMaker::composers( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Composer && m_collection->collectionId() == id ) - { - Meta::ComposerList list; - foreach( DataPtr p, d->data ) - { - list << Meta::ComposerPtr::staticCast( p ); - } - return list; - } - else - return Meta::ComposerList(); + Q_UNUSED( id ); + return d->blockingComposers; } Meta::YearList SqlQueryMaker::years( const QString &id ) const { - if ( d->blocking && d->used && d->queryType == QueryMaker::Year && m_collection->collectionId() == id ) - { - Meta::YearList list; - foreach( DataPtr p, d->data ) - { - list << Meta::YearPtr::staticCast( p ); - } - return list; - } - else - return Meta::YearList(); + Q_UNUSED( id ); + return d->blockingYears; } QStringList SqlQueryMaker::customData( const QString &id ) const { - AMAROK_NOTIMPLEMENTED - Q_UNUSED( id ) - // not implemented yet - return QStringList(); + Q_UNUSED( id ); + return d->blockingCustomData; } QString @@ -1016,116 +943,10 @@ SqlQueryMaker::andOr() const return d->andStack.top() ? " AND " : " OR "; } -// What's worse, a bunch of almost identical repeated code, or a not so obvious macro? :-) -// The macro below will emit the proper result signal. If m_resultAsDataPtrs is true, -// it'll emit the signal that takes a list of DataPtrs. Otherwise, it'll call the -// signal that takes the list of the specific class. -// If qm is used blocking it only stores the result ptrs into data as DataPtrs - -#define emitOrStoreProperResult( PointerType, list ) { \ - if ( d->resultAsDataPtrs || d->blocking ) { \ - foreach( PointerType p, list ) { \ - d->data << DataPtr::staticCast( p ); \ - } \ - if ( !d->blocking ) \ - emit newResultReady( m_collection->collectionId(), d->data ); \ - } \ - else { \ - emit newResultReady( m_collection->collectionId(), list ); \ - } \ - } - -void -SqlQueryMaker::handleTracks( const QStringList &result ) -{ - TrackList tracks; - SqlRegistry* reg = m_collection->registry(); - //there are 29 columns in the result set as generated by startTrackQuery() - int returnCount = SqlTrack::getTrackReturnValueCount(); - int resultRows = result.size() / returnCount; - for( int i = 0; i < resultRows; i++ ) - { - QStringList row = result.mid( i*returnCount, returnCount ); - tracks.append( reg->getTrack( row ) ); - } - emitOrStoreProperResult( TrackPtr, tracks ); -} - -void -SqlQueryMaker::handleArtists( const QStringList &result ) -{ - ArtistList artists; - SqlRegistry* reg = m_collection->registry(); - for( QStringListIterator iter( result ); iter.hasNext(); ) - { - QString name = iter.next(); - QString id = iter.next(); - artists.append( reg->getArtist( name, id.toInt() ) ); - } - emitOrStoreProperResult( ArtistPtr, artists ); -} - -void -SqlQueryMaker::handleAlbums( const QStringList &result ) -{ - AlbumList albums; - SqlRegistry* reg = m_collection->registry(); - for( QStringListIterator iter( result ); iter.hasNext(); ) - { - QString name = iter.next(); - QString id = iter.next(); - QString artist = iter.next(); - albums.append( reg->getAlbum( name, id.toInt(), artist.toInt() ) ); - } - emitOrStoreProperResult( AlbumPtr, albums ); -} - -void -SqlQueryMaker::handleGenres( const QStringList &result ) -{ - GenreList genres; - SqlRegistry* reg = m_collection->registry(); - for( QStringListIterator iter( result ); iter.hasNext(); ) - { - QString name = iter.next(); - QString id = iter.next(); - genres.append( reg->getGenre( name, id.toInt() ) ); - } - emitOrStoreProperResult( GenrePtr, genres ); -} - -void -SqlQueryMaker::handleComposers( const QStringList &result ) -{ - ComposerList composers; - SqlRegistry* reg = m_collection->registry(); - for( QStringListIterator iter( result ); iter.hasNext(); ) - { - QString name = iter.next(); - QString id = iter.next(); - composers.append( reg->getComposer( name, id.toInt() ) ); - } - emitOrStoreProperResult( ComposerPtr, composers ); -} - -void -SqlQueryMaker::handleYears( const QStringList &result ) -{ - YearList years; - SqlRegistry* reg = m_collection->registry(); - for( QStringListIterator iter( result ); iter.hasNext(); ) - { - QString name = iter.next(); - QString id = iter.next(); - years.append( reg->getYear( name, id.toInt() ) ); - } - emitOrStoreProperResult( YearPtr, years ); -} - QString SqlQueryMaker::escape( QString text ) const //krazy:exclude=constref { - return m_collection->escape( text ); + return CollectionManager::instance()->sqlStorage()->escape( text ); } QString @@ -1167,5 +988,61 @@ SqlQueryMaker::likeCondition( const QString &text, bool anyBegin, bool anyEnd ) } } +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::AlbumList &albums) +{ + Q_UNUSED( id ); + d->blockingAlbums = albums; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::ArtistList &artists) +{ + Q_UNUSED( id ); + d->blockingArtists = artists; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::GenreList &genres) +{ + Q_UNUSED( id ); + d->blockingGenres = genres; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::ComposerList &composers) +{ + Q_UNUSED( id ); + d->blockingComposers = composers; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::YearList &years) +{ + Q_UNUSED( id ); + d->blockingYears = years; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::TrackList &tracks) +{ + Q_UNUSED( id ); + d->blockingTracks = tracks; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const Meta::DataList &data) +{ + Q_UNUSED( id ); + d->blockingData = data; +} + +void +SqlQueryMaker::blockingNewResultReady(const QString &id, const QStringList &customData) +{ + Q_UNUSED( id ); + d->blockingCustomData = customData; +} + #include "SqlQueryMaker.moc" diff --git a/src/collection/sqlcollection/SqlQueryMaker.h b/src/collection/sqlcollection/SqlQueryMaker.h index c20766e..b58b86c 100644 --- a/src/collection/sqlcollection/SqlQueryMaker.h +++ b/src/collection/sqlcollection/SqlQueryMaker.h @@ -17,7 +17,7 @@ #ifndef AMAROK_COLLECTION_SQLQUERYMAKER_H #define AMAROK_COLLECTION_SQLQUERYMAKER_H -#include "QueryMaker.h" +#include "collection/QueryMaker.h" #include "amarok_export.h" @@ -103,6 +103,14 @@ class /*AMAROK_EXPORT*/ SqlQueryMaker : public QueryMaker public slots: void done( ThreadWeaver::Job * job ); + void blockingNewResultReady( const QString &id, const QStringList &customData ); + void blockingNewResultReady( const QString &id, const Meta::AlbumList &albums ); + void blockingNewResultReady( const QString &id, const Meta::ArtistList &artists ); + void blockingNewResultReady( const QString &id, const Meta::GenreList &genres ); + void blockingNewResultReady( const QString &id, const Meta::ComposerList &composers ); + void blockingNewResultReady( const QString &id, const Meta::YearList &years ); + void blockingNewResultReady( const QString &id, const Meta::TrackList &tracks ); + void blockingNewResultReady( const QString &id, const Meta::DataList &data ); private: @@ -112,13 +120,6 @@ class /*AMAROK_EXPORT*/ SqlQueryMaker : public QueryMaker QString nameForValue( qint64 value ); QString andOr() const; - void handleTracks( const QStringList &result ); - void handleArtists( const QStringList &result ); - void handleAlbums( const QStringList &result ); - void handleGenres( const QStringList &result ); - void handleComposers( const QStringList &result ); - void handleYears( const QStringList &result ); - SqlCollection *m_collection; struct Private; @@ -126,4 +127,10 @@ class /*AMAROK_EXPORT*/ SqlQueryMaker : public QueryMaker }; +class SqlQueryMakerFactory +{ +public: + virtual SqlQueryMaker* createQueryMaker() const = 0; +}; + #endif /* AMAROK_COLLECTION_SQLQUERYMAKER_H */ diff --git a/src/collection/sqlcollection/SqlQueryMakerInternal.cpp b/src/collection/sqlcollection/SqlQueryMakerInternal.cpp new file mode 100644 index 0000000..db999d1 --- /dev/null +++ b/src/collection/sqlcollection/SqlQueryMakerInternal.cpp @@ -0,0 +1,250 @@ +/**************************************************************************************** + * Copyright (c) 2009 Maximilian Kossick <maximilian.kossick@googlemail.com> * + * * + * This program is free software; you can redistribute it and/or modify it under * + * the terms of the GNU General Public License as published by the Free Software * + * Foundation; either version 2 of the License, or (at your option) any later * + * version. * + * * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY * + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * + * PARTICULAR PURPOSE. See the GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License along with * + * this program. If not, see <http://www.gnu.org/licenses/>. * + ****************************************************************************************/ + +#include "SqlQueryMakerInternal.h" + +#include "collection/SqlStorage.h" +#include "Debug.h" +#include "SqlCollection.h" +#include "SqlMeta.h" +#include "SqlRegistry.h" + +#include <QStringList> + +SqlQueryMakerInternal::SqlQueryMakerInternal( SqlCollection *collection ) + : QObject() + , m_collection( collection ) + , m_resultAsDataPtrs( false ) + , m_queryType( QueryMaker::None ) +{ +} + +SqlQueryMakerInternal::~ SqlQueryMakerInternal() +{ + disconnect(); +} + +void +SqlQueryMakerInternal::run() +{ + Q_ASSERT( !m_query.isEmpty() ); + if( m_collection ) + { + QStringList result = m_collection->query( m_query ); + handleResult( result ); + } + else + { + deleteLater(); + } + +} + +void +SqlQueryMakerInternal::setQuery( const QString &query ) +{ + m_query = query; +} + +void +SqlQueryMakerInternal::setResultAsDataPtrs( bool value ) +{ + m_resultAsDataPtrs = value; +} + +void +SqlQueryMakerInternal::setQueryType( QueryMaker::QueryType type ) +{ + m_queryType = type; +} + +void +SqlQueryMakerInternal::handleResult( const QStringList &result ) +{ + if( !result.isEmpty() ) + { + switch( m_queryType ) { + case QueryMaker::Custom: + emit newResultReady( m_collection->collectionId(), result ); + break; + case QueryMaker::Track: + handleTracks( result ); + break; + case QueryMaker::Artist: + handleArtists( result ); + break; + case QueryMaker::Album: + handleAlbums( result ); + break; + case QueryMaker::Genre: + handleGenres( result ); + break; + case QueryMaker::Composer: + handleComposers( result ); + break; + case QueryMaker::Year: + handleYears( result ); + break; + + case QueryMaker::None: + debug() << "Warning: queryResult with queryType == NONE"; + } + } + else + { + if( m_resultAsDataPtrs ) + { + emit newResultReady( m_collection->collectionId(), Meta::DataList() ); + } + else + { + switch( m_queryType ) { + case QueryMaker::Custom: + emit newResultReady( m_collection->collectionId(), QStringList() ); + break; + case QueryMaker::Track: + emit newResultReady( m_collection->collectionId(), Meta::TrackList() ); + break; + case QueryMaker::Artist: + emit newResultReady( m_collection->collectionId(), Meta::ArtistList() ); + break; + case QueryMaker::Album: + emit newResultReady( m_collection->collectionId(), Meta::AlbumList() ); + break; + case QueryMaker::Genre: + emit newResultReady( m_collection->collectionId(), Meta::GenreList() ); + break; + case QueryMaker::Composer: + emit newResultReady( m_collection->collectionId(), Meta::ComposerList() ); + break; + case QueryMaker::Year: + emit newResultReady( m_collection->collectionId(), Meta::YearList() ); + break; + + case QueryMaker::None: + debug() << "Warning: queryResult with queryType == NONE"; + } + } + } + + //queryDone will be emitted in done(Job*) +} + +// What's worse, a bunch of almost identical repeated code, or a not so obvious macro? :-) +// The macro below will emit the proper result signal. If m_resultAsDataPtrs is true, +// it'll emit the signal that takes a list of DataPtrs. Otherwise, it'll call the +// signal that takes the list of the specific class. +// If qm is used blocking it only stores the result ptrs into data as DataPtrs + +#define emitOrStoreProperResult( PointerType, list ) { \ + if ( m_resultAsDataPtrs ) { \ + Meta::DataList data; \ + foreach( PointerType p, list ) { \ + data << Meta::DataPtr::staticCast( p ); \ + } \ + emit newResultReady( m_collection->collectionId(), data ); \ + } \ + else { \ + emit newResultReady( m_collection->collectionId(), list ); \ + } \ + } + +void +SqlQueryMakerInternal::handleTracks( const QStringList &result ) +{ + Meta::TrackList tracks; + SqlRegistry* reg = m_collection->registry(); + //there are 29 columns in the result set as generated by startTrackQuery() + int returnCount = Meta::SqlTrack::getTrackReturnValueCount(); + int resultRows = result.size() / returnCount; + for( int i = 0; i < resultRows; i++ ) + { + QStringList row = result.mid( i*returnCount, returnCount ); + tracks.append( reg->getTrack( row ) ); + } + emitOrStoreProperResult( Meta::TrackPtr, tracks ); +} + +void +SqlQueryMakerInternal::handleArtists( const QStringList &result ) +{ + Meta::ArtistList artists; + SqlRegistry* reg = m_collection->registry(); + for( QStringListIterator iter( result ); iter.hasNext(); ) + { + QString name = iter.next(); + QString id = iter.next(); + artists.append( reg->getArtist( name, id.toInt() ) ); + } + emitOrStoreProperResult( Meta::ArtistPtr, artists ); +} + +void +SqlQueryMakerInternal::handleAlbums( const QStringList &result ) +{ + Meta::AlbumList albums; + SqlRegistry* reg = m_collection->registry(); + for( QStringListIterator iter( result ); iter.hasNext(); ) + { + QString name = iter.next(); + QString id = iter.next(); + QString artist = iter.next(); + albums.append( reg->getAlbum( name, id.toInt(), artist.toInt() ) ); + } + emitOrStoreProperResult( Meta::AlbumPtr, albums ); +} + +void +SqlQueryMakerInternal::handleGenres( const QStringList &result ) +{ + Meta::GenreList genres; + SqlRegistry* reg = m_collection->registry(); + for( QStringListIterator iter( result ); iter.hasNext(); ) + { + QString name = iter.next(); + QString id = iter.next(); + genres.append( reg->getGenre( name, id.toInt() ) ); + } + emitOrStoreProperResult( Meta::GenrePtr, genres ); +} + +void +SqlQueryMakerInternal::handleComposers( const QStringList &result ) +{ + Meta::ComposerList composers; + SqlRegistry* reg = m_collection->registry(); + for( QStringListIterator iter( result ); iter.hasNext(); ) + { + QString name = iter.next(); + QString id = iter.next(); + composers.append( reg->getComposer( name, id.toInt() ) ); + } + emitOrStoreProperResult( Meta::ComposerPtr, composers ); +} + +void +SqlQueryMakerInternal::handleYears( const QStringList &result ) +{ + Meta::YearList years; + SqlRegistry* reg = m_collection->registry(); + for( QStringListIterator iter( result ); iter.hasNext(); ) + { + QString name = iter.next(); + QString id = iter.next(); + years.append( reg->getYear( name, id.toInt() ) ); + } + emitOrStoreProperResult( Meta::YearPtr, years ); +} diff --git a/src/collection/sqlcollection/SqlQueryMakerInternal.h b/src/collection/sqlcollection/SqlQueryMakerInternal.h new file mode 100644 index 0000000..b8ecda4 --- /dev/null +++ b/src/collection/sqlcollection/SqlQueryMakerInternal.h @@ -0,0 +1,68 @@ +/**************************************************************************************** + * Copyright (c) 2009 Maximilian Kossick <maximilian.kossick@googlemail.com> * + * * + * This program is free software; you can redistribute it and/or modify it under * + * the terms of the GNU General Public License as published by the Free Software * + * Foundation; either version 2 of the License, or (at your option) any later * + * version. * + * * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY * + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * + * PARTICULAR PURPOSE. See the GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License along with * + * this program. If not, see <http://www.gnu.org/licenses/>. * + ****************************************************************************************/ + +#ifndef SQLQUERYMAKERINTERNAL_H +#define SQLQUERYMAKERINTERNAL_H + +#include "collection/QueryMaker.h" +#include "meta/Meta.h" + +#include <QObject> +#include <QPointer> +#include <QString> + +class SqlCollection; + +class SqlQueryMakerInternal : public QObject +{ +Q_OBJECT +public: + explicit SqlQueryMakerInternal( SqlCollection *collection ); + virtual ~ SqlQueryMakerInternal(); + + void run(); + void setQuery( const QString &query ); + void setQueryType( QueryMaker::QueryType type ); + void setResultAsDataPtrs( bool value ); + +signals: + void newResultReady( QString collectionId, Meta::TrackList ); + void newResultReady( QString collectionId, Meta::ArtistList ); + void newResultReady( QString collectionId, Meta::AlbumList ); + void newResultReady( QString collectionId, Meta::GenreList ); + void newResultReady( QString collectionId, Meta::ComposerList ); + void newResultReady( QString collectionId, Meta::YearList ); + void newResultReady( QString collectionId, Meta::DataList ); + void newResultReady( QString collectionId, QStringList ); + +private: + void handleResult( const QStringList &result ); + void handleTracks( const QStringList &result ); + void handleArtists( const QStringList &result ); + void handleAlbums( const QStringList &result ); + void handleGenres( const QStringList &result ); + void handleComposers( const QStringList &result ); + void handleYears( const QStringList &result ); + +private: + QPointer<SqlCollection> m_collection; + bool m_resultAsDataPtrs; + QueryMaker::QueryType m_queryType; + QString m_query; + +}; + +#endif // SQLQUERYMAKERINTERNAL_H *** Bug 221432 has been marked as a duplicate of this bug. *** |