d32df59517
In Tracker 0.9.26, tracker database file names have been changed. So, update them.
653 lines
22 KiB
C++
653 lines
22 KiB
C++
/*
|
|
* Copyright (C) 2010 Intel Corporation
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) version 3.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301 USA
|
|
*/
|
|
|
|
#include "syncevo/util.h"
|
|
#include "client-test-buteo.h"
|
|
#include <libsyncprofile/SyncResults.h>
|
|
#include <libsyncprofile/ProfileEngineDefs.h>
|
|
#include <libsyncprofile/Profile.h>
|
|
#include <libsyncprofile/SyncProfile.h>
|
|
#include <syncmlcommon/SyncMLCommon.h>
|
|
#include <QDomDocument>
|
|
#include <QtDBus>
|
|
|
|
// 3 databases used by tracker to store contacts
|
|
// empty string is used as separator
|
|
const string trackerdb_old[5] = {"meta.db",
|
|
"contents.db",
|
|
"fulltext.db", // 3 databases used by tracker
|
|
"", // separator
|
|
"hcontacts.db" // database to record deleted contact items
|
|
};
|
|
const string trackerdb_new[5] = {"meta.db",
|
|
"meta.db-shm",
|
|
"meta.db-wal", // 3 databases used by tracker
|
|
"", // separator
|
|
"hcontacts.db" // database to record deleted contact items
|
|
};
|
|
string QtContactsSwitcher::m_databases[5] = {};
|
|
string QtContactsSwitcher::m_dirs[2] = {"/.cache/tracker/",
|
|
"/.sync/sync-app/"};
|
|
|
|
using namespace Buteo;
|
|
using namespace SyncEvo;
|
|
|
|
// execute a command. If 'check' is true, throw an exception when
|
|
// execution encounters error(s)
|
|
static void execCmd(const std::string &cmd, bool check = true)
|
|
{
|
|
int result = Execute(cmd, ExecuteFlags(EXECUTE_NO_STDERR | EXECUTE_NO_STDOUT));
|
|
if (result < 0 && check) {
|
|
throw runtime_error("failed to excute command: " + cmd);
|
|
}
|
|
}
|
|
|
|
bool ButeoTest::m_inited = false;
|
|
QString ButeoTest::m_deviceIds[2];
|
|
map<string, string> ButeoTest::m_source2storage;
|
|
|
|
ButeoTest::ButeoTest(ClientTest &client,
|
|
const string &server,
|
|
const string &logbase,
|
|
const SyncEvo::SyncOptions &options) :
|
|
m_client(client), m_server(server), m_logbase(logbase), m_options(options)
|
|
{
|
|
init();
|
|
}
|
|
|
|
void ButeoTest::init()
|
|
{
|
|
if (!m_inited) {
|
|
m_inited = true;
|
|
// generate device ids
|
|
for(int i = 0; i < sizeof(m_deviceIds)/sizeof(m_deviceIds[0]); i++) {
|
|
QString id;
|
|
UUID uuid;
|
|
QTextStream(&id) << "sc-pim-" << uuid.c_str();
|
|
m_deviceIds[i] = id;
|
|
}
|
|
|
|
// insert source -> storage mappings
|
|
m_source2storage.insert(std::make_pair("qt_vcard30", "hcontacts"));
|
|
m_source2storage.insert(std::make_pair("kcal_ical20", "hcalendar"));
|
|
m_source2storage.insert(std::make_pair("kcal_itodo20", "htodo"));
|
|
m_source2storage.insert(std::make_pair("kcal_text", "hnotes"));
|
|
|
|
//init qcoreapplication to use qt
|
|
static const char *argv[] = { "SyncEvolution" };
|
|
static int argc = 1;
|
|
new QCoreApplication(argc, (char **)argv);
|
|
}
|
|
}
|
|
|
|
void ButeoTest::prepareSources(const int *sources,
|
|
const vector<string> &source2Config)
|
|
{
|
|
for(int i = 0; sources[i] >= 0; i++) {
|
|
string source = source2Config[sources[i]];
|
|
map<string, string>::iterator it = m_source2storage.find(source);
|
|
if (it != m_source2storage.end()) {
|
|
m_configedSources.insert(it->second);
|
|
} else {
|
|
throw runtime_error("unsupported source '" + source + "'");
|
|
}
|
|
}
|
|
}
|
|
|
|
SyncMLStatus ButeoTest::doSync(SyncReport *report)
|
|
{
|
|
SyncMLStatus status = STATUS_OK;
|
|
|
|
// kill msyncd
|
|
killAllMsyncd();
|
|
//set sync options
|
|
setupOptions();
|
|
// restore qtcontacts if needed
|
|
if (inclContacts()) {
|
|
QtContactsSwitcher::restoreStorage(m_client);
|
|
}
|
|
|
|
//start msyncd
|
|
int pid = startMsyncd();
|
|
//kill 'sh' process which is the parent of 'msyncd'
|
|
stringstream cmd;
|
|
cmd << "kill -9 " << pid;
|
|
//run sync
|
|
if (!run()) {
|
|
execCmd(cmd.str(), false);
|
|
killAllMsyncd();
|
|
return STATUS_FATAL;
|
|
}
|
|
|
|
execCmd(cmd.str(), false);
|
|
killAllMsyncd();
|
|
// save qtcontacts if needed
|
|
if (inclContacts()) {
|
|
QtContactsSwitcher::backupStorage(m_client);
|
|
}
|
|
//get sync results
|
|
genSyncResults(m_syncResults, report);
|
|
return report->getStatus();
|
|
}
|
|
|
|
void ButeoTest::setupOptions()
|
|
{
|
|
// 1. set deviceid, max-message-size options to /etc/sync/meego-sync-conf.xml
|
|
QString meegoSyncmlConf = "/etc/sync/meego-syncml-conf.xml";
|
|
QFile syncmlFile(meegoSyncmlConf);
|
|
if (!syncmlFile.open(QIODevice::ReadOnly)) {
|
|
throw runtime_error("can't open syncml config");
|
|
}
|
|
// don't invoke buteo-syncml API for it doesn't support flushing
|
|
QString syncmlContent(syncmlFile.readAll());
|
|
syncmlFile.close();
|
|
int id = 0;
|
|
if (!boost::ends_with(m_server, "_1")) {
|
|
id = 1;
|
|
}
|
|
|
|
//specify the db path which saves anchors related info, then we can wipe
|
|
//out it if want to slow sync.
|
|
replaceElement(syncmlContent, "dbpath", QString((m_server + ".db").c_str()));
|
|
replaceElement(syncmlContent, "local-device-name", m_deviceIds[id]);
|
|
|
|
QString msgSize;
|
|
QTextStream(&msgSize) << m_options.m_maxMsgSize;
|
|
replaceElement(syncmlContent, "max-message-size", msgSize);
|
|
|
|
writeToFile(meegoSyncmlConf, syncmlContent);
|
|
|
|
// 2. set storage 'Notebook Name' for calendar, todo and notes
|
|
// for contacts, we have to set corresponding tracker db
|
|
string storageDir = getHome() + "/.sync/profiles/storage/";
|
|
BOOST_FOREACH(const string &source, m_configedSources) {
|
|
if (boost::iequals(source, "hcalendar") ||
|
|
boost::iequals(source, "htodo") ||
|
|
boost::iequals(source, "hnotes")) {
|
|
string filePath = storageDir + source + ".xml";
|
|
QDomDocument doc(m_server.c_str());
|
|
buildDomFromFile(doc, filePath.c_str());
|
|
QString notebookName;
|
|
QTextStream(¬ebookName) << "client_test_" << id;
|
|
Profile profile(doc.documentElement());
|
|
profile.setKey("Notebook Name", notebookName);
|
|
writeToFile(filePath.c_str(), profile.toString());
|
|
}
|
|
}
|
|
|
|
// 3. set wbxml option, sync mode, enabled selected sources and disable other sources
|
|
QDomDocument doc(m_server.c_str());
|
|
//copy profile
|
|
string profileDir = getHome() + "/.sync/profiles/sync/";
|
|
string profilePath = profileDir + m_server + ".xml";
|
|
size_t pos = m_server.rfind('_');
|
|
if (pos != m_server.npos) {
|
|
string prefix = m_server.substr(0, pos);
|
|
stringstream cmd;
|
|
cmd << "cp " << profileDir
|
|
<< prefix << ".xml "
|
|
<< profilePath;
|
|
execCmd(cmd.str());
|
|
}
|
|
buildDomFromFile(doc, profilePath.c_str());
|
|
SyncProfile syncProfile(doc.documentElement());
|
|
syncProfile.setName(m_server.c_str());
|
|
QList<Profile *> storages = syncProfile.storageProfilesNonConst();
|
|
QListIterator<Profile *> it(storages);
|
|
while (it.hasNext()) {
|
|
Profile * profile = it.next();
|
|
set<string>::iterator configedIt = m_configedSources.find(profile->name().toStdString());
|
|
if (configedIt != m_configedSources.end()) {
|
|
profile->setKey(KEY_ENABLED, "true");
|
|
} else {
|
|
profile->setKey(KEY_ENABLED, "false");
|
|
}
|
|
}
|
|
|
|
// set syncml client
|
|
Profile * syncml = syncProfile.subProfile("syncml", "client");
|
|
if (syncml) {
|
|
// set whether using wbxml
|
|
syncml->setBoolKey(PROF_USE_WBXML, m_options.m_isWBXML);
|
|
// set sync mode
|
|
QString syncMode;
|
|
switch(m_options.m_syncMode) {
|
|
case SYNC_NONE:
|
|
break;
|
|
case SYNC_TWO_WAY:
|
|
syncMode = VALUE_TWO_WAY;
|
|
break;
|
|
case SYNC_ONE_WAY_FROM_CLIENT:
|
|
// work around here since buteo doesn't support refresh mode now
|
|
syncMode = VALUE_TO_REMOTE;
|
|
break;
|
|
case SYNC_REFRESH_FROM_CLIENT:
|
|
// don't support, no workaround here
|
|
throw runtime_error("Buteo doesn't support refresh mode");
|
|
case SYNC_ONE_WAY_FROM_SERVER:
|
|
syncMode = VALUE_FROM_REMOTE;
|
|
break;
|
|
case SYNC_REFRESH_FROM_SERVER: {
|
|
//workaround here since buteo doesn't support refresh-from-server
|
|
//wipe out anchors and remove tracker database
|
|
//so we will do refresh-from-server by slow sync
|
|
stringstream cmd1;
|
|
cmd1 << "rm -f " << m_server << ".db";
|
|
execCmd(cmd1.str(), false);
|
|
if (inclContacts()) {
|
|
execCmd("tracker-control -r", false);
|
|
stringstream cmd2;
|
|
cmd2 << "rm -f "
|
|
<< getHome() << "/.cache/tracker/*.db "
|
|
<< getHome() << "/.cache/tracker/*.db_"
|
|
<< m_client.getClientB() ? "1" : "2";
|
|
execCmd(cmd2.str(), false);
|
|
}
|
|
syncMode = VALUE_TWO_WAY;
|
|
break;
|
|
}
|
|
case SYNC_SLOW: {
|
|
//workaround here since buteo doesn't support explicite slow-sync
|
|
//wipe out anchors so we will do slow sync
|
|
stringstream cmd;
|
|
cmd << "rm -f " << m_server << ".db";
|
|
execCmd(cmd.str(), false);
|
|
syncMode = VALUE_TWO_WAY;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
syncml->setKey(KEY_SYNC_DIRECTION, syncMode);
|
|
}
|
|
writeToFile(profilePath.c_str(), syncProfile.toString());
|
|
}
|
|
|
|
void ButeoTest::killAllMsyncd()
|
|
{
|
|
execCmd("killall -9 msyncd", false);
|
|
}
|
|
|
|
int ButeoTest::startMsyncd()
|
|
{
|
|
int pid = fork();
|
|
if (pid == 0) {
|
|
//child
|
|
stringstream cmd;
|
|
cmd << "msyncd >" << m_logbase << ".log 2>&1";
|
|
if (execlp("sh", "sh", "-c", cmd.str().c_str(), (char *)0) < 0 ) {
|
|
exit(1);
|
|
}
|
|
} else if (pid < 0) {
|
|
throw runtime_error("can't fork process");
|
|
}
|
|
// wait for msyncd get prepared
|
|
execCmd("sleep 2", false);
|
|
return pid;
|
|
}
|
|
|
|
bool ButeoTest::run()
|
|
{
|
|
static const QString msyncdService = "com.meego.msyncd";
|
|
static const QString msyncdObject = "/synchronizer";
|
|
static const QString msyncdInterface = "com.meego.msyncd";
|
|
|
|
QDBusConnection conn = QDBusConnection::sessionBus();
|
|
std::auto_ptr<QDBusInterface> interface(new QDBusInterface(msyncdService, msyncdObject, msyncdInterface, conn));
|
|
if (!interface->isValid()) {
|
|
QString error = interface->lastError().message();
|
|
return false;
|
|
}
|
|
|
|
// add watcher for watching unregistering service
|
|
std::auto_ptr<QDBusServiceWatcher> dbusWatcher(new QDBusServiceWatcher(msyncdService, conn, QDBusServiceWatcher::WatchForUnregistration));
|
|
dbusWatcher->connect(dbusWatcher.get(), SIGNAL(serviceUnregistered(QString)),
|
|
this, SLOT(serviceUnregistered(QString)));
|
|
|
|
//connect signals
|
|
interface->connect(interface.get(), SIGNAL(syncStatus(QString, int, QString, int)),
|
|
this, SLOT(syncStatus(QString, int, QString, int)));
|
|
interface->connect(interface.get(), SIGNAL(resultsAvailable(QString, QString)),
|
|
this, SLOT(resultsAvailable(QString, QString)));
|
|
|
|
// start sync
|
|
QDBusReply<bool> reply = interface->call(QString("startSync"), m_server.c_str());
|
|
if (reply.isValid() && !reply.value()) {
|
|
return false;
|
|
}
|
|
|
|
// wait sync completed
|
|
return QCoreApplication::exec() == 0;
|
|
}
|
|
|
|
void ButeoTest::genSyncResults(const QString &text, SyncReport *report)
|
|
{
|
|
QDomDocument domResults;
|
|
if (domResults.setContent(text, true)) {
|
|
SyncResults syncResults(domResults.documentElement());
|
|
switch(syncResults.majorCode()) {
|
|
case SyncResults::SYNC_RESULT_SUCCESS:
|
|
report->setStatus(STATUS_OK);
|
|
break;
|
|
case SyncResults::SYNC_RESULT_FAILED:
|
|
report->setStatus(STATUS_FATAL);
|
|
break;
|
|
case SyncResults::SYNC_RESULT_CANCELLED:
|
|
report->setStatus(STATUS_FATAL);
|
|
break;
|
|
};
|
|
QList<TargetResults> targetResults = syncResults.targetResults();
|
|
QListIterator<TargetResults> it(targetResults);
|
|
while (it.hasNext()) {
|
|
// get item sync info
|
|
TargetResults target = it.next();
|
|
SyncSourceReport targetReport;
|
|
// temporary set this mode due to no this information in report
|
|
targetReport.recordFinalSyncMode(m_options.m_syncMode);
|
|
ItemCounts itemCounts = target.localItems();
|
|
targetReport.setItemStat(SyncSourceReport::ITEM_LOCAL,
|
|
SyncSourceReport::ITEM_ADDED,
|
|
SyncSourceReport::ITEM_TOTAL,
|
|
itemCounts.added);
|
|
targetReport.setItemStat(SyncSourceReport::ITEM_LOCAL,
|
|
SyncSourceReport::ITEM_UPDATED,
|
|
SyncSourceReport::ITEM_TOTAL,
|
|
itemCounts.modified);
|
|
targetReport.setItemStat(SyncSourceReport::ITEM_LOCAL,
|
|
SyncSourceReport::ITEM_REMOVED,
|
|
SyncSourceReport::ITEM_TOTAL,
|
|
itemCounts.deleted);
|
|
|
|
// get item info for remote
|
|
itemCounts = target.remoteItems();
|
|
targetReport.setItemStat(SyncSourceReport::ITEM_REMOTE,
|
|
SyncSourceReport::ITEM_ADDED,
|
|
SyncSourceReport::ITEM_TOTAL,
|
|
itemCounts.added);
|
|
targetReport.setItemStat(SyncSourceReport::ITEM_REMOTE,
|
|
SyncSourceReport::ITEM_UPDATED,
|
|
SyncSourceReport::ITEM_TOTAL,
|
|
itemCounts.modified);
|
|
targetReport.setItemStat(SyncSourceReport::ITEM_REMOTE,
|
|
SyncSourceReport::ITEM_REMOVED,
|
|
SyncSourceReport::ITEM_TOTAL,
|
|
itemCounts.deleted);
|
|
// set to sync report
|
|
report->addSyncSourceReport(target.targetName().toStdString(), targetReport);
|
|
}
|
|
} else {
|
|
report->setStatus(STATUS_FATAL);
|
|
}
|
|
}
|
|
|
|
void ButeoTest::syncStatus(QString profile, int status, QString message, int moreDetails)
|
|
{
|
|
if (profile == m_server.c_str()) {
|
|
switch(status) {
|
|
case 0: // QUEUED
|
|
case 1: // STARTED
|
|
case 2: // PROGRESS
|
|
break;
|
|
case 3: // ERROR
|
|
case 5: // ABORTED
|
|
QCoreApplication::exit(1);
|
|
break;
|
|
case 4: // DONE
|
|
QCoreApplication::exit(0);
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ButeoTest::resultsAvailable(QString profile, QString syncResults)
|
|
{
|
|
if (profile == m_server.c_str()) {
|
|
m_syncResults = syncResults;
|
|
}
|
|
}
|
|
|
|
void ButeoTest::serviceUnregistered(QString service)
|
|
{
|
|
QCoreApplication::exit(1);
|
|
}
|
|
|
|
bool ButeoTest::inclContacts()
|
|
{
|
|
set<string>::iterator sit = m_configedSources.find("hcontacts");
|
|
if (sit != m_configedSources.end()) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ButeoTest::writeToFile(const QString &filePath, const QString &content)
|
|
{
|
|
// clear tempoary file firstly
|
|
stringstream rmCmd;
|
|
rmCmd << "rm -f " << filePath.toStdString() << "_tmp";
|
|
execCmd(rmCmd.str(), false);
|
|
|
|
// open temporary file and serialize dom to the file
|
|
QFile file(filePath + "_tmp");
|
|
if (!file.open(QIODevice::WriteOnly)) {
|
|
stringstream msg;
|
|
msg << "can't open file '" << filePath.toStdString() << "' with 'write' mode";
|
|
throw runtime_error(msg.str());
|
|
}
|
|
if (file.write(content.toUtf8()) == -1) {
|
|
file.close();
|
|
stringstream msg;
|
|
msg << "can't write file '" << filePath.toStdString() << "'";
|
|
throw runtime_error(msg.str());
|
|
}
|
|
file.close();
|
|
|
|
// move temp file to destination file
|
|
stringstream mvCmd;
|
|
mvCmd << "mv " << filePath.toStdString() << "_tmp "
|
|
<< filePath.toStdString();
|
|
execCmd(mvCmd.str());
|
|
}
|
|
|
|
void ButeoTest::replaceElement(QString &xml, const QString &elem, const QString &value)
|
|
{
|
|
// TODO: use DOM to parse xml
|
|
// currently this could work
|
|
QString startTag = "<" + elem +">";
|
|
QString endTag = "</" + elem +">";
|
|
|
|
int start = xml.indexOf(startTag);
|
|
if ( start == -1) {
|
|
return;
|
|
}
|
|
int end = xml.indexOf(endTag, start);
|
|
int pos = start + startTag.size();
|
|
|
|
xml.replace(pos, end - pos, value);
|
|
}
|
|
|
|
void ButeoTest::buildDomFromFile(QDomDocument &doc, const QString &filePath)
|
|
{
|
|
// open it
|
|
QFile file(filePath);
|
|
if (!file.open(QIODevice::ReadOnly)) {
|
|
stringstream msg;
|
|
msg << "can't open profile file '" << filePath.toStdString() << "'";
|
|
throw runtime_error(msg.str());
|
|
}
|
|
|
|
// parse it
|
|
if (!doc.setContent(&file)) {
|
|
file.close();
|
|
stringstream msg;
|
|
msg << "can't parse profile file '" << filePath.toStdString() << "'";
|
|
throw runtime_error(msg.str());
|
|
}
|
|
file.close();
|
|
}
|
|
|
|
static bool isButeo()
|
|
{
|
|
static bool checked = false;
|
|
static bool useButeo = false;
|
|
|
|
if (!checked) {
|
|
const char *buteo = getenv("CLIENT_TEST_BUTEO");
|
|
if (buteo &&
|
|
(boost::equals(buteo, "1") || boost::iequals(buteo, "t"))) {
|
|
useButeo = true;
|
|
}
|
|
checked = true;
|
|
}
|
|
|
|
return useButeo;
|
|
}
|
|
|
|
string QtContactsSwitcher::getId(ClientTest &client) {
|
|
if (client.getClientB()) {
|
|
return "1";
|
|
}
|
|
return "2";
|
|
}
|
|
|
|
void QtContactsSwitcher::prepare(ClientTest &client) {
|
|
// check if version of tracker is equal or greater than 0.9.26
|
|
// set tracker databases according it's version
|
|
FILE *fp;
|
|
int version;
|
|
char cmd[] = "tracker-control -V | awk 'NR==2 {print $2}' | awk '{split($0,A,\".\"); X=256*256*A[1]+256*A[2]+A[3];print X;}'";
|
|
char buffer[10];
|
|
fp = popen(cmd,"r");
|
|
fgets(buffer,sizeof(buffer),fp);
|
|
sscanf(buffer,"%d", &version);
|
|
pclose(fp);
|
|
if (version >= 2330) {
|
|
QtContactsSwitcher::setDatabases(trackerdb_new);
|
|
} else {
|
|
QtContactsSwitcher::setDatabases(trackerdb_old);
|
|
}
|
|
|
|
int index = 0;
|
|
for (int i = 0; i < sizeof(m_databases)/sizeof(m_databases[0]); i++) {
|
|
if (m_databases[i].empty()) {
|
|
index++;
|
|
continue;
|
|
}
|
|
|
|
stringstream cmd;
|
|
cmd << "rm -f " << getDatabasePath(index) << m_databases[i]
|
|
<< "_";
|
|
execCmd(cmd.str() + "1", false);
|
|
execCmd(cmd.str() + "2", false);
|
|
}
|
|
execCmd("tracker-control -r", false);
|
|
}
|
|
|
|
void QtContactsSwitcher::restoreStorage(ClientTest &client)
|
|
{
|
|
// if CLIENT_TEST_BUTEO is not enabled, skip it for LocalTests may also use it
|
|
if (!isButeo()) {
|
|
return;
|
|
}
|
|
|
|
string id = getId(client);
|
|
terminate();
|
|
copyDatabases(client, false);
|
|
start();
|
|
}
|
|
|
|
void QtContactsSwitcher::backupStorage(ClientTest &client)
|
|
{
|
|
// if CLIENT_TEST_BUTEO is not enabled, skip it for LocalTests may also use it
|
|
if (!isButeo()) {
|
|
return;
|
|
}
|
|
|
|
string id = getId(client);
|
|
terminate();
|
|
copyDatabases(client);
|
|
start();
|
|
}
|
|
|
|
void QtContactsSwitcher::setDatabases(const string databases[])
|
|
{
|
|
for (int i = 0; i < sizeof(m_databases)/sizeof(m_databases[0]); i++) {
|
|
m_databases[i] = databases[i];
|
|
}
|
|
}
|
|
string QtContactsSwitcher::getDatabasePath(int index)
|
|
{
|
|
string m_path = getHome() + m_dirs[index];
|
|
return m_path;
|
|
}
|
|
|
|
void QtContactsSwitcher::copyDatabases(ClientTest &client, bool fromDefault)
|
|
{
|
|
static string m_cmds[] = {"",
|
|
"",
|
|
"",
|
|
"",
|
|
"\"delete from deleteditems;\""};
|
|
|
|
string id = getId(client);
|
|
|
|
int index = 0;
|
|
for (int i = 0; i < sizeof(m_databases)/sizeof(m_databases[0]); i++) {
|
|
if (m_databases[i].empty()) {
|
|
index++;
|
|
continue;
|
|
}
|
|
string src = getDatabasePath(index) + m_databases[i];
|
|
string dest = src + "_" + id;
|
|
if (!fromDefault) {
|
|
// in this case, we copy *_1/2.db to default db
|
|
// if *_1/2.db doesn't exist, we copy default with initial commands
|
|
if (access(dest.c_str(), F_OK) < 0) {
|
|
if (access(src.c_str(), F_OK) >= 0) {
|
|
if (!m_cmds[i].empty()) {
|
|
stringstream temp;
|
|
temp << "sqlite3 " << src << " " << m_cmds[i];
|
|
execCmd(temp.str(), false);
|
|
}
|
|
}
|
|
} else {
|
|
string tmp = src;
|
|
src = dest;
|
|
dest = tmp;
|
|
}
|
|
}
|
|
stringstream cmd;
|
|
cmd << "cp -f " << src << " " << dest;
|
|
execCmd(cmd.str(), false);
|
|
}
|
|
}
|
|
|
|
void QtContactsSwitcher::terminate()
|
|
{
|
|
execCmd("tracker-control -t");
|
|
}
|
|
|
|
void QtContactsSwitcher::start()
|
|
{
|
|
// sleep one second to let tracker daemon get prepared
|
|
execCmd("tracker-control -s");
|
|
execCmd("sleep 2");
|
|
}
|