db/upnp/Discovery: eliminate Error attribute

Move code to method Start() and add Error& parameters to several
methods.
This commit is contained in:
Max Kellermann 2014-01-18 16:08:30 +01:00
parent 53573e950f
commit 7d696a7063
3 changed files with 32 additions and 51 deletions

View File

@ -165,8 +165,7 @@ UpnpDatabase::Open(Error &error)
} }
m_superdir = new UPnPDeviceDirectory(m_lib); m_superdir = new UPnPDeviceDirectory(m_lib);
if (!m_superdir->ok()) { if (!m_superdir->Start(error)) {
error.Set(m_superdir->GetError());
delete m_superdir; delete m_superdir;
delete m_lib; delete m_lib;
return false; return false;
@ -215,20 +214,12 @@ upnpItemToSong(const UPnPDirObject &dirent, const char *uri)
Song * Song *
UpnpDatabase::GetSong(const char *uri, Error &error) const UpnpDatabase::GetSong(const char *uri, Error &error) const
{ {
if (!m_superdir->ok()) {
error.Set(upnp_domain,
"UpnpDatabase::GetSong() superdir is sick");
return nullptr;
}
Song *song = nullptr; Song *song = nullptr;
auto vpath = stringToTokens(uri, "/", true); auto vpath = stringToTokens(uri, "/", true);
if (vpath.size() >= 2) { if (vpath.size() >= 2) {
ContentDirectoryService server; ContentDirectoryService server;
if (!m_superdir->getServer(vpath[0].c_str(), server)) { if (!m_superdir->getServer(vpath[0].c_str(), server, error))
error.Set(upnp_domain, "server not found");
return nullptr; return nullptr;
}
vpath.erase(vpath.begin()); vpath.erase(vpath.begin());
UPnPDirObject dirent; UPnPDirObject dirent;
@ -688,12 +679,8 @@ UpnpDatabase::Visit(const DatabaseSelection &selection,
Error &error) const Error &error) const
{ {
std::vector<ContentDirectoryService> servers; std::vector<ContentDirectoryService> servers;
if (!m_superdir->ok() || if (!m_superdir->getDirServices(servers, error))
!m_superdir->getDirServices(servers)) {
error.Set(upnp_domain,
"UpnpDatabase::Visit() superdir is sick");
return false; return false;
}
auto vpath = stringToTokens(selection.uri, "/", true); auto vpath = stringToTokens(selection.uri, "/", true);
if (vpath.empty()) { if (vpath.empty()) {
@ -748,12 +735,8 @@ UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection,
return true; return true;
std::vector<ContentDirectoryService> servers; std::vector<ContentDirectoryService> servers;
if (!m_superdir->ok() || if (!m_superdir->getDirServices(servers, error))
!m_superdir->getDirServices(servers)) {
error.Set(upnp_domain,
"UpnpDatabase::Visit() superdir is sick");
return false; return false;
}
std::set<std::string> values; std::set<std::string> values;
for (auto& server : servers) { for (auto& server : servers) {

View File

@ -160,8 +160,8 @@ UPnPDeviceDirectory::cluCallBack(Upnp_EventType et, void *evp)
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
void bool
UPnPDeviceDirectory::expireDevices() UPnPDeviceDirectory::expireDevices(Error &error)
{ {
const ScopeLock protect(mutex); const ScopeLock protect(mutex);
time_t now = time(0); time_t now = time(0);
@ -178,28 +178,35 @@ UPnPDeviceDirectory::expireDevices()
} }
if (didsomething) if (didsomething)
search(); return search(error);
return true;
} }
UPnPDeviceDirectory::UPnPDeviceDirectory(LibUPnP *_lib) UPnPDeviceDirectory::UPnPDeviceDirectory(LibUPnP *_lib)
:lib(_lib), :lib(_lib),
discoveredQueue("DiscoveredQueue"), discoveredQueue("DiscoveredQueue"),
m_searchTimeout(2), m_lastSearch(0) m_searchTimeout(2), m_lastSearch(0)
{
}
bool
UPnPDeviceDirectory::Start(Error &error)
{ {
if (!discoveredQueue.start(1, discoExplorer, this)) { if (!discoveredQueue.start(1, discoExplorer, this)) {
error.Set(upnp_domain, "Discover work queue start failed"); error.Set(upnp_domain, "Discover work queue start failed");
return; return false;
} }
lib->SetHandler([this](Upnp_EventType type, void *event){ lib->SetHandler([this](Upnp_EventType type, void *event){
cluCallBack(type, event); cluCallBack(type, event);
}); });
search(); return search(error);
} }
bool bool
UPnPDeviceDirectory::search() UPnPDeviceDirectory::search(Error &error)
{ {
time_t now = time(0); time_t now = time(0);
if (now - m_lastSearch < 10) if (now - m_lastSearch < 10)
@ -229,13 +236,12 @@ UPnPDeviceDirectory::search()
} }
bool bool
UPnPDeviceDirectory::getDirServices(std::vector<ContentDirectoryService> &out) UPnPDeviceDirectory::getDirServices(std::vector<ContentDirectoryService> &out,
Error &error)
{ {
if (!ok())
return false;
// Has locking, do it before our own lock // Has locking, do it before our own lock
expireDevices(); if (!expireDevices(error))
return false;
const ScopeLock protect(mutex); const ScopeLock protect(mutex);
@ -253,12 +259,12 @@ UPnPDeviceDirectory::getDirServices(std::vector<ContentDirectoryService> &out)
bool bool
UPnPDeviceDirectory::getServer(const char *friendlyName, UPnPDeviceDirectory::getServer(const char *friendlyName,
ContentDirectoryService &server) ContentDirectoryService &server,
Error &error)
{ {
std::vector<ContentDirectoryService> ds; std::vector<ContentDirectoryService> ds;
if (!getDirServices(ds)) { if (!getDirServices(ds, error))
return false; return false;
}
for (const auto &i : ds) { for (const auto &i : ds) {
if (strcmp(friendlyName, i.getFriendlyName()) == 0) { if (strcmp(friendlyName, i.getFriendlyName()) == 0) {
@ -267,5 +273,6 @@ UPnPDeviceDirectory::getServer(const char *friendlyName,
} }
} }
error.Set(upnp_domain, "Server not found");
return false; return false;
} }

View File

@ -82,8 +82,6 @@ class UPnPDeviceDirectory {
LibUPnP *const lib; LibUPnP *const lib;
Error error;
Mutex mutex; Mutex mutex;
std::map<std::string, ContentDirectoryDescriptor> directories; std::map<std::string, ContentDirectoryDescriptor> directories;
WorkQueue<DiscoveredTask *> discoveredQueue; WorkQueue<DiscoveredTask *> discoveredQueue;
@ -103,8 +101,10 @@ public:
UPnPDeviceDirectory(const UPnPDeviceDirectory &) = delete; UPnPDeviceDirectory(const UPnPDeviceDirectory &) = delete;
UPnPDeviceDirectory& operator=(const UPnPDeviceDirectory &) = delete; UPnPDeviceDirectory& operator=(const UPnPDeviceDirectory &) = delete;
bool Start(Error &error);
/** Retrieve the directory services currently seen on the network */ /** Retrieve the directory services currently seen on the network */
bool getDirServices(std::vector<ContentDirectoryService> &); bool getDirServices(std::vector<ContentDirectoryService> &, Error &);
/** /**
* Get server by friendly name. It's a bit wasteful to copy * Get server by friendly name. It's a bit wasteful to copy
@ -112,27 +112,18 @@ public:
* there isn't going to be millions... * there isn't going to be millions...
*/ */
bool getServer(const char *friendlyName, bool getServer(const char *friendlyName,
ContentDirectoryService &server); ContentDirectoryService &server,
Error &error);
/** My health */
bool ok() const {
return !error.IsDefined();
}
/** My diagnostic if health is bad */
const Error &GetError() const {
return error;
}
private: private:
bool search(); bool search(Error &error);
/** /**
* Look at the devices and get rid of those which have not * Look at the devices and get rid of those which have not
* been seen for too long. We do this when listing the top * been seen for too long. We do this when listing the top
* directory. * directory.
*/ */
void expireDevices(); bool expireDevices(Error &error);
/** /**
* Worker routine for the discovery queue. Get messages about * Worker routine for the discovery queue. Get messages about