https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #18 from Christian <[hidden email]> --- Missed a /database/ in the path in Comment 17, sorry. -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #19 from Gilles Caulier <[hidden email]> --- Excepted the fact that valgrind report a memory allocation exception, there is no more information about the suspicious part where memory is mangled. I get a better vision of the problem in report #323888 Which is fully relevant of Qt SQlite plugin. This one mangle memory at each commit in database. This is exactly what i want to proof also in your report. Perhaps you don't see these information with valgrind because you miss to install sqlite, Qt, opencv, and libkface debug packages. Look well all my valgrind traces at end of report #323888. Gilles Caulier -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #20 from Christian <[hidden email]> --- Dear Gilles! The valgrind trace is all I get, there is no other output from Valgrind. See Comment 14. I have all the debug packages installed. -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #21 from Christian <[hidden email]> --- The bug is still present in 4.4.0. After using the face labeling tool for a few times, eventually it will crash. Deleting the face recognition database file restores the functionality to working order, but of course it has to relearn the faces then. It seems the bug is in the component that the face recognition tool uses to learn from a new face when a name is changed or attached to a face. -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
Gilles Caulier <[hidden email]> changed: What |Removed |Added ---------------------------------------------------------------------------- Version|4.2.0 |4.4.0 --- Comment #22 from Gilles Caulier <[hidden email]> --- Can you get a backtrace of crash with 4.4.0 ? Gilles Culier -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #23 from Christian <[hidden email]> --- Dear Gilles! I can - I followed the instructions in the Digikam webpage https://www.digikam.org/?q=contrib . But I'm afraid it's not very useful. Here you are: Program terminated with signal SIGKILL, Killed. The program no longer exists. (gdb) bt No stack. (gdb) This happens a short while after tagging a few faces. The way I notice the bug is, initially the face tagging appears to work and it attaches tags, this always takes a short moment. Then after a while, changing the face tags becomes very fast (almost instantaneous), and the tags are no longer saved to the files. A while later the program window just disappears. Any other ideas I can do? -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #24 from Christian <[hidden email]> --- Dear Gilles! I'm getting some errors on Valgrind now :-) maybe this is helpful? It hasn't crashed yet, but I'm waiting for the crash to happen soon. Will post the rest of this log if it doesn't crash Valgrind like the last time I tried... ca@puolukka ~ $ valgrind --tool=memcheck --leak-check=full --error-limit=no digikam ==17859== Memcheck, a memory error detector ==17859== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==17859== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info ==17859== Command: digikam ==17859== Object::connect: No such signal org::freedesktop::UPower::DeviceAdded(QString) Object::connect: No such signal org::freedesktop::UPower::DeviceRemoved(QString) ==17859== Thread 9 Thread (pooled): ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0x2860BC87: picReadHeader(QIODevice*, PICHeader*, bool) (pic_read.cpp:54) ==17859== by 0x2860D170: SoftimagePICHandler::canRead(QIODevice*) (pic_io_handler.cpp:44) ==17859== by 0x2860C9D4: SoftimagePICPlugin::capabilities(QIODevice*, QByteArray const&) const (pic_io_plugin.cpp:33) ==17859== by 0x9B4D23B: createReadHandlerHelper(QIODevice*, QByteArray const&, bool, bool) (qimagereader.cpp:393) ==17859== by 0x9B4E72B: QImageReaderPrivate::initHandler() (qimagereader.cpp:618) ==17859== by 0x9B4FC1F: QImageReader::read(QImage*) (qimagereader.cpp:1185) ==17859== by 0x9B4FDFE: QImageReader::read() (qimagereader.cpp:1155) ==17859== by 0x9B4AE92: QImage::fromData(unsigned char const*, int, char const*) (qimage.cpp:5177) ==17859== by 0x9B4AF4F: QImage::loadFromData(unsigned char const*, int, char const*) (qimage.cpp:5135) ==17859== by 0x6D9FA14: KExiv2Iface::KExiv2::getImagePreview(QImage&) const (qimage.h:252) ==17859== by 0x759D03F: Digikam::ThumbnailCreator::loadImagePreview(Digikam::DMetadata const&) const (thumbnailcreator.cpp:629) ==17859== by 0x759D573: Digikam::ThumbnailCreator::createThumbnail(Digikam::ThumbnailInfo const&, QRect const&) const (thumbnailcreator.cpp:465) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD4C45E: CSubband::Quantize(int) (Subband.cpp:132) ==17859== by 0xFD4CDEE: CWaveletTransform::ForwardTransform(int, int) (WaveletTransform.cpp:164) ==17859== by 0xFD46CEA: CPGFImage::WriteHeader(CPGFStream*) (PGFimage.cpp:949) ==17859== by 0xFD47561: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1145) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859== by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859== by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859== by 0x7586F85: Digikam::LoadSaveThread::run() (loadsavethread.cpp:136) ==17859== by 0x75B5C2D: Digikam::DynamicThread::DynamicThreadPriv::run() (dynamicthread.cpp:186) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD4C463: CSubband::Quantize(int) (Subband.cpp:134) ==17859== by 0xFD4CDEE: CWaveletTransform::ForwardTransform(int, int) (WaveletTransform.cpp:164) ==17859== by 0xFD46CEA: CPGFImage::WriteHeader(CPGFStream*) (PGFimage.cpp:949) ==17859== by 0xFD47561: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1145) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859== by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859== by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859== by 0x7586F85: Digikam::LoadSaveThread::run() (loadsavethread.cpp:136) ==17859== by 0x75B5C2D: Digikam::DynamicThread::DynamicThreadPriv::run() (dynamicthread.cpp:186) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859== by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859== by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859== by 0xFD47024: CPGFImage::WriteLevel() (PGFimage.cpp:1029) ==17859== by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859== by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859== by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859== by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859== by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859== by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859== by 0xFD46F64: CPGFImage::WriteLevel() (PGFimage.cpp:1032) ==17859== by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859== by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859== by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859== by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859== by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859== by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859== by 0xFD46F98: CPGFImage::WriteLevel() (PGFimage.cpp:1033) ==17859== by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859== by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859== by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859== by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859== by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859== by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859== by 0xFD46FCF: CPGFImage::WriteLevel() (PGFimage.cpp:1034) ==17859== by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859== by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859== by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859== by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD43DF4: CEncoder::CMacroBlock::DecomposeBitplane(unsigned int, unsigned int, unsigned int, unsigned int*, unsigned int*, unsigned int*, unsigned int&, unsigned int&) (Encoder.cpp:647) ==17859== by 0xFD444D3: CEncoder::CMacroBlock::BitplaneEncode() (Encoder.cpp:513) ==17859== by 0xFD44A64: CEncoder::EncodeBuffer(ROIBlockHeader) (Encoder.cpp:347) ==17859== by 0xFD44AF9: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:323) ==17859== by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859== by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859== by 0xFD46F64: CPGFImage::WriteLevel() (PGFimage.cpp:1032) ==17859== by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859== by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD43D7B: CEncoder::CMacroBlock::DecomposeBitplane(unsigned int, unsigned int, unsigned int, unsigned int*, unsigned int*, unsigned int*, unsigned int&, unsigned int&) (Encoder.cpp:662) ==17859== by 0xFD444D3: CEncoder::CMacroBlock::BitplaneEncode() (Encoder.cpp:513) ==17859== by 0xFD44A64: CEncoder::EncodeBuffer(ROIBlockHeader) (Encoder.cpp:347) ==17859== by 0xFD44AF9: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:323) ==17859== by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859== by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859== by 0xFD46F64: CPGFImage::WriteLevel() (PGFimage.cpp:1032) ==17859== by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859== by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD43E7A: CEncoder::CMacroBlock::DecomposeBitplane(unsigned int, unsigned int, unsigned int, unsigned int*, unsigned int*, unsigned int*, unsigned int&, unsigned int&) (Encoder.cpp:702) ==17859== by 0xFD444D3: CEncoder::CMacroBlock::BitplaneEncode() (Encoder.cpp:513) ==17859== by 0xFD44A64: CEncoder::EncodeBuffer(ROIBlockHeader) (Encoder.cpp:347) ==17859== by 0xFD44AF9: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:323) ==17859== by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859== by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859== by 0xFD46F64: CPGFImage::WriteLevel() (PGFimage.cpp:1032) ==17859== by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859== by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0x9A83450: qt_blend_argb32_on_argb32_ssse3(unsigned char*, int, unsigned char const*, int, int, int, int) (qdrawhelper_ssse3.cpp:52) ==17859== by 0x9C50F4B: QRasterPaintEngine::drawImage(QPointF const&, QImage const&) (qpaintengine_raster.cpp:2182) ==17859== by 0x9BDDB4D: QPainter::drawImage(QPointF const&, QImage const&) (qpainter.cpp:5636) ==17859== by 0x759CC5E: Digikam::ThumbnailCreator::handleAlphaChannel(QImage const&) const (qpainter.h:935) ==17859== by 0x75A0432: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:300) ==17859== by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859== by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859== by 0x7586F85: Digikam::LoadSaveThread::run() (loadsavethread.cpp:136) ==17859== by 0x75B5C2D: Digikam::DynamicThread::DynamicThreadPriv::run() (dynamicthread.cpp:186) ==17859== by 0xAAC2DBA: QThreadPoolThread::run() (qthreadpool.cpp:107) ==17859== by 0xAACF2DB: QThreadPrivate::start(void*) (qthread_unix.cpp:338) ==17859== by 0xDB512D9: start_thread (pthread_create.c:309) ==17859== ==17859== Thread 11 Thread (pooled): ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859== by 0xFD44CF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:283) ==17859== by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859== by 0xFD47024: CPGFImage::WriteLevel() (PGFimage.cpp:1029) ==17859== by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859== by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859== by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859== by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859== by 0xFD44CF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:283) ==17859== by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859== by 0xFD46F64: CPGFImage::WriteLevel() (PGFimage.cpp:1032) ==17859== by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859== by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859== by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859== by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859== by 0xFD44CF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:283) ==17859== by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859== by 0xFD46F98: CPGFImage::WriteLevel() (PGFimage.cpp:1033) ==17859== by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859== by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859== by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859== by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859== ==17859== Conditional jump or move depends on uninitialised value(s) ==17859== at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859== by 0xFD44CF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:283) ==17859== by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859== by 0xFD46FCF: CPGFImage::WriteLevel() (PGFimage.cpp:1034) ==17859== by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859== by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859== by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859== by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859== by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859== by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859== by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859== by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859== digikam(17859)/digikam (core) Digikam::ThumbnailCreator::createThumbnail: Cannot create thumbnail for "/home/ca/path/to/filename.JPG" digikam(17859)/digikam (core) Digikam::ThumbnailCreator::load: Thumbnail is null for "/home/ca/path/to/samefilename.JPG" -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #25 from Christian <[hidden email]> --- Oops what a messy paste. Is there any way I can paste the valgrind output without making a mess? I took it from the console window with "select all", "copy". Even copying to e.g. Kate to make a text file, it is all on one line and messy. Sorry about that. -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #26 from Christian <[hidden email]> --- Created attachment 89414 --> https://bugs.kde.org/attachment.cgi?id=89414&action=edit valgrind output (end of it) The end of the Valgrind output is below. There's a piece missing in the middle because the console buffer was too small. I think the previous post is more helpful for debugging. (And for some reason, this copy-paste looks ok in Kate, so I'm attaching it as txt.) -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #27 from Christian <[hidden email]> --- Created attachment 89469 --> https://bugs.kde.org/attachment.cgi?id=89469&action=edit Another valgrind output Maybe the lines at the end are useful? ==4837== Warning: set address range perms: large range [0x175191028, 0x231f97038) (noaccess) digikam(4837)/KFACE: cv::Exception training LBPH: /portage_builddir/portage/media-libs/opencv-2.4.9/work/opencv-2.4.9/modules/core/src/alloc.cpp:52: error: (-4) Failed to allocate 262144 bytes in function OutOfMemoryError -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
Gilles Caulier <[hidden email]> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |UNCONFIRMED Resolution|BACKTRACE |--- -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #28 from Gilles Caulier <[hidden email]> --- Git commit f6bcec9d07f0f6530835498370a6042f9b1e1675 by Marcel Wiesweg. Committed on 14/11/2014 at 09:56. Pushed by mwiesweg into branch 'master'. Some fixes in face progress calculation M +1 -0 utilities/facemanagement/facepipeline.cpp M +2 -0 utilities/facemanagement/facepipeline.h M +31 -14 utilities/maintenance/facedetector.cpp http://commits.kde.org/digikam/f6bcec9d07f0f6530835498370a6042f9b1e1675 diff --git a/utilities/facemanagement/facepipeline.cpp b/utilities/facemanagement/facepipeline.cpp index a655385..d512a92 100644 --- a/utilities/facemanagement/facepipeline.cpp +++ b/utilities/facemanagement/facepipeline.cpp @@ -1171,6 +1171,7 @@ void FacePipeline::Private::send(FacePipelineExtendedPackage::Ptr package) { start(); ++totalPackagesAdded; + emit(q->processing(*package)); if (senderFlowControl(package)) { diff --git a/utilities/facemanagement/facepipeline.h b/utilities/facemanagement/facepipeline.h index 4b381ca..45e733a 100644 --- a/utilities/facemanagement/facepipeline.h +++ b/utilities/facemanagement/facepipeline.h @@ -292,6 +292,8 @@ Q_SIGNALS: /// Emitted when processing has started void started(const QString& message); + /// Emitted when one package begins processing + void processing(const FacePipelinePackage& package); /// Emitted when one package has finished processing void processed(const FacePipelinePackage& package); void progressValueChanged(float progress); diff --git a/utilities/maintenance/facedetector.cpp b/utilities/maintenance/facedetector.cpp index 7bd8c0e..222652b 100644 --- a/utilities/maintenance/facedetector.cpp +++ b/utilities/maintenance/facedetector.cpp @@ -96,18 +96,27 @@ class FaceDetector::Private public: Private() + : benchmark(false), + total(0), + progressValue(0), + currentProgressChunk(0), + currentScheduled(0), + currentFinished(0) { - benchmark = false; - total = 0; } - bool benchmark; + bool benchmark; - int total; + int total; - AlbumPointerList<> albumTodoList; - ImageInfoJob albumListing; - FacePipeline pipeline; + AlbumPointerList<> albumTodoList; + ImageInfoJob albumListing; + FacePipeline pipeline; + QMap<Album*,double> relativeProgressValue; + double progressValue; + double currentProgressChunk; + int currentScheduled; + int currentFinished; }; FaceDetector::FaceDetector(const FaceScanSettings& settings, ProgressItem* const parent) @@ -275,25 +284,33 @@ void FaceDetector::slotStart() QApplication::restoreOverrideCursor(); } - d->total = 0; - + // first, we use the relativeProgressValue map to store absolute counts foreach(Album* const album, d->albumTodoList) { if (album->type() == Album::PHYSICAL) { - d->total += palbumCounts.value(album->id()); + d->relativeProgressValue[album] = palbumCounts.value(album->id()); } else // this is possibly broken of course because we do not know if images have multiple tags, // but there's no better solution without expensive operation { - d->total += talbumCounts.value(album->id()); + d->relativeProgressValue[album] = talbumCounts.value(album->id()); } } - - kDebug() << "Total is" << d->total; - + // second, calculate (approximate) overall sum + d->total = 0; + foreach (double count, d->relativeProgressValue) + { + d->total += (int)count; + } d->total = qMax(1, d->total); + kDebug() << "Total is" << d->total; + // third, break absolute to relative values + for (QMap<Album*,double>::iterator it = d->relativeProgressValue.begin(); it != d->relativeProgressValue.end(); ++it) + { + it.value() /= double(d->total); + } setUsesBusyIndicator(false); setTotalItems(d->total); -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #29 from Gilles Caulier <[hidden email]> --- Git commit 59f0bdb6b2709171354418ed297d4aa1d667ebad by Marcel Wiesweg. Committed on 15/11/2014 at 13:47. Pushed by mwiesweg into branch 'master'. Add database cleanup calls to have a clean shutdown of SQLite data at application termination M +3 -0 app/main/main.cpp M +17 -3 tests/testdatabase.cpp http://commits.kde.org/digikam/59f0bdb6b2709171354418ed297d4aa1d667ebad diff --git a/app/main/main.cpp b/app/main/main.cpp index 3564d23..85fcbc7 100644 --- a/app/main/main.cpp +++ b/app/main/main.cpp @@ -62,6 +62,7 @@ #include "databaseparameters.h" #include "digikamapp.h" #include "scancontroller.h" +#include "thumbnaildatabaseaccess.h" #include "version.h" using namespace Digikam; @@ -235,6 +236,8 @@ int main(int argc, char* argv[]) int ret = app.exec(); + DatabaseAccess::cleanUpDatabase(); + ThumbnailDatabaseAccess::cleanUpDatabase(); KExiv2Iface::KExiv2::cleanupExiv2(); return ret; diff --git a/tests/testdatabase.cpp b/tests/testdatabase.cpp index 10c14ad..0930029 100644 --- a/tests/testdatabase.cpp +++ b/tests/testdatabase.cpp @@ -30,6 +30,7 @@ #include <QSqlDatabase> #include <QDBusConnection> #include <QString> +#include <QTimer> // KDE includes @@ -47,6 +48,7 @@ #include "databaseparameters.h" #include "scancontroller.h" #include "setup.h" +#include "thumbnaildatabaseaccess.h" #include "version.h" namespace Digikam @@ -76,16 +78,28 @@ int main(int argc, char** argv) KCmdLineArgs::init(argc, argv, &aboutData); KApplication app; - DatabaseParameters params = DatabaseParameters::parametersFromConfig(KGlobal::config()); + DatabaseParameters params; + params.databaseType = DatabaseParameters::SQLiteDatabaseType(); + params.setDatabasePath(QDir::currentPath() + "/digikam-test.db"); + params.setThumbsDatabasePath(QDir::currentPath() + "/digikam-thumbs-test.db"); + params.legacyAndDefaultChecks(); QDBusConnection::sessionBus().registerService("org.kde.digikam.startup-" + QString::number(QCoreApplication::instance()->applicationPid())); // initialize database - bool b = AlbumManager::instance()->setDatabase(params, false); + bool b = AlbumManager::instance()->setDatabase(params, false, "/media/fotos/Digikam Sample/"); kDebug() << "Database initialization done: " << b; - + + QTimer::singleShot(500, &app, SLOT(quit())); + app.exec(); + + ScanController::instance()->shutDown(); + + DatabaseAccess::cleanUpDatabase(); + ThumbnailDatabaseAccess::cleanUpDatabase(); + return 0; } -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #30 from Gilles Caulier <[hidden email]> --- Git commit b9f8dbfe470609ef31c5442cb2a4c97e02344233 by Marcel Wiesweg. Committed on 15/11/2014 at 13:45. Pushed by mwiesweg into branch 'master'. Rewrite per-thread database connection cleanup Use QThreadStorage of a per-thread DatabaseThreadData object which is destroyed when the thread finishes. M +103 -113 libs/database/core/databasecorebackend.cpp M +0 -5 libs/database/core/databasecorebackend.h M +22 -12 libs/database/core/databasecorebackend_p.h http://commits.kde.org/digikam/b9f8dbfe470609ef31c5442cb2a4c97e02344233 diff --git a/libs/database/core/databasecorebackend.cpp b/libs/database/core/databasecorebackend.cpp index c553bb1..76a958a 100644 --- a/libs/database/core/databasecorebackend.cpp +++ b/libs/database/core/databasecorebackend.cpp @@ -79,22 +79,64 @@ public: } }; +DatabaseThreadData::DatabaseThreadData() + : valid(0), + transactionCount(0) +{ +} + +DatabaseThreadData::~DatabaseThreadData() +{ + if (transactionCount) + { + kDebug() << "WARNING !!! Transaction count is" << transactionCount << "when destroying database!!!"; + } + closeDatabase(); +} + +void DatabaseThreadData::closeDatabase() +{ + QString connectionToRemove; + if (database.isOpen()) + { + connectionToRemove = database.connectionName(); + } + + // Destroy object + database = QSqlDatabase(); + + valid = 0; + transactionCount = 0; + lastError = QSqlError(); + + // Remove connection + if (!connectionToRemove.isNull()) + { + QSqlDatabase::removeDatabase(connectionToRemove); + } +} + DatabaseCoreBackendPrivate::DatabaseCoreBackendPrivate(DatabaseCoreBackend* const backend) - : q(backend) + : currentValidity(0), + isInTransaction(false), + status(DatabaseCoreBackend::Unavailable), + lock(0), + operationStatus(DatabaseCoreBackend::ExecuteNormal), + errorLockOperationStatus(DatabaseCoreBackend::ExecuteNormal), + errorHandler(0), + q(backend) { - status = DatabaseCoreBackend::Unavailable; - isInTransaction = false; - operationStatus = DatabaseCoreBackend::ExecuteNormal; - errorHandler = 0; - lock = 0; - errorLockOperationStatus = DatabaseCoreBackend::ExecuteNormal; } -void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* const l) +DatabaseCoreBackendPrivate::~DatabaseCoreBackendPrivate() { - QObject::connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), - q, SLOT(slotMainThreadFinished())); + // Must be shut down from the main thread. + // Clean up the QThreadStorage. It deletes any stored data. + threadDataStorage.setLocalData(0); +} +void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* const l) +{ backendName = name; lock = l; @@ -110,82 +152,43 @@ void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* cons // finishing of the thread. QSqlDatabase DatabaseCoreBackendPrivate::databaseForThread() { - QThread* const thread = QThread::currentThread(); - QSqlDatabase db = threadDatabases[thread]; - int isValid = databasesValid[thread]; - - if (!isValid || !db.isOpen()) + DatabaseThreadData* threadData = 0; + if (!threadDataStorage.hasLocalData()) { - // need to open a db for thread - bool success = open(db); - - if (!success) - { - kDebug() << "Error while opening the database. Details: [" << db.lastError() << "]"; - } - - QObject::connect(thread, SIGNAL(finished()), - q, SLOT(slotThreadFinished())); + threadData = new DatabaseThreadData; + threadDataStorage.setLocalData(threadData); } - -#ifdef DATABASCOREBACKEND_DEBUG else { - kDebug() << "Database ["<< connectionName(thread) <<"] already open for thread ["<< thread <<"]."; + threadData = threadDataStorage.localData(); } -#endif - - return db; -} - -void DatabaseCoreBackendPrivate::closeDatabaseForThread() -{ - QThread* const thread = QThread::currentThread(); + // do we need to reopen the database because parameter changed and validity was increased? + if (threadData->valid && threadData->valid < currentValidity) + { + threadData->closeDatabase(); + } - // scope, so that db is destructed when calling removeDatabase + if (!threadData->valid || !threadData->database.isOpen()) { - QSqlDatabase db = threadDatabases[thread]; + threadData->database = createDatabaseConnection(); - if (db.isValid()) + if (threadData->database.open()) + { + threadData->valid = currentValidity; + } + else { - db.close(); + kDebug() << "Error while opening the database. Error was" << threadData->database.lastError(); } } - threadDatabases.remove(thread); - databaseErrors.remove(thread); - databasesValid[thread] = 0; - transactionCount.remove(thread); - QSqlDatabase::removeDatabase(connectionName(thread)); -} - -QSqlError DatabaseCoreBackendPrivate::databaseErrorForThread() -{ - QThread* const thread = QThread::currentThread(); - return databaseErrors[thread]; -} - -void DatabaseCoreBackendPrivate::setDatabaseErrorForThread(const QSqlError& lastError) -{ - QThread* const thread = QThread::currentThread(); - databaseErrors.insert(thread, lastError); -} - -QString DatabaseCoreBackendPrivate::connectionName(QThread* const thread) -{ - return backendName + QString::number((quintptr)thread); + return threadData->database; } -bool DatabaseCoreBackendPrivate::open(QSqlDatabase& db) +QSqlDatabase DatabaseCoreBackendPrivate::createDatabaseConnection() { - if (db.isValid()) - { - db.close(); - } - - QThread* const thread = QThread::currentThread(); - db = QSqlDatabase::addDatabase(parameters.databaseType, connectionName(thread)); + QSqlDatabase db = QSqlDatabase::addDatabase(parameters.databaseType, connectionName()); QString connectOptions = parameters.connectOptions; if (parameters.isSQLite()) @@ -211,46 +214,47 @@ bool DatabaseCoreBackendPrivate::open(QSqlDatabase& db) db.setUserName(parameters.userName); db.setPassword(parameters.password); - bool success = db.open(); + return db; +} - if (success==false) +void DatabaseCoreBackendPrivate::closeDatabaseForThread() +{ + if (threadDataStorage.hasLocalData()) { - kDebug() << "Error while opening the database. Error was <" << db.lastError() << ">"; + threadDataStorage.localData()->closeDatabase(); } - - threadDatabases[thread] = db; - databasesValid[thread] = 1; - transactionCount[thread] = 0; - - return success; } -bool DatabaseCoreBackendPrivate::incrementTransactionCount() +QSqlError DatabaseCoreBackendPrivate::databaseErrorForThread() { - QThread* const thread = QThread::currentThread(); - return (!transactionCount[thread]++); + if (threadDataStorage.hasLocalData()) + { + return threadDataStorage.localData()->lastError; + } + return QSqlError(); } -bool DatabaseCoreBackendPrivate::decrementTransactionCount() +void DatabaseCoreBackendPrivate::setDatabaseErrorForThread(const QSqlError& lastError) { - QThread* const thread = QThread::currentThread(); - return (!--transactionCount[thread]); + if (threadDataStorage.hasLocalData()) + { + threadDataStorage.localData()->lastError = lastError; + } } -bool DatabaseCoreBackendPrivate::isInTransactionInOtherThread() const +QString DatabaseCoreBackendPrivate::connectionName() { - QThread* const thread = QThread::currentThread(); - QHash<QThread*, int>::const_iterator it; + return backendName + QString::number((quintptr)QThread::currentThread()); +} - for (it = transactionCount.constBegin(); it != transactionCount.constEnd(); ++it) - { - if (it.key() != thread && it.value()) - { - return true; - } - } +bool DatabaseCoreBackendPrivate::incrementTransactionCount() +{ + return (!threadDataStorage.localData()->transactionCount++); +} - return false; +bool DatabaseCoreBackendPrivate::decrementTransactionCount() +{ + return (!--threadDataStorage.localData()->transactionCount); } bool DatabaseCoreBackendPrivate::isInMainThread() const @@ -740,18 +744,6 @@ void DatabaseCoreBackend::setDatabaseErrorHandler(DatabaseErrorHandler* const ha d->errorHandler = handler; } -void DatabaseCoreBackend::slotThreadFinished() -{ - Q_D(DatabaseCoreBackend); - d->closeDatabaseForThread(); -} - -void DatabaseCoreBackend::slotMainThreadFinished() -{ - Q_D(DatabaseCoreBackend); - d->closeDatabaseForThread(); -} - bool DatabaseCoreBackend::isCompatible(const DatabaseParameters& parameters) { return QSqlDatabase::drivers().contains(parameters.databaseType); @@ -761,10 +753,8 @@ bool DatabaseCoreBackend::open(const DatabaseParameters& parameters) { Q_D(DatabaseCoreBackend); d->parameters = parameters; - - // Force possibly opened thread dbs to re-open with new parameters. - // They are not accessible from this thread! - d->databasesValid.clear(); + // This will make possibly opened thread dbs reload at next access + d->currentValidity++; int retries = 0; @@ -1634,7 +1624,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::commitTransaction() bool DatabaseCoreBackend::isInTransaction() const { Q_D(const DatabaseCoreBackend); - return d->isInTransactionInOtherThread(); + return d->isInTransaction; } void DatabaseCoreBackend::rollbackTransaction() diff --git a/libs/database/core/databasecorebackend.h b/libs/database/core/databasecorebackend.h index 41e47da..fa4dba4 100644 --- a/libs/database/core/databasecorebackend.h +++ b/libs/database/core/databasecorebackend.h @@ -472,11 +472,6 @@ public: LastInsertId */ -private Q_SLOTS: - - void slotThreadFinished(); - void slotMainThreadFinished(); - protected: DatabaseCoreBackendPrivate* const d_ptr; diff --git a/libs/database/core/databasecorebackend_p.h b/libs/database/core/databasecorebackend_p.h index 2078509..ff3a3fa 100644 --- a/libs/database/core/databasecorebackend_p.h +++ b/libs/database/core/databasecorebackend_p.h @@ -29,6 +29,7 @@ #include <QHash> #include <QSqlDatabase> #include <QThread> +#include <QThreadStorage> #include <QWaitCondition> // Local includes @@ -40,25 +41,38 @@ namespace Digikam { +class DatabaseThreadData +{ +public: + + DatabaseThreadData(); + ~DatabaseThreadData(); + + void closeDatabase(); + + QSqlDatabase database; + int valid; + int transactionCount; + QSqlError lastError; +}; + class DIGIKAM_EXPORT DatabaseCoreBackendPrivate : public DatabaseErrorAnswer { public: explicit DatabaseCoreBackendPrivate(DatabaseCoreBackend* const backend); - virtual ~DatabaseCoreBackendPrivate() - { - } + virtual ~DatabaseCoreBackendPrivate(); void init(const QString& connectionName, DatabaseLocking* const locking); - QString connectionName(QThread* const thread); + QString connectionName(); QSqlDatabase databaseForThread(); QSqlError databaseErrorForThread(); void setDatabaseErrorForThread(const QSqlError& lastError); + QSqlDatabase createDatabaseConnection(); void closeDatabaseForThread(); - bool open(QSqlDatabase& db); bool incrementTransactionCount(); bool decrementTransactionCount(); bool isInTransactionInOtherThread() const; @@ -88,14 +102,10 @@ public: public: - // this is always accessed in mutex context, no need for QThreadStorage - QHash<QThread*, QSqlDatabase> threadDatabases; - // this is not only db.isValid(), but also "parameters changed, need to reopen" - QHash<QThread*, int> databasesValid; - // for recursive transactions - QHash<QThread*, int> transactionCount; + QThreadStorage<DatabaseThreadData*> threadDataStorage; - QHash<QThread*, QSqlError> databaseErrors; + // This compares to DatabaseThreadData's valid. If currentValidity is increased and > valid, the db is marked as invalid + int currentValidity; bool isInTransaction; -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #31 from Gilles Caulier <[hidden email]> --- Git commit bab8c3f159930a3b0b31d09b25b9eb42ab1c3c62 by Marcel Wiesweg. Committed on 15/11/2014 at 14:45. Pushed by mwiesweg into branch 'master'. Backport all core db changes regarding thread clean up from main digikam Back and forward port code polish and style changes M +153 -150 libkface/database/databasecorebackend.cpp M +15 -12 libkface/database/databasecorebackend.h M +35 -25 libkface/database/databasecorebackend_p.h M +1 -0 libkface/database/databaseparameters.h http://commits.kde.org/libkface/bab8c3f159930a3b0b31d09b25b9eb42ab1c3c62 diff --git a/libkface/database/databasecorebackend.cpp b/libkface/database/databasecorebackend.cpp index 784e9b7..2193ce2 100644 --- a/libkface/database/databasecorebackend.cpp +++ b/libkface/database/databasecorebackend.cpp @@ -21,12 +21,6 @@ * * ============================================================ */ -/* -#ifndef DATABASCOREBACKEND_DEBUG -#define DATABASCOREBACKEND_DEBUG -#endif -*/ - #include "databasecorebackend.moc" #include "databasecorebackend_p.h" @@ -51,8 +45,8 @@ // Local includes -#include "schemaupdater.h" #include "dbactiontype.h" +#include "schemaupdater.h" namespace KFaceIface { @@ -102,22 +96,65 @@ DatabaseCoreBackendPrivate::ErrorLocker::ErrorLocker(DatabaseCoreBackendPrivate* // ----------------------------------------------------------------------------------------- + +DatabaseThreadData::DatabaseThreadData() + : valid(0), + transactionCount(0) +{ +} + +DatabaseThreadData::~DatabaseThreadData() +{ + if (transactionCount) + { + kDebug() << "WARNING !!! Transaction count is" << transactionCount << "when destroying database!!!"; + } + closeDatabase(); +} + +void DatabaseThreadData::closeDatabase() +{ + QString connectionToRemove; + if (database.isOpen()) + { + connectionToRemove = database.connectionName(); + } + + // Destroy object + database = QSqlDatabase(); + + valid = 0; + transactionCount = 0; + lastError = QSqlError(); + + // Remove connection + if (!connectionToRemove.isNull()) + { + QSqlDatabase::removeDatabase(connectionToRemove); + } +} + DatabaseCoreBackendPrivate::DatabaseCoreBackendPrivate(DatabaseCoreBackend* const backend) - : q(backend) + : currentValidity(0), + isInTransaction(false), + status(DatabaseCoreBackend::Unavailable), + lock(0), + operationStatus(DatabaseCoreBackend::ExecuteNormal), + errorLockOperationStatus(DatabaseCoreBackend::ExecuteNormal), + errorHandler(0), + q(backend) { - status = DatabaseCoreBackend::Unavailable; - isInTransaction = false; - operationStatus = DatabaseCoreBackend::ExecuteNormal; - errorLockOperationStatus = DatabaseCoreBackend::ExecuteNormal; - errorHandler = 0; - lock = 0; } -void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* const l) +DatabaseCoreBackendPrivate::~DatabaseCoreBackendPrivate() { - QObject::connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), - q, SLOT(slotMainThreadFinished())); + // Must be shut down from the main thread. + // Clean up the QThreadStorage. It deletes any stored data. + threadDataStorage.setLocalData(0); +} +void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* const l) +{ backendName = name; lock = l; @@ -133,84 +170,44 @@ void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* cons // finishing of the thread. QSqlDatabase DatabaseCoreBackendPrivate::databaseForThread() { - QThread* const thread = QThread::currentThread(); - QSqlDatabase db = threadDatabases[thread]; - int isValid = databasesValid[thread]; - - if (!isValid || !db.isOpen()) + DatabaseThreadData* threadData = 0; + if (!threadDataStorage.hasLocalData()) { - // need to open a db for thread - bool success = open(db); - - if (!success) - { - kDebug() << "Error while opening the database. Details: [" << db.lastError() << "]"; - } - - QObject::connect(thread, SIGNAL(finished()), - q, SLOT(slotThreadFinished())); + threadData = new DatabaseThreadData; + threadDataStorage.setLocalData(threadData); } - -#ifdef DATABASCOREBACKEND_DEBUG else { - kDebug() << "Database ["<< connectionName(thread) <<"] already open for thread ["<< thread <<"]."; + threadData = threadDataStorage.localData(); } -#endif - - return db; -} - -void DatabaseCoreBackendPrivate::closeDatabaseForThread() -{ - QThread* const thread = QThread::currentThread(); + // do we need to reopen the database because parameter changed and validity was increased? + if (threadData->valid && threadData->valid < currentValidity) + { + threadData->closeDatabase(); + } - // scope, so that db is destructed when calling removeDatabase + if (!threadData->valid || !threadData->database.isOpen()) { - QSqlDatabase db = threadDatabases[thread]; + threadData->database = createDatabaseConnection(); - if (db.isValid()) + if (threadData->database.open()) { - db.close(); + threadData->valid = currentValidity; + } + else + { + kDebug() << "Error while opening the database. Error was" << threadData->database.lastError(); } } - threadDatabases.remove(thread); - databaseErrors.remove(thread); - databasesValid[thread] = 0; - transactionCount.remove(thread); - QSqlDatabase::removeDatabase(connectionName(thread)); -} - -QSqlError DatabaseCoreBackendPrivate::databaseErrorForThread() -{ - QThread* const thread = QThread::currentThread(); - return databaseErrors[thread]; -} - -void DatabaseCoreBackendPrivate::setDatabaseErrorForThread(const QSqlError& lastError) -{ - QThread* const thread = QThread::currentThread(); - databaseErrors.insert(thread, lastError); -} - -QString DatabaseCoreBackendPrivate::connectionName(QThread* const thread) -{ - return backendName + QString::number((quintptr)thread); + return threadData->database; } -bool DatabaseCoreBackendPrivate::open(QSqlDatabase& db) +QSqlDatabase DatabaseCoreBackendPrivate::createDatabaseConnection() { - if (db.isValid()) - { - db.close(); - } - - QThread* const thread = QThread::currentThread(); - db = QSqlDatabase::addDatabase(parameters.databaseType, connectionName(thread)); - - QString connectOptions;// = parameters.connectOptions; + QSqlDatabase db = QSqlDatabase::addDatabase(parameters.databaseType, connectionName()); + QString connectOptions = parameters.connectOptions; if (parameters.isSQLite()) { @@ -230,55 +227,48 @@ bool DatabaseCoreBackendPrivate::open(QSqlDatabase& db) db.setDatabaseName(parameters.databaseName); db.setConnectOptions(connectOptions); - /*db.setHostName(parameters.hostName); - db.setPort(parameters.port); - db.setUserName(parameters.userName); - db.setPassword(parameters.password);*/ - bool success = db.open(); + return db; +} - if (success) +void DatabaseCoreBackendPrivate::closeDatabaseForThread() +{ + if (threadDataStorage.hasLocalData()) { - db.exec("PRAGMA synchronous=1;"); + threadDataStorage.localData()->closeDatabase(); } - else +} + +QSqlError DatabaseCoreBackendPrivate::databaseErrorForThread() +{ + if (threadDataStorage.hasLocalData()) { - kDebug() << "Error while opening the database. Error was <" << db.lastError() << ">"; + return threadDataStorage.localData()->lastError; } - - threadDatabases[thread] = db; - databasesValid[thread] = 1; - transactionCount[thread] = 0; - - return success; + return QSqlError(); } -bool DatabaseCoreBackendPrivate::incrementTransactionCount() +void DatabaseCoreBackendPrivate::setDatabaseErrorForThread(const QSqlError& lastError) { - QThread* const thread = QThread::currentThread(); - return !transactionCount[thread]++; + if (threadDataStorage.hasLocalData()) + { + threadDataStorage.localData()->lastError = lastError; + } } -bool DatabaseCoreBackendPrivate::decrementTransactionCount() +QString DatabaseCoreBackendPrivate::connectionName() { - QThread* const thread = QThread::currentThread(); - return !--transactionCount[thread]; + return backendName + QString::number((quintptr)QThread::currentThread()); } -bool DatabaseCoreBackendPrivate::isInTransactionInOtherThread() const +bool DatabaseCoreBackendPrivate::incrementTransactionCount() { - QThread* const thread = QThread::currentThread(); - QHash<QThread*, int>::const_iterator it; - - for (it = transactionCount.constBegin(); it != transactionCount.constEnd(); ++it) - { - if (it.key() != thread && it.value()) - { - return true; - } - } + return (!threadDataStorage.localData()->transactionCount++); +} - return false; +bool DatabaseCoreBackendPrivate::decrementTransactionCount() +{ + return (!--threadDataStorage.localData()->transactionCount); } bool DatabaseCoreBackendPrivate::isInMainThread() const @@ -295,7 +285,7 @@ bool DatabaseCoreBackendPrivate::isInUIThread() const return false; } - return QThread::currentThread() == app->thread(); + return (QThread::currentThread() == app->thread()); } bool DatabaseCoreBackendPrivate::reconnectOnError() const @@ -325,7 +315,8 @@ bool DatabaseCoreBackendPrivate::isConnectionError(const SqlQuery& query) const return false; } - return (query.lastError().type() == QSqlError::ConnectionError || query.lastError().number()==2006); + return query.lastError().type() == QSqlError::ConnectionError || + query.lastError().number() == 2006; } bool DatabaseCoreBackendPrivate::needToConsultUserForError(const SqlQuery&) const @@ -336,12 +327,15 @@ bool DatabaseCoreBackendPrivate::needToConsultUserForError(const SqlQuery&) cons bool DatabaseCoreBackendPrivate::needToHandleWithErrorHandler(const SqlQuery& query) const { - return isConnectionError(query) || needToConsultUserForError(query); + return (isConnectionError(query) || needToConsultUserForError(query)); } bool DatabaseCoreBackendPrivate::checkRetrySQLiteLockError(int retries) { - kDebug() << "Database is locked. Waited" << retries*10; + if (!(retries % 25)) + { + kDebug() << "Database is locked. Waited" << retries*10; + } const int uiMaxRetries = 50; const int maxRetries = 1000; @@ -476,7 +470,7 @@ bool DatabaseCoreBackendPrivate::handleWithErrorHandler(const SqlQuery* const qu } else { - //TODO check if it's better to use an own error handler for kio slaves. + // TODO check if it's better to use an own error handler for kio slaves. // But for now, close only the database in the hope, that the next // access will be successful. closeDatabaseForThread(); @@ -755,18 +749,6 @@ void DatabaseCoreBackend::setDatabaseErrorHandler(DatabaseErrorHandler* const ha d->errorHandler = handler; } -void DatabaseCoreBackend::slotThreadFinished() -{ - Q_D(DatabaseCoreBackend); - d->closeDatabaseForThread(); -} - -void DatabaseCoreBackend::slotMainThreadFinished() -{ - Q_D(DatabaseCoreBackend); - d->closeDatabaseForThread(); -} - bool DatabaseCoreBackend::isCompatible(const DatabaseParameters& parameters) { return QSqlDatabase::drivers().contains(parameters.databaseType); @@ -776,10 +758,8 @@ bool DatabaseCoreBackend::open(const DatabaseParameters& parameters) { Q_D(DatabaseCoreBackend); d->parameters = parameters; - - // Force possibly opened thread dbs to re-open with new parameters. - // They are not accessible from this thread! - d->databasesValid.clear(); + // This will make possibly opened thread dbs reload at next access + d->currentValidity++; int retries = 0; @@ -913,7 +893,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::handleQueryResult(SqlQuery& return DatabaseCoreBackend::NoErrors; } -// ---------------------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------- DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, QList<QVariant>* const values, QVariant* const lastInsertId) { @@ -922,52 +902,54 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QVariant& boundValue1, - QList<QVariant>* const values, QVariant* const lastInsertId) + QList<QVariant>* const values, QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, boundValue1); return handleQueryResult(query, values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, - const QVariant& boundValue1, const QVariant& boundValue2, - QList<QVariant>* const values, QVariant* const lastInsertId) + const QVariant& boundValue1, const QVariant& boundValue2, + QList<QVariant>* const values, QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, boundValue1, boundValue2); return handleQueryResult(query, values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, - const QVariant& boundValue1, const QVariant& boundValue2, - const QVariant& boundValue3, QList<QVariant>* const values, - QVariant* const lastInsertId) + const QVariant& boundValue1, const QVariant& boundValue2, + const QVariant& boundValue3, QList<QVariant>* const values, + QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, boundValue1, boundValue2, boundValue3); return handleQueryResult(query, values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, - const QVariant& boundValue1, const QVariant& boundValue2, - const QVariant& boundValue3, const QVariant& boundValue4, - QList<QVariant>* const values, QVariant* const lastInsertId) + const QVariant& boundValue1, const QVariant& boundValue2, + const QVariant& boundValue3, const QVariant& boundValue4, + QList<QVariant>* const values, QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, boundValue1, boundValue2, boundValue3, boundValue4); return handleQueryResult(query, values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QList<QVariant>& boundValues, - QList<QVariant>* const values, QVariant* const lastInsertId) + QList<QVariant>* const values, QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, boundValues); return handleQueryResult(query, values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QMap<QString, QVariant>& bindingMap, - QList<QVariant>* const values, QVariant* const lastInsertId) + QList<QVariant>* const values, QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, bindingMap); return handleQueryResult(query, values, lastInsertId); } +// ------------------------------------------------------------------------------------- + DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(SqlQuery& preparedQuery, QList<QVariant>* const values, QVariant* const lastInsertId) { exec(preparedQuery); @@ -1014,6 +996,8 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(SqlQuery& preparedQ return handleQueryResult(preparedQuery, values, lastInsertId); } +// ------------------------------------------------------------------------------------- + SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QVariant& boundValue1) { SqlQuery query = prepareQuery(sql); @@ -1066,6 +1050,8 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql) return query; } +// ------------------------------------------------------------------------------------- + void DatabaseCoreBackend::execQuery(SqlQuery& query, const QVariant& boundValue1) { query.bindValue(0, boundValue1); @@ -1111,6 +1097,8 @@ void DatabaseCoreBackend::execQuery(SqlQuery& query, const QList<QVariant>& boun exec(query); } +// ------------------------------------------------------------------------------------- + SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString, QVariant>& bindingMap) { QString preparedString = sql; @@ -1252,7 +1240,7 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString, SqlQuery query = prepareQuery(preparedString); - for (int i=0; i<valuesToBind.size(); ++i) + for (int i=0; i < valuesToBind.size(); ++i) { query.bindValue(i, valuesToBind.at(i)); } @@ -1262,12 +1250,12 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString, } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execUpsertDBAction(const DatabaseAction& action, const QVariant& id, - const QStringList fieldNames, const QList<QVariant>& values) + const QStringList fieldNames, const QList<QVariant>& values) { QMap<QString, QVariant> parameters; QMap<QString, QVariant> fieldValueMap; - for (int i=0; i<fieldNames.size(); ++i) + for (int i = 0; i < fieldNames.size(); ++i) { fieldValueMap.insert(fieldNames.at(i), values.at(i)); } @@ -1285,7 +1273,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execUpsertDBAction(const Da } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execUpsertDBAction(const QString& action, const QVariant& id, - const QStringList fieldNames, const QList<QVariant>& values) + const QStringList fieldNames, const QList<QVariant>& values) { return execUpsertDBAction(getDBAction(action), id, fieldNames, values); } @@ -1516,6 +1504,7 @@ SqlQuery DatabaseCoreBackend::copyQuery(const SqlQuery& old) #endif query.prepare(old.lastQuery()); query.setForwardOnly(old.isForwardOnly()); + // only for positional binding QList<QVariant> boundValues = old.boundValues().values(); @@ -1635,7 +1624,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::commitTransaction() bool DatabaseCoreBackend::isInTransaction() const { Q_D(const DatabaseCoreBackend); - return d->isInTransactionInOtherThread(); + return d->isInTransaction; } void DatabaseCoreBackend::rollbackTransaction() @@ -1663,4 +1652,18 @@ QString DatabaseCoreBackend::lastError() return d->databaseForThread().lastError().text(); } +int DatabaseCoreBackend::maximumBoundValues() const +{ + Q_D(const DatabaseCoreBackend); + + if (d->parameters.isSQLite()) + { + return 999; // SQLITE_MAX_VARIABLE_NUMBER + } + else + { + return 65535; // MySQL + } +} + } // namespace KFaceIface diff --git a/libkface/database/databasecorebackend.h b/libkface/database/databasecorebackend.h index 9ce859a..a1beac3 100644 --- a/libkface/database/databasecorebackend.h +++ b/libkface/database/databasecorebackend.h @@ -44,6 +44,7 @@ namespace KFaceIface { class DatabaseCoreBackendPrivate; +class DatabaseErrorHandler; class SchemaUpdater; class DatabaseLocking @@ -147,17 +148,18 @@ public: */ void close(); - // ----------------------------------------------------------- +public: class QueryState { public: - QueryState() : value(DatabaseCoreBackend::NoErrors) + QueryState() + : value(DatabaseCoreBackend::NoErrors) { } - QueryState(QueryStateEnum value) + QueryState(const QueryStateEnum value) : value(value) { } @@ -177,6 +179,8 @@ public: QueryStateEnum value; }; +public: + /** * Returns the current status of the database backend */ @@ -275,10 +279,8 @@ public: const QVariant& boundValue1, const QVariant& boundValue2, const QVariant& boundValue3, const QVariant& boundValue4, QList<QVariant>* const values = 0, QVariant* const lastInsertId = 0); - QueryState execSql(const QString& sql, - const QList<QVariant>& boundValues, - QList<QVariant>* const values = 0, - QVariant* const lastInsertId = 0); + QueryState execSql(const QString& sql, const QList<QVariant>& boundValues, + QList<QVariant>* const values = 0, QVariant* const lastInsertId = 0); QueryState execSql(SqlQuery& preparedQuery, QList<QVariant>* const values = 0, QVariant* const lastInsertId = 0); QueryState execSql(SqlQuery& preparedQuery, const QVariant& boundValue1, @@ -438,6 +440,12 @@ public: */ QSqlError lastSQLError(); + /** + * Returns the maximum number of bound parameters allowed per query. + * This value depends on the database engine. + */ + int maximumBoundValues() const; + /* Qt SQL driver supported features SQLITE3: @@ -462,11 +470,6 @@ public: LastInsertId */ -private Q_SLOTS: - - void slotThreadFinished(); - void slotMainThreadFinished(); - protected: DatabaseCoreBackendPrivate* const d_ptr; diff --git a/libkface/database/databasecorebackend_p.h b/libkface/database/databasecorebackend_p.h index c39b33f..27faaa5 100644 --- a/libkface/database/databasecorebackend_p.h +++ b/libkface/database/databasecorebackend_p.h @@ -29,6 +29,7 @@ #include <QHash> #include <QSqlDatabase> #include <QThread> +#include <QThreadStorage> #include <QWaitCondition> // Local includes @@ -38,40 +39,54 @@ namespace KFaceIface { +class DatabaseThreadData +{ +public: + + DatabaseThreadData(); + ~DatabaseThreadData(); + + void closeDatabase(); + + QSqlDatabase database; + int valid; + int transactionCount; + QSqlError lastError; +}; + class DatabaseCoreBackendPrivate : public DatabaseErrorAnswer { public: - DatabaseCoreBackendPrivate(DatabaseCoreBackend* const backend); - virtual ~DatabaseCoreBackendPrivate() {} + explicit DatabaseCoreBackendPrivate(DatabaseCoreBackend* const backend); + virtual ~DatabaseCoreBackendPrivate(); void init(const QString& connectionName, DatabaseLocking* const locking); - QString connectionName(QThread* const thread); + QString connectionName(); QSqlDatabase databaseForThread(); QSqlError databaseErrorForThread(); void setDatabaseErrorForThread(const QSqlError& lastError); + QSqlDatabase createDatabaseConnection(); void closeDatabaseForThread(); - bool open(QSqlDatabase& db); bool incrementTransactionCount(); bool decrementTransactionCount(); - bool isInTransactionInOtherThread() const; bool isInMainThread() const; - bool isInUIThread() const; + bool isInUIThread() const; - bool reconnectOnError() const; - bool isSQLiteLockError(const SqlQuery& query) const; + bool reconnectOnError() const; + bool isSQLiteLockError(const SqlQuery& query) const; bool isSQLiteLockTransactionError(const QSqlError& lastError) const; - bool checkRetrySQLiteLockError(int retries); - bool isConnectionError(const SqlQuery& query) const; - bool needToConsultUserForError(const SqlQuery& query) const; - bool needToHandleWithErrorHandler(const SqlQuery& query) const; - void debugOutputFailedQuery(const QSqlQuery& query) const; - void debugOutputFailedTransaction(const QSqlError& error) const; + bool isConnectionError(const SqlQuery& query) const; + bool needToConsultUserForError(const SqlQuery& query) const; + bool needToHandleWithErrorHandler(const SqlQuery& query) const; + void debugOutputFailedQuery(const QSqlQuery& query) const; + void debugOutputFailedTransaction(const QSqlError& error) const; + bool checkRetrySQLiteLockError(int retries); bool checkOperationStatus(); bool handleWithErrorHandler(const SqlQuery* const query); void setQueryOperationFlag(DatabaseCoreBackend::QueryOperationStatus status); @@ -80,19 +95,14 @@ public: // called by DatabaseErrorHandler, implementing DatabaseErrorAnswer virtual void connectionErrorContinueQueries(); virtual void connectionErrorAbortQueries(); - virtual void transactionFinished(); public: - // this is always accessed in mutex context, no need for QThreadStorage - QHash<QThread*, QSqlDatabase> threadDatabases; - // this is not only db.isValid(), but also "parameters changed, need to reopen" - QHash<QThread*, int> databasesValid; - // for recursive transactions - QHash<QThread*, int> transactionCount; + QThreadStorage<DatabaseThreadData*> threadDataStorage; - QHash<QThread*, QSqlError> databaseErrors; + // This compares to DatabaseThreadData's valid. If currentValidity is increased and > valid, the db is marked as invalid + int currentValidity; bool isInTransaction; @@ -121,7 +131,7 @@ public : { public: - AbstractUnlocker(DatabaseCoreBackendPrivate* const d); + explicit AbstractUnlocker(DatabaseCoreBackendPrivate* const d); ~AbstractUnlocker(); void finishAcquire(); @@ -157,7 +167,7 @@ public : { public: - ErrorLocker(DatabaseCoreBackendPrivate* const d); + explicit ErrorLocker(DatabaseCoreBackendPrivate* const d); void wait(); }; @@ -167,7 +177,7 @@ public : { public: - BusyWaiter(DatabaseCoreBackendPrivate* const d); + explicit BusyWaiter(DatabaseCoreBackendPrivate* const d); }; public : diff --git a/libkface/database/databaseparameters.h b/libkface/database/databaseparameters.h index 655b87a..7cf84ec 100644 --- a/libkface/database/databaseparameters.h +++ b/libkface/database/databaseparameters.h @@ -52,6 +52,7 @@ public: QString databaseType; QString databaseName; + QString connectOptions; bool operator==(const DatabaseParameters& other) const; bool operator!=(const DatabaseParameters& other) const; -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #32 from Gilles Caulier <[hidden email]> --- Git commit 0fb2b35c650b20f7c208bb5b07bd701fd4d09d1f by Marcel Wiesweg. Committed on 15/11/2014 at 14:46. Pushed by mwiesweg into branch 'master'. Back and forward port code polish and style changes from libkface db backend. The files have now only the needed minor differences M +140 -136 libs/database/core/databasecorebackend.cpp M +6 -9 libs/database/core/databasecorebackend.h M +4 -5 libs/database/core/databasecorebackend_p.h http://commits.kde.org/digikam/0fb2b35c650b20f7c208bb5b07bd701fd4d09d1f diff --git a/libs/database/core/databasecorebackend.cpp b/libs/database/core/databasecorebackend.cpp index 76a958a..480f437 100644 --- a/libs/database/core/databasecorebackend.cpp +++ b/libs/database/core/databasecorebackend.cpp @@ -6,7 +6,7 @@ * Date : 2007-04-15 * Description : Abstract database backend * - * Copyright (C) 2007-2010 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> + * Copyright (C) 2007-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General @@ -42,22 +42,23 @@ // KDE includes #include <kdebug.h> -#include <kglobal.h> // Local includes -#include "thumbnailschemaupdater.h" #include "dbactiontype.h" +#include "thumbnailschemaupdater.h" -//#define DATABASCOREBACKEND_DEBUG 1 namespace Digikam { DatabaseLocking::DatabaseLocking() - : mutex(QMutex::Recursive), lockCount(0) // create a recursive mutex + : mutex(QMutex::Recursive), + lockCount(0) // create a recursive mutex { } +// ----------------------------------------------------------------------------------------- + // For whatever reason, these methods are "static protected" class sotoSleep : public QThread { @@ -79,6 +80,23 @@ public: } }; +// ----------------------------------------------------------------------------------------- + +DatabaseCoreBackendPrivate::BusyWaiter::BusyWaiter(DatabaseCoreBackendPrivate* const d) + : AbstractWaitingUnlocker(d, &d->busyWaitMutex, &d->busyWaitCondVar) +{ +} + +// ----------------------------------------------------------------------------------------- + +DatabaseCoreBackendPrivate::ErrorLocker::ErrorLocker(DatabaseCoreBackendPrivate* const d) + : AbstractWaitingUnlocker(d, &d->errorLockMutex, &d->errorLockCondVar) +{ +} + +// ----------------------------------------------------------------------------------------- + + DatabaseThreadData::DatabaseThreadData() : valid(0), transactionCount(0) @@ -288,7 +306,7 @@ bool DatabaseCoreBackendPrivate::isSQLiteLockError(const SqlQuery& query) const bool DatabaseCoreBackendPrivate::isSQLiteLockTransactionError(const QSqlError& lastError) const { return parameters.isSQLite() && - lastError.type() == QSqlError::TransactionError && + lastError.type() == QSqlError::TransactionError && lastError.databaseText() == QLatin1String("database is locked"); // wouldnt it be great if they gave us the database error number... } @@ -356,74 +374,6 @@ void DatabaseCoreBackendPrivate::debugOutputFailedTransaction(const QSqlError& e << error.number() << error.type(); } - -DatabaseCoreBackendPrivate::AbstractUnlocker::AbstractUnlocker(DatabaseCoreBackendPrivate* const d) - : count(0), d(d) -{ - // Why two mutexes? The main mutex is recursive and won't work with a condvar. - - // acquire lock - d->lock->mutex.lock(); - // store lock count - count = d->lock->lockCount; - // set lock count to 0 - d->lock->lockCount = 0; - - // unlock - for (int i=0; i<count; ++i) - { - d->lock->mutex.unlock(); - } -} - -void DatabaseCoreBackendPrivate::AbstractUnlocker::finishAcquire() -{ - // drop lock acquired in first line. Main mutex is now free. - // We maintain lock order (first main mutex, second error lock mutex) - // but we drop main mutex lock for waiting on the cond var. - d->lock->mutex.unlock(); -} - -DatabaseCoreBackendPrivate::AbstractUnlocker::~AbstractUnlocker() -{ - // lock main mutex as often as it was locked before - for (int i=0; i<count; ++i) - { - d->lock->mutex.lock(); - } - - // update lock count - d->lock->lockCount += count; -} - -DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::AbstractWaitingUnlocker(DatabaseCoreBackendPrivate* const d, - QMutex* const mutex, QWaitCondition* const condVar) - : AbstractUnlocker(d), mutex(mutex), condVar(condVar) -{ - // Why two mutexes? The main mutex is recursive and won't work with a condvar. - // lock condvar mutex (lock only if main mutex is locked) - mutex->lock(); - - finishAcquire(); -} - -DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::~AbstractWaitingUnlocker() -{ - // unlock condvar mutex. Both mutexes are now free. - mutex->unlock(); - // now base class destructor is executed, reallocating main mutex -} - -bool DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::wait(unsigned long time) -{ - return condVar->wait(mutex, time); -} - -DatabaseCoreBackendPrivate::BusyWaiter::BusyWaiter(DatabaseCoreBackendPrivate* const d) - : AbstractWaitingUnlocker(d, &d->busyWaitMutex, &d->busyWaitCondVar) -{ -} - void DatabaseCoreBackendPrivate::transactionFinished() { // wakes up any BusyWaiter waiting on the busyWaitCondVar. @@ -431,39 +381,18 @@ void DatabaseCoreBackendPrivate::transactionFinished() busyWaitCondVar.wakeOne(); } -DatabaseCoreBackendPrivate::ErrorLocker::ErrorLocker(DatabaseCoreBackendPrivate* const d) - : AbstractWaitingUnlocker(d, &d->errorLockMutex, &d->errorLockCondVar) -{ -} - -/** This suspends the current thread if the query status as - * set by setFlag() is Wait and until the thread is woken with wakeAll(). - * The DatabaseAccess mutex will be unlocked while waiting. - */ -void DatabaseCoreBackendPrivate::ErrorLocker::wait() -{ - // we use a copy of the flag under lock of the errorLockMutex to be able to check it here - while (d->errorLockOperationStatus == DatabaseCoreBackend::Wait) - { - wait(); - } -} - -/** Set the wait flag to queryStatus. Typically, call this with Wait. - */ +/** Set the wait flag to queryStatus. Typically, call this with Wait. */ void DatabaseCoreBackendPrivate::setQueryOperationFlag(DatabaseCoreBackend::QueryOperationStatus status) { // Enforce lock order (first main mutex, second error lock mutex) QMutexLocker l(&errorLockMutex); - // this change must be done under errorLockMutex lock errorLockOperationStatus = status; operationStatus = status; } /** Set the wait flag to queryStatus and wake all waiting threads. - * Typically, call wakeAll with status ExecuteNormal or AbortQueries. - */ + * Typically, call wakeAll with status ExecuteNormal or AbortQueries. */ void DatabaseCoreBackendPrivate::queryOperationWakeAll(DatabaseCoreBackend::QueryOperationStatus status) { QMutexLocker l(&errorLockMutex); @@ -530,7 +459,7 @@ bool DatabaseCoreBackendPrivate::handleWithErrorHandler(const SqlQuery* const qu } else { - kError() << "Failed to invoke DatabaseErrorHandler. Aborting all queries."; + kWarning() << "Failed to invoke DatabaseErrorHandler. Aborting all queries."; operationStatus = DatabaseCoreBackend::AbortQueries; } @@ -568,7 +497,88 @@ void DatabaseCoreBackendPrivate::connectionErrorAbortQueries() queryOperationWakeAll(DatabaseCoreBackend::AbortQueries); } -// ----------------------------------------------------------------------------------------------- +// ----------------------------------------------------------------------------------------- + +DatabaseCoreBackendPrivate::AbstractUnlocker::AbstractUnlocker(DatabaseCoreBackendPrivate* const d) + : count(0), d(d) +{ + // Why two mutexes? The main mutex is recursive and won't work with a condvar. + + // acquire lock + d->lock->mutex.lock(); + // store lock count + count = d->lock->lockCount; + // set lock count to 0 + d->lock->lockCount = 0; + + // unlock + for (int i=0; i<count; ++i) + { + d->lock->mutex.unlock(); + } +} + +void DatabaseCoreBackendPrivate::AbstractUnlocker::finishAcquire() +{ + // drop lock acquired in first line. Main mutex is now free. + // We maintain lock order (first main mutex, second error lock mutex) + // but we drop main mutex lock for waiting on the cond var. + d->lock->mutex.unlock(); +} + +DatabaseCoreBackendPrivate::AbstractUnlocker::~AbstractUnlocker() +{ + // lock main mutex as often as it was locked before + for (int i=0; i<count; ++i) + { + d->lock->mutex.lock(); + } + + // update lock count + d->lock->lockCount += count; +} + +// ----------------------------------------------------------------------------------------- + +DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::AbstractWaitingUnlocker(DatabaseCoreBackendPrivate* const d, + QMutex* const mutex, QWaitCondition* const condVar) + : AbstractUnlocker(d), mutex(mutex), condVar(condVar) +{ + // Why two mutexes? The main mutex is recursive and won't work with a condvar. + // lock condvar mutex (lock only if main mutex is locked) + mutex->lock(); + + finishAcquire(); +} + +DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::~AbstractWaitingUnlocker() +{ + // unlock condvar mutex. Both mutexes are now free. + mutex->unlock(); + // now base class destructor is executed, reallocating main mutex +} + +bool DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::wait(unsigned long time) +{ + return condVar->wait(mutex, time); +} + +// ----------------------------------------------------------------------------------------- + +/** This suspends the current thread if the query status as + * set by setFlag() is Wait and until the thread is woken with wakeAll(). + * The DatabaseAccess mutex will be unlocked while waiting. + */ +void DatabaseCoreBackendPrivate::ErrorLocker::wait() +{ + // we use a copy of the flag under lock of the errorLockMutex to be able to check it here + while (d->errorLockOperationStatus == DatabaseCoreBackend::Wait) + { + wait(); + } +} + +// ----------------------------------------------------------------------------------------- DatabaseCoreBackend::DatabaseCoreBackend(const QString& backendName, DatabaseLocking* const locking) : d_ptr(new DatabaseCoreBackendPrivate(this)) @@ -602,33 +612,32 @@ DatabaseAction DatabaseCoreBackend::getDBAction(const QString& actionName) const if (action.name.isNull()) { - kError() << "No DB action defined for" << actionName << "! Implementation missing for this database type."; + kWarning() << "No DB action defined for" << actionName << "! Implementation missing for this database type."; } return action; } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const DatabaseAction& action, QList<QVariant>* const values, - QVariant* const lastInsertId) + QVariant* const lastInsertId) { return execDBAction(action, QMap<QString, QVariant>(), values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const QString& action, QList<QVariant>* const values, - QVariant* const lastInsertId) + QVariant* const lastInsertId) { return execDBAction(getDBAction(action), QMap<QString, QVariant>(), values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const QString& action, const QMap<QString, QVariant>& bindingMap, - QList<QVariant>* const values, QVariant* const lastInsertId) + QList<QVariant>* const values, QVariant* const lastInsertId) { return execDBAction(getDBAction(action), bindingMap, values, lastInsertId); } -DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const DatabaseAction& action, const QMap<QString, - QVariant>& bindingMap, QList<QVariant>* const values, - QVariant* const lastInsertId) +DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const DatabaseAction& action, const QMap<QString, QVariant>& bindingMap, + QList<QVariant>* const values, QVariant* const lastInsertId) { Q_D(DatabaseCoreBackend); @@ -637,7 +646,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const Database if (action.name.isNull()) { - kError() << "Attempt to execute null action"; + kWarning() << "Attempt to execute null action"; return DatabaseCoreBackend::SQLError; } @@ -726,8 +735,8 @@ QSqlQuery DatabaseCoreBackend::execDBActionQuery(const DatabaseAction& action, c if (result.lastError().isValid() && result.lastError().number()) { - kDebug() << "Error while executing DBAction ["<< action.name - <<"] Statement ["<<actionElement.statement<<"] Errornr. [" << result.lastError() << "]"; + kDebug() << "Error while executing DBAction [" << action.name + << "] Statement [" << actionElement.statement << "] Errornr. [" << result.lastError() << "]"; break; } } @@ -822,7 +831,7 @@ DatabaseCoreBackend::Status DatabaseCoreBackend::status() const } /* -bool DatabaseCoreBackend::execSql(const QString& sql, QStringList* values) +bool DatabaseCoreBackend::execSql(const QString& sql, QStringList* const values) { QSqlQuery query = execQuery(sql); @@ -865,8 +874,7 @@ QList<QVariant> DatabaseCoreBackend::readToList(SqlQuery& query) return list; } -DatabaseCoreBackend::QueryState DatabaseCoreBackend::handleQueryResult(SqlQuery& query, QList<QVariant>* const values, - QVariant* const lastInsertId) +DatabaseCoreBackend::QueryState DatabaseCoreBackend::handleQueryResult(SqlQuery& query, QList<QVariant>* const values, QVariant* const lastInsertId) { if (!query.isActive()) { @@ -891,57 +899,54 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::handleQueryResult(SqlQuery& // ------------------------------------------------------------------------------------- -DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, QList<QVariant>* const values, - QVariant* const lastInsertId) +DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, QList<QVariant>* const values, QVariant* const lastInsertId) { SqlQuery query = execQuery(sql); return handleQueryResult(query, values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QVariant& boundValue1, - QList<QVariant>* values, QVariant* lastInsertId) + QList<QVariant>* const values, QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, boundValue1); return handleQueryResult(query, values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, - const QVariant& boundValue1, const QVariant& boundValue2, - QList<QVariant>* const values, QVariant* const lastInsertId) + const QVariant& boundValue1, const QVariant& boundValue2, + QList<QVariant>* const values, QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, boundValue1, boundValue2); return handleQueryResult(query, values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, - const QVariant& boundValue1, const QVariant& boundValue2, - const QVariant& boundValue3, QList<QVariant>* const values, - QVariant* const lastInsertId) + const QVariant& boundValue1, const QVariant& boundValue2, + const QVariant& boundValue3, QList<QVariant>* const values, + QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, boundValue1, boundValue2, boundValue3); return handleQueryResult(query, values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, - const QVariant& boundValue1, const QVariant& boundValue2, - const QVariant& boundValue3, const QVariant& boundValue4, - QList<QVariant>* const values, QVariant* const lastInsertId) + const QVariant& boundValue1, const QVariant& boundValue2, + const QVariant& boundValue3, const QVariant& boundValue4, + QList<QVariant>* const values, QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, boundValue1, boundValue2, boundValue3, boundValue4); return handleQueryResult(query, values, lastInsertId); } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QList<QVariant>& boundValues, - QList<QVariant>* const values, QVariant* const lastInsertId) + QList<QVariant>* const values, QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, boundValues); return handleQueryResult(query, values, lastInsertId); } -// ------------------------------------------------------------------------------------- - DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QMap<QString, QVariant>& bindingMap, - QList<QVariant>* const values, QVariant* const lastInsertId) + QList<QVariant>* const values, QVariant* const lastInsertId) { SqlQuery query = execQuery(sql, bindingMap); return handleQueryResult(query, values, lastInsertId); @@ -949,8 +954,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, // ------------------------------------------------------------------------------------- -DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(SqlQuery& preparedQuery, - QList<QVariant>* const values, QVariant* const lastInsertId) +DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(SqlQuery& preparedQuery, QList<QVariant>* const values, QVariant* const lastInsertId) { exec(preparedQuery); return handleQueryResult(preparedQuery, values, lastInsertId); @@ -996,7 +1000,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(SqlQuery& preparedQ return handleQueryResult(preparedQuery, values, lastInsertId); } -// ---------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------- SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QVariant& boundValue1) { @@ -1119,9 +1123,9 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString, if (!bindingMap.contains(namedPlaceholder)) { - kError() << "Missing place holder" << namedPlaceholder - << "in binding map. The following values are defined for this action:" - << bindingMap.keys() <<". This is a setup error!"; + kWarning() << "Missing place holder" << namedPlaceholder + << "in binding map. The following values are defined for this action:" + << bindingMap.keys() <<". This is a setup error!"; //TODO What should we do here? How can we cancel that action? } @@ -1240,7 +1244,7 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString, SqlQuery query = prepareQuery(preparedString); - for (int i=0; i<valuesToBind.size(); ++i) + for (int i=0; i < valuesToBind.size(); ++i) { query.bindValue(i, valuesToBind.at(i)); } @@ -1250,7 +1254,7 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString, } DatabaseCoreBackend::QueryState DatabaseCoreBackend::execUpsertDBAction(const DatabaseAction& action, const QVariant& id, - const QStringList fieldNames, const QList<QVariant>& values) + const QStringList fieldNames, const QList<QVariant>& values) { QMap<QString, QVariant> parameters; QMap<QString, QVariant> fieldValueMap; @@ -1266,7 +1270,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execUpsertDBAction(const Da parameters.insert(":id", id); parameters.insert(":fieldValueList", qVariantFromValue(fieldValueList)); - parameters.insert(":fieldList", qVariantFromValue (fieldList)); + parameters.insert(":fieldList", qVariantFromValue(fieldList)); parameters.insert(":valueList", qVariantFromValue(valueList)); return execDBAction(action, parameters); diff --git a/libs/database/core/databasecorebackend.h b/libs/database/core/databasecorebackend.h index fa4dba4..ea8d558 100644 --- a/libs/database/core/databasecorebackend.h +++ b/libs/database/core/databasecorebackend.h @@ -42,15 +42,12 @@ namespace Digikam { -class ThumbnailSchemaUpdater; -class DatabaseErrorHandler; class DatabaseCoreBackendPrivate; - -// ------------------------------------------------------------------------------------------------------------ +class DatabaseErrorHandler; +class ThumbnailSchemaUpdater; class DIGIKAM_EXPORT DatabaseLocking { - public: DatabaseLocking(); @@ -61,7 +58,7 @@ public: int lockCount; }; -// ------------------------------------------------------------------------------------------------------------ +// ----------------------------------------------------------------- class DIGIKAM_EXPORT DatabaseCoreBackend : public QObject { @@ -202,7 +199,7 @@ public: * Add a DatabaseErrorHandler. This object must be created in the main thread. * If a database error occurs, this object can handle problem solving and user interaction. */ - void setDatabaseErrorHandler(DatabaseErrorHandler* handler); + void setDatabaseErrorHandler(DatabaseErrorHandler* const handler); /** * Return config read from XML, @@ -265,10 +262,10 @@ public: * Executes the SQL statement, and write the returned data into the values list. * If you are not interested in the returned data, set values to 0. * Methods are provided for up to four bound values (positional binding), or for a list of bound values. - * If you want the last inserted id (and your query is suitable), sett lastInsertId to the address of a QVariant. + * If you want the last inserted id (and your query is suitable), set lastInsertId to the address of a QVariant. * Additionally, methods are provided for prepared statements. */ - QueryState execSql(const QString& sql, QList<QVariant>* values = 0, QVariant* const lastInsertId = 0); + QueryState execSql(const QString& sql, QList<QVariant>* const values = 0, QVariant* const lastInsertId = 0); QueryState execSql(const QString& sql, const QVariant& boundValue1, QList<QVariant>* const values = 0, QVariant* const lastInsertId = 0); QueryState execSql(const QString& sql, diff --git a/libs/database/core/databasecorebackend_p.h b/libs/database/core/databasecorebackend_p.h index ff3a3fa..1f60dd7 100644 --- a/libs/database/core/databasecorebackend_p.h +++ b/libs/database/core/databasecorebackend_p.h @@ -75,7 +75,6 @@ public: void closeDatabaseForThread(); bool incrementTransactionCount(); bool decrementTransactionCount(); - bool isInTransactionInOtherThread() const; bool isInMainThread() const; bool isInUIThread() const; @@ -145,10 +144,10 @@ public : DatabaseCoreBackendPrivate* const d; }; - // ---------------------------------------------------------------------- - friend class AbstractUnlocker; + // ------------------------------------------------------------------ + class AbstractWaitingUnlocker : public AbstractUnlocker { public: @@ -164,7 +163,7 @@ public : QWaitCondition* const condVar; }; - // ---------------------------------------------------------------------- + // ------------------------------------------------------------------ class ErrorLocker : public AbstractWaitingUnlocker { @@ -174,7 +173,7 @@ public : void wait(); }; - // ---------------------------------------------------------------------- + // ------------------------------------------------------------------ class BusyWaiter : public AbstractWaitingUnlocker { -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #33 from Gilles Caulier <[hidden email]> --- Next digiKam release 4.6.0 will include several important commits from Marcel to try to fix this memory leak with SQlite database Gilles Caulier -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
Christoph Feck <[hidden email]> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |[hidden email] --- Comment #34 from Christoph Feck <[hidden email]> --- *** Bug 342144 has been marked as a duplicate of this bug. *** -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #35 from Christian <[hidden email]> --- The problem is better in Digikam 4.6.0, but the issue remains. I am not sure about the details yet (still testing), but it seems to me that, most of the time, the following task works now: * Change the name on a face with a name However, I still get memory problems/crashes when I do the following: * Assign an "Unidentified face" to an assisting name * Remove face detection marks when they do not show a face. I'm not sure which of these two is the problem in 4.6.0, but I think it's the face-name assignment. -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
In reply to this post by Christian-3
https://bugs.kde.org/show_bug.cgi?id=338176
--- Comment #36 from Christian <[hidden email]> --- One thing that has definitely been improved in 4.6.0 is, that the digikam remembers everything that I do with the faces - even after the crash the modified information is still there. (In 4.4.0 it let me continue assign names and they were not saved any longer after a while.) -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
Free forum by Nabble | Edit this page |