ip2cloader.cpp
1 #include "ip2cloader.h"
2 
3 #include "configuration/doomseekerconfig.h"
4 #include "doomseekerfilepaths.h"
5 #include "ip2c/ip2c.h"
6 #include "ip2c/ip2cparser.h"
7 #include "ip2c/ip2cupdater.h"
8 #include "global.h"
9 #include "log.h"
10 #include <QFile>
11 #include <QTimer>
12 
13 DClass<IP2CLoader>
14 {
15  public:
16  IP2CParser* ip2cParser;
17  IP2CUpdater* ip2cUpdater;
18  bool updateInProgress;
19 };
20 
21 DPointered(IP2CLoader)
22 
23 IP2CLoader::IP2CLoader(QObject *parent)
25 :QObject(parent)
26 {
27  d->updateInProgress = false;
28 
29  d->ip2cParser = new IP2CParser(IP2C::instance());
30  this->connect(d->ip2cParser, SIGNAL( parsingFinished(bool) ),
31  SLOT( ip2cFinishedParsing(bool) ) );
32 
33  d->ip2cUpdater = new IP2CUpdater();
34  d->ip2cUpdater->setFilePath(DoomseekerFilePaths::ip2cDatabase());
35  this->connect(d->ip2cUpdater, SIGNAL( databaseDownloadFinished(const QByteArray&) ),
36  SLOT( ip2cFinishUpdate(const QByteArray&) ) );
37  this->connect(d->ip2cUpdater, SIGNAL( downloadProgress(qint64, qint64) ),
38  SIGNAL( downloadProgress(qint64, qint64) ) );
39  this->connect(d->ip2cUpdater, SIGNAL(updateNeeded(int)),
40  SLOT(onUpdateNeeded(int)));
41 }
42 
43 IP2CLoader::~IP2CLoader()
44 {
45  if (d->ip2cParser->isParsing())
46  {
47  gLog << tr("IP2C parser is still working, awaiting stop...");
48  while (d->ip2cParser->isParsing())
49  {
50  Sleep::sleep(1);
51  }
52  }
53 
54  delete d->ip2cParser;
55  delete d->ip2cUpdater;
56 }
57 
58 void IP2CLoader::load()
59 {
60  if (gConfig.doomseeker.bIP2CountryAutoUpdate)
61  {
62  QString databasePath = DoomseekerFilePaths::ip2cDatabase();
63  d->ip2cUpdater->needsUpdate(databasePath);
64  }
65  ip2cParseDatabase();
66 }
67 
68 void IP2CLoader::onUpdateNeeded(int status)
69 {
70  if (status == IP2CUpdater::UpdateNeeded)
71  {
72  update();
73  }
74  else
75  {
76  switch (status)
77  {
78  case IP2CUpdater::UpToDate:
79  gLog << tr("IP2C update not needed.");
80  break;
81  case IP2CUpdater::UpdateCheckError:
82  gLog << tr("IP2C update errored. See log for details.");
83  break;
84  default:
85  gLog << tr("IP2C update bugged out.");
86  break;
87  }
88  ip2cJobsFinished();
89  }
90 }
91 
92 void IP2CLoader::update()
93 {
94  d->updateInProgress = true;
95  if (!d->ip2cParser->isParsing())
96  {
97  gLog << tr("Starting IP2C update.");
98  IP2C::instance()->setDataAccessLockEnabled(true);
99  d->ip2cUpdater->downloadDatabase();
100  }
101  else
102  {
103  // Delay in hope that parser finishes
104  gLog << tr("IP2C update must wait until parsing of current database finishes. "
105  "Waiting 1 second");
106  QTimer::singleShot(1000, this, SLOT(update()));
107  }
108 }
109 
110 void IP2CLoader::ip2cFinishUpdate(const QByteArray& downloadedData)
111 {
112  d->updateInProgress = false;
113  if (!downloadedData.isEmpty())
114  {
115  gLog << tr("IP2C database finished downloading.");
116  QString filePath = DoomseekerFilePaths::ip2cDatabase();
117  d->ip2cUpdater->getRollbackData();
118  if (!d->ip2cUpdater->saveDownloadedData())
119  {
120  gLog << tr("Unable to save IP2C database at path: %1").arg(filePath);
121  }
122  ip2cParseDatabase();
123  }
124  else
125  {
126  gLog << tr("IP2C download has failed.");
127  ip2cJobsFinished();
128  }
129 }
130 
131 void IP2CLoader::ip2cFinishedParsing(bool bSuccess)
132 {
133  QString filePath = DoomseekerFilePaths::ip2cDatabase();
134 
135  if (!bSuccess)
136  {
137  gLog << tr("Failed to read IP2C database. Reverting...");
138 
139  if (d->ip2cUpdater == NULL || !d->ip2cUpdater->hasRollbackData())
140  {
141  gLog << tr("IP2C revert attempt failed. Nothing to go back to.");
142 
143  // Delete file in this case.
144  QFile file(filePath);
145  file.remove();
146 
147  gLog << tr("Using precompiled IP2C database.");
148  d->ip2cParser->readDatabaseThreaded(DoomseekerFilePaths::IP2C_QT_SEARCH_PATH);
149  }
150  else
151  {
152  // Revert to old content.
153  d->ip2cUpdater->rollback();
154 
155  // Must succeed now.
156  d->ip2cParser->readDatabaseThreaded(filePath);
157  }
158  }
159  else
160  {
161  gLog << tr("IP2C parsing finished.");
162  ip2cJobsFinished();
163  }
164 }
165 
166 void IP2CLoader::ip2cJobsFinished()
167 {
168  if (!d->ip2cUpdater->isWorking() && !d->ip2cParser->isParsing() && !d->updateInProgress)
169  {
170  IP2C::instance()->setDataAccessLockEnabled(false);
171  emit finished();
172  }
173 }
174 
175 void IP2CLoader::ip2cParseDatabase()
176 {
177  QString filePath = DoomseekerFilePaths::IP2C_QT_SEARCH_PATH;
178 
179  gLog << tr("Please wait. IP2C database is being read. This may take some time.");
180  // Attempt to read IP2C database.
181 
182  IP2C::instance()->setDataAccessLockEnabled(true);
183  d->ip2cParser->readDatabaseThreaded(filePath);
184 }
IP2CUpdater is responsible for downloading a new version of database from the site.
Definition: ip2cupdater.h:40