HaikuDepot: Move repo fetch to background worker thread.

- Factor out functions for refreshing the repositories and
  retrieving the package lists.

- Add a background worker thread which handles those tasks and
  then notifies the window when the model is ready.

- Check if we already have a repository cache, and if so, skip the
  refresh step, unless forced. The latter will eventually be possible
  via the UI.
This commit is contained in:
Rene Gollent
2013-09-18 18:39:32 +02:00
parent 2c287f5bae
commit d882cc2812
2 changed files with 85 additions and 16 deletions
+73 -10
View File
@@ -26,6 +26,7 @@
#include <package/Context.h> #include <package/Context.h>
#include <package/RefreshRepositoryRequest.h> #include <package/RefreshRepositoryRequest.h>
#include <package/PackageRoster.h> #include <package/PackageRoster.h>
#include "package/RepositoryCache.h"
#include <package/solver/SolverPackage.h> #include <package/solver/SolverPackage.h>
#include "DecisionProvider.h" #include "DecisionProvider.h"
@@ -40,6 +41,11 @@
#define B_TRANSLATION_CONTEXT "MainWindow" #define B_TRANSLATION_CONTEXT "MainWindow"
enum {
MSG_MODEL_WORKER_DONE = 'mmwd'
};
using namespace BPackageKit; using namespace BPackageKit;
@@ -53,10 +59,10 @@ MainWindow::MainWindow(BRect frame)
BWindow(frame, B_TRANSLATE_SYSTEM_NAME("HaikuDepot"), BWindow(frame, B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
fPackageManager(B_PACKAGE_INSTALLATION_LOCATION_HOME) fPackageManager(B_PACKAGE_INSTALLATION_LOCATION_HOME),
fTerminating(false),
fModelWorker(B_BAD_THREAD_ID)
{ {
_InitModel();
BMenuBar* menuBar = new BMenuBar(B_TRANSLATE("Main Menu")); BMenuBar* menuBar = new BMenuBar(B_TRANSLATE("Main Menu"));
_BuildMenu(menuBar); _BuildMenu(menuBar);
@@ -83,12 +89,21 @@ MainWindow::MainWindow(BRect frame)
fSplitView->SetCollapsible(0, false); fSplitView->SetCollapsible(0, false);
fSplitView->SetCollapsible(1, false); fSplitView->SetCollapsible(1, false);
_AdoptModel(); fModelWorker = spawn_thread(&_RefreshModelThreadWorker, "model loader",
B_LOW_PRIORITY, this);
if (fModelWorker > 0)
resume_thread(fModelWorker);
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
fTerminating = true;
if (fModelWorker > 0) {
status_t result;
wait_for_thread(fModelWorker, &result);
}
} }
@@ -107,6 +122,12 @@ void
MainWindow::MessageReceived(BMessage* message) MainWindow::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case MSG_MODEL_WORKER_DONE:
{
fModelWorker = B_BAD_THREAD_ID;
_AdoptModel();
break;
}
case B_SIMPLE_DATA: case B_SIMPLE_DATA:
case B_REFS_RECEIVED: case B_REFS_RECEIVED:
// TODO: ? // TODO: ?
@@ -206,23 +227,20 @@ MainWindow::_ClearPackage()
void void
MainWindow::_InitModel() MainWindow::_RefreshRepositories(bool force)
{ {
BPackageRoster roster; BPackageRoster roster;
BStringList repositoryNames; BStringList repositoryNames;
status_t result = roster.GetRepositoryNames(repositoryNames);
// TODO: notify user status_t result = roster.GetRepositoryNames(repositoryNames);
if (result != B_OK) if (result != B_OK)
return; return;
DepotInfoMap depots;
DecisionProvider decisionProvider; DecisionProvider decisionProvider;
JobStateListener listener; JobStateListener listener;
BContext context(decisionProvider, listener); BContext context(decisionProvider, listener);
BRepositoryCache cache;
for (int32 i = 0; i < repositoryNames.CountStrings(); ++i) { for (int32 i = 0; i < repositoryNames.CountStrings(); ++i) {
const BString& repoName = repositoryNames.StringAt(i); const BString& repoName = repositoryNames.StringAt(i);
BRepositoryConfig repoConfig; BRepositoryConfig repoConfig;
@@ -232,13 +250,32 @@ MainWindow::_InitModel()
continue; continue;
} }
if (roster.GetRepositoryCache(repoName, &cache) != B_OK
|| force) {
BRefreshRepositoryRequest refreshRequest(context, repoConfig); BRefreshRepositoryRequest refreshRequest(context, repoConfig);
result = refreshRequest.Process(); result = refreshRequest.Process();
if (result != B_OK) { if (result != B_OK) {
// TODO: notify user // TODO: notify user
continue; continue;
} }
}
}
}
void
MainWindow::_RefreshPackageList()
{
BPackageRoster roster;
BStringList repositoryNames;
status_t result = roster.GetRepositoryNames(repositoryNames);
if (result != B_OK)
return;
DepotInfoMap depots;
for (int32 i = 0; i < repositoryNames.CountStrings(); i++) {
const BString& repoName = repositoryNames.StringAt(i);
depots[repoName] = DepotInfo(repoName); depots[repoName] = DepotInfo(repoName);
} }
@@ -317,6 +354,10 @@ MainWindow::_InitModel()
} }
} }
BAutolock lock(fModel.Lock());
fModel.Clear();
for (DepotInfoMap::iterator it = depots.begin(); it != depots.end(); for (DepotInfoMap::iterator it = depots.begin(); it != depots.end();
++it) { ++it) {
fModel.AddDepot(it->second); fModel.AddDepot(it->second);
@@ -332,3 +373,25 @@ MainWindow::_InitModel()
} }
} }
} }
status_t
MainWindow::_RefreshModelThreadWorker(void* arg)
{
MainWindow* mainWindow = reinterpret_cast<MainWindow*>(arg);
BMessenger messenger(mainWindow);
mainWindow->_RefreshRepositories();
if (mainWindow->fTerminating)
return B_OK;
mainWindow->_RefreshPackageList();
messenger.SendMessage(MSG_MODEL_WORKER_DONE);
return B_OK;
}
+7 -1
View File
@@ -38,7 +38,10 @@ private:
void _AdoptPackage(const PackageInfoRef& package); void _AdoptPackage(const PackageInfoRef& package);
void _ClearPackage(); void _ClearPackage();
void _InitModel(); void _RefreshRepositories(bool force = false);
void _RefreshPackageList();
static status_t _RefreshModelThreadWorker(void* arg);
private: private:
FilterView* fFilterView; FilterView* fFilterView;
@@ -51,6 +54,9 @@ private:
PackageManager PackageManager
fPackageManager; fPackageManager;
bool fTerminating;
thread_id fModelWorker;
}; };
#endif // MAIN_WINDOW_H #endif // MAIN_WINDOW_H