diff --git a/docs/develop/apps/haikudepot/images/process-interplay.svg b/docs/develop/apps/haikudepot/images/process-interplay.svg
new file mode 100644
index 0000000000..835e33779b
--- /dev/null
+++ b/docs/develop/apps/haikudepot/images/process-interplay.svg
@@ -0,0 +1,612 @@
+
+
+
\ No newline at end of file
diff --git a/docs/develop/apps/haikudepot/images/processes.svg b/docs/develop/apps/haikudepot/images/processes.svg
new file mode 100644
index 0000000000..d5f3c632ad
--- /dev/null
+++ b/docs/develop/apps/haikudepot/images/processes.svg
@@ -0,0 +1,173 @@
+
+
+
\ No newline at end of file
diff --git a/docs/develop/apps/haikudepot/server.md b/docs/develop/apps/haikudepot/server.md
new file mode 100644
index 0000000000..4a9b35c4c3
--- /dev/null
+++ b/docs/develop/apps/haikudepot/server.md
@@ -0,0 +1,60 @@
+# HaikuDepot and Server Interactions
+
+## Introduction
+
+This document aims to outline the general approach taken within the HaikuDepot application with regard to coordinating processes that relate to fetching and consuming data from remote systems.
+
+There are two main sources of remote data that are downloaded and consumed from network sources into the HaikuDepot desktop application;
+
+* Repository HPKR data from a Haiku mirror such as "HaikuPorts"
+* Meta-data related to packages from [HaikuDepotServer](http://depot.haiku-os.org) (HDS) such as icons, localizations, ratings and so on.
+
+## Process, ProcessNode and Coordinator
+
+A _Process_ (root class ```AbstractProcess```) is a class that takes responsibility for some aspect of pulling material down from a network source and processing it.
+
+A _ProcessNode_ is a holder for a Process, but also takes responsibility for the following;
+
+* Maintaining the relationship between the Processes. For example, if Process A needs to complete before Process B then the ProcessNode would record this fact. It does this by storing _predecessor_ and _successor_ ProcessNodes.
+* Starting the held Process in a newly spawned thread.
+* Stopping the held Process.
+
+A _Coordinator_ holds a list of ProcessNodes. It will start, stop and cancel nodes as necessary such that, in an ideal case, the various ProcessNodes are completed in the correct order.
+
+The _ProcessCoordinatorFactory_ is able to create Coordinators.
+
+## Bulk Load Processes
+
+The following diagram shows the logical dependencies of the various Processes that are involved in refreshing the HPKR data from remote repositories and then loading data from the HDS system.
+
+
+
+For example, the ```ServerRepositoryDataUpdateProcess``` must wait until the ```LocalRepositoryUpdateProcess``` has completed before it is able to be started. It is the reponsibility of the Coordinator to ensure that this sequencing is enforced. There are many instances of ```ServerPkgDataUpdateProcess``` shown because there will be one launched for each of the Repositories for which data will be downloaded; "HaikuDepot" etc...
+
+## Process / ProcessNode / Coordinator
+
+The following diagram shows the relationship and interplay between the various objects that are involved in running a larger task. Only fictional Processes are shown to keep the diagram tidy. See above for the actual Processes.
+
+
+
+Dotted lines show associations between elements and red lines show interaction or data-flow. Green arrows here demonstratively show some dependency; Process C cannot start until A and B are completed.
+
+The MainWindow owns the Coordinator for the life-span of undertaking some larger task.
+
+Each Process is coupled with a ProcessNode and then the Coordinator has a list of the ProcessNodes-s. The Processes are generally writing to the local disk system (often with compressed files) to cache data (see ```~/config/cache/HaikuDepot```) and also relay data into the ```Model``` object that maintains state for the HaikuDepot desktop application.
+
+The Processes communicate when they have finished to the Coordinator and it is at these events that the Coordinator is able to introspect the state of the Processes in order to know what to do next.
+
+The Coordinator also communicates with MainWindow. It communicates with the MainWindow in order to signal changes or progress in the overall larger task. The MainWindow also uses these events to discover when the Coordinator has completely finished.
+
+## Failure
+
+A Process may fail or be stopped. If a Process fails or is stopped then successor Processes, or those that would have run after the failed process, are stopped so that they will not run.
+
+The Coordinator will still try to complete any other Processes that could still run or are running already.
+
+Upon the Coordinator completing, the Coordinator will signal to the MainWindow client the change in state and then the MainWindow will be able to identify that the Coordinator has completed, but that something has gone wrong along the way.
+
+## Concurrency
+
+It is important to note that Processes may run concurrently. The Processes' are modelled by the Coordinator as a list rather than a tree. The dependencies are likely to form a tree or web of Processes that dictates the order of execution, but it is also quite possible to have multiple non-intersecting trees or webs such that Processes will execute independently.
diff --git a/src/apps/haikudepot/HaikuDepotConstants.h b/src/apps/haikudepot/HaikuDepotConstants.h
index edb5520b05..d251f69c20 100644
--- a/src/apps/haikudepot/HaikuDepotConstants.h
+++ b/src/apps/haikudepot/HaikuDepotConstants.h
@@ -16,13 +16,14 @@ enum {
MSG_NETWORK_TRANSPORT_ERROR = 'nett',
MSG_SERVER_ERROR = 'svre',
MSG_SERVER_DATA_CHANGED = 'svdc',
+ MSG_ALERT_SIMPLE_ERROR = 'nser',
MSG_DID_ADD_USER_RATING = 'adur',
MSG_DID_UPDATE_USER_RATING = 'upur'
};
-#define RATING_MISSING -1.0f
-#define RATING_MIN 0.0f
+#define RATING_MISSING -1.0f
+#define RATING_MIN 0.0f
#define HD_ERROR_BASE (B_ERRORS_END + 1)
@@ -32,8 +33,16 @@ enum {
#define HD_ERR_NO_DATA (HD_ERROR_BASE + 4)
-#define REPOSITORY_NAME_SYSTEM "system"
-#define REPOSITORY_NAME_INSTALLED "installed"
+#define REPOSITORY_NAME_SYSTEM "system"
+#define REPOSITORY_NAME_INSTALLED "installed"
+
+
+#define KEY_ALERT_TEXT "alert_text"
+#define KEY_ALERT_TITLE "alert_title"
+#define KEY_WORK_STATUS_TEXT "work_status_text"
+#define KEY_WORK_STATUS_PROGRESS "work_status_progress"
+#define KEY_WINDOW_SETTINGS "window_settings"
+#define KEY_MAIN_SETTINGS "main_settings"
// These constants reference resources in 'HaikuDepot.ref'
diff --git a/src/apps/haikudepot/Jamfile b/src/apps/haikudepot/Jamfile
index b659510a9e..dc76250103 100644
--- a/src/apps/haikudepot/Jamfile
+++ b/src/apps/haikudepot/Jamfile
@@ -69,8 +69,6 @@ Application HaikuDepot :
MarkupTextView.cpp
MessagePackageListener.cpp
Model.cpp
- BulkLoadContext.cpp
- BulkLoadStateMachine.cpp
PackageAction.cpp
PackageActionHandler.cpp
PackageContentsView.cpp
@@ -98,23 +96,30 @@ Application HaikuDepot :
DumpExportRepositorySource.cpp
DumpExportRepositoryJsonListener.cpp
- # network + server
+ # network + server / local processes
+ AbstractProcess.cpp
AbstractServerProcess.cpp
AbstractSingleFileServerProcess.cpp
+ LocalPkgDataLoadProcess.cpp
+ LocalRepositoryUpdateProcess.cpp
+ ProcessCoordinator.cpp
+ ProcessCoordinatorFactory.cpp
+ ProcessNode.cpp
ServerHelper.cpp
ServerSettings.cpp
- WebAppInterface.cpp
- PkgDataUpdateProcess.cpp
- RepositoryDataUpdateProcess.cpp
+ ServerPkgDataUpdateProcess.cpp
+ ServerRepositoryDataUpdateProcess.cpp
ServerIconExportUpdateProcess.cpp
StandardMetaDataJsonEventListener.cpp
StandardMetaData.cpp
+ WebAppInterface.cpp
# tar
TarArchiveHeader.cpp
TarArchiveService.cpp
#util
+ AppUtils.cpp
DataIOUtils.cpp
RepositoryUrlUtils.cpp
StorageUtils.cpp
diff --git a/src/apps/haikudepot/List.h b/src/apps/haikudepot/List.h
index 186801875f..c32651e5ab 100644
--- a/src/apps/haikudepot/List.h
+++ b/src/apps/haikudepot/List.h
@@ -1,5 +1,6 @@
/*
* Copyright 2009-2013, Stephan Aßmus
+ * Copyright 2018, Andrew Lindesay
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef LIST_H
@@ -20,12 +21,28 @@
template
class List {
typedef List SelfType;
+ typedef int32 (*CompareItemFn)(const ItemType& one, const ItemType& two);
+ typedef int32 (*CompareContextFn)(const void* context,
+ const ItemType& item);
public:
List()
:
fItems(NULL),
fCount(0),
- fAllocatedCount(0)
+ fAllocatedCount(0),
+ fCompareItemsFunction(NULL),
+ fCompareContextFunction(NULL)
+ {
+ }
+
+ List(CompareItemFn compareItemsFunction,
+ CompareContextFn compareContextFunction)
+ :
+ fItems(NULL),
+ fCount(0),
+ fAllocatedCount(0),
+ fCompareItemsFunction(compareItemsFunction),
+ fCompareContextFunction(compareContextFunction)
{
}
@@ -33,9 +50,11 @@ public:
:
fItems(NULL),
fCount(0),
- fAllocatedCount(0)
+ fAllocatedCount(0),
+ fCompareItemsFunction(other.fCompareItemsFunction),
+ fCompareContextFunction(other.fCompareContextFunction)
{
- *this = other;
+ _AddAllVerbatim(other);
}
virtual ~List()
@@ -49,29 +68,12 @@ public:
SelfType& operator=(const SelfType& other)
{
- if (this == &other)
- return *this;
-
- if (PlainOldData) {
- if (_Resize(other.fCount))
- memcpy(fItems, other.fItems, fCount * sizeof(ItemType));
- } else {
- // Make sure to call destructors of old objects.
- // NOTE: Another option would be to use
- // ItemType::operator=(const ItemType& other), but then
- // we would need to be carefull which objects are already
- // initialized. Also ItemType would be required to implement the
- // operator, while doing it this way requires only a copy
- // constructor.
- _Resize(0);
- for (uint32 i = 0; i < other.fCount; i++) {
- if (!Add(other.ItemAtFast(i)))
- break;
- }
- }
+ if (this != &other)
+ _AddAllVerbatim(other);
return *this;
}
+
bool operator==(const SelfType& other) const
{
if (this == &other)
@@ -114,64 +116,40 @@ public:
return fCount;
}
-/*! Note that the use of this method will depend on the list being ordered.
+/*! Note that the use of this method will depend on the list being sorted.
*/
- inline int32 BinarySearch(const void* context,
- int32 (*compareFunc)(const void* context, const ItemType& item))
+ inline int32 Search(const void* context) const
{
- if (fCount == 0)
+ if (fCount == 0 || fCompareContextFunction == NULL)
return -1;
- return _BinarySearchBounded(context, compareFunc, 0, fCount - 1);
+ return _BinarySearchBounded(context, 0, fCount - 1);
}
- inline bool AddOrdered(const ItemType& copyFrom,
- int32 (*compareFunc)(const ItemType& one, const ItemType& two))
- {
- // special case
- if (fCount == 0
- || compareFunc(copyFrom, ItemAtFast(fCount - 1)) > 0) {
- return Add(copyFrom);
- }
-
- return _AddOrderedBounded(copyFrom, compareFunc, 0, fCount - 1);
- }
+ /*! This function will add the item into the list. If the list is sorted
+ then the item will be insert in order. If the list is not sorted then
+ the item will be inserted at the end of the list.
+ */
inline bool Add(const ItemType& copyFrom)
{
- if (_Resize(fCount + 1)) {
- ItemType* item = fItems + fCount - 1;
- // Initialize the new object from the original.
- if (!PlainOldData)
- new (item) ItemType(copyFrom);
- else
- *item = copyFrom;
- return true;
+ if (fCompareItemsFunction != NULL) {
+ return _AddOrdered(copyFrom);
}
- return false;
+
+ return _AddTail(copyFrom);
}
inline bool Add(const ItemType& copyFrom, int32 index)
{
- if (index < 0 || index > (int32)fCount)
- return false;
+ // if the list is sorted then ignore the index and just insert in
+ // order.
+ if (fCompareItemsFunction != NULL) {
+ return _AddOrdered(copyFrom);
+ }
- if (!_Resize(fCount + 1))
- return false;
-
- int32 nextIndex = index + 1;
- if ((int32)fCount > nextIndex)
- memmove(fItems + nextIndex, fItems + index,
- (fCount - nextIndex) * sizeof(ItemType));
-
- ItemType* item = fItems + index;
- if (!PlainOldData)
- new (item) ItemType(copyFrom);
- else
- *item = copyFrom;
-
- return true;
+ return _AddAtIndex(copyFrom, index);
}
inline bool Remove()
@@ -210,6 +188,12 @@ public:
inline bool Replace(int32 index, const ItemType& copyFrom)
{
+ if (fCompareItemsFunction != NULL) {
+ bool result = Remove(index);
+ _AddOrdered(copyFrom);
+ return result;
+ }
+
if (index < 0 || index >= (int32)fCount)
return false;
@@ -259,11 +243,10 @@ public:
private:
inline int32 _BinarySearchLinearBounded(
const void* context,
- int32 (*compareFunc)(const void* context, const ItemType& item),
- int32 start, int32 end)
+ int32 start, int32 end) const
{
for(int32 i = start; i <= end; i++) {
- if (compareFunc(context, ItemAtFast(i)) == 0)
+ if (fCompareContextFunction(context, ItemAtFast(i)) == 0)
return i;
}
@@ -271,35 +254,53 @@ private:
}
inline int32 _BinarySearchBounded(
- const void* context,
- int32 (*compareFunc)(const void* context, const ItemType& item),
- int32 start, int32 end)
+ const void* context, int32 start, int32 end) const
{
if (end - start < BINARY_SEARCH_LINEAR_THRESHOLD)
- return _BinarySearchLinearBounded(context, compareFunc, start, end);
+ return _BinarySearchLinearBounded(context, start, end);
int32 mid = start + ((end - start) >> 1);
- if (compareFunc(context, ItemAtFast(mid)) >= 0)
- return _BinarySearchBounded(context, compareFunc, mid, end);
- return _BinarySearchBounded(context, compareFunc, start, mid - 1);
+ if (fCompareContextFunction(context, ItemAtFast(mid)) >= 0)
+ return _BinarySearchBounded(context, mid, end);
+ return _BinarySearchBounded(context, start, mid - 1);
}
+ inline void _AddAllVerbatim(const SelfType& other)
+ {
+ if (PlainOldData) {
+ if (_Resize(other.fCount))
+ memcpy(fItems, other.fItems, fCount * sizeof(ItemType));
+ } else {
+ // Make sure to call destructors of old objects.
+ // NOTE: Another option would be to use
+ // ItemType::operator=(const ItemType& other), but then
+ // we would need to be careful which objects are already
+ // initialized. Also ItemType would be required to implement the
+ // operator, while doing it this way requires only a copy
+ // constructor.
+ _Resize(0);
+ for (uint32 i = 0; i < other.fCount; i++) {
+ if (!Add(other.ItemAtFast(i)))
+ break;
+ }
+ }
+ }
+
+
inline bool _AddOrderedLinearBounded(
- const ItemType& copyFrom,
- int32 (*compareFunc)(const ItemType& one, const ItemType& two),
- int32 start, int32 end)
+ const ItemType& copyFrom, int32 start, int32 end)
{
for(int32 i = start; i <= (end + 1); i++) {
bool greaterBefore = (i == start)
- || (compareFunc(copyFrom, ItemAtFast(i - 1)) > 0);
+ || (fCompareItemsFunction(copyFrom, ItemAtFast(i - 1)) > 0);
if (greaterBefore) {
bool lessAfter = (i == end + 1)
- || (compareFunc(copyFrom, ItemAtFast(i)) <= 0);
+ || (fCompareItemsFunction(copyFrom, ItemAtFast(i)) <= 0);
if (lessAfter)
- return Add(copyFrom, i);
+ return _AddAtIndex(copyFrom, i);
}
}
@@ -308,18 +309,65 @@ private:
}
inline bool _AddOrderedBounded(
- const ItemType& copyFrom,
- int32 (*compareFunc)(const ItemType& one, const ItemType& two),
- int32 start, int32 end)
+ const ItemType& copyFrom, int32 start, int32 end)
{
if(end - start < BINARY_SEARCH_LINEAR_THRESHOLD)
- return _AddOrderedLinearBounded(copyFrom, compareFunc, start, end);
+ return _AddOrderedLinearBounded(copyFrom, start, end);
int32 mid = start + ((end - start) >> 1);
- if (compareFunc(copyFrom, ItemAtFast(mid)) >= 0)
- return _AddOrderedBounded(copyFrom, compareFunc, mid, end);
- return _AddOrderedBounded(copyFrom, compareFunc, start, mid - 1);
+ if (fCompareItemsFunction(copyFrom, ItemAtFast(mid)) >= 0)
+ return _AddOrderedBounded(copyFrom, mid, end);
+ return _AddOrderedBounded(copyFrom, start, mid - 1);
+ }
+
+ inline bool _AddTail(const ItemType& copyFrom)
+ {
+ if (_Resize(fCount + 1)) {
+ ItemType* item = fItems + fCount - 1;
+ // Initialize the new object from the original.
+ if (!PlainOldData)
+ new (item) ItemType(copyFrom);
+ else
+ *item = copyFrom;
+ return true;
+ }
+ return false;
+ }
+
+
+ inline bool _AddAtIndex(const ItemType& copyFrom, int32 index)
+ {
+ if (index < 0 || index > (int32)fCount)
+ return false;
+
+ if (!_Resize(fCount + 1))
+ return false;
+
+ int32 nextIndex = index + 1;
+ if ((int32)fCount > nextIndex)
+ memmove(fItems + nextIndex, fItems + index,
+ (fCount - nextIndex) * sizeof(ItemType));
+
+ ItemType* item = fItems + index;
+ if (!PlainOldData)
+ new (item) ItemType(copyFrom);
+ else
+ *item = copyFrom;
+
+ return true;
+ }
+
+
+ inline bool _AddOrdered(const ItemType& copyFrom)
+ {
+ // special case
+ if (fCount == 0
+ || fCompareItemsFunction(copyFrom, ItemAtFast(fCount - 1)) > 0) {
+ return _AddTail(copyFrom);
+ }
+
+ return _AddOrderedBounded(copyFrom, 0, fCount - 1);
}
inline bool _Resize(uint32 count)
@@ -348,10 +396,12 @@ private:
return true;
}
- ItemType* fItems;
- ItemType fNullItem;
- uint32 fCount;
- uint32 fAllocatedCount;
+ ItemType* fItems;
+ ItemType fNullItem;
+ uint32 fCount;
+ uint32 fAllocatedCount;
+ CompareItemFn fCompareItemsFunction;
+ CompareContextFn fCompareContextFunction;
};
diff --git a/src/apps/haikudepot/model/Model.cpp b/src/apps/haikudepot/model/Model.cpp
index e477bbe7ff..6b77a2bfe6 100644
--- a/src/apps/haikudepot/model/Model.cpp
+++ b/src/apps/haikudepot/model/Model.cpp
@@ -1060,39 +1060,20 @@ Model::_NotifyAuthorizationChanged()
}
+/*! This method will find the stored 'DepotInfo' that correlates to the
+ supplied 'url' and will invoke the mapper function in order to get a
+ replacement for the 'DepotInfo'. The 'url' is a unique identifier
+ for the repository that holds across mirrors.
+*/
+
void
-Model::ForAllDepots(void (*func)(const DepotInfo& depot, void* context),
+Model::ReplaceDepotByUrl(const BString& URL, DepotMapper* depotMapper,
void* context)
{
for (int32 i = 0; i < fDepots.CountItems(); i++) {
DepotInfo depotInfo = fDepots.ItemAtFast(i);
- func(depotInfo, context);
- }
-}
-
-/*! This method will find the stored 'DepotInfo' that correlates to the
- supplied 'url' or 'baseUrl' and will invoke the mapper function in
- order to get a replacement for the 'DepotInfo'. The two URLs are
- different. The 'url' is a unique identifier for the repository that
- holds across mirrors. The 'baseUrl' is the URL stem that was used
- to access the repository data in the first place. The 'baseUrl' is
- a legacy construct that exists from a time where the identifying
- 'url' was not being relayed properly.
-*/
-
-void
-Model::ReplaceDepotByUrl(
- const BString& URL,
- const BString& baseURL,
- // deprecated
- DepotMapper* depotMapper, void* context)
-{
- for (int32 i = 0; i < fDepots.CountItems(); i++) {
- DepotInfo depotInfo = fDepots.ItemAtFast(i);
-
- if (RepositoryUrlUtils::EqualsOnUrlOrBaseUrl(URL, depotInfo.URL(),
- baseURL, depotInfo.BaseURL())) {
+ if (RepositoryUrlUtils::EqualsNormalized(URL, depotInfo.URL())) {
BAutolock locker(&fLock);
fDepots.Replace(i, depotMapper->MapDepot(depotInfo, context));
}
@@ -1100,53 +1081,6 @@ Model::ReplaceDepotByUrl(
}
-void
-Model::ForAllPackages(PackageConsumer* packageConsumer, void* context)
-{
- for (int32 i = 0; i < fDepots.CountItems(); i++) {
- DepotInfo depotInfo = fDepots.ItemAtFast(i);
- PackageList packages = depotInfo.Packages();
- for(int32 j = 0; j < packages.CountItems(); j++) {
- const PackageInfoRef& packageInfoRef = packages.ItemAtFast(j);
-
- if (packageInfoRef != NULL) {
- BAutolock locker(&fLock);
- if (!packageConsumer->ConsumePackage(packageInfoRef, context))
- return;
- }
- }
- }
-}
-
-
-void
-Model::ForPackageByNameInDepot(const BString& depotName,
- const BString& packageName, PackageConsumer* packageConsumer, void* context)
-{
- int32 depotCount = fDepots.CountItems();
-
- for (int32 i = 0; i < depotCount; i++) {
- DepotInfo depotInfo = fDepots.ItemAtFast(i);
-
- if (depotInfo.Name() == depotName) {
- int32 packageIndex = depotInfo.PackageIndexByName(packageName);
-
- if (-1 != packageIndex) {
- PackageList packages = depotInfo.Packages();
- const PackageInfoRef& packageInfoRef =
- packages.ItemAtFast(packageIndex);
-
- BAutolock locker(&fLock);
- packageConsumer->ConsumePackage(packageInfoRef,
- context);
- }
-
- return;
- }
- }
-}
-
-
void
Model::LogDepotsWithNoWebAppRepositoryCode() const
{
@@ -1158,8 +1092,8 @@ Model::LogDepotsWithNoWebAppRepositoryCode() const
if (depot.WebAppRepositoryCode().Length() == 0) {
printf("depot [%s]", depot.Name().String());
- if (depot.BaseURL().Length() > 0)
- printf(" (%s)", depot.BaseURL().String());
+ if (depot.URL().Length() > 0)
+ printf(" (%s)", depot.URL().String());
printf(" correlates with no repository in the haiku"
"depot server system\n");
diff --git a/src/apps/haikudepot/model/Model.h b/src/apps/haikudepot/model/Model.h
index 52c01b1d54..3799c408f3 100644
--- a/src/apps/haikudepot/model/Model.h
+++ b/src/apps/haikudepot/model/Model.h
@@ -9,9 +9,8 @@
#include
#include
-#include "AbstractServerProcess.h"
+#include "AbstractProcess.h"
#include "LocalIconStore.h"
-#include "BulkLoadContext.h"
#include "PackageInfo.h"
#include "WebAppInterface.h"
@@ -168,24 +167,9 @@ public:
void ReplaceDepotByUrl(
const BString& URL,
- const BString& baseURL,
DepotMapper* depotMapper,
void* context);
- void ForAllDepots(
- void (*func)(const DepotInfo& depot,
- void* context),
- void* context);
-
- void ForAllPackages(PackageConsumer* packageConsumer,
- void* context);
-
- void ForPackageByNameInDepot(
- const BString& depotName,
- const BString& packageName,
- PackageConsumer* packageConsumer,
- void* context);
-
status_t IconStoragePath(BPath& path) const;
status_t DumpExportRepositoryDataPath(BPath& path) const;
status_t DumpExportPkgDataPath(BPath& path,
diff --git a/src/apps/haikudepot/model/PackageInfo.cpp b/src/apps/haikudepot/model/PackageInfo.cpp
index 24551d5693..e0ba889dde 100644
--- a/src/apps/haikudepot/model/PackageInfo.cpp
+++ b/src/apps/haikudepot/model/PackageInfo.cpp
@@ -15,7 +15,6 @@
#include
-
// #pragma mark - UserInfo
@@ -1036,13 +1035,40 @@ PackageInfo::_NotifyListenersImmediate(uint32 changes)
}
+// #pragma mark - Sorting Functions
+
+
+/*! This function is used with the List class in order to facilitate fast
+ ordered inserting of packages.
+ */
+
+static int32
+PackageCompare(const PackageInfoRef& p1, const PackageInfoRef& p2)
+{
+ return p1->Name().Compare(p2->Name());
+}
+
+
+/*! This function is used with the List class in order to facilitate fast
+ searching of packages.
+ */
+
+static int32
+PackageFixedNameCompare(const void* context,
+ const PackageInfoRef& package)
+{
+ const BString* packageName = static_cast(context);
+ return packageName->Compare(package->Name());
+}
+
+
// #pragma mark -
DepotInfo::DepotInfo()
:
fName(),
- fPackages(),
+ fPackages(&PackageCompare, &PackageFixedNameCompare),
fWebAppRepositoryCode()
{
}
@@ -1051,7 +1077,7 @@ DepotInfo::DepotInfo()
DepotInfo::DepotInfo(const BString& name)
:
fName(name),
- fPackages(),
+ fPackages(&PackageCompare, &PackageFixedNameCompare),
fWebAppRepositoryCode(),
fWebAppRepositorySourceCode()
{
@@ -1064,7 +1090,6 @@ DepotInfo::DepotInfo(const DepotInfo& other)
fPackages(other.fPackages),
fWebAppRepositoryCode(other.fWebAppRepositoryCode),
fWebAppRepositorySourceCode(other.fWebAppRepositorySourceCode),
- fBaseURL(other.fBaseURL),
fURL(other.fURL)
{
}
@@ -1075,7 +1100,6 @@ DepotInfo::operator=(const DepotInfo& other)
{
fName = other.fName;
fPackages = other.fPackages;
- fBaseURL = other.fBaseURL;
fURL = other.fURL;
fWebAppRepositoryCode = other.fWebAppRepositoryCode;
fWebAppRepositorySourceCode = other.fWebAppRepositorySourceCode;
@@ -1098,12 +1122,6 @@ DepotInfo::operator!=(const DepotInfo& other) const
}
-static int32 PackageCompare(const PackageInfoRef& p1, const PackageInfoRef& p2)
-{
- return p1->Name().Compare(p2->Name());
-}
-
-
/*! This method will insert the package into the list of packages
in order so that the list of packages remains in order.
*/
@@ -1111,23 +1129,14 @@ static int32 PackageCompare(const PackageInfoRef& p1, const PackageInfoRef& p2)
bool
DepotInfo::AddPackage(const PackageInfoRef& package)
{
- return fPackages.AddOrdered(package, &PackageCompare);
-}
-
-
-static int32
-PackageFixedNameCompare(const void* context,
- const PackageInfoRef& package)
-{
- const BString* packageName = static_cast(context);
- return packageName->Compare(package->Name());
+ return fPackages.Add(package);
}
int32
-DepotInfo::PackageIndexByName(const BString& packageName)
+DepotInfo::PackageIndexByName(const BString& packageName) const
{
- return fPackages.BinarySearch(&packageName, &PackageFixedNameCompare);
+ return fPackages.Search(&packageName);
}
@@ -1142,8 +1151,6 @@ DepotInfo::SyncPackages(const PackageList& otherPackages)
for (int32 j = packages.CountItems() - 1; j >= 0; j--) {
const PackageInfoRef& package = packages.ItemAtFast(j);
if (package->Name() == otherPackage->Name()) {
-// printf("%s: found package: '%s'\n", fName.String(),
-// package->Name().String());
package->SetState(otherPackage->State());
package->SetLocalFilePath(otherPackage->LocalFilePath());
package->SetSystemDependency(
@@ -1169,13 +1176,6 @@ DepotInfo::SyncPackages(const PackageList& otherPackages)
}
-void
-DepotInfo::SetBaseURL(const BString& baseURL)
-{
- fBaseURL = baseURL;
-}
-
-
void
DepotInfo::SetURL(const BString& URL)
{
diff --git a/src/apps/haikudepot/model/PackageInfo.h b/src/apps/haikudepot/model/PackageInfo.h
index 28e98f33ff..263d052e4a 100644
--- a/src/apps/haikudepot/model/PackageInfo.h
+++ b/src/apps/haikudepot/model/PackageInfo.h
@@ -423,14 +423,11 @@ public:
bool AddPackage(const PackageInfoRef& package);
- int32 PackageIndexByName(const BString& packageName);
+ int32 PackageIndexByName(const BString& packageName)
+ const;
void SyncPackages(const PackageList& packages);
- void SetBaseURL(const BString& baseURL);
- const BString& BaseURL() const
- { return fBaseURL; }
-
void SetURL(const BString& URL);
const BString& URL() const
{ return fURL; }
@@ -449,9 +446,6 @@ private:
PackageList fPackages;
BString fWebAppRepositoryCode;
BString fWebAppRepositorySourceCode;
- BString fBaseURL;
- // this is the URL at which the configured repository will be
- // accessed to get data.
BString fURL;
// this is actually a unique identifier for the repository.
};
diff --git a/src/apps/haikudepot/server/AbstractProcess.cpp b/src/apps/haikudepot/server/AbstractProcess.cpp
new file mode 100644
index 0000000000..bc74cedf73
--- /dev/null
+++ b/src/apps/haikudepot/server/AbstractProcess.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2018, Andrew Lindesay .
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+#include "AbstractProcess.h"
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "HaikuDepotConstants.h"
+#include "Logger.h"
+
+
+AbstractProcess::AbstractProcess()
+ :
+ fLock(),
+ fListener(NULL),
+ fWasStopped(false),
+ fProcessState(PROCESS_INITIAL),
+ fErrorStatus(B_OK)
+{
+}
+
+
+AbstractProcess::~AbstractProcess()
+{
+}
+
+
+void
+AbstractProcess::SetListener(AbstractProcessListener* listener)
+{
+ AutoLocker locker(&fLock);
+ fListener = listener;
+}
+
+
+status_t
+AbstractProcess::Run()
+{
+ {
+ AutoLocker locker(&fLock);
+
+ if (ProcessState() != PROCESS_INITIAL) {
+ printf("cannot start process as it is not idle");
+ return B_NOT_ALLOWED;
+ }
+
+ if (fWasStopped) {
+ printf("cannot start process as it was stopped");
+ return B_CANCELED;
+ }
+
+ fProcessState = PROCESS_RUNNING;
+ }
+
+ status_t runResult = RunInternal();
+
+ if (runResult != B_OK)
+ printf("[%s] an error has arisen; %s\n", Name(), strerror(runResult));
+
+ AbstractProcessListener* listener;
+
+ {
+ AutoLocker locker(&fLock);
+ fProcessState = PROCESS_COMPLETE;
+ fErrorStatus = runResult;
+ listener = fListener;
+ }
+
+ // this process may be part of a larger bulk-load process and
+ // if so, the process orchestration needs to know when this
+ // process has completed.
+ if (listener != NULL)
+ listener->ProcessExited();
+
+ return runResult;
+}
+
+
+bool
+AbstractProcess::WasStopped()
+{
+ AutoLocker locker(&fLock);
+ return fWasStopped;
+}
+
+
+status_t
+AbstractProcess::ErrorStatus()
+{
+ AutoLocker locker(&fLock);
+ return fErrorStatus;
+}
+
+
+/*! This method will stop the process. The actual process may carry on to
+ perform some tidy-ups on its thread so this does not stop the thread or
+ change the state of the process; just indicates to the running thread that
+ it should stop. If it has not yet been started then it will be put into
+ finished state.
+*/
+
+status_t
+AbstractProcess::Stop()
+{
+ status_t result = B_CANCELED;
+ AbstractProcessListener* listener = NULL;
+
+ {
+ AutoLocker locker(&fLock);
+
+ if (!fWasStopped) {
+ fWasStopped = true;
+ result = StopInternal();
+
+ if (fProcessState == PROCESS_INITIAL) {
+ listener = fListener;
+ fProcessState = PROCESS_COMPLETE;
+ }
+ }
+ }
+
+ if (listener != NULL)
+ listener->ProcessExited();
+
+ return result;
+}
+
+
+status_t
+AbstractProcess::StopInternal()
+{
+ return B_NOT_ALLOWED;
+}
+
+
+bool
+AbstractProcess::IsRunning()
+{
+ return ProcessState() == PROCESS_RUNNING;
+}
+
+
+process_state
+AbstractProcess::ProcessState()
+{
+ AutoLocker locker(&fLock);
+ return fProcessState;
+}
\ No newline at end of file
diff --git a/src/apps/haikudepot/server/AbstractProcess.h b/src/apps/haikudepot/server/AbstractProcess.h
new file mode 100644
index 0000000000..001ff8724e
--- /dev/null
+++ b/src/apps/haikudepot/server/AbstractProcess.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018, Andrew Lindesay .
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#ifndef ABSTRACT_PROCESS_H
+#define ABSTRACT_PROCESS_H
+
+#include
+#include
+
+#include "StandardMetaData.h"
+#include "Stoppable.h"
+
+
+typedef enum process_state {
+ PROCESS_INITIAL = 1 << 0,
+ PROCESS_RUNNING = 1 << 1,
+ PROCESS_COMPLETE = 1 << 2
+} process_state;
+
+
+/*! Clients are able to subclass from this 'interface' in order to accept
+ call-backs when a process has exited; either through success or through
+ failure.
+ */
+
+class AbstractProcessListener {
+public:
+ virtual void ProcessExited() = 0;
+};
+
+
+/*! This is the superclass of all Processes. */
+
+class AbstractProcess : public Stoppable {
+public:
+ AbstractProcess();
+ virtual ~AbstractProcess();
+
+ virtual const char* Name() const = 0;
+ virtual const char* Description() const = 0;
+ status_t Run();
+ status_t Stop();
+ status_t ErrorStatus();
+ bool IsRunning();
+ bool WasStopped();
+ process_state ProcessState();
+ void SetListener(AbstractProcessListener* listener);
+
+protected:
+ virtual status_t RunInternal() = 0;
+ virtual status_t StopInternal();
+
+private:
+ BLocker fLock;
+ AbstractProcessListener*
+ fListener;
+ bool fWasStopped;
+ process_state fProcessState;
+ status_t fErrorStatus;
+};
+
+#endif // ABSTRACT_PROCESS_H
diff --git a/src/apps/haikudepot/server/AbstractServerProcess.cpp b/src/apps/haikudepot/server/AbstractServerProcess.cpp
index 3187476515..c6cd574af3 100644
--- a/src/apps/haikudepot/server/AbstractServerProcess.cpp
+++ b/src/apps/haikudepot/server/AbstractServerProcess.cpp
@@ -2,6 +2,8 @@
* Copyright 2017-2018, Andrew Lindesay .
* All rights reserved. Distributed under the terms of the MIT License.
*/
+
+
#include "AbstractServerProcess.h"
#include
@@ -9,10 +11,8 @@
#include
#include
-#include
#include
#include
-#include
#include
#include
@@ -34,14 +34,9 @@
#define TIMEOUT_MICROSECONDS 3e+7
-AbstractServerProcess::AbstractServerProcess(
- AbstractServerProcessListener* listener, uint32 options)
+AbstractServerProcess::AbstractServerProcess(uint32 options)
:
- fLock(),
- fListener(listener),
- fWasStopped(false),
- fProcessState(SERVER_PROCESS_INITIAL),
- fErrorStatus(B_OK),
+ AbstractProcess(),
fOptions(options),
fRequest(NULL)
{
@@ -69,60 +64,6 @@ AbstractServerProcess::ShouldAttemptNetworkDownload(bool hasDataAlready)
}
-status_t
-AbstractServerProcess::Run()
-{
- {
- BAutolock locker(&fLock);
-
- if (ProcessState() != SERVER_PROCESS_INITIAL) {
- printf("cannot start server process as it is not idle");
- return B_NOT_ALLOWED;
- }
-
- fProcessState = SERVER_PROCESS_RUNNING;
- }
-
- SetErrorStatus(RunInternal());
-
- SetProcessState(SERVER_PROCESS_COMPLETE);
-
- // this process may be part of a larger bulk-load process and
- // if so, the process orchestration needs to know when this
- // process has completed.
-
- if (fListener != NULL)
- fListener->ServerProcessExited();
-
- return ErrorStatus();
-}
-
-
-bool
-AbstractServerProcess::WasStopped()
-{
- BAutolock locker(&fLock);
- return fWasStopped;
-}
-
-
-status_t
-AbstractServerProcess::ErrorStatus()
-{
- BAutolock locker(&fLock);
- return fErrorStatus;
-}
-
-
-status_t
-AbstractServerProcess::Stop()
-{
- BAutolock locker(&fLock);
- fWasStopped = true;
- return StopInternal();
-}
-
-
status_t
AbstractServerProcess::StopInternal()
{
@@ -130,41 +71,7 @@ AbstractServerProcess::StopInternal()
return fRequest->Stop();
}
- return B_NOT_ALLOWED;
-}
-
-
-bool
-AbstractServerProcess::IsRunning()
-{
- return ProcessState() == SERVER_PROCESS_RUNNING;
-}
-
-
-void
-AbstractServerProcess::SetErrorStatus(status_t value)
-{
- BAutolock locker(&fLock);
-
- if (fErrorStatus == B_OK) {
- fErrorStatus = value;
- }
-}
-
-
-void
-AbstractServerProcess::SetProcessState(process_state value)
-{
- BAutolock locker(&fLock);
- fProcessState = value;
-}
-
-
-process_state
-AbstractServerProcess::ProcessState()
-{
- BAutolock locker(&fLock);
- return fProcessState;
+ return AbstractProcess::StopInternal();
}
@@ -174,7 +81,11 @@ AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue) const
BPath metaDataPath;
BString jsonPath;
- GetStandardMetaDataPath(metaDataPath);
+ status_t result = GetStandardMetaDataPath(metaDataPath);
+
+ if (result != B_OK)
+ return result;
+
GetStandardMetaDataJsonPath(jsonPath);
return IfModifiedSinceHeaderValue(headerValue, metaDataPath, jsonPath);
@@ -246,8 +157,8 @@ AbstractServerProcess::PopulateMetaData(
}
-bool
-AbstractServerProcess::LooksLikeGzip(const char *pathStr) const
+/* static */ bool
+AbstractServerProcess::LooksLikeGzip(const char *pathStr)
{
int l = strlen(pathStr);
return l > 4 && 0 == strncmp(&pathStr[l - 3], ".gz", 3);
@@ -268,7 +179,7 @@ AbstractServerProcess::ParseJsonFromFileWithListener(
FILE* file = fopen(pathStr, "rb");
if (file == NULL) {
- fprintf(stderr, "unable to find the meta data file at [%s]\n",
+ printf("[%s] unable to find the meta data file at [%s]\n", Name(),
path.Path());
return B_FILE_NOT_FOUND;
}
@@ -348,17 +259,18 @@ AbstractServerProcess::DownloadToLocalFile(const BPath& targetFilePath,
return B_CANCELED;
if (redirects > MAX_REDIRECTS) {
- fprintf(stdout, "exceeded %d redirects --> failure\n", MAX_REDIRECTS);
+ printf("[%s] exceeded %d redirects --> failure\n", Name(),
+ MAX_REDIRECTS);
return B_IO_ERROR;
}
if (failures > MAX_FAILURES) {
- fprintf(stdout, "exceeded %d failures\n", MAX_FAILURES);
+ printf("[%s] exceeded %d failures\n", Name(), MAX_FAILURES);
return B_IO_ERROR;
}
- fprintf(stdout, "[%s] will stream '%s' to [%s]\n",
- Name(), url.UrlString().String(), targetFilePath.Path());
+ printf("[%s] will stream '%s' to [%s]\n", Name(), url.UrlString().String(),
+ targetFilePath.Path());
ToFileUrlProtocolListener listener(targetFilePath, Name(),
Logger::IsTraceEnabled());
diff --git a/src/apps/haikudepot/server/AbstractServerProcess.h b/src/apps/haikudepot/server/AbstractServerProcess.h
index 11e7cf5602..12e7e7ee69 100644
--- a/src/apps/haikudepot/server/AbstractServerProcess.h
+++ b/src/apps/haikudepot/server/AbstractServerProcess.h
@@ -3,6 +3,7 @@
* All rights reserved. Distributed under the terms of the MIT License.
*/
+
#ifndef ABSTRACT_SERVER_PROCESS_H
#define ABSTRACT_SERVER_PROCESS_H
@@ -11,54 +12,29 @@
#include
#include
+#include "AbstractProcess.h"
#include "StandardMetaData.h"
-#include "Stoppable.h"
-typedef enum process_options {
+typedef enum server_process_options {
SERVER_PROCESS_NO_NETWORKING = 1 << 0,
SERVER_PROCESS_PREFER_CACHE = 1 << 1,
SERVER_PROCESS_DROP_CACHE = 1 << 2
-} process_options;
+} server_process_options;
-typedef enum process_state {
- SERVER_PROCESS_INITIAL = 1,
- SERVER_PROCESS_RUNNING = 2,
- SERVER_PROCESS_COMPLETE = 3
-} process_state;
+/*! This is the superclass of Processes that communicate with the Haiku Depot
+ Server (HDS) system.
+*/
-/*! Clients are able to subclass from this 'interface' in order to accept
- call-backs when a process has exited; either through success or through
- failure.
- */
-
-class AbstractServerProcessListener {
+class AbstractServerProcess : public AbstractProcess {
public:
- virtual void ServerProcessExited() = 0;
-};
-
-
-class AbstractServerProcess : public Stoppable {
-public:
- AbstractServerProcess(
- AbstractServerProcessListener* listener,
- uint32 options);
+ AbstractServerProcess(uint32 options);
virtual ~AbstractServerProcess();
- virtual const char* Name() = 0;
- status_t Run();
- status_t Stop();
- status_t ErrorStatus();
- bool IsRunning();
- bool WasStopped();
-
protected:
- virtual status_t RunInternal() = 0;
- virtual status_t StopInternal();
-
- virtual void GetStandardMetaDataPath(
+ virtual status_t GetStandardMetaDataPath(
BPath& path) const = 0;
virtual void GetStandardMetaDataJsonPath(
BString& jsonPath) const = 0;
@@ -92,27 +68,20 @@ protected:
static bool IsSuccess(status_t e);
+protected:
+ virtual status_t StopInternal();
+
private:
- BLocker fLock;
- AbstractServerProcessListener*
- fListener;
- bool fWasStopped;
- process_state fProcessState;
- status_t fErrorStatus;
uint32 fOptions;
BHttpRequest* fRequest;
- process_state ProcessState();
- void SetErrorStatus(status_t value);
- void SetProcessState(process_state value);
-
status_t DownloadToLocalFile(
const BPath& targetFilePath,
const BUrl& url,
uint32 redirects, uint32 failures);
- bool LooksLikeGzip(const char *pathStr) const;
+ static bool LooksLikeGzip(const char *pathStr);
};
diff --git a/src/apps/haikudepot/server/AbstractSingleFileServerProcess.cpp b/src/apps/haikudepot/server/AbstractSingleFileServerProcess.cpp
index b470ba2f30..1bd16f0e45 100644
--- a/src/apps/haikudepot/server/AbstractSingleFileServerProcess.cpp
+++ b/src/apps/haikudepot/server/AbstractSingleFileServerProcess.cpp
@@ -2,18 +2,21 @@
* Copyright 2017-2018, Andrew Lindesay .
* All rights reserved. Distributed under the terms of the MIT License.
*/
+
+
#include "AbstractSingleFileServerProcess.h"
#include "HaikuDepotConstants.h"
#include "Logger.h"
+#include "ServerHelper.h"
#include "ServerSettings.h"
#include "StorageUtils.h"
AbstractSingleFileServerProcess::AbstractSingleFileServerProcess(
- AbstractServerProcessListener* listener, uint32 options)
+ uint32 options)
:
- AbstractServerProcess(listener, options)
+ AbstractServerProcess(options)
{
}
@@ -29,9 +32,13 @@ AbstractSingleFileServerProcess::RunInternal()
if (Logger::IsInfoEnabled())
printf("[%s] will fetch data\n", Name());
- BPath localPath = LocalPath();
+ BPath localPath;
+ status_t result = GetLocalPath(localPath);
+
+ if (result != B_OK)
+ return result;
+
BString urlPathComponent = UrlPathComponent();
- status_t result = B_OK;
if (IsSuccess(result) && HasOption(SERVER_PROCESS_DROP_CACHE))
result = DeleteLocalFile(localPath);
@@ -48,6 +55,19 @@ AbstractSingleFileServerProcess::RunInternal()
result = DownloadToLocalFileAtomically(
localPath,
ServerSettings::CreateFullUrl(urlPathComponent));
+
+ if (!IsSuccess(result)) {
+ if (hasData) {
+ printf("[%s] failed to update data, but have old data "
+ "anyway so carry on with that\n", Name());
+ result = B_OK;
+ } else {
+ printf("[%s] failed to obtain data\n", Name());
+ }
+ } else {
+ if (Logger::IsInfoEnabled())
+ printf("[%s] did fetch data\n", Name());
+ }
}
if (IsSuccess(result)) {
@@ -61,11 +81,6 @@ AbstractSingleFileServerProcess::RunInternal()
}
if (IsSuccess(result)) {
- if (Logger::IsInfoEnabled())
- printf("[%s] did fetch data\n", Name());
-
- // now load the data in and process it.
-
printf("[%s] will process data\n", Name());
result = ProcessLocalData();
@@ -82,3 +97,9 @@ AbstractSingleFileServerProcess::RunInternal()
return result;
}
+
+status_t
+AbstractSingleFileServerProcess::GetStandardMetaDataPath(BPath& path) const
+{
+ return GetLocalPath(path);
+}
\ No newline at end of file
diff --git a/src/apps/haikudepot/server/AbstractSingleFileServerProcess.h b/src/apps/haikudepot/server/AbstractSingleFileServerProcess.h
index d069d7bc0d..698261c394 100644
--- a/src/apps/haikudepot/server/AbstractSingleFileServerProcess.h
+++ b/src/apps/haikudepot/server/AbstractSingleFileServerProcess.h
@@ -1,8 +1,9 @@
/*
- * Copyright 2017, Andrew Lindesay .
+ * Copyright 2017-2018, Andrew Lindesay .
* All rights reserved. Distributed under the terms of the MIT License.
*/
+
#ifndef ABSTRACT_SINGLE_FILE_SERVER_PROCESS_H
#define ABSTRACT_SINGLE_FILE_SERVER_PROCESS_H
@@ -12,9 +13,7 @@
class AbstractSingleFileServerProcess : public AbstractServerProcess {
public:
- AbstractSingleFileServerProcess(
- AbstractServerProcessListener* listener,
- uint32 options);
+ AbstractSingleFileServerProcess(uint32 options);
virtual ~AbstractSingleFileServerProcess();
protected:
@@ -24,7 +23,9 @@ protected:
virtual BString UrlPathComponent() = 0;
- virtual BPath& LocalPath() = 0;
+ virtual status_t GetLocalPath(BPath& path) const = 0;
+
+ virtual status_t GetStandardMetaDataPath(BPath& path) const;
};
#endif // ABSTRACT_SINGLE_FILE_SERVER_PROCESS_H
\ No newline at end of file
diff --git a/src/apps/haikudepot/server/BulkLoadContext.cpp b/src/apps/haikudepot/server/BulkLoadContext.cpp
deleted file mode 100644
index ffa24302d7..0000000000
--- a/src/apps/haikudepot/server/BulkLoadContext.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2017, Andrew Lindesay .
- * All rights reserved. Distributed under the terms of the MIT License.
- */
-#include "BulkLoadContext.h"
-
-
-BulkLoadContext::BulkLoadContext()
- :
- fState(BULK_LOAD_INITIAL),
- fIconProcess(NULL),
- fRepositoryProcess(NULL),
- fPkgProcesses(new List()),
- fProcessOptions(0)
-{
-}
-
-
-BulkLoadContext::~BulkLoadContext()
-{
- StopAllProcesses();
-
- if (fIconProcess != NULL)
- delete fIconProcess;
-
- if (fRepositoryProcess != NULL)
- delete fRepositoryProcess;
-
- int32 count = fPkgProcesses->CountItems();
- int32 i;
-
- for (i = 0; i < count; i++)
- delete fPkgProcesses->ItemAt(i);
-
- delete fPkgProcesses;
-}
-
-
-bulk_load_state
-BulkLoadContext::State()
-{
- return fState;
-}
-
-
-void
-BulkLoadContext::SetState(bulk_load_state value)
-{
- fState = value;
-}
-
-
-void
-BulkLoadContext::StopAllProcesses()
-{
- if (fIconProcess != NULL)
- fIconProcess->Stop();
-
- if (fRepositoryProcess != NULL)
- fRepositoryProcess->Stop();
-
- int32 count = fPkgProcesses->CountItems();
- int32 i;
-
- for (i = 0; i < count; i++)
- fPkgProcesses->ItemAt(i)->Stop();
-}
-
-
-AbstractServerProcess*
-BulkLoadContext::IconProcess()
-{
- return fIconProcess;
-}
-
-
-void
-BulkLoadContext::SetIconProcess(AbstractServerProcess* value)
-{
- fIconProcess = value;
-}
-
-
-AbstractServerProcess*
-BulkLoadContext::RepositoryProcess()
-{
- return fRepositoryProcess;
-}
-
-
-void
-BulkLoadContext::SetRepositoryProcess(
- AbstractServerProcess* value)
-{
- fRepositoryProcess = value;
-}
-
-
-int32
-BulkLoadContext::CountPkgProcesses()
-{
- return fPkgProcesses->CountItems();
-}
-
-
-AbstractServerProcess*
-BulkLoadContext::PkgProcessAt(int32 index)
-{
- return fPkgProcesses->ItemAt(index);
-}
-
-
-void
-BulkLoadContext::AddPkgProcess(AbstractServerProcess *value)
-{
- fPkgProcesses->Add(value);
-}
-
-
-void
-BulkLoadContext::AddProcessOption(uint32 flag)
-{
- fProcessOptions = fProcessOptions | flag;
-}
-
-
-uint32
-BulkLoadContext::ProcessOptions()
-{
- return fProcessOptions;
-}
\ No newline at end of file
diff --git a/src/apps/haikudepot/server/BulkLoadContext.h b/src/apps/haikudepot/server/BulkLoadContext.h
deleted file mode 100644
index 04d8ce2c2f..0000000000
--- a/src/apps/haikudepot/server/BulkLoadContext.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2017, Andrew Lindesay .
- * All rights reserved. Distributed under the terms of the MIT License.
- */
-#ifndef BULK_LOAD_CONTEXT_H
-#define BULK_LOAD_CONTEXT_H
-
-#include
-#include
-#include
-
-#include "AbstractServerProcess.h"
-#include "List.h"
-
-
-typedef enum bulk_load_state {
- BULK_LOAD_INITIAL = 1,
- BULK_LOAD_REPOSITORY_AND_REFERENCE = 2,
- BULK_LOAD_PKGS_AND_ICONS = 3,
- BULK_LOAD_COMPLETE = 4
-} bulk_load_state;
-
-
-class BulkLoadContext {
-public:
- BulkLoadContext();
- virtual ~BulkLoadContext();
-
- void StopAllProcesses();
-
- bulk_load_state State();
- void SetState(bulk_load_state value);
-
- AbstractServerProcess*
- IconProcess();
- void SetIconProcess(AbstractServerProcess* value);
-
- AbstractServerProcess*
- RepositoryProcess();
- void SetRepositoryProcess(
- AbstractServerProcess* value);
-
- int32 CountPkgProcesses();
- AbstractServerProcess*
- PkgProcessAt(int32 index);
- void AddPkgProcess(AbstractServerProcess *value);
-
- void AddProcessOption(uint32 flag);
- uint32 ProcessOptions();
-
-private:
- bulk_load_state
- fState;
-
- AbstractServerProcess*
- fIconProcess;
- AbstractServerProcess*
- fRepositoryProcess;
- List*
- fPkgProcesses;
- uint32 fProcessOptions;
-
-};
-
-
-#endif // BULK_LOAD_CONTEXT_H
diff --git a/src/apps/haikudepot/server/BulkLoadStateMachine.cpp b/src/apps/haikudepot/server/BulkLoadStateMachine.cpp
deleted file mode 100644
index c88964816b..0000000000
--- a/src/apps/haikudepot/server/BulkLoadStateMachine.cpp
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright 2017-2018, Andrew Lindesay .
- * All rights reserved. Distributed under the terms of the MIT License.
- */
-#include "BulkLoadStateMachine.h"
-
-#include
-
-#include "Logger.h"
-#include "PkgDataUpdateProcess.h"
-#include "RepositoryDataUpdateProcess.h"
-#include "ServerIconExportUpdateProcess.h"
-#include "ServerSettings.h"
-#include "ServerHelper.h"
-
-
-BulkLoadStateMachine::BulkLoadStateMachine(Model* model)
- :
- fBulkLoadContext(NULL),
- fModel(model)
-{
-}
-
-
-BulkLoadStateMachine::~BulkLoadStateMachine()
-{
- Stop();
-}
-
-
-bool
-BulkLoadStateMachine::IsRunning()
-{
- BAutolock locker(&fLock);
- return fBulkLoadContext != NULL;
-}
-
-
-/*! This gets invoked when one of the background processes has exited. */
-
-void
-BulkLoadStateMachine::ServerProcessExited()
-{
- ContextPoll();
-}
-
-
-static const char* bulk_load_state_name(bulk_load_state state) {
- switch(state) {
- case BULK_LOAD_INITIAL:
- return "BULK_LOAD_INITIAL";
- case BULK_LOAD_REPOSITORY_AND_REFERENCE:
- return "BULK_LOAD_REPOSITORY_AND_REFERENCE";
- case BULK_LOAD_PKGS_AND_ICONS:
- return "BULK_LOAD_PKGS_AND_ICONS";
- case BULK_LOAD_COMPLETE:
- return "BULK_LOAD_COMPLETE";
- default:
- return "???";
- }
-}
-
-
-void
-BulkLoadStateMachine::SetContextState(bulk_load_state state)
-{
- if (Logger::IsDebugEnabled()) {
- printf("bulk load - transition to state [%s]\n",
- bulk_load_state_name(state));
- }
-
- fBulkLoadContext->SetState(state);
-}
-
-
-/*! Bulk loading data into the model can be considered to be a state
- machine. This method is invoked each time that an event state
- change happens.
- */
-
-void
-BulkLoadStateMachine::ContextPoll()
-{
- BAutolock locker(&fLock);
-
- if (Logger::IsDebugEnabled())
- printf("bulk load - context poll\n");
-
- if (CanTransitionTo(BULK_LOAD_REPOSITORY_AND_REFERENCE)) {
- SetContextState(BULK_LOAD_REPOSITORY_AND_REFERENCE);
- InitiateBulkPopulateIcons();
- if (InitiateBulkRepositories() != B_OK)
- ContextPoll();
- return;
- }
-
- if (CanTransitionTo(BULK_LOAD_PKGS_AND_ICONS)) {
- fModel->LogDepotsWithNoWebAppRepositoryCode();
- SetContextState(BULK_LOAD_PKGS_AND_ICONS);
- InitiateBulkPopulatePackagesForAllDepots();
- return;
- }
-
- if (CanTransitionTo(BULK_LOAD_COMPLETE)) {
- SetContextState(BULK_LOAD_COMPLETE);
- delete fBulkLoadContext;
- fBulkLoadContext = NULL;
- return;
- }
-}
-
-
-bool
-BulkLoadStateMachine::CanTransitionTo(bulk_load_state targetState)
-{
- if (fBulkLoadContext != NULL) {
- bulk_load_state existingState = fBulkLoadContext->State();
-
- switch (targetState) {
- case BULK_LOAD_INITIAL:
- return false;
- case BULK_LOAD_REPOSITORY_AND_REFERENCE:
- return existingState == BULK_LOAD_INITIAL;
- case BULK_LOAD_PKGS_AND_ICONS:
- return (existingState == BULK_LOAD_REPOSITORY_AND_REFERENCE)
- && ((fBulkLoadContext->RepositoryProcess() == NULL)
- || !fBulkLoadContext->RepositoryProcess()->IsRunning());
- case BULK_LOAD_COMPLETE:
- if ((existingState == BULK_LOAD_PKGS_AND_ICONS)
- && ((fBulkLoadContext->IconProcess() == NULL)
- || !fBulkLoadContext->IconProcess()->IsRunning())) {
- int32 i;
-
- for (i = 0; i < fBulkLoadContext->CountPkgProcesses(); i++) {
- AbstractServerProcess* process =
- fBulkLoadContext->PkgProcessAt(i);
- if (process->IsRunning())
- return false;
- }
-
- return true;
- }
- break;
- }
- }
-
- return false;
-}
-
-
-void
-BulkLoadStateMachine::StopAllProcesses()
-{
- BAutolock locker(&fLock);
-
- if (fBulkLoadContext != NULL) {
- if (NULL != fBulkLoadContext->IconProcess())
- fBulkLoadContext->IconProcess()->Stop();
-
- if (NULL != fBulkLoadContext->RepositoryProcess())
- fBulkLoadContext->RepositoryProcess()->Stop();
-
- int32 i;
-
- for(i = 0; i < fBulkLoadContext->CountPkgProcesses(); i++) {
- AbstractServerProcess* serverProcess =
- fBulkLoadContext->PkgProcessAt(i);
- serverProcess->Stop();
- }
- }
-}
-
-
-void
-BulkLoadStateMachine::Start()
-{
- if (Logger::IsInfoEnabled())
- printf("bulk load - start\n");
-
- Stop();
-
- {
- BAutolock locker(&fLock);
-
- if (!IsRunning()) {
- fBulkLoadContext = new BulkLoadContext();
-
- if (ServerSettings::IsClientTooOld()) {
- printf("bulk load proceeding without network communications "
- "because the client is too old\n");
- fBulkLoadContext->AddProcessOption(
- SERVER_PROCESS_NO_NETWORKING);
- }
-
- if (!ServerHelper::IsNetworkAvailable()) {
- fBulkLoadContext->AddProcessOption(
- SERVER_PROCESS_NO_NETWORKING);
- }
-
- if (ServerSettings::PreferCache())
- fBulkLoadContext->AddProcessOption(SERVER_PROCESS_PREFER_CACHE);
-
- if (ServerSettings::DropCache())
- fBulkLoadContext->AddProcessOption(SERVER_PROCESS_DROP_CACHE);
-
- ContextPoll();
- }
- }
-}
-
-
-void
-BulkLoadStateMachine::Stop()
-{
- StopAllProcesses();
-
- // spin lock to wait for the bulk-load processes to complete.
-
- while (IsRunning())
- snooze(500000);
-}
-
-
-/*! This method is the initial function that is invoked on starting a new
- thread. It will start a server process that is part of the bulk-load.
- */
-
-status_t
-BulkLoadStateMachine::StartProcess(void* cookie)
-{
- AbstractServerProcess* process =
- static_cast(cookie);
-
- if (Logger::IsInfoEnabled()) {
- printf("bulk load - starting process [%s]\n",
- process->Name());
- }
-
- process->Run();
- return B_OK;
-}
-
-
-status_t
-BulkLoadStateMachine::InitiateServerProcess(AbstractServerProcess* process)
-{
- if (Logger::IsInfoEnabled())
- printf("bulk load - initiating [%s]\n", process->Name());
-
- thread_id tid = spawn_thread(&StartProcess,
- process->Name(), B_NORMAL_PRIORITY, process);
-
- if (tid >= 0) {
- resume_thread(tid);
- return B_OK;
- }
-
- return B_ERROR;
-}
-
-
-status_t
-BulkLoadStateMachine::InitiateBulkRepositories()
-{
- status_t result = B_OK;
- BPath dataPath;
-
- fBulkLoadContext->SetRepositoryProcess(NULL);
- result = fModel->DumpExportRepositoryDataPath(dataPath);
-
- if (result != B_OK) {
- BAutolock locker(&fLock);
- printf("unable to obtain the path for storing the repository data\n");
- ContextPoll();
- return B_ERROR;
- }
-
- fBulkLoadContext->SetRepositoryProcess(
- new RepositoryDataUpdateProcess(this, dataPath, fModel,
- fBulkLoadContext->ProcessOptions()));
- return InitiateServerProcess(fBulkLoadContext->RepositoryProcess());
-}
-
-
-status_t
-BulkLoadStateMachine::InitiateBulkPopulateIcons()
-{
- BPath path;
-
- if (fModel->IconStoragePath(path) != B_OK) {
- BAutolock locker(&fLock);
- printf("unable to obtain the path for storing icons\n");
- ContextPoll();
- return B_ERROR;
- }
-
- AbstractServerProcess *process = new ServerIconExportUpdateProcess(
- this, path, fModel, fBulkLoadContext->ProcessOptions());
- fBulkLoadContext->SetIconProcess(process);
- return InitiateServerProcess(process);
-}
-
-
-status_t
-BulkLoadStateMachine::InitiateBulkPopulatePackagesForDepot(
- const DepotInfo& depotInfo)
-{
- BString repositorySourceCode = depotInfo.WebAppRepositorySourceCode();
-
- if (repositorySourceCode.Length() == 0) {
- printf("the depot [%s] has no repository source code\n",
- depotInfo.Name().String());
- return B_ERROR;
- }
-
- BPath repositorySourcePkgDataPath;
-
- if (fModel->DumpExportPkgDataPath(repositorySourcePkgDataPath,
- repositorySourceCode) != B_OK) {
- BAutolock locker(&fLock);
- printf("unable to obtain the path for storing data for [%s]\n",
- repositorySourceCode.String());
- ContextPoll();
- return B_ERROR;
- }
-
- AbstractServerProcess *process = new PkgDataUpdateProcess(
- this, repositorySourcePkgDataPath, fModel->PreferredLanguage(),
- repositorySourceCode, depotInfo.Name(), fModel,
- fBulkLoadContext->ProcessOptions());
- fBulkLoadContext->AddPkgProcess(process);
-
- return InitiateServerProcess(process);
-}
-
-
-// static
-void
-BulkLoadStateMachine::InitiatePopulatePackagesForDepotCallback(
- const DepotInfo& depotInfo, void* context)
-{
- BulkLoadStateMachine* stateMachine =
- static_cast(context);
- stateMachine->InitiateBulkPopulatePackagesForDepot(depotInfo);
-}
-
-
-void
-BulkLoadStateMachine::InitiateBulkPopulatePackagesForAllDepots()
-{
- fModel->ForAllDepots(&InitiatePopulatePackagesForDepotCallback, this);
-
- printf("did initiate populate package data for %" B_PRId32 " depots\n",
- fBulkLoadContext->CountPkgProcesses());
-
- if (0 == fBulkLoadContext->CountPkgProcesses())
- ContextPoll();
-}
\ No newline at end of file
diff --git a/src/apps/haikudepot/server/BulkLoadStateMachine.h b/src/apps/haikudepot/server/BulkLoadStateMachine.h
deleted file mode 100644
index b1063e5d6d..0000000000
--- a/src/apps/haikudepot/server/BulkLoadStateMachine.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2017-2018, Andrew Lindesay .
- * All rights reserved. Distributed under the terms of the MIT License.
- */
-#ifndef BULK_LOAD_STATE_MACHINE_H
-#define BULK_LOAD_STATE_MACHINE_H
-
-#include
-#include
-#include
-#include
-
-#include "AbstractServerProcess.h"
-#include "Model.h"
-
-
-class BulkLoadStateMachine : public AbstractServerProcessListener {
-public:
- BulkLoadStateMachine(Model* model);
- virtual ~BulkLoadStateMachine();
-
- bool IsRunning();
-
- void Start();
- void Stop();
-
- void ServerProcessExited();
-
-private:
- static status_t StartProcess(void* cookie);
- void ContextPoll();
- void SetContextState(bulk_load_state state);
- void StopAllProcesses();
-
- bool CanTransitionTo(
- bulk_load_state targetState);
-
- static void InitiatePopulatePackagesForDepotCallback(
- const DepotInfo& depotInfo,
- void* context);
-
- status_t InitiateServerProcess(
- AbstractServerProcess* process);
- status_t InitiateBulkRepositories();
- status_t InitiateBulkPopulateIcons();
- status_t InitiateBulkPopulatePackagesForDepot(
- const DepotInfo& depotInfo);
- void InitiateBulkPopulatePackagesForAllDepots();
-
-
-private:
- BLocker fLock;
- BulkLoadContext* fBulkLoadContext;
- Model* fModel;
-
-};
-
-
-#endif // BULK_LOAD_STATE_MACHINE_H
diff --git a/src/apps/haikudepot/server/LocalPkgDataLoadProcess.cpp b/src/apps/haikudepot/server/LocalPkgDataLoadProcess.cpp
new file mode 100644
index 0000000000..e9b0d3fba8
--- /dev/null
+++ b/src/apps/haikudepot/server/LocalPkgDataLoadProcess.cpp
@@ -0,0 +1,393 @@
+/*
+ * Copyright 2018, Andrew Lindesay .
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include "LocalPkgDataLoadProcess.h"
+
+#include