Cleaned up some old code -- removed ThreadHelper and integrated the

functionality into Indexer. In the future we should use asio for this sort
of thing.
This commit is contained in:
casey langen 2016-10-19 23:06:28 -07:00
parent dd0e413e38
commit 144e5eeadc
7 changed files with 54 additions and 221 deletions

View File

@ -23,7 +23,6 @@ set(CORE_SOURCES
./support/NonLibraryTrackHelper.cpp
./support/Preferences.cpp
./support/PreferenceKeys.cpp
./support/ThreadHelper.cpp
./support/Version.cpp
../3rdparty/src/md5/md5.c
../3rdparty/src/sqlite/sqlite3.c

View File

@ -111,7 +111,6 @@
<ClCompile Include="support\NonLibraryTrackHelper.cpp" />
<ClCompile Include="support\PreferenceKeys.cpp" />
<ClCompile Include="support\Preferences.cpp" />
<ClCompile Include="support\ThreadHelper.cpp" />
<ClCompile Include="support\Version.cpp" />
</ItemGroup>
<ItemGroup>
@ -159,7 +158,6 @@
<ClInclude Include="support\NonLibraryTrackHelper.h" />
<ClInclude Include="support\PreferenceKeys.h" />
<ClInclude Include="support\Preferences.h" />
<ClInclude Include="support\ThreadHelper.h" />
<ClInclude Include="support\Version.h" />
</ItemGroup>
<ItemGroup>

View File

@ -70,9 +70,6 @@
<ClCompile Include="support\Preferences.cpp">
<Filter>src\support</Filter>
</ClCompile>
<ClCompile Include="support\ThreadHelper.cpp">
<Filter>src\support</Filter>
</ClCompile>
<ClCompile Include="support\Common.cpp">
<Filter>src\support</Filter>
</ClCompile>
@ -183,9 +180,6 @@
<ClInclude Include="support\Preferences.h">
<Filter>src\support</Filter>
</ClInclude>
<ClInclude Include="support\ThreadHelper.h">
<Filter>src\support</Filter>
</ClInclude>
<ClInclude Include="library\Indexer.h">
<Filter>src\library</Filter>
</ClInclude>

View File

@ -57,7 +57,7 @@
static const std::string TAG = "Indexer";
static const int MAX_THREADS = 10;
static const int NOTIFY_INTERVAL = 300;
static const size_t NOTIFY_INTERVAL = 300;
using namespace musik::core;
using namespace musik::core::metadata;
@ -82,9 +82,7 @@ static std::string normalizePath(const std::string& path) {
Indexer::Indexer(const std::string& libraryPath, const std::string& dbFilename)
: thread(nullptr)
, status(0)
, restart(false)
, filesIndexed(0)
, filesSaved(0)
, prefs(Preferences::ForComponent(prefs::components::Settings))
, readSemaphore(prefs->GetInt(prefs::keys::MaxTagReadThreads, MAX_THREADS)) {
@ -95,7 +93,11 @@ Indexer::Indexer(const std::string& libraryPath, const std::string& dbFilename)
Indexer::~Indexer() {
if (this->thread) {
this->Exit();
{
boost::mutex::scoped_lock lock(this->stateMutex);
this->exit = true;
}
this->thread->join();
delete this->thread;
this->thread = nullptr;
@ -103,23 +105,18 @@ Indexer::~Indexer() {
}
void Indexer::Synchronize(bool restart) {
boost::mutex::scoped_lock lock(this->exitMutex);
boost::mutex::scoped_lock lock(this->stateMutex);
this->restart = restart;
this->Notify();
}
bool Indexer::Restarted() {
boost::mutex::scoped_lock lock(this->exitMutex);
return this->restart;
}
void Indexer::AddPath(const std::string& path) {
Indexer::AddRemoveContext context;
context.add = true;
context.path = normalizeDir(path);
{
boost::mutex::scoped_lock lock(this->exitMutex);
boost::mutex::scoped_lock lock(this->stateMutex);
this->addRemoveQueue.push_back(context);
}
@ -132,7 +129,7 @@ void Indexer::RemovePath(const std::string& path) {
context.path = normalizeDir(path);
{
boost::mutex::scoped_lock lock(this->exitMutex);
boost::mutex::scoped_lock lock(this->stateMutex);
this->addRemoveQueue.push_back(context);
}
@ -150,11 +147,6 @@ void Indexer::SynchronizeInternal(boost::asio::io_service* io) {
this->audioDecoders = PluginFactory::Instance()
.QueryInterface<IDecoderFactory, DecoderDeleter>("GetDecoderFactory");
{
boost::mutex::scoped_lock lock(this->progressMutex);
this->filesIndexed = 0;
}
this->ProcessAddRemoveQueue();
/* get sync paths and ids from the db */
@ -182,12 +174,7 @@ void Indexer::SynchronizeInternal(boost::asio::io_service* io) {
}
/* add new files */
{
boost::mutex::scoped_lock lock(this->progressMutex);
this->status = 2;
this->filesSaved = 0;
}
this->filesSaved = 0;
for(std::size_t i = 0; i < paths.size(); ++i) {
this->trackTransaction.reset(new db::ScopedTransaction(this->dbConnection));
@ -204,11 +191,6 @@ void Indexer::SynchronizeInternal(boost::asio::io_service* io) {
musik::debug::info(TAG, "cleanup 1/2");
{
boost::mutex::scoped_lock lock(this->progressMutex);
this->status = 3;
}
if (!this->Restarted() && !this->Exited()) {
this->SyncDelete();
}
@ -217,12 +199,6 @@ void Indexer::SynchronizeInternal(boost::asio::io_service* io) {
musik::debug::info(TAG, "cleanup 2/2");
{
boost::mutex::scoped_lock lock(this->progressMutex);
this->status = 4;
}
if (!this->Restarted() && !this->Exited()){
this->SyncCleanup();
}
@ -231,11 +207,6 @@ void Indexer::SynchronizeInternal(boost::asio::io_service* io) {
musik::debug::info(TAG, "optimizing");
{
boost::mutex::scoped_lock lock(this->progressMutex);
this->status = 5;
}
if (!this->Restarted() && !this->Exited()){
this->SyncOptimize();
}
@ -244,11 +215,6 @@ void Indexer::SynchronizeInternal(boost::asio::io_service* io) {
this->metadataReaders.clear();
{
boost::mutex::scoped_lock lock(this->progressMutex);
this->status = 0;
}
musik::debug::info(TAG, "done!");
}
@ -351,13 +317,13 @@ void Indexer::SyncDirectory(
std::vector<Thread> threads;
for( ; file != end && !this->Exited() && !this->Restarted(); file++) {
if (this->filesSaved.load() > NOTIFY_INTERVAL) {
if (this->filesSaved > NOTIFY_INTERVAL) {
if (this->trackTransaction) {
this->trackTransaction->CommitAndRestart();
}
this->TrackRefreshed();
this->filesSaved.store(0);
this->filesSaved = 0;
}
if (is_directory(file->status())) {
/* recursion here */
@ -365,8 +331,6 @@ void Indexer::SyncDirectory(
this->SyncDirectory(io, syncRoot, file->path().string(), pathId);
}
else {
++this->filesIndexed;
if (io) {
this->readSemaphore.wait();
@ -400,7 +364,7 @@ void Indexer::ThreadLoop() {
while (!this->Exited()) {
this->restart = false;
if(!firstTime || (firstTime && prefs->GetBool(prefs::keys::SyncOnStartup, true))) { /* first time through the loop skips this */
if(!firstTime || (firstTime && prefs->GetBool(prefs::keys::SyncOnStartup, false))) { /* first time through the loop skips this */
this->SynchronizeStart();
this->dbConnection.Open(this->dbFilename.c_str(), 0); /* ensure the db is open */
@ -427,12 +391,6 @@ void Indexer::ThreadLoop() {
#endif
this->RunAnalyzers();
{
boost::mutex::scoped_lock lock(this->progressMutex);
this->status = 0;
}
this->dbConnection.Close(); /* TODO: raii */
this->SynchronizeEnd();
@ -573,10 +531,6 @@ static int optimize(
return count;
}
//////////////////////////////////////////
///\brief
///Optimizes and fixing sorting and indexes
//////////////////////////////////////////
void Indexer::SyncOptimize() {
DBID count = 0, id = 0;
@ -602,7 +556,7 @@ void Indexer::SyncOptimize() {
}
void Indexer::ProcessAddRemoveQueue() {
boost::mutex::scoped_lock lock(this->exitMutex);
boost::mutex::scoped_lock lock(this->stateMutex);
while (!this->addRemoveQueue.empty()) {
AddRemoveContext context = this->addRemoveQueue.front();
@ -644,13 +598,6 @@ void Indexer::RunAnalyzers() {
return;
}
/* initialize status */
{
boost::mutex::scoped_lock lock(this->progressMutex);
this->status = 6;
}
/* for each track... */
DBID trackId = 0;
@ -730,3 +677,32 @@ void Indexer::RunAnalyzers() {
getNextTrack.BindInt(0, trackId);
}
}
bool Indexer::Restarted() {
boost::mutex::scoped_lock lock(this->stateMutex);
return this->restart;
}
bool Indexer::Exited() {
boost::mutex::scoped_lock lock(this->stateMutex);
return this->exit;
}
void Indexer::NotificationWait() {
boost::mutex::scoped_lock lock(this->stateMutex);
if (!this->exit) {
this->waitCondition.wait(lock);
}
}
void Indexer::NotificationTimedWait(const boost::xtime &time) {
boost::mutex::scoped_lock lock(this->stateMutex);
if (!this->exit) {
this->waitCondition.timed_wait(lock, time);
}
}
void Indexer::Notify() {
this->waitCondition.notify_all();
}

View File

@ -34,7 +34,6 @@
#pragma once
#include <core/support/ThreadHelper.h>
#include <core/db/Connection.h>
#include <core/sdk/IMetadataReader.h>
#include <core/sdk/IDecoderFactory.h>
@ -44,6 +43,7 @@
#include <sigslot/sigslot.h>
#include <boost/thread/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/filesystem.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
@ -54,7 +54,7 @@
namespace musik { namespace core {
class Indexer : public IIndexer, public ThreadHelper, private boost::noncopyable {
class Indexer : public IIndexer, private boost::noncopyable {
public:
Indexer(
const std::string& libraryPath,
@ -70,6 +70,11 @@ namespace musik { namespace core {
private:
void ThreadLoop();
bool Exited();
void NotificationWait();
void NotificationTimedWait(const boost::xtime &oTime);
void Notify();
bool Restarted();
void SyncDelete();
@ -77,7 +82,6 @@ namespace musik { namespace core {
void ProcessAddRemoveQueue();
void SyncOptimize();
void RunAnalyzers();
void SynchronizeInternal(boost::asio::io_service* io);
void SyncDirectory(
@ -95,13 +99,13 @@ namespace musik { namespace core {
std::string libraryPath;
std::string dbFilename;
int status;
bool restart;
bool exit;
boost::mutex stateMutex;
boost::condition waitCondition;
boost::thread *thread;
boost::mutex progressMutex;
size_t filesIndexed;
std::atomic<size_t> filesSaved;
struct AddRemoveContext {

View File

@ -1,74 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#include "pch.hpp"
#include <core/support/ThreadHelper.h>
using namespace musik::core;
ThreadHelper::ThreadHelper()
: exit(false) {
}
ThreadHelper::~ThreadHelper() {
}
bool ThreadHelper::Exited() {
boost::mutex::scoped_lock lock(this->exitMutex);
return this->exit;
}
void ThreadHelper::Exit() {
boost::mutex::scoped_lock lock(this->exitMutex);
this->exit = true;
this->notify.notify_all();
}
void ThreadHelper::NotificationWait(){
boost::mutex::scoped_lock lock(this->exitMutex);
if (!this->exit) {
this->notify.wait(lock);
}
}
void ThreadHelper::NotificationTimedWait(const boost::xtime &time) {
boost::mutex::scoped_lock lock(this->exitMutex);
if (!this->exit) {
this->notify.timed_wait(lock, time);
}
}
void ThreadHelper::Notify(){
this->notify.notify_all();
}

View File

@ -1,64 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include <core/config.h>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
namespace musik{ namespace core{
class ThreadHelper{
public:
ThreadHelper(void);
virtual ~ThreadHelper(void);
virtual void Exit();
boost::mutex exitMutex;
protected:
bool Exited();
void NotificationWait();
void NotificationTimedWait(const boost::xtime &oTime);
void Notify();
bool exit;
boost::condition notify;
};
} }