local sync: disambiguate source names

During local sync names like "addressbook" are no longer unique,
because they may exist in both the local and the remote context. This
patch introduces a "display name" composed from context and source name,
like this: "@<context>/<source>" (@default/addressbook).

The context is only used if needed, which currently is the case during
a local sync.

Changing the SyncSourceBase::getName() result was also considered, but
several places expect this to be the name of the source inside its
context, so an explicit SyncSourceBase::getDisplayName() turned out
to be safer.
This commit is contained in:
Patrick Ohly 2010-10-22 14:02:01 +02:00
parent 783cad557e
commit a9ee4e87ee
4 changed files with 77 additions and 41 deletions

View file

@ -132,7 +132,7 @@ void LocalTransportAgent::run()
// process.
int res = 0;
try {
SE_LOG_INFO(NULL, NULL, "client is running");
SE_LOG_DEBUG(NULL, NULL, "client is running");
// TODO: password and abort handling in a derived class
SyncContext client(std::string("source-config") + m_clientContext,
m_server->getRootPath() + "/." + m_clientContext,

View file

@ -1539,20 +1539,20 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
// not active, suppress output
} else if (extra2) {
SE_LOG_INFO(NULL, NULL, "%s: preparing %d/%d",
source.getName(), extra1, extra2);
source.getDisplayName(), extra1, extra2);
} else {
SE_LOG_INFO(NULL, NULL, "%s: preparing %d",
source.getName(), extra1);
source.getDisplayName(), extra1);
}
break;
case sysync::PEV_DELETING:
/* deleting (zapping datastore), extra1=progress, extra2=total */
if (extra2) {
SE_LOG_INFO(NULL, NULL, "%s: deleting %d/%d",
source.getName(), extra1, extra2);
source.getDisplayName(), extra1, extra2);
} else {
SE_LOG_INFO(NULL, NULL, "%s: deleting %d",
source.getName(), extra1);
source.getDisplayName(), extra1);
}
break;
case sysync::PEV_ALERTED: {
@ -1562,7 +1562,7 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
// -1 is used for alerting a restore from backup. Synthesis won't use this
if (extra1 != -1) {
SE_LOG_INFO(NULL, NULL, "%s: %s %s sync%s",
source.getName(),
source.getDisplayName(),
extra2 ? "resuming" : "starting",
extra1 == 0 ? "normal" :
extra1 == 1 ? "slow" :
@ -1607,7 +1607,7 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
source.recordFirstSync(extra1 == 2);
source.recordResumeSync(extra2 == 1);
} else {
SE_LOG_INFO(NULL, NULL, "%s: restore from backup", source.getName());
SE_LOG_INFO(NULL, NULL, "%s: restore from backup", source.getDisplayName());
source.recordFinalSyncMode(SYNC_RESTORE_FROM_BACKUP);
}
break;
@ -1615,7 +1615,7 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
case sysync::PEV_SYNCSTART:
/* sync started */
SE_LOG_INFO(NULL, NULL, "%s: started",
source.getName());
source.getDisplayName());
break;
case sysync::PEV_ITEMRECEIVED:
/* item received, extra1=current item count,
@ -1623,10 +1623,10 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
if (source.getFinalSyncMode() == SYNC_NONE) {
} else if (extra2 > 0) {
SE_LOG_INFO(NULL, NULL, "%s: received %d/%d",
source.getName(), extra1, extra2);
source.getDisplayName(), extra1, extra2);
} else {
SE_LOG_INFO(NULL, NULL, "%s: received %d",
source.getName(), extra1);
source.getDisplayName(), extra1);
}
break;
case sysync::PEV_ITEMSENT:
@ -1635,10 +1635,10 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
if (source.getFinalSyncMode() == SYNC_NONE) {
} else if (extra2 > 0) {
SE_LOG_INFO(NULL, NULL, "%s: sent %d/%d",
source.getName(), extra1, extra2);
source.getDisplayName(), extra1, extra2);
} else {
SE_LOG_INFO(NULL, NULL, "%s: sent %d",
source.getName(), extra1);
source.getDisplayName(), extra1);
}
break;
case sysync::PEV_ITEMPROCESSED:
@ -1648,7 +1648,7 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
if (source.getFinalSyncMode() == SYNC_NONE) {
} else if (source.getFinalSyncMode() != SYNC_NONE) {
SE_LOG_INFO(NULL, NULL, "%s: added %d, updated %d, removed %d",
source.getName(), extra1, extra2, extra3);
source.getDisplayName(), extra1, extra2, extra3);
}
break;
case sysync::PEV_SYNCEND:
@ -1656,14 +1656,14 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
syncmode in extra2 (0=normal, 1=slow, 2=first time),
extra3=1 for resumed session) */
if (source.getFinalSyncMode() == SYNC_NONE) {
SE_LOG_INFO(NULL, NULL, "%s: inactive", source.getName());
SE_LOG_INFO(NULL, NULL, "%s: inactive", source.getDisplayName());
} else if(source.getFinalSyncMode() == SYNC_RESTORE_FROM_BACKUP) {
SE_LOG_INFO(NULL, NULL, "%s: restore done %s",
source.getName(),
source.getDisplayName(),
extra1 ? "unsuccessfully" : "successfully" );
} else {
SE_LOG_INFO(NULL, NULL, "%s: %s%s sync done %s",
source.getName(),
source.getDisplayName(),
extra3 ? "resumed " : "",
extra2 == 0 ? "normal" :
extra2 == 1 ? "slow" :
@ -1792,7 +1792,7 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
break;
default:
SE_LOG_DEBUG(NULL, NULL, "%s: progress event %d, extra %d/%d/%d",
source.getName(),
source.getDisplayName(),
type, extra1, extra2, extra3);
}
}
@ -1896,6 +1896,15 @@ void SyncContext::initSources(SourceList &sourceList)
list<string> configuredSources = getSyncSources();
map<string, string> subSources;
// Disambiguate source names because we have multiple with the same
// name active?
string contextName;
if (m_localSync) {
string dummy;
splitConfigString(getConfigName(), dummy, contextName);
contextName.insert(0, "@");
}
// Phase 1, check all virtual sync soruces
BOOST_FOREACH(const string &name, configuredSources) {
boost::shared_ptr<PersistentSyncSourceConfig> sc(getSyncSourceConfig(name));
@ -1908,7 +1917,7 @@ void SyncContext::initSources(SourceList &sourceList)
if (sourceType.m_backend == "virtual") {
//This is a virtual sync source, check and enable the referenced
//sub syncsources here
SyncSourceParams params(name, source, boost::shared_ptr<SyncConfig>(this, SyncConfigNOP()));
SyncSourceParams params(name, source, boost::shared_ptr<SyncConfig>(this, SyncConfigNOP()), contextName);
boost::shared_ptr<VirtualSyncSource> vSource = boost::shared_ptr<VirtualSyncSource> (new VirtualSyncSource (params));
std::vector<std::string> mappedSources = vSource->getMappedSources();
BOOST_FOREACH (std::string source, mappedSources) {
@ -1954,7 +1963,8 @@ void SyncContext::initSources(SourceList &sourceList)
if (sourceType.m_backend != "virtual") {
SyncSourceParams params(name,
source,
boost::shared_ptr<SyncConfig>(this, SyncConfigNOP()));
boost::shared_ptr<SyncConfig>(this, SyncConfigNOP()),
contextName);
cxxptr<SyncSource> syncSource(SyncSource::createSource(params));
if (!syncSource) {
throwError(name + ": type unknown" );
@ -1968,7 +1978,7 @@ void SyncContext::initSources(SourceList &sourceList)
// the Synthesis engine is never going to see this source,
// therefore we have to mark it as 100% complete and
// "done"
class DummySyncSource source(name);
class DummySyncSource source(name, contextName);
source.recordFinalSyncMode(SYNC_NONE);
displaySourceProgress(sysync::PEV_PREPARING,
source,
@ -2444,7 +2454,7 @@ void SyncContext::getConfigXML(string &xml, string &configname)
sourceType.m_forceFormat != subType.m_forceFormat)) {
SE_LOG_WARNING(NULL, NULL,
"Virtual data source \"%s\" and sub data source \"%s\" have different data format. Will use the format in virtual data source.",
vSource->getName(), source.c_str());
vSource->getDisplayName(), source.c_str());
}
}
@ -2698,6 +2708,9 @@ SyncMLStatus SyncContext::sync(SyncReport *report)
SwapContext syncSentinel(this);
try {
m_sourceListPtr = &sourceList;
if (boost::starts_with(getUsedSyncURL(), "local://")) {
m_localSync = true;
}
if (getenv("SYNCEVOLUTION_GNUTLS_DEBUG")) {
// Enable libgnutls debugging without creating a hard dependency on it,
@ -2731,10 +2744,6 @@ SyncMLStatus SyncContext::sync(SyncReport *report)
getLogLevel(),
report);
if (boost::starts_with(getUsedSyncURL(), "local://")) {
m_localSync = true;
}
/* Must detect server or client session before creating the
* underlying SynthesisEngine
* */

View file

@ -54,7 +54,7 @@ void SyncSourceBase::throwError(const string &action, int error)
void SyncSourceBase::throwError(const string &failure)
{
SyncContext::throwError(string(getName()) + ": " + failure);
SyncContext::throwError(string(getDisplayName()) + ": " + failure);
}
SyncMLStatus SyncSourceBase::handleException()
@ -73,7 +73,7 @@ void SyncSourceBase::messagev(Level level,
const char *format,
va_list args)
{
string newprefix = getName();
string newprefix = getDisplayName();
if (prefix) {
newprefix += ": ";
newprefix += prefix;
@ -177,6 +177,14 @@ string SyncSourceBase::getNativeDatatypeName()
return info.m_native;
}
SyncSource::SyncSource(const SyncSourceParams &params) :
SyncSourceConfig(params.m_name, params.m_nodes),
m_numDeleted(0),
m_forceSlowSync(false),
m_name(params.getDisplayName())
{
}
SDKInterface *SyncSource::getSynthesisAPI() const
{
return m_synthesisAPI.empty() ?
@ -317,7 +325,7 @@ SyncSource *SyncSource::createSource(const SyncSourceParams &params, bool error,
SyncSource *source = NULL;
source = new VirtualSyncSource(params, config);
if (error && !source) {
SyncContext::throwError(params.m_name + ": virtual source cannot be instantiated");
SyncContext::throwError(params.getDisplayName() + ": virtual source cannot be instantiated");
}
return source;
}
@ -327,8 +335,8 @@ SyncSource *SyncSource::createSource(const SyncSourceParams &params, bool error,
SyncSource *source = sourceInfos->m_create(params);
if (source) {
if (source == RegisterSyncSource::InactiveSource) {
SyncContext::throwError(params.m_name + ": access to " + sourceInfos->m_shortDescr +
" not enabled, therefore type = " + sourceTypeString + " not supported");
SyncContext::throwError(params.getDisplayName() + ": access to " + sourceInfos->m_shortDescr +
" not enabled, therefore type = " + sourceTypeString + " not supported");
}
return source;
}

View file

@ -53,18 +53,26 @@ struct SyncSourceParams {
* Testing uses "source-config@client-test". On the
* command line, this is the config chosen by the
* user, which may or may not have peer-specific settings!
* @param contextName optional name of context in which the source is defined,
* needed to disambiguates "name" when sources from
* different contexts are active in a sync
*/
SyncSourceParams(const string &name,
const SyncSourceNodes &nodes,
const boost::shared_ptr<const SyncConfig> &context) :
const boost::shared_ptr<const SyncConfig> &context,
const string &contextName = "") :
m_name(name),
m_nodes(nodes),
m_context(context)
m_context(context),
m_contextName(contextName)
{}
std::string getDisplayName() const { return m_contextName.empty() ? m_name : m_contextName + "/" + m_name; }
string m_name;
SyncSourceNodes m_nodes;
boost::shared_ptr<const SyncConfig> m_context;
string m_contextName;
};
/**
@ -555,9 +563,21 @@ class SyncSourceBase : public Logger {
public:
virtual ~SyncSourceBase() {}
/** the unique name of the sync source (for example, "addressbook") */
/**
* the name of the sync source (for example, "addressbook"),
* unique in the context of its own configuration
**/
virtual const char *getName() const { return "uninitialized SyncSourceBase"; }
/**
* the name of the sync source as it should be displayed to users
* in debug messages; typically the same as getName(), but may
* also include a context ("@foobar/addressbook") to disambiguate
* the name when "addressbook" is used multiple times in a sync (as
* with local sync)
*/
virtual const char *getDisplayName() const { return "uninitialized SyncSourceBase"; }
/**
* Convenience function, to be called inside a catch() block of
* (or for) the sync source.
@ -751,12 +771,7 @@ class SyncSourceBase : public Logger {
class SyncSource : virtual public SyncSourceBase, public SyncSourceConfig, public SyncSourceReport
{
public:
SyncSource(const SyncSourceParams &params) :
SyncSourceConfig(params.m_name, params.m_nodes),
m_numDeleted(0),
m_forceSlowSync(false)
{
}
SyncSource(const SyncSourceParams &params);
virtual ~SyncSource() {}
/**
@ -1109,6 +1124,7 @@ class SyncSource : virtual public SyncSourceBase, public SyncSourceConfig, publi
/* implementation of SyncSourceBase */
virtual const char * getName() const { return SyncSourceConfig::getName(); }
virtual const char * getDisplayName() const { return m_name.c_str(); }
virtual long getNumDeleted() const { return m_numDeleted; }
virtual void setNumDeleted(long num) { m_numDeleted = num; }
virtual void incrementNumDeleted() { m_numDeleted++; }
@ -1146,6 +1162,9 @@ class SyncSource : virtual public SyncSourceBase, public SyncSourceConfig, publi
* the engine is running.
*/
std::vector<sysync::SDK_InterfaceType *> m_synthesisAPI;
/** actual name of the source */
std::string m_name;
};
/**
@ -1157,8 +1176,8 @@ class DummySyncSource : public SyncSource
DummySyncSource(const SyncSourceParams &params) :
SyncSource(params) {}
DummySyncSource(const std::string &name) :
SyncSource(SyncSourceParams(name, SyncSourceNodes(), boost::shared_ptr<const SyncConfig>())) {}
DummySyncSource(const std::string &name, const std::string &contextName) :
SyncSource(SyncSourceParams(name, SyncSourceNodes(), boost::shared_ptr<const SyncConfig>(), contextName)) {}
virtual Databases getDatabases() { return Databases(); }
virtual void open() {}