SyncSource: remove special RegisterSyncSource::InactiveSource pointer

The special semantic of the former RegisterSyncSource::InactiveSource
(invalid pointer of value 1) caused bugs, like using it in
--print-databases (=> segfault) or not being able to store the result
of a createSource() directly in a smart pointer (=> potential leak in
SyncSource::createSource()).

Obviously a bad idea to start with. Replaced with a
RegisterSyncSource::InactiveSource() method which creates a real,
inactive SyncSource instance which can and must be deleted by the
caller.

This is a SyncSource API change for backend developers.
Instead of RegisterSyncSource::InactiveSource, return
RegisterSyncSource::InactiveSource().

Comparisons against RegisterSyncSource::InactiveSource needs
to be replaced with a call to the new SyncSource::isInactive().

User visible fixes:
* --print-databases: no longer crashes when EDS or KDE backends
  are not usable. Instead it prints "not enabled during compilation or
  not usable in the current environment".
* --print-databases: continues with other backends even if
  one backend throws an exception, as the KDE backend does
  when it cannot find Akonadi. Error messages are printed.
This commit is contained in:
Patrick Ohly 2012-03-08 10:15:22 +00:00
parent eafc49cb35
commit 12334eb676
16 changed files with 83 additions and 51 deletions

View File

@ -46,7 +46,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_ACTIVESYNC
new ActiveSyncContactSource(params)
#else
RegisterSyncSource::InactiveSource
RegisterSyncSource::InactiveSource(params)
#endif
;
}
@ -57,7 +57,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_ACTIVESYNC
new ActiveSyncCalendarSource(params, EAS_ITEM_CALENDAR)
#else
RegisterSyncSource::InactiveSource
RegisterSyncSource::InactiveSource(params)
#endif
;
}
@ -68,7 +68,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_ACTIVESYNC
new ActiveSyncCalFormatSource(params, EAS_ITEM_TODO)
#else
RegisterSyncSource::InactiveSource
RegisterSyncSource::InactiveSource(params)
#endif
;
}
@ -79,7 +79,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_ACTIVESYNC
new ActiveSyncCalFormatSource(params, EAS_ITEM_JOURNAL)
#else
RegisterSyncSource::InactiveSource
RegisterSyncSource::InactiveSource(params)
#endif
;
}

View File

@ -29,7 +29,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
bool isMe = sourceType.m_backend == "apple-contacts";
#ifndef ENABLE_ADDRESSBOOK
return isMe ? RegisterSyncSource::InactiveSource : NULL;
return isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
#else
bool maybeMe = sourceType.m_backend == "addressbook";

View File

@ -42,7 +42,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_AKONADI
new AkonadiContactSource(params)
#else
isMe ? RegisterSyncSource::InactiveSource : NULL
isMe ? RegisterSyncSource::InactiveSource(params) : NULL
#endif
;
} else {
@ -58,7 +58,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_AKONADI
new AkonadiTaskSource(params)
#else
isMe ? RegisterSyncSource::InactiveSource : NULL
isMe ? RegisterSyncSource::InactiveSource(params) : NULL
#endif
;
} else {
@ -73,7 +73,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_AKONADI
new AkonadiMemoSource(params)
#else
isMe ? RegisterSyncSource::InactiveSource : NULL
isMe ? RegisterSyncSource::InactiveSource(params) : NULL
#endif
;
} else {
@ -89,7 +89,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_AKONADI
new AkonadiCalendarSource(params)
#else
isMe ? RegisterSyncSource::InactiveSource : NULL
isMe ? RegisterSyncSource::InactiveSource(params) : NULL
#endif
;
} else {

View File

@ -46,7 +46,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_ECAL
enabled ? new EvolutionCalendarSource(E_CAL_SOURCE_TYPE_TODO, params) :
#endif
isMe ? RegisterSyncSource::InactiveSource : NULL;
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
}
}
@ -57,13 +57,13 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_ECAL
enabled ? new EvolutionMemoSource(params) :
#endif
isMe ? RegisterSyncSource::InactiveSource : NULL;
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
} else if (sourceType.m_format == "text/calendar") {
return
#ifdef ENABLE_ECAL
enabled ? new EvolutionCalendarSource(E_CAL_SOURCE_TYPE_JOURNAL, params) :
#endif
isMe ? RegisterSyncSource::InactiveSource : NULL;
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
} else {
return NULL;
}
@ -79,7 +79,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_ECAL
enabled ? new EvolutionCalendarSource(E_CAL_SOURCE_TYPE_EVENT, params) :
#endif
isMe ? RegisterSyncSource::InactiveSource : NULL;
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
} else {
return NULL;
}

View File

@ -40,13 +40,13 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_EBOOK
enabled ? new EvolutionContactSource(params, EVC_FORMAT_VCARD_21) :
#endif
isMe ? RegisterSyncSource::InactiveSource : NULL;
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
} else if (sourceType.m_format == "text/vcard") {
return
#ifdef ENABLE_EBOOK
enabled ? new EvolutionContactSource(params, EVC_FORMAT_VCARD_30) :
#endif
isMe ? RegisterSyncSource::InactiveSource : NULL;
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
}
}
return NULL;

View File

@ -34,7 +34,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifndef ENABLE_FILE
// tell SyncEvolution if the user wanted to use a disabled sync source,
// otherwise let it continue searching
return isMe ? RegisterSyncSource::InactiveSource : NULL;
return isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
#else
// Also recognize one of the standard types?
// Not in the FileSyncSource!

View File

@ -39,7 +39,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_KCALEXTENDED
true ? new KCalExtendedSource(params) :
#endif
isMe ? RegisterSyncSource::InactiveSource : NULL;
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
}
}
return NULL;

View File

@ -29,7 +29,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
bool isMe = sourceType.m_backend == "Maemo Calendar";
#ifndef ENABLE_MAEMO_CALENDAR
if (isMe) return RegisterSyncSource::InactiveSource;
if (isMe) return RegisterSyncSource::InactiveSource(params);
#else
bool maybeMe = sourceType.m_backend == "calendar";
@ -46,7 +46,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
isMe = sourceType.m_backend == "Maemo Tasks";
#ifndef ENABLE_MAEMO_CALENDAR
if (isMe) return RegisterSyncSource::InactiveSource;
if (isMe) return RegisterSyncSource::InactiveSource(params);
#else
maybeMe = sourceType.m_backend == "todo";
@ -63,7 +63,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
isMe = sourceType.m_backend == "Maemo Notes";
#ifndef ENABLE_MAEMO_CALENDAR
if (isMe) return RegisterSyncSource::InactiveSource;
if (isMe) return RegisterSyncSource::InactiveSource(params);
#else
maybeMe = sourceType.m_backend == "memo";

View File

@ -44,7 +44,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifdef ENABLE_QTCONTACTS
true ? new QtContactsSource(params) :
#endif
isMe ? RegisterSyncSource::InactiveSource : NULL;
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
}
}
return NULL;

View File

@ -34,7 +34,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
bool isMe = sourceType.m_backend == "SQLite Address Book";
#ifndef ENABLE_SQLITE
return isMe ? RegisterSyncSource::InactiveSource : NULL;
return isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
#else
bool maybeMe = sourceType.m_backend == "addressbook";

View File

@ -59,7 +59,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
return new MapSyncSource(params, sub);
}
#endif
return RegisterSyncSource::InactiveSource;
return RegisterSyncSource::InactiveSource(params);
}
}
@ -74,7 +74,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
return new CardDAVSource(params, settings);
}
#endif
return RegisterSyncSource::InactiveSource;
return RegisterSyncSource::InactiveSource(params);
}
}

View File

@ -35,7 +35,7 @@ static SyncSource *createSource(const SyncSourceParams &params)
#ifndef ENABLE_XMLRPC
// tell SyncEvolution if the user wanted to use a disabled sync source,
// otherwise let it continue searching
return isMe ? RegisterSyncSource::InactiveSource : NULL;
return isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
#else
// Also recognize one of the standard types?
// Not in the FileSyncSource!

View File

@ -325,14 +325,13 @@ void ReadOperations::getDatabases(const string &sourceName, SourceDatabases_t &d
SyncSourceParams params(sourceName, config->getSyncSourceNodes(sourceName), config);
const SourceRegistry &registry(SyncSource::getSourceRegistry());
BOOST_FOREACH(const RegisterSyncSource *sourceInfo, registry) {
SyncSource *source = sourceInfo->m_create(params);
if (!source) {
auto_ptr<SyncSource> source(sourceInfo->m_create(params));
if (!source.get()) {
continue;
} else if (source == RegisterSyncSource::InactiveSource) {
} else if (source->isInactive()) {
SE_THROW_EXCEPTION(NoSuchSource, "'" + m_configName + "' backend of source '" + sourceName + "' is not supported");
} else {
auto_ptr<SyncSource> autoSource(source);
databases = autoSource->getDatabases();
databases = source->getDatabases();
return;
}
}

View File

@ -724,10 +724,19 @@ bool Cmdline::run() {
if (!alias.empty() && source->m_enabled) {
SourceType type(*alias.begin());
nodes->getProperties()->setProperty("backend", type.m_backend);
auto_ptr<SyncSource> source(SyncSource::createSource(params, false));
if (source.get() != NULL) {
listSources(*source, boost::join(alias, " = "));
m_out << "\n";
std::string header = boost::join(alias, " = ");
try {
auto_ptr<SyncSource> source(SyncSource::createSource(params, false));
if (!source.get()) {
// silently skip backends like the "file" backend which do not support
// listing databases and return NULL unless configured properly
} else {
listSources(*source, header);
m_out << "\n";
}
} catch (...) {
SE_LOG_ERROR(NULL, NULL, "%s:\nlisting databases failed", header.c_str());
Exception::handle();
}
}
}
@ -1884,6 +1893,12 @@ void Cmdline::checkForPeerProps()
void Cmdline::listSources(SyncSource &syncSource, const string &header)
{
m_out << header << ":\n";
if (syncSource.isInactive()) {
m_out << "not enabled during compilation or not usable in the current environment\n";
return;
}
SyncSource::Databases databases = syncSource.getDatabases();
BOOST_FOREACH(const SyncSource::Database &database, databases) {

View File

@ -259,7 +259,25 @@ RegisterSyncSource::RegisterSyncSource(const string &shortDescr,
registry.push_back(this);
}
SyncSource *const RegisterSyncSource::InactiveSource = (SyncSource *)1;
class InactiveSyncSource : public SyncSource
{
public:
InactiveSyncSource(const SyncSourceParams &params) : SyncSource(params) {}
virtual bool isInactive() const { return true; }
virtual void enableServerMode() {}
virtual bool serverModeEnabled() const { return false; }
virtual void getSynthesisInfo(SyncEvo::SyncSourceBase::SynthesisInfo&, SyncEvo::XMLConfigFragments&) { throwError("inactive"); }
virtual Databases getDatabases() { throwError("inactive"); return Databases(); }
virtual void open() { throwError("inactive"); }
virtual void close() { throwError("inactive"); }
virtual std::string getPeerMimeType() const { return ""; }
};
SyncSource *RegisterSyncSource::InactiveSource(const SyncSourceParams &params)
{
return new InactiveSyncSource(params);
}
TestRegistry &SyncSource::getTestRegistry()
{
@ -371,23 +389,19 @@ SyncSource *SyncSource::createSource(const SyncSourceParams &params, bool error,
}
const SourceRegistry &registry(getSourceRegistry());
SyncSource *source = NULL;
auto_ptr<SyncSource> source;
BOOST_FOREACH(const RegisterSyncSource *sourceInfos, registry) {
SyncSource *nextSource = sourceInfos->m_create(params);
if (nextSource) {
if (source) {
auto_ptr<SyncSource> nextSource(sourceInfos->m_create(params));
if (nextSource.get()) {
if (source.get()) {
SyncContext::throwError(params.getDisplayName() + ": backend " + sourceType.m_backend +
" is ambiguous, avoid the alias and pick a specific backend instead directly");
}
if (source == RegisterSyncSource::InactiveSource) {
SyncContext::throwError(params.getDisplayName() + ": access to " + sourceInfos->m_shortDescr +
" not enabled");
}
source = nextSource;
}
}
if (source) {
return source;
if (source.get()) {
return source.release();
}
if (error) {

View File

@ -108,15 +108,16 @@ class RegisterSyncSource
* selected type.
*
* Inactive sources should return the special InactiveSource
* pointer value if they recognize without a doubt that the user
* wanted to instantiate them: for example, an inactive
* EvolutionContactSource will return NULL for "addressbook" but
* InactiveSource for "evolution-contacts".
* instance (created with InactiveSource() below) if they
* recognize without a doubt that the user wanted to instantiate
* them: for example, an inactive EvolutionContactSource will
* return NULL for "addressbook" but InactiveSource for
* "evolution-contacts".
*/
typedef SyncSource *(*Create_t)(const SyncSourceParams &params);
/** special return value of Create_t, not a real sync source! */
static SyncSource *const InactiveSource;
/** create special result of Create_t: a source which just throws errors when used */
static SyncSource *InactiveSource(const SyncSourceParams &params);
/**
* @param shortDescr a few words identifying the data to be synchronized,
@ -1428,6 +1429,9 @@ class SyncSource : virtual public SyncSourceBase, public SyncSourceConfig, publi
SyncSource(const SyncSourceParams &params);
virtual ~SyncSource() {}
/** true in sources which are not meant to be used, see RegisterSyncSource::InactiveSource() */
virtual bool isInactive() const { return false; }
/**
* SyncSource implementations must register themselves here via
* RegisterSyncSource