kpilot Library API Documentation

hotSync.cc

00001 /* hotSync.cc KPilot 00002 ** 00003 ** Copyright (C) 2001 by Dan Pilone 00004 ** 00005 ** This file defines SyncActions, which are used to perform some specific 00006 ** task during a HotSync. Conduits are not included here, nor are 00007 ** sync actions requiring user interaction. Those can be found in the 00008 ** conduits subdirectory or interactiveSync.h. 00009 */ 00010 00011 /* 00012 ** This program is free software; you can redistribute it and/or modify 00013 ** it under the terms of the GNU General Public License as published by 00014 ** the Free Software Foundation; either version 2 of the License, or 00015 ** (at your option) any later version. 00016 ** 00017 ** This program is distributed in the hope that it will be useful, 00018 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 ** GNU General Public License for more details. 00021 ** 00022 ** You should have received a copy of the GNU General Public License 00023 ** along with this program in a file called COPYING; if not, write to 00024 ** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 00025 ** MA 02111-1307, USA. 00026 */ 00027 00028 /* 00029 ** Bug reports and questions can be sent to kde-pim@kde.org. 00030 */ 00031 00032 static const char *hotsync_id = 00033 "$Id: hotSync.cc,v 1.27.4.1 2004/03/26 22:47:02 adridg Exp $"; 00034 00035 #include "options.h" 00036 00037 #include <time.h> 00038 #include <unistd.h> 00039 00040 #include <pi-file.h> 00041 00042 #include <qtimer.h> 00043 #include <qfile.h> 00044 #include <qfileinfo.h> 00045 #include <qdir.h> 00046 #include <qvaluelist.h> 00047 #include <qregexp.h> 00048 #include <qtextcodec.h> 00049 00050 #include <kglobal.h> 00051 #include <kstandarddirs.h> 00052 #include <kapplication.h> 00053 00054 #include "pilotUser.h" 00055 #include "pilotAppCategory.h" 00056 #include "syncStack.h" 00057 #include "pilotSerialDatabase.h" 00058 #include "pilotLocalDatabase.h" 00059 #include "pilotDatabase.h" 00060 #include "kpilotConfig.h" 00061 00062 #include "hotSync.moc" 00063 00064 TestLink::TestLink(KPilotDeviceLink * p) : 00065 SyncAction(p, "testLink") 00066 { 00067 FUNCTIONSETUP; 00068 00069 (void) hotsync_id; 00070 } 00071 00072 /* virtual */ bool TestLink::exec() 00073 { 00074 FUNCTIONSETUP; 00075 00076 int i; 00077 int dbindex = 0; 00078 int count = 0; 00079 struct DBInfo db; 00080 00081 addSyncLogEntry(i18n("Testing.\n")); 00082 00083 #ifdef BRUTE_FORCE 00084 for (i=0; i<32; i++) 00085 #else 00086 while ((i = fHandle->getNextDatabase(dbindex,&db)) > 0) 00087 #endif 00088 { 00089 #ifdef BRUTE_FORCE 00090 if (fHandle->getNextDatabase(i,&db) < 1) 00091 { 00092 DEBUGKPILOT << fname << ": No database index " << i << endl; 00093 continue; 00094 } 00095 #endif 00096 00097 count++; 00098 dbindex = db.index + 1; 00099 00100 #ifdef DEBUG 00101 DEBUGKPILOT << fname << ": Read database " << db.name << endl; 00102 #endif 00103 00104 // Let the Pilot User know what's happening 00105 openConduit(); 00106 // Let the KDE User know what's happening 00107 // Pretty sure all database names are in latin1. 00108 emit logMessage(i18n("Syncing database %1...") 00109 .arg(QString::fromLatin1(db.name))); 00110 00111 kapp->processEvents(); 00112 } 00113 00114 emit logMessage(i18n("HotSync finished.")); 00115 emit syncDone(this); 00116 return true; 00117 } 00118 00119 BackupAction::BackupAction(KPilotDeviceLink * p, int mode) : 00120 SyncAction(p, "backupAction"), fMode(mode), fFullBackup(mode & ActionQueue::FlagFull) 00121 { 00122 FUNCTIONSETUP; 00123 00124 fDatabaseDir = KGlobal::dirs()->saveLocation("data", 00125 CSL1("kpilot/DBBackup/")); 00126 } 00127 00128 /* virtual */ QString BackupAction::statusString() const 00129 { 00130 FUNCTIONSETUP; 00131 QString s(CSL1("BackupAction=")); 00132 00133 switch (status()) 00134 { 00135 case Init: 00136 s.append(CSL1("Init")); 00137 break; 00138 case Error: 00139 s.append(CSL1("Error")); 00140 break; 00141 case FullBackup: 00142 s.append(CSL1("FullBackup")); 00143 break; 00144 case FastBackup: 00145 s.append(CSL1("FastBackup")); 00146 break; 00147 case BackupEnded: 00148 s.append(CSL1("BackupEnded")); 00149 break; 00150 case BackupIncomplete: 00151 s.append(CSL1("BackupIncomplete")); 00152 break; 00153 case BackupComplete: 00154 s.append(CSL1("BackupComplete")); 00155 break; 00156 default: 00157 s.append(CSL1("(unknown ")); 00158 s.append(QString::number(status())); 00159 s.append(CSL1(")")); 00160 } 00161 00162 return s; 00163 } 00164 00165 00166 /* virtual */ bool BackupAction::exec() 00167 { 00168 FUNCTIONSETUP; 00169 00170 #ifdef DEBUG 00171 DEBUGDAEMON << fname 00172 << ": This Pilot user's name is \"" 00173 << fHandle->getPilotUser()->getUserName() << "\"" << endl; 00174 #endif 00175 00176 fBackupDir = 00177 fDatabaseDir + 00178 PilotAppCategory::codec()->toUnicode(fHandle->getPilotUser()->getUserName()) + 00179 CSL1("/"); 00180 00181 if (fFullBackup) 00182 { 00183 fStatus = FullBackup; 00184 addSyncLogEntry(i18n("Full backup started.")); 00185 } 00186 else 00187 { 00188 fStatus = FastBackup; 00189 addSyncLogEntry(i18n("Fast backup started")); 00190 } 00191 00192 if (!checkBackupDirectory(fBackupDir)) 00193 { 00194 fStatus=BackupIncomplete; 00195 // Don't issue an error message, checkBackupDirectory 00196 // did this already... 00197 return false; 00198 } 00199 00200 fTimer = new QTimer(this); 00201 QObject::connect(fTimer, SIGNAL(timeout()), 00202 this, SLOT(backupOneDB())); 00203 00204 fDBIndex = 0; 00205 00206 fTimer->start(0, false); 00207 return true; 00208 } 00209 00210 bool BackupAction::checkBackupDirectory(QString backupDir) 00211 { 00212 FUNCTIONSETUP; 00213 QFileInfo fi(backupDir); 00214 00215 if (!(fi.exists() && fi.isDir())) 00216 { 00217 #ifdef DEBUG 00218 DEBUGDAEMON << fname 00219 << ": Need to create backup directory for user " 00220 << fHandle->getPilotUser()->getUserName() << endl; 00221 #endif 00222 00223 fi = QFileInfo(fDatabaseDir); 00224 if (!(fi.exists() && fi.isDir())) 00225 { 00226 kdError() << k_funcinfo 00227 << ": Database backup directory " 00228 << "doesn't exist." 00229 << endl; 00230 return false; 00231 } 00232 00233 QDir databaseDir(backupDir); 00234 00235 if (!databaseDir.mkdir(backupDir, true)) 00236 { 00237 kdError() << k_funcinfo 00238 << ": Can't create backup directory." << endl; 00239 return false; 00240 } 00241 } 00242 return true; 00243 } 00244 00245 00246 /* slot */ void BackupAction::backupOneDB() 00247 { 00248 FUNCTIONSETUP; 00249 00250 struct DBInfo info; 00251 00252 emit logProgress(QString::null, fDBIndex); 00253 00254 if (openConduit() < 0) 00255 { 00256 #ifdef DEBUG 00257 DEBUGDAEMON << fname 00258 << ": openConduit failed. User cancel?" << endl; 00259 #endif 00260 00261 addSyncLogEntry(i18n("Exiting on cancel.")); 00262 endBackup(); 00263 fStatus = BackupIncomplete; 00264 return; 00265 } 00266 00267 // TODO: Is there a way to skip unchanged databases? 00268 int res=fHandle->getNextDatabase(fDBIndex, &info); 00269 if (res < 0) 00270 { 00271 #ifdef DEBUG 00272 DEBUGDAEMON << fname << ": Backup complete." << endl; 00273 #endif 00274 00275 if (fFullBackup) 00276 addSyncLogEntry(i18n("Full backup complete.")); 00277 else 00278 addSyncLogEntry(i18n("Fast backup complete.")); 00279 endBackup(); 00280 fStatus = BackupComplete; 00281 return; 00282 } 00283 00284 fDBIndex = info.index + 1; 00285 00286 QStringList nobackupdb = KPilotConfig::getConfig().getNoBackupDatabases(); 00287 QStringList match = nobackupdb.grep(QString::fromLatin1(info.name)); 00288 if (match.isEmpty()) 00289 { 00290 00291 // Pretty sure all database names are latin1. 00292 QString s = i18n("Backing up: %1") 00293 .arg(QString::fromLatin1(info.name)); 00294 addSyncLogEntry(s); 00295 00296 if (!createLocalDatabase(&info)) 00297 { 00298 kdError() << k_funcinfo 00299 << ": Couldn't create local database for " 00300 << info.name << endl; 00301 addSyncLogEntry(i18n("Backup of %1 failed.\n") 00302 .arg(QString::fromLatin1(info.name))); 00303 } 00304 else 00305 { 00306 addSyncLogEntry(i18n(" .. OK\n"),false); // Not in kpilot log. 00307 } 00308 } 00309 else 00310 { 00311 QString s = CSL1("Skipping %1") 00312 .arg(QString::fromLatin1(info.name)); 00313 addSyncLogEntry(s); 00314 } 00315 00316 } 00317 00318 bool BackupAction::createLocalDatabase(DBInfo * info) 00319 { 00320 FUNCTIONSETUP; 00321 00322 #ifdef DEBUG 00323 DEBUGDAEMON << fname 00324 << ": Looking in directory " << fBackupDir << endl; 00325 #endif 00326 00327 QString databaseName(QString::fromLatin1(info->name)); 00328 if (!fFullBackup) 00329 { 00330 // open the serial db first so that the local db is not read into memory 00331 // in case of an error 00332 PilotSerialDatabase*serial=new PilotSerialDatabase(pilotSocket(), databaseName); 00333 if (serial->isDBOpen()) 00334 { 00335 PilotLocalDatabase*local=new PilotLocalDatabase(fBackupDir, databaseName); 00336 if (local->isDBOpen()) 00337 { 00338 // Now walk through all modified records 00339 int index=0; 00340 PilotRecord*rec=serial->readNextModifiedRec(&index); 00341 while (rec) 00342 { 00343 local->writeRecord(rec); 00344 KPILOT_DELETE(rec); 00345 rec=serial->readNextModifiedRec(&index); 00346 } 00347 KPILOT_DELETE(local); 00348 KPILOT_DELETE(serial); 00349 return true; 00350 } 00351 KPILOT_DELETE(local); 00352 } 00353 KPILOT_DELETE(serial); 00354 #ifdef DEBUG 00355 DEBUGCONDUIT<<"Fast backup not possible with database "<<info->name<<". Will do full backup on it"<<endl; 00356 #endif 00357 } 00358 00359 // Either we want a full backup, or fast backup encoutered a problem 00360 // Just fetch the database to the backup dir 00361 if (!checkBackupDirectory(fBackupDir)) return false; 00362 00363 #if QT_VERSION < 0x30100 00364 databaseName.replace(QRegExp(CSL1("/")), CSL1("_")); 00365 #else 00366 databaseName.replace('/', CSL1("_")); 00367 #endif 00368 00369 QString fullBackupName = fBackupDir + databaseName; 00370 00371 if (info->flags & dlpDBFlagResource) 00372 { 00373 fullBackupName.append(CSL1(".prc")); 00374 } 00375 else 00376 { 00377 fullBackupName.append(CSL1(".pdb")); 00378 } 00379 00380 #ifdef DEBUG 00381 DEBUGDB << fname 00382 << ": Creating local database " << fullBackupName << endl; 00383 #endif 00384 00385 /* Ensure that DB-open flag is not kept */ 00386 info->flags &= ~dlpDBFlagOpen; 00387 00388 return fHandle->retrieveDatabase(fullBackupName,info); 00389 } 00390 00391 void BackupAction::endBackup() 00392 { 00393 FUNCTIONSETUP; 00394 00395 KPILOT_DELETE(fTimer); 00396 fDBIndex = (-1); 00397 fStatus = BackupEnded; 00398 00399 emit syncDone(this); 00400 } 00401 00402 FileInstallAction::FileInstallAction(KPilotDeviceLink * p, 00403 const QString & d, 00404 const QStringList & l) : 00405 SyncAction(p, "fileInstall"), 00406 fDBIndex(-1), 00407 fTimer(0L), 00408 fDir(d), 00409 fList(l) 00410 { 00411 FUNCTIONSETUP; 00412 00413 #ifdef DEBUG 00414 DEBUGDAEMON << fname << ": File list has " 00415 << fList. count() << " entries" << endl; 00416 00417 QStringList::ConstIterator i; 00418 00419 for (i = fList.begin(); i != fList.end(); ++i) 00420 { 00421 DEBUGDAEMON << fname << ": " << *i << endl; 00422 } 00423 #endif 00424 } 00425 00426 FileInstallAction::~FileInstallAction() 00427 { 00428 FUNCTIONSETUP; 00429 00430 KPILOT_DELETE(fTimer); 00431 } 00432 00433 /* virtual */ bool FileInstallAction::exec() 00434 { 00435 FUNCTIONSETUP; 00436 00437 fDBIndex = 0; 00438 00439 #ifdef DEBUG 00440 DEBUGDAEMON << fname 00441 << ": Installing " << fList.count() << " files" << endl; 00442 #endif 00443 00444 emit logMessage(i18n("[File Installer]")); 00445 00446 // Possibly no files to install? 00447 if (!fList.count()) 00448 { 00449 emit logMessage(i18n("No Files to install")); 00450 return delayDone(); 00451 } 00452 00453 fTimer = new QTimer(this); 00454 QObject::connect(fTimer, SIGNAL(timeout()), 00455 this, SLOT(installNextFile())); 00456 00457 fTimer->start(0, false); 00458 00459 emit logProgress(i18n("Installing one file", 00460 "Installing %n Files",fList.count()), 0); 00461 return true; 00462 } 00463 00464 /* slot */ void FileInstallAction::installNextFile() 00465 { 00466 FUNCTIONSETUP; 00467 00468 Q_ASSERT(fDBIndex >= 0); 00469 Q_ASSERT((unsigned) fDBIndex <= fList.count()); 00470 00471 #ifdef DEBUG 00472 DEBUGDAEMON << fname 00473 << ": Installing file index " 00474 << fDBIndex << " (of " << fList.count() << ")" << endl; 00475 #endif 00476 00477 if ((!fList.count()) || ((unsigned) fDBIndex >= fList.count())) 00478 { 00479 #ifdef DEBUG 00480 DEBUGDAEMON << fname 00481 << ": Peculiar file index, bailing out." << endl; 00482 #endif 00483 KPILOT_DELETE(fTimer); 00484 fDBIndex = (-1); 00485 emit logProgress(i18n("Done Installing Files"), 100); 00486 emit syncDone(this); 00487 return; 00488 } 00489 00490 const QString filePath = fDir + fList[fDBIndex]; 00491 const QString fileName = fList[fDBIndex]; 00492 00493 fDBIndex++; 00494 00495 #ifdef DEBUG 00496 DEBUGDAEMON << fname << ": Installing file " << filePath << endl; 00497 #endif 00498 00499 QString m = i18n("Installing %1").arg(fileName); 00500 emit logProgress(m,(100 * fDBIndex) / (fList.count()+1)); 00501 m+=QString::fromLatin1("\n"); 00502 emit addSyncLogEntry(m,true /* Don't print in KPilot's log. */ ); 00503 00504 00505 struct pi_file *f = 0L; 00506 00507 f = pi_file_open(const_cast <char *> 00508 ((const char *) QFile::encodeName(filePath))); 00509 00510 if (!f) 00511 { 00512 kdWarning() << k_funcinfo 00513 << ": Unable to open file." << endl; 00514 00515 emit logError(i18n("Unable to open file &quot;%1&quot;!"). 00516 arg(fileName)); 00517 goto nextFile; 00518 } 00519 00520 if (pi_file_install(f, pilotSocket(), 0) < 0) 00521 { 00522 kdWarning() << k_funcinfo << ": failed to install." << endl; 00523 00524 00525 emit logError(i18n("Cannot install file &quot;%1&quot;!"). 00526 arg(fileName)); 00527 } 00528 else 00529 { 00530 QFile::remove(filePath); 00531 } 00532 00533 00534 nextFile: 00535 if (f) pi_file_close(f); 00536 if (fDBIndex == -1) 00537 { 00538 emit syncDone(this); 00539 } 00540 } 00541 00542 /* virtual */ QString FileInstallAction::statusString() const 00543 { 00544 FUNCTIONSETUP; 00545 if (fDBIndex < 0) 00546 { 00547 return QString(CSL1("Idle")); 00548 } 00549 else 00550 { 00551 if ((unsigned) fDBIndex >= fList.count()) 00552 { 00553 return QString(CSL1("Index out of range")); 00554 } 00555 else 00556 { 00557 return QString(CSL1("Installing %1")).arg(fList[fDBIndex]); 00558 } 00559 } 00560 } 00561 00562 CleanupAction::CleanupAction(KPilotDeviceLink *p) : SyncAction(p,"cleanupAction") 00563 { 00564 FUNCTIONSETUP; 00565 } 00566 00567 CleanupAction::~CleanupAction() 00568 { 00569 #ifdef DEBUG 00570 FUNCTIONSETUP; 00571 DEBUGDAEMON << fname 00572 << ": Deleting @" << (int)this << endl; 00573 #endif 00574 } 00575 00576 /* virtual */ bool CleanupAction::exec() 00577 { 00578 FUNCTIONSETUP; 00579 00580 fHandle->finishSync(); 00581 emit syncDone(this); 00582 return true; 00583 } 00584 00585
KDE Logo
This file is part of the documentation for kpilot Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jul 28 23:57:48 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003