From 3094fef308a6aaaef9827863a0a99640bdaaa5af Mon Sep 17 00:00:00 2001 From: Andrew Lindesay Date: Tue, 19 Dec 2017 20:56:53 +0100 Subject: [PATCH] HaikuDepot : More Backend Communications Improvements * Further improves the logging and provides some basic performance numbers. * Moves the bulk-load logic out of the data-model class. * Introduces a state-machine for the bulk-load process so that it will be more easily able to be shifted to non-blocking IO when the HTTP libraries can do that. * Implements concurrent loading of the bulk-data to hopefully improve lead time for icons and meta-data. * Loads data to a temporary file and then moves to the final location in order to avoid partially written data in the cache. * Handles situations where no network is available; prevents attempt to access the network. * Allows bulk-load processes to be cancelled when the application quits. * Introduces command-line arguments to help simulate scenarios to help with testing performance and network absence. * Implements ordered insert and binary search in the 'List' class + basic unit test. --- src/apps/haikudepot/Jamfile | 3 + src/apps/haikudepot/List.h | 92 +++++ src/apps/haikudepot/model/LocalIconStore.cpp | 75 +--- src/apps/haikudepot/model/LocalIconStore.h | 4 +- src/apps/haikudepot/model/Logger.h | 2 - src/apps/haikudepot/model/Model.cpp | 329 ++++++++---------- src/apps/haikudepot/model/Model.h | 72 ++-- src/apps/haikudepot/model/PackageInfo.cpp | 29 +- src/apps/haikudepot/model/PackageInfo.h | 4 +- .../server/AbstractServerProcess.cpp | 276 +++++++++++++-- .../haikudepot/server/AbstractServerProcess.h | 82 ++++- .../server/PkgDataUpdateProcess.cpp | 276 ++++++++------- .../haikudepot/server/PkgDataUpdateProcess.h | 26 +- .../server/RepositoryDataUpdateProcess.cpp | 198 +++++------ .../server/RepositoryDataUpdateProcess.h | 19 +- .../server/ServerIconExportUpdateProcess.cpp | 144 +++++++- .../server/ServerIconExportUpdateProcess.h | 25 +- src/apps/haikudepot/server/ServerSettings.cpp | 44 +++ src/apps/haikudepot/server/ServerSettings.h | 10 + .../server/dumpexportpkg/DumpExportPkg.cpp | 2 +- .../server/dumpexportpkg/DumpExportPkg.h | 2 +- .../dumpexportpkg/DumpExportPkgCategory.cpp | 2 +- .../dumpexportpkg/DumpExportPkgCategory.h | 2 +- .../DumpExportPkgJsonListener.cpp | 325 +++++++++-------- .../dumpexportpkg/DumpExportPkgJsonListener.h | 4 +- .../dumpexportpkg/DumpExportPkgScreenshot.cpp | 2 +- .../dumpexportpkg/DumpExportPkgScreenshot.h | 2 +- .../dumpexportpkg/DumpExportPkgVersion.cpp | 2 +- .../dumpexportpkg/DumpExportPkgVersion.h | 2 +- .../DumpExportRepository.cpp | 2 +- .../DumpExportRepository.h | 2 +- .../DumpExportRepositoryJsonListener.cpp | 217 ++++++------ .../DumpExportRepositoryJsonListener.h | 4 +- .../DumpExportRepositorySource.cpp | 38 +- .../DumpExportRepositorySource.h | 8 +- src/apps/haikudepot/tar/TarArchiveService.cpp | 8 +- src/apps/haikudepot/tar/TarArchiveService.h | 4 +- src/apps/haikudepot/ui/App.cpp | 46 ++- src/apps/haikudepot/ui/MainWindow.cpp | 11 +- src/apps/haikudepot/ui/MainWindow.h | 4 + src/apps/haikudepot/util/StorageUtils.cpp | 55 ++- src/apps/haikudepot/util/StorageUtils.h | 6 +- .../util/ToFileUrlProtocolListener.cpp | 9 + .../util/ToFileUrlProtocolListener.h | 3 + .../DumpExportRepositoryJsonListenerTest.cpp | 6 +- .../apps/haikudepot/HaikuDepotTestAddon.cpp | 2 + src/tests/apps/haikudepot/Jamfile | 22 +- 47 files changed, 1549 insertions(+), 953 deletions(-) diff --git a/src/apps/haikudepot/Jamfile b/src/apps/haikudepot/Jamfile index f6db9f37c2..02a988d599 100644 --- a/src/apps/haikudepot/Jamfile +++ b/src/apps/haikudepot/Jamfile @@ -69,6 +69,8 @@ Application HaikuDepot : MarkupTextView.cpp MessagePackageListener.cpp Model.cpp + BulkLoadContext.cpp + BulkLoadStateMachine.cpp PackageAction.cpp PackageActionHandler.cpp PackageContentsView.cpp @@ -98,6 +100,7 @@ Application HaikuDepot : # network + server AbstractServerProcess.cpp + AbstractSingleFileServerProcess.cpp ServerSettings.cpp WebAppInterface.cpp PkgDataUpdateProcess.cpp diff --git a/src/apps/haikudepot/List.h b/src/apps/haikudepot/List.h index 3c2ce08511..f6abc1dab6 100644 --- a/src/apps/haikudepot/List.h +++ b/src/apps/haikudepot/List.h @@ -13,6 +13,9 @@ #include +#define BINARY_SEARCH_LINEAR_THRESHOLD 4 + + template class List { typedef List SelfType; @@ -110,6 +113,30 @@ public: return fCount; } +/*! Note that the use of this method will depend on the list being ordered. +*/ + + inline int32 BinarySearch(const void* context, + int32 (*compareFunc)(const void* context, const ItemType& item)) + { + if (fCount == 0) + return -1; + + return _BinarySearchBounded(context, compareFunc, 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); + } + inline bool Add(const ItemType& copyFrom) { if (_Resize(fCount + 1)) { @@ -229,6 +256,71 @@ public: } private: + inline int32 _BinarySearchLinearBounded( + const void* context, + int32 (*compareFunc)(const void* context, const ItemType& item), + int32 start, int32 end) + { + for(int32 i = start; i <= end; i++) { + if (compareFunc(context, ItemAtFast(i)) == 0) + return i; + } + + return -1; + } + + inline int32 _BinarySearchBounded( + const void* context, + int32 (*compareFunc)(const void* context, const ItemType& item), + int32 start, int32 end) + { + if (end - start < BINARY_SEARCH_LINEAR_THRESHOLD) + return _BinarySearchLinearBounded(context, compareFunc, start, end); + + int32 mid = start + (end - start); + + if (compareFunc(context, ItemAtFast(mid)) >= 0) + return _BinarySearchBounded(context, compareFunc, mid, end); + return _BinarySearchBounded(context, compareFunc, start, mid - 1); + } + + inline bool _AddOrderedLinearBounded( + const ItemType& copyFrom, + int32 (*compareFunc)(const ItemType& one, const ItemType& two), + int32 start, int32 end) + { + for(int32 i = start; i <= (end + 1); i++) { + bool greaterBefore = (i == start) + || (compareFunc(copyFrom, ItemAtFast(i - 1)) > 0); + + if (greaterBefore) { + bool lessAfter = (i == end + 1) + || (compareFunc(copyFrom, ItemAtFast(i)) <= 0); + + if (lessAfter) + return Add(copyFrom, i); + } + } + + printf("illegal state; unable to insert item into list\n"); + exit(EXIT_FAILURE); + } + + inline bool _AddOrderedBounded( + const ItemType& copyFrom, + int32 (*compareFunc)(const ItemType& one, const ItemType& two), + int32 start, int32 end) + { + if(end - start < BINARY_SEARCH_LINEAR_THRESHOLD) + return _AddOrderedLinearBounded(copyFrom, compareFunc, start, end); + + int32 mid = start + (end - start); + + if (compareFunc(copyFrom, ItemAtFast(mid)) >= 0) + return _AddOrderedBounded(copyFrom, compareFunc, mid, end); + return _AddOrderedBounded(copyFrom, compareFunc, start, mid - 1); + } + inline bool _Resize(uint32 count) { if (count > fAllocatedCount) { diff --git a/src/apps/haikudepot/model/LocalIconStore.cpp b/src/apps/haikudepot/model/LocalIconStore.cpp index c01bfd1bed..5cc8823127 100644 --- a/src/apps/haikudepot/model/LocalIconStore.cpp +++ b/src/apps/haikudepot/model/LocalIconStore.cpp @@ -15,10 +15,9 @@ #include "StorageUtils.h" -LocalIconStore::LocalIconStore() +LocalIconStore::LocalIconStore(const BPath& path) { - if (_EnsureIconStoragePath(fIconStoragePath) != B_OK) - fprintf(stdout, "unable to setup icon storage\n"); + fIconStoragePath = path; } @@ -42,62 +41,26 @@ LocalIconStore::_HasIconStoragePath() const status_t LocalIconStore::TryFindIconPath(const BString& pkgName, BPath& path) const { - if (_HasIconStoragePath()) { - BPath bestIconPath; - BPath iconPkgPath(fIconStoragePath); - bool exists; - bool isDir; + BPath bestIconPath; + BPath iconPkgPath(fIconStoragePath); + bool exists; + bool isDir; - if ( (iconPkgPath.Append("hicn") == B_OK) - && (iconPkgPath.Append(pkgName) == B_OK) - && (StorageUtils::ExistsDirectory(iconPkgPath, &exists, &isDir) - == B_OK) - && exists - && isDir - && (_IdentifyBestIconFileAtDirectory(iconPkgPath, bestIconPath) - == B_OK) - ) { - path = bestIconPath; - return B_OK; - } - } - - path.Unset(); - return B_FILE_NOT_FOUND; -} - - -void -LocalIconStore::UpdateFromServerIfNecessary() const -{ - if (_HasIconStoragePath()) { - BPath iconStoragePath(fIconStoragePath); - ServerIconExportUpdateProcess service(iconStoragePath); - service.Run(); - - if (Logger::IsDebugEnabled()) { - printf("did update the icons from server\n"); - } - } -} - - -status_t -LocalIconStore::_EnsureIconStoragePath(BPath& path) const -{ - BPath iconStoragePath; - - if (find_directory(B_USER_CACHE_DIRECTORY, &iconStoragePath) == B_OK - && iconStoragePath.Append("HaikuDepot") == B_OK - && iconStoragePath.Append("__allicons") == B_OK - && create_directory(iconStoragePath.Path(), 0777) == B_OK) { - path.SetTo(iconStoragePath.Path()); + if ( (iconPkgPath.Append("hicn") == B_OK) + && (iconPkgPath.Append(pkgName) == B_OK) + && (StorageUtils::ExistsObject(iconPkgPath, &exists, &isDir, NULL) + == B_OK) + && exists + && isDir + && (_IdentifyBestIconFileAtDirectory(iconPkgPath, bestIconPath) + == B_OK) + ) { + path = bestIconPath; return B_OK; } path.Unset(); - fprintf(stdout, "unable to find the user cache directory for icons"); - return B_ERROR; + return B_FILE_NOT_FOUND; } @@ -121,8 +84,8 @@ LocalIconStore::_IdentifyBestIconFileAtDirectory(const BPath& directory, bool isDir; if ( (workingPath.Append(iconLeafname) == B_OK - && StorageUtils::ExistsDirectory( - workingPath, &exists, &isDir) == B_OK) + && StorageUtils::ExistsObject( + workingPath, &exists, &isDir, NULL) == B_OK) && exists && !isDir) { bestIconPath.SetTo(workingPath.Path()); diff --git a/src/apps/haikudepot/model/LocalIconStore.h b/src/apps/haikudepot/model/LocalIconStore.h index 350455a99c..5745d21137 100644 --- a/src/apps/haikudepot/model/LocalIconStore.h +++ b/src/apps/haikudepot/model/LocalIconStore.h @@ -16,15 +16,13 @@ class LocalIconStore { public: - LocalIconStore(); + LocalIconStore(const BPath& path); virtual ~LocalIconStore(); status_t TryFindIconPath(const BString& pkgName, BPath& path) const; - void UpdateFromServerIfNecessary() const; private: bool _HasIconStoragePath() const; - status_t _EnsureIconStoragePath(BPath& path) const; status_t _IdentifyBestIconFileAtDirectory( const BPath& directory, BPath& bestIconPath) const; diff --git a/src/apps/haikudepot/model/Logger.h b/src/apps/haikudepot/model/Logger.h index 33cfa13ef2..95237cd6e2 100644 --- a/src/apps/haikudepot/model/Logger.h +++ b/src/apps/haikudepot/model/Logger.h @@ -2,8 +2,6 @@ * Copyright 2017, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ - - #ifndef LOGGER_H #define LOGGER_H diff --git a/src/apps/haikudepot/model/Model.cpp b/src/apps/haikudepot/model/Model.cpp index 235864685d..4093cea9b0 100644 --- a/src/apps/haikudepot/model/Model.cpp +++ b/src/apps/haikudepot/model/Model.cpp @@ -23,8 +23,6 @@ #include #include "Logger.h" -#include "PkgDataUpdateProcess.h" -#include "RepositoryDataUpdateProcess.h" #include "StorageUtils.h" @@ -359,10 +357,7 @@ Model::Model() fShowAvailablePackages(true), fShowInstalledPackages(true), fShowSourcePackages(false), - fShowDevelopPackages(false), - - fPopulateAllPackagesThread(-1), - fStopPopulatingAllPackages(false) + fShowDevelopPackages(false) { _UpdateIsFeaturedFilter(); @@ -417,7 +412,6 @@ Model::Model() Model::~Model() { - StopPopulatingAllPackages(); } @@ -701,7 +695,6 @@ Model::PopulatePackage(const PackageInfoRef& package, uint32 flags) BMessage item; if (items.FindMessage(name, &item) != B_OK) break; -// item.PrintToStream(); BString user; BMessage userInfo; @@ -768,32 +761,6 @@ Model::PopulatePackage(const PackageInfoRef& package, uint32 flags) } -void -Model::PopulateAllPackages() -{ - StopPopulatingAllPackages(); - - fStopPopulatingAllPackages = false; - - fPopulateAllPackagesThread = spawn_thread(&_PopulateAllPackagesEntry, - "Package populator", B_NORMAL_PRIORITY, this); - if (fPopulateAllPackagesThread >= 0) - resume_thread(fPopulateAllPackagesThread); -} - - -void -Model::StopPopulatingAllPackages() -{ - if (fPopulateAllPackagesThread < 0) - return; - - fStopPopulatingAllPackages = true; - wait_for_thread(fPopulateAllPackagesThread, NULL); - fPopulateAllPackagesThread = -1; -} - - void Model::SetUsername(BString username) { @@ -837,8 +804,6 @@ Model::SetAuthorization(const BString& username, const BString& password, } -// #pragma mark - private - /*! When bulk repository data comes down from the server, it will arrive as a json.gz payload. This is stored locally as a cache and this method will provide the on-disk storage location for @@ -846,7 +811,7 @@ Model::SetAuthorization(const BString& username, const BString& password, */ status_t -Model::_DumpExportRepositoryDataPath(BPath& path) const +Model::DumpExportRepositoryDataPath(BPath& path) const { BPath repoDataPath; @@ -866,7 +831,26 @@ Model::_DumpExportRepositoryDataPath(BPath& path) const status_t -Model::_DumpExportPkgDataPath(BPath& path, +Model::IconStoragePath(BPath& path) const +{ + BPath iconStoragePath; + + if (find_directory(B_USER_CACHE_DIRECTORY, &iconStoragePath) == B_OK + && iconStoragePath.Append("HaikuDepot") == B_OK + && iconStoragePath.Append("__allicons") == B_OK + && create_directory(iconStoragePath.Path(), 0777) == B_OK) { + path.SetTo(iconStoragePath.Path()); + return B_OK; + } + + path.Unset(); + fprintf(stdout, "unable to find the user cache directory for icons"); + return B_ERROR; +} + + +status_t +Model::DumpExportPkgDataPath(BPath& path, const BString& repositorySourceCode) const { BPath repoDataPath; @@ -889,24 +873,6 @@ Model::_DumpExportPkgDataPath(BPath& path, } -status_t -Model::PopulateWebAppRepositoryCodes() -{ - status_t result = B_OK; - BPath dataPath; - - result = _DumpExportRepositoryDataPath(dataPath); - - if (result != B_OK) - return result; - - RepositoryDataUpdateProcess process(dataPath, &fDepots); - result = process.Run(); - - return result; -} - - void Model::_UpdateIsFeaturedFilter() { @@ -917,141 +883,6 @@ Model::_UpdateIsFeaturedFilter() } -int32 -Model::_PopulateAllPackagesEntry(void* cookie) -{ - Model* model = static_cast(cookie); - model->_PopulateAllPackagesThread(); - model->_PopulateAllPackagesIcons(); - return 0; -} - - -void -Model::_PopulateAllPackagesIcons() -{ - fLocalIconStore.UpdateFromServerIfNecessary(); - - int32 depotIndex = 0; - int32 packageIndex = 0; - int32 countIconsSet = 0; - - fprintf(stdout, "will populate all packages' icons\n"); - - while (true) { - PackageInfoRef package; - BAutolock locker(&fLock); - - if (depotIndex > fDepots.CountItems()) { - fprintf(stdout, "did populate %" B_PRId32 " packages' icons\n", - countIconsSet); - return; - } - - const DepotInfo& depot = fDepots.ItemAt(depotIndex); - const PackageList& packages = depot.Packages(); - - if (packageIndex >= packages.CountItems()) { - // Need the next depot - packageIndex = 0; - depotIndex++; - } else { - package = packages.ItemAt(packageIndex); - - if (Logger::IsDebugEnabled()) { - fprintf(stdout, "will populate package icon for [%s]\n", - package->Name().String()); - } - - if (_PopulatePackageIcon(package) == B_OK) - countIconsSet++; - - packageIndex++; - } - } -} - - -void -Model::_PopulatePackagesForDepot(const DepotInfo& depotInfo) -{ - BString repositorySourceCode = depotInfo.WebAppRepositorySourceCode(); - BPath repositorySourcePkgDataPath; - - if (B_OK != _DumpExportPkgDataPath(repositorySourcePkgDataPath, - repositorySourceCode)) { - printf("unable to obtain the path for storing data for [%s]\n", - repositorySourceCode.String()); - } else { - - printf("will fetch and process data for repository source [%s]\n", - repositorySourceCode.String()); - - PkgDataUpdateProcess process( - repositorySourcePkgDataPath, - fLock, repositorySourceCode, fPreferredLanguage, - depotInfo.Packages(), - fCategories); - - process.Run(); - - printf("did fetch and process data for repository source [%s]\n", - repositorySourceCode.String()); - } -} - - -void -Model::_PopulateAllPackagesThread() -{ - int32 depotIndex = 0; - int32 count = 0; - - for (depotIndex = 0; - depotIndex < fDepots.CountItems() && !fStopPopulatingAllPackages; - depotIndex++) { - const DepotInfo& depot = fDepots.ItemAt(depotIndex); - - if (depot.WebAppRepositorySourceCode().Length() > 0) { - _PopulatePackagesForDepot(depot); - count++; - } - } - - printf("did populate package data for %" B_PRIi32 " depots\n", count); -} - - -status_t -Model::_PopulatePackageIcon(const PackageInfoRef& package) -{ - BPath bestIconPath; - - if ( fLocalIconStore.TryFindIconPath( - package->Name(), bestIconPath) == B_OK) { - - BFile bestIconFile(bestIconPath.Path(), O_RDONLY); - BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(bestIconFile), true); - BAutolock locker(&fLock); - package->SetIcon(bitmapRef); - - if (Logger::IsDebugEnabled()) { - fprintf(stdout, "have set the package icon for [%s] from [%s]\n", - package->Name().String(), bestIconPath.Path()); - } - - return B_OK; - } - - if (Logger::IsDebugEnabled()) { - fprintf(stdout, "did not set the package icon for [%s]; no data\n", - package->Name().String()); - } - - return B_FILE_NOT_FOUND; -} - - void Model::_PopulatePackageScreenshot(const PackageInfoRef& package, const ScreenshotInfo& info, int32 scaledWidth, bool fromCacheOnly) @@ -1128,3 +959,119 @@ Model::_NotifyAuthorizationChanged() listener->AuthorizationChanged(); } } + + +// temporary - should not be required once the repo info url is used. +static void +normalize_repository_base_url(BUrl& url) +{ + if (url.Protocol() == "https") + url.SetProtocol("http"); + + BString path(url.Path()); + + if (path.EndsWith("/")) + url.SetPath(path.Truncate(path.Length() - 1)); +} + + +void +Model::ForAllDepots(void (*func)(const DepotInfo& depot, void* context), + void* context) +{ + for (int32 i = 0; i < fDepots.CountItems(); i++) { + DepotInfo depotInfo = fDepots.ItemAtFast(i); + func(depotInfo, context); + } +} + + +// TODO; should use the repo.info url and not the base url. + +void +Model::ReplaceDepotByUrl(const BString& url, + DepotMapper* depotMapper, void* context) +{ + for (int32 i = 0; i < fDepots.CountItems(); i++) { + DepotInfo depotInfo = fDepots.ItemAtFast(i); + + BUrl url(url); + BUrl depotUrlNormalized(depotInfo.BaseURL()); + + normalize_repository_base_url(url); + normalize_repository_base_url(depotUrlNormalized); + + if (url == depotUrlNormalized) { + BAutolock locker(&fLock); + fDepots.Replace(i, depotMapper->MapDepot(depotInfo, context)); + } + } +} + + +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 +{ + int32 i; + + for (i = 0; i < fDepots.CountItems(); i++) { + const DepotInfo& depot = fDepots.ItemAt(i); + + if (depot.WebAppRepositoryCode().Length() == 0) { + printf("depot [%s]", depot.Name().String()); + + if (depot.BaseURL().Length() > 0) + printf(" (%s)", depot.BaseURL().String()); + + printf(" correlates with no repository in the haiku" + "depot server system\n"); + } + } +} \ No newline at end of file diff --git a/src/apps/haikudepot/model/Model.h b/src/apps/haikudepot/model/Model.h index 0394e83b60..fa852b176a 100644 --- a/src/apps/haikudepot/model/Model.h +++ b/src/apps/haikudepot/model/Model.h @@ -9,7 +9,9 @@ #include #include +#include "AbstractServerProcess.h" #include "LocalIconStore.h" +#include "BulkLoadContext.h" #include "PackageInfo.h" #include "WebAppInterface.h" @@ -37,6 +39,22 @@ public: virtual void AuthorizationChanged() = 0; }; + +class DepotMapper { +public: + virtual DepotInfo MapDepot(const DepotInfo& depot, + void* context) = 0; +}; + + +class PackageConsumer { +public: + virtual bool ConsumePackage( + const PackageInfoRef& packageInfoRef, + void* context) = 0; +}; + + typedef BReference ModelListenerRef; typedef List ModelListenerList; @@ -118,8 +136,6 @@ public: bool ShowDevelopPackages() const { return fShowDevelopPackages; } - status_t PopulateWebAppRepositoryCodes(); - // Retrieve package information static const uint32 POPULATE_CACHED_RATING = 1 << 0; static const uint32 POPULATE_CACHED_ICON = 1 << 1; @@ -131,8 +147,6 @@ public: void PopulatePackage(const PackageInfoRef& package, uint32 flags); - void PopulateAllPackages(); - void StopPopulatingAllPackages(); const StringList& SupportedLanguages() const { return fSupportedLanguages; } @@ -149,20 +163,41 @@ public: const WebAppInterface& GetWebAppInterface() const { return fWebAppInterface; } + void ReplaceDepotByUrl( + const BString& url, + 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, + const BString& repositorySourceCode) const; + + void LogDepotsWithNoWebAppRepositoryCode() const; private: - status_t _DumpExportRepositoryDataPath( - BPath& path) const; - status_t _DumpExportPkgDataPath(BPath& path, - const BString& repositorySourceCode) const; void _UpdateIsFeaturedFilter(); static int32 _PopulateAllPackagesEntry(void* cookie); - void _PopulateAllPackagesThread(); - void _PopulatePackagesForDepot( - const DepotInfo& depotInfo); - void _PopulateAllPackagesIcons(); + void _PopulatePackageScreenshot( + const PackageInfoRef& package, + const ScreenshotInfo& info, + int32 scaledWidth, bool fromCacheOnly); bool _GetCacheFile(BPath& path, BFile& file, directory_which directory, @@ -175,14 +210,6 @@ private: const char* fileName, bool ignoreAge, time_t maxAge) const; - status_t _PopulatePackageIcon( - const PackageInfoRef& package); - void _PopulatePackageScreenshot( - const PackageInfoRef& package, - const ScreenshotInfo& info, - int32 scaledWidth, - bool fromCacheOnly); - void _NotifyAuthorizationChanged(); private: @@ -190,8 +217,6 @@ private: DepotList fDepots; - LocalIconStore fLocalIconStore; - CategoryRef fCategoryAudio; CategoryRef fCategoryBusiness; CategoryRef fCategoryDevelopment; @@ -225,9 +250,6 @@ private: bool fShowSourcePackages; bool fShowDevelopPackages; - thread_id fPopulateAllPackagesThread; - volatile bool fStopPopulatingAllPackages; - StringList fSupportedLanguages; BString fPreferredLanguage; diff --git a/src/apps/haikudepot/model/PackageInfo.cpp b/src/apps/haikudepot/model/PackageInfo.cpp index 94e67f9e77..6607a35629 100644 --- a/src/apps/haikudepot/model/PackageInfo.cpp +++ b/src/apps/haikudepot/model/PackageInfo.cpp @@ -1,7 +1,7 @@ /* * Copyright 2013-2014, Stephan Aßmus . * Copyright 2013, Rene Gollent . - * Copyright 2016, Andrew Lindesay . + * Copyright 2016-2017, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ @@ -1047,10 +1047,35 @@ 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. + */ + bool DepotInfo::AddPackage(const PackageInfoRef& package) { - return fPackages.Add(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()); +} + + +int32 +DepotInfo::PackageIndexByName(const BString& packageName) +{ + return fPackages.BinarySearch(&packageName, &PackageFixedNameCompare); } diff --git a/src/apps/haikudepot/model/PackageInfo.h b/src/apps/haikudepot/model/PackageInfo.h index 0a754a8000..99d508a2e7 100644 --- a/src/apps/haikudepot/model/PackageInfo.h +++ b/src/apps/haikudepot/model/PackageInfo.h @@ -1,6 +1,6 @@ /* * Copyright 2013-2014, Stephan Aßmus . - * Copyright 2016, Andrew Lindesay . + * Copyright 2016-2017, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ #ifndef PACKAGE_INFO_H @@ -411,6 +411,8 @@ public: bool AddPackage(const PackageInfoRef& package); + int32 PackageIndexByName(const BString& packageName); + void SyncPackages(const PackageList& packages); void SetBaseURL(const BString& baseURL); diff --git a/src/apps/haikudepot/server/AbstractServerProcess.cpp b/src/apps/haikudepot/server/AbstractServerProcess.cpp index ebb20bad12..5b8b77f80d 100644 --- a/src/apps/haikudepot/server/AbstractServerProcess.cpp +++ b/src/apps/haikudepot/server/AbstractServerProcess.cpp @@ -4,13 +4,15 @@ */ #include "AbstractServerProcess.h" +#include #include #include #include +#include #include -#include #include +#include #include #include @@ -18,6 +20,7 @@ #include "Logger.h" #include "ServerSettings.h" #include "StandardMetaDataJsonEventListener.h" +#include "StorageUtils.h" #include "ToFileUrlProtocolListener.h" @@ -31,6 +34,140 @@ #define TIMEOUT_MICROSECONDS 3e+7 +AbstractServerProcess::AbstractServerProcess( + AbstractServerProcessListener* listener, uint32 options) + : + fLock(), + fListener(listener), + fWasStopped(false), + fProcessState(SERVER_PROCESS_INITIAL), + fErrorStatus(B_OK), + fOptions(options), + fRequest(NULL) +{ +} + + +AbstractServerProcess::~AbstractServerProcess() +{ +} + + +bool +AbstractServerProcess::HasOption(uint32 flag) +{ + return (fOptions & flag) == flag; +} + + +bool +AbstractServerProcess::ShouldAttemptNetworkDownload(bool hasDataAlready) +{ + return + !HasOption(SERVER_PROCESS_NO_NETWORKING) + && !(HasOption(SERVER_PROCESS_PREFER_CACHE) && 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() +{ + if (fRequest != NULL) { + 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; +} + + status_t AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue) const { @@ -74,8 +211,9 @@ AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue, headerValue.SetTo(modifiedHttpTime .ToString(BPrivate::B_HTTP_TIME_FORMAT_COOKIE)); } else { - fprintf(stderr, "unable to parse the meta-data date and time -" - " cannot set the 'If-Modified-Since' header\n"); + fprintf(stderr, "unable to parse the meta-data date and time from [%s]" + " - cannot set the 'If-Modified-Since' header\n", + metaDataPath.Path()); } return result; @@ -163,10 +301,52 @@ AbstractServerProcess::ParseJsonFromFileWithListener( } +/*! In order to reduce the chance of failure half way through downloading a + large file, this method will download the file to a temporary file and + then it can rename the file to the final target file. +*/ + +status_t +AbstractServerProcess::DownloadToLocalFileAtomically( + const BPath& targetFilePath, + const BUrl& url) +{ + BPath temporaryFilePath(tmpnam(NULL), NULL, true); + status_t result = DownloadToLocalFile( + temporaryFilePath, url, 0, 0); + + // not copying if the data has not changed because the data will be + // zero length. This is if the result is APP_ERR_NOT_MODIFIED. + if (result == B_OK) { + + // if the file is zero length then assume that something has + // gone wrong. + off_t size; + bool hasFile; + + result = StorageUtils::ExistsObject(temporaryFilePath, &hasFile, NULL, + &size); + + if (result == B_OK && hasFile && size > 0) { + if (rename(temporaryFilePath.Path(), targetFilePath.Path()) != 0) { + printf("[%s] did rename [%s] --> [%s]\n", + Name(), temporaryFilePath.Path(), targetFilePath.Path()); + result = B_IO_ERROR; + } + } + } + + return result; +} + + status_t AbstractServerProcess::DownloadToLocalFile(const BPath& targetFilePath, const BUrl& url, uint32 redirects, uint32 failures) { + if (WasStopped()) + return B_CANCELED; + if (redirects > MAX_REDIRECTS) { fprintf(stdout, "exceeded %d redirects --> failure\n", MAX_REDIRECTS); return B_IO_ERROR; @@ -177,10 +357,10 @@ AbstractServerProcess::DownloadToLocalFile(const BPath& targetFilePath, return B_IO_ERROR; } - fprintf(stdout, "will stream '%s' to [%s]\n", url.UrlString().String(), - targetFilePath.Path()); + fprintf(stdout, "[%s] will stream '%s' to [%s]\n", + Name(), url.UrlString().String(), targetFilePath.Path()); - ToFileUrlProtocolListener listener(targetFilePath, LoggingName(), + ToFileUrlProtocolListener listener(targetFilePath, Name(), Logger::IsTraceEnabled()); BHttpHeaders headers; @@ -195,57 +375,77 @@ AbstractServerProcess::DownloadToLocalFile(const BPath& targetFilePath, headers.AddHeader("If-Modified-Since", ifModifiedSinceHeader); } - BHttpRequest *request = dynamic_cast( - BUrlProtocolRoster::MakeRequest(url, &listener)); - ObjectDeleter requestDeleter(request); - request->SetHeaders(headers); - request->SetMaxRedirections(0); - request->SetTimeout(TIMEOUT_MICROSECONDS); + thread_id thread; + + { + fRequest = dynamic_cast( + BUrlProtocolRoster::MakeRequest(url, &listener)); + fRequest->SetHeaders(headers); + fRequest->SetMaxRedirections(0); + fRequest->SetTimeout(TIMEOUT_MICROSECONDS); + thread = fRequest->Run(); + } - thread_id thread = request->Run(); wait_for_thread(thread, NULL); const BHttpResult& result = dynamic_cast( - request->Result()); - + fRequest->Result()); int32 statusCode = result.StatusCode(); + const BHttpHeaders responseHeaders = result.Headers(); + const char *locationC = responseHeaders["Location"]; + BString location; + + if (locationC != NULL) + location.SetTo(locationC); + + delete fRequest; + fRequest = NULL; if (BHttpRequest::IsSuccessStatusCode(statusCode)) { - fprintf(stdout, "did complete streaming data\n"); + fprintf(stdout, "[%s] did complete streaming data [%" + B_PRIdSSIZE " bytes]\n", Name(), listener.ContentLength()); return B_OK; } else if (statusCode == HTTP_STATUS_NOT_MODIFIED) { - fprintf(stdout, "remote data has not changed since [%s]\n", - ifModifiedSinceHeader.String()); + fprintf(stdout, "[%s] remote data has not changed since [%s]\n", + Name(), ifModifiedSinceHeader.String()); return APP_ERR_NOT_MODIFIED; } else if (BHttpRequest::IsRedirectionStatusCode(statusCode)) { - const BHttpHeaders responseHeaders = result.Headers(); - const char *locationValue = responseHeaders["Location"]; - - if (locationValue != NULL && strlen(locationValue) != 0) { - BUrl location(result.Url(), locationValue); - fprintf(stdout, "will redirect to; %s\n", - location.UrlString().String()); - return DownloadToLocalFile(targetFilePath, location, - redirects + 1, 0); + if (location.Length() != 0) { + BUrl location(result.Url(), location); + fprintf(stdout, "[%s] will redirect to; %s\n", + Name(), location.UrlString().String()); + return DownloadToLocalFile(targetFilePath, location, + redirects + 1, 0); } - fprintf(stdout, "unable to find 'Location' header for redirect\n"); + fprintf(stdout, "[%s] unable to find 'Location' header for redirect\n", + Name()); return B_IO_ERROR; } else { if (statusCode == 0 || (statusCode / 100) == 5) { - fprintf(stdout, "error response from server; %" B_PRId32 " --> " + fprintf(stdout, "error response from server [%" B_PRId32 "] --> " "retry...\n", statusCode); return DownloadToLocalFile(targetFilePath, url, redirects, failures + 1); } - fprintf(stdout, "unexpected response from server; %" B_PRId32 "\n", - statusCode); + fprintf(stdout, "[%s] unexpected response from server [%" B_PRId32 "]\n", + Name(), statusCode); return B_IO_ERROR; } } +status_t +AbstractServerProcess::DeleteLocalFile(const BPath& currentFilePath) +{ + if (0 == remove(currentFilePath.Path())) + return B_OK; + + return B_IO_ERROR; +} + + /*! When a file is damaged or corrupted in some way, the file should be 'moved aside' so that it is not involved in the next update. This method will create such an alternative 'damaged' file location and move this file to @@ -263,13 +463,19 @@ AbstractServerProcess::MoveDamagedFileAside(const BPath& currentFilePath) damagedFilePath.Append(damagedLeaf.String()); if (0 != rename(currentFilePath.Path(), damagedFilePath.Path())) { - printf("unable to move damaged file [%s] aside to [%s]\n", - currentFilePath.Path(), damagedFilePath.Path()); + printf("[%s] unable to move damaged file [%s] aside to [%s]\n", + Name(), currentFilePath.Path(), damagedFilePath.Path()); return B_IO_ERROR; } - printf("did move damaged file [%s] aside to [%s]\n", - currentFilePath.Path(), damagedFilePath.Path()); + printf("[%s] did move damaged file [%s] aside to [%s]\n", + Name(), currentFilePath.Path(), damagedFilePath.Path()); return B_OK; } + + +bool +AbstractServerProcess::IsSuccess(status_t e) { + return e == B_OK || e == APP_ERR_NOT_MODIFIED; +} diff --git a/src/apps/haikudepot/server/AbstractServerProcess.h b/src/apps/haikudepot/server/AbstractServerProcess.h index de8c0d0229..f8288b13e3 100644 --- a/src/apps/haikudepot/server/AbstractServerProcess.h +++ b/src/apps/haikudepot/server/AbstractServerProcess.h @@ -6,26 +6,66 @@ #ifndef ABSTRACT_SERVER_PROCESS_H #define ABSTRACT_SERVER_PROCESS_H +#include #include #include #include #include "StandardMetaData.h" +#include "Stoppable.h" -#define APP_ERR_NOT_MODIFIED (B_APP_ERROR_BASE + 452) +#define APP_ERR_NOT_MODIFIED (B_APP_ERROR_BASE + 452) +#define APP_ERR_NO_DATA (B_APP_ERROR_BASE + 453) -class AbstractServerProcess { +typedef enum process_options { + SERVER_PROCESS_NO_NETWORKING = 1 << 0, + SERVER_PROCESS_PREFER_CACHE = 1 << 1, + SERVER_PROCESS_DROP_CACHE = 1 << 2 +} process_options; + + +typedef enum process_state { + SERVER_PROCESS_INITIAL = 1, + SERVER_PROCESS_RUNNING = 2, + SERVER_PROCESS_COMPLETE = 3 +} 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 AbstractServerProcessListener { public: - virtual status_t Run() = 0; + virtual void ServerProcessExited() = 0; +}; + + +class AbstractServerProcess : public Stoppable { +public: + AbstractServerProcess( + AbstractServerProcessListener* listener, + 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( BPath& path) const = 0; virtual void GetStandardMetaDataJsonPath( BString& jsonPath) const = 0; - virtual const char* LoggingName() const = 0; status_t IfModifiedSinceHeaderValue( BString& headerValue) const; @@ -43,15 +83,41 @@ protected: BJsonEventListener *listener, const BPath& path) const; + status_t DownloadToLocalFileAtomically( + const BPath& targetFilePath, + const BUrl& url); + + status_t DeleteLocalFile(const BPath& currentFilePath); + + status_t MoveDamagedFileAside( + const BPath& currentFilePath); + + bool HasOption(uint32 flag); + bool ShouldAttemptNetworkDownload( + bool hasDataAlready); + + static bool IsSuccess(status_t e); + +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); - status_t MoveDamagedFileAside( - const BPath& currentFilePath); - -private: bool LooksLikeGzip(const char *pathStr) const; }; diff --git a/src/apps/haikudepot/server/PkgDataUpdateProcess.cpp b/src/apps/haikudepot/server/PkgDataUpdateProcess.cpp index 961f8a447a..c5d1b23b19 100644 --- a/src/apps/haikudepot/server/PkgDataUpdateProcess.cpp +++ b/src/apps/haikudepot/server/PkgDataUpdateProcess.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include "Logger.h" @@ -27,39 +28,46 @@ packages as they are parsed and processing them. */ -class PackageFillingPkgListener : public DumpExportPkgListener { +class PackageFillingPkgListener : + public DumpExportPkgListener, public PackageConsumer { public: - PackageFillingPkgListener( - const PackageList& packages, - const CategoryList& categories, - BLocker& lock); + PackageFillingPkgListener(Model *model, + BString& depotName, Stoppable* stoppable); virtual ~PackageFillingPkgListener(); - virtual void Handle(DumpExportPkg* item); + virtual bool ConsumePackage(const PackageInfoRef& package, + void *context); + virtual bool Handle(DumpExportPkg* item); virtual void Complete(); + uint32 Count(); + private: int32 IndexOfPackageByName(const BString& name) const; int32 IndexOfCategoryByName( const BString& name) const; int32 IndexOfCategoryByCode( const BString& code) const; - const PackageList& fPackages; - const CategoryList& fCategories; - BLocker& fLock; - + BString fDepotName; + Model* fModel; + CategoryList fCategories; + Stoppable* fStoppable; + uint32 fCount; + bool fDebugEnabled; }; -PackageFillingPkgListener::PackageFillingPkgListener( - const PackageList& packages, const CategoryList& categories, - BLocker& lock) +PackageFillingPkgListener::PackageFillingPkgListener(Model* model, + BString& depotName, Stoppable* stoppable) : - fPackages(packages), - fCategories(categories), - fLock(lock) + fDepotName(depotName), + fModel(model), + fStoppable(stoppable), + fCount(0), + fDebugEnabled(Logger::IsDebugEnabled()) { + fCategories = model->Categories(); } @@ -70,32 +78,14 @@ PackageFillingPkgListener::~PackageFillingPkgListener() // TODO; performance could be improved by not needing the linear search -int32 -PackageFillingPkgListener::IndexOfPackageByName( - const BString& name) const -{ - int32 i; - - for (i = 0; i < fPackages.CountItems(); i++) { - const PackageInfoRef& packageInfo = fPackages.ItemAt(i); - - if (packageInfo->Name() == name) - return i; - } - - return -1; -} - - - // TODO; performance could be improved by not needing the linear search - -int32 +inline int32 PackageFillingPkgListener::IndexOfCategoryByName( const BString& name) const { int32 i; + int32 categoryCount = fCategories.CountItems(); - for (i = 0; i < fCategories.CountItems(); i++) { + for (i = 0; i < categoryCount; i++) { const CategoryRef categoryRef = fCategories.ItemAtFast(i); if (categoryRef->Name() == name) @@ -106,81 +96,95 @@ PackageFillingPkgListener::IndexOfCategoryByName( } -void -PackageFillingPkgListener::Handle(DumpExportPkg* pkg) +bool +PackageFillingPkgListener::ConsumePackage(const PackageInfoRef& package, + void *context) { - BAutolock locker(fLock); // lock from the model. - int32 packageIndex = IndexOfPackageByName(*(pkg->Name())); + DumpExportPkg* pkg = static_cast(context); + int32 i; - if (packageIndex == -1) { - printf("unable to find package data for pkg name [%s]\n", - pkg->Name()->String()); - } else { - int32 i; - const PackageInfoRef& packageInfo = fPackages.ItemAt(packageIndex); + if (0 != pkg->CountPkgVersions()) { - if (0 != pkg->CountPkgVersions()) { + // this makes the assumption that the only version will be the + // latest one. - // this makes the assumption that the only version will be the - // latest one. + DumpExportPkgVersion* pkgVersion = pkg->PkgVersionsItemAt(0); - DumpExportPkgVersion* pkgVersion = pkg->PkgVersionsItemAt(0); + if (!pkgVersion->TitleIsNull()) + package->SetTitle(*(pkgVersion->Title())); - if (!pkgVersion->TitleIsNull()) - packageInfo->SetTitle(*(pkgVersion->Title())); + if (!pkgVersion->SummaryIsNull()) + package->SetShortDescription(*(pkgVersion->Summary())); - if (!pkgVersion->SummaryIsNull()) - packageInfo->SetShortDescription(*(pkgVersion->Summary())); + if (!pkgVersion->DescriptionIsNull()) + package->SetFullDescription(*(pkgVersion->Description())); - if (!pkgVersion->DescriptionIsNull()) { - packageInfo->SetFullDescription(*(pkgVersion->Description())); - } + if (!pkgVersion->PayloadLengthIsNull()) + package->SetSize(pkgVersion->PayloadLength()); + } - if (!pkgVersion->PayloadLengthIsNull()) - packageInfo->SetSize(pkgVersion->PayloadLength()); - } + int32 countPkgCategories = pkg->CountPkgCategories(); - for (i = 0; i < pkg->CountPkgCategories(); i++) { - BString* categoryCode = pkg->PkgCategoriesItemAt(i)->Code(); - int categoryIndex = IndexOfCategoryByName(*(categoryCode)); + for (i = 0; i < countPkgCategories; i++) { + BString* categoryCode = pkg->PkgCategoriesItemAt(i)->Code(); + int categoryIndex = IndexOfCategoryByName(*(categoryCode)); - if (categoryIndex == -1) { - printf("unable to find the category for [%s]\n", - categoryCode->String()); - } else { - packageInfo->AddCategory( - fCategories.ItemAtFast(categoryIndex)); - } - } - - if (!pkg->DerivedRatingIsNull()) { - RatingSummary summary; - summary.averageRating = pkg->DerivedRating(); - packageInfo->SetRatingSummary(summary); - } - - if (!pkg->ProminenceOrderingIsNull()) { - packageInfo->SetProminence(pkg->ProminenceOrdering()); - } - - if (!pkg->PkgChangelogContentIsNull()) { - packageInfo->SetChangelog(*(pkg->PkgChangelogContent())); - } - - for (i = 0; i < pkg->CountPkgScreenshots(); i++) { - DumpExportPkgScreenshot* screenshot = pkg->PkgScreenshotsItemAt(i); - packageInfo->AddScreenshotInfo(ScreenshotInfo( - *(screenshot->Code()), - static_cast(screenshot->Width()), - static_cast(screenshot->Height()), - static_cast(screenshot->Length()) - )); - } - - if (Logger::IsDebugEnabled()) { - printf("did populate data for [%s]\n", pkg->Name()->String()); + if (categoryIndex == -1) { + printf("unable to find the category for [%s]\n", + categoryCode->String()); + } else { + package->AddCategory( + fCategories.ItemAtFast(categoryIndex)); } } + + if (!pkg->DerivedRatingIsNull()) { + RatingSummary summary; + summary.averageRating = pkg->DerivedRating(); + package->SetRatingSummary(summary); + } + + if (!pkg->ProminenceOrderingIsNull()) + package->SetProminence(pkg->ProminenceOrdering()); + + if (!pkg->PkgChangelogContentIsNull()) + package->SetChangelog(*(pkg->PkgChangelogContent())); + + int32 countPkgScreenshots = pkg->CountPkgScreenshots(); + + for (i = 0; i < countPkgScreenshots; i++) { + DumpExportPkgScreenshot* screenshot = pkg->PkgScreenshotsItemAt(i); + package->AddScreenshotInfo(ScreenshotInfo( + *(screenshot->Code()), + static_cast(screenshot->Width()), + static_cast(screenshot->Height()), + static_cast(screenshot->Length()) + )); + } + + if (fDebugEnabled) { + printf("did populate data for [%s] (%s)\n", pkg->Name()->String(), + fDepotName.String()); + } + + fCount++; + + return !fStoppable->WasStopped(); +} + + +uint32 +PackageFillingPkgListener::Count() +{ + return fCount; +} + + +bool +PackageFillingPkgListener::Handle(DumpExportPkg* pkg) +{ + fModel->ForPackageByNameInDepot(fDepotName, *(pkg->Name()), this, pkg); + return !fStoppable->WasStopped(); } @@ -191,20 +195,22 @@ PackageFillingPkgListener::Complete() PkgDataUpdateProcess::PkgDataUpdateProcess( + AbstractServerProcessListener* listener, const BPath& localFilePath, - BLocker& lock, - BString repositorySourceCode, BString naturalLanguageCode, - const PackageList& packages, - const CategoryList& categories) + BString repositorySourceCode, + BString depotName, + Model *model, + uint32 options) : + AbstractSingleFileServerProcess(listener, options), fLocalFilePath(localFilePath), fNaturalLanguageCode(naturalLanguageCode), fRepositorySourceCode(repositorySourceCode), - fPackages(packages), - fCategories(categories), - fLock(lock) + fModel(model), + fDepotName(depotName) { + fName.SetToFormat("PkgDataUpdateProcess<%s>", depotName.String()); } @@ -213,53 +219,50 @@ PkgDataUpdateProcess::~PkgDataUpdateProcess() } -status_t -PkgDataUpdateProcess::Run() +const char* +PkgDataUpdateProcess::Name() { - printf("will fetch packages' data\n"); + return fName.String(); +} + +BString +PkgDataUpdateProcess::UrlPathComponent() +{ BString urlPath; urlPath.SetToFormat("/__pkg/all-%s-%s.json.gz", fRepositorySourceCode.String(), fNaturalLanguageCode.String()); + return urlPath; +} - status_t result = DownloadToLocalFile(fLocalFilePath, - ServerSettings::CreateFullUrl(urlPath), - 0, 0); - if (result == B_OK || result == APP_ERR_NOT_MODIFIED) { - printf("did fetch packages' data\n"); - - // now load the data in and process it. - - printf("will process packages' data\n"); - result = PopulateDataToDepots(); - - switch (result) { - case B_OK: - printf("did process packages' data\n"); - break; - default: - MoveDamagedFileAside(fLocalFilePath); - break; - } - } - - return result; +BPath& +PkgDataUpdateProcess::LocalPath() +{ + return fLocalFilePath; } status_t -PkgDataUpdateProcess::PopulateDataToDepots() +PkgDataUpdateProcess::ProcessLocalData() { + BStopWatch watch("PkgDataUpdateProcess::ProcessLocalData", true); + PackageFillingPkgListener* itemListener = - new PackageFillingPkgListener(fPackages, fCategories, fLock); + new PackageFillingPkgListener(fModel, fDepotName, this); BulkContainerDumpExportPkgJsonListener* listener = new BulkContainerDumpExportPkgJsonListener(itemListener); status_t result = ParseJsonFromFileWithListener(listener, fLocalFilePath); + if (Logger::IsInfoEnabled()) { + double secs = watch.ElapsedTime() / 1000000.0; + fprintf(stdout, "[%s] did process %" B_PRIi32 " packages' data " + "in (%6.3g secs)\n", Name(), itemListener->Count(), secs); + } + if (B_OK != result) return result; @@ -280,10 +283,3 @@ PkgDataUpdateProcess::GetStandardMetaDataJsonPath( { jsonPath.SetTo("$.info"); } - - -const char* -PkgDataUpdateProcess::LoggingName() const -{ - return "pkg-data-update"; -} diff --git a/src/apps/haikudepot/server/PkgDataUpdateProcess.h b/src/apps/haikudepot/server/PkgDataUpdateProcess.h index 749783acfc..7d1486a40e 100644 --- a/src/apps/haikudepot/server/PkgDataUpdateProcess.h +++ b/src/apps/haikudepot/server/PkgDataUpdateProcess.h @@ -7,8 +7,9 @@ #define PACKAGE_DATA_UPDATE_PROCESS_H -#include "AbstractServerProcess.h" +#include "AbstractSingleFileServerProcess.h" +#include "Model.h" #include "PackageInfo.h" #include @@ -17,34 +18,37 @@ #include -class PkgDataUpdateProcess : public AbstractServerProcess { +class PkgDataUpdateProcess : public AbstractSingleFileServerProcess { public: PkgDataUpdateProcess( + AbstractServerProcessListener* listener, const BPath& localFilePath, - BLocker& lock, BString naturalLanguageCode, BString repositorySourceCode, - const PackageList& packages, - const CategoryList& categories); + BString depotName, + Model *model, + uint32 options); virtual ~PkgDataUpdateProcess(); - status_t Run(); + const char* Name(); protected: void GetStandardMetaDataPath(BPath& path) const; void GetStandardMetaDataJsonPath( BString& jsonPath) const; - const char* LoggingName() const; + + BString UrlPathComponent(); + status_t ProcessLocalData(); + BPath& LocalPath(); private: - status_t PopulateDataToDepots(); BPath fLocalFilePath; BString fNaturalLanguageCode; BString fRepositorySourceCode; - const PackageList& fPackages; - const CategoryList& fCategories; - BLocker& fLock; + Model* fModel; + BString fDepotName; + BString fName; }; diff --git a/src/apps/haikudepot/server/RepositoryDataUpdateProcess.cpp b/src/apps/haikudepot/server/RepositoryDataUpdateProcess.cpp index 321807576c..bbd0eac64f 100644 --- a/src/apps/haikudepot/server/RepositoryDataUpdateProcess.cpp +++ b/src/apps/haikudepot/server/RepositoryDataUpdateProcess.cpp @@ -14,6 +14,7 @@ #include "ServerSettings.h" #include "StorageUtils.h" +#include "Logger.h" #include "DumpExportRepository.h" #include "DumpExportRepositorySource.h" #include "DumpExportRepositoryJsonListener.h" @@ -25,13 +26,15 @@ from the server with the data about the depot. */ -class DepotMatchingRepositoryListener : public DumpExportRepositoryListener { +class DepotMatchingRepositoryListener : + public DumpExportRepositoryListener, public DepotMapper { public: - DepotMatchingRepositoryListener( - DepotList* depotList); + DepotMatchingRepositoryListener(Model* model, + Stoppable* stoppable); virtual ~DepotMatchingRepositoryListener(); - virtual void Handle(DumpExportRepository* item); + virtual DepotInfo MapDepot(const DepotInfo& depot, void *context); + virtual bool Handle(DumpExportRepository* item); virtual void Complete(); private: @@ -43,15 +46,17 @@ private: int32 IndexOfUnassociatedDepotByUrl( const BString& url) const; - DepotList* fDepotList; - + Model* fModel; + Stoppable* fStoppable; }; DepotMatchingRepositoryListener::DepotMatchingRepositoryListener( - DepotList* depotList) + Model* model, Stoppable* stoppable) + : + fModel(model), + fStoppable(stoppable) { - fDepotList = depotList; } @@ -60,110 +65,86 @@ DepotMatchingRepositoryListener::~DepotMatchingRepositoryListener() } -void -DepotMatchingRepositoryListener::NormalizeUrl(BUrl& url) const +struct repository_and_repository_source { + DumpExportRepository* repository; + DumpExportRepositorySource* repositorySource; +}; + + +/*! This is invoked as a result of logic in 'Handle(..)' that requests that the + model call this method with the requested DepotInfo instance. +*/ + +DepotInfo +DepotMatchingRepositoryListener::MapDepot(const DepotInfo& depot, void *context) { - if (url.Protocol() == "https") - url.SetProtocol("http"); + repository_and_repository_source* repositoryAndRepositorySource = + (repository_and_repository_source*) context; + BString* repositoryCode = + repositoryAndRepositorySource->repository->Code(); + BString* repositorySourceCode = + repositoryAndRepositorySource->repositorySource->Code(); - BString path(url.Path()); + DepotInfo modifiedDepotInfo(depot); + modifiedDepotInfo.SetWebAppRepositoryCode(BString(*repositoryCode)); + modifiedDepotInfo.SetWebAppRepositorySourceCode( + BString(*repositorySourceCode)); - if (path.EndsWith("/")) - url.SetPath(path.Truncate(path.Length() - 1)); + if (Logger::IsDebugEnabled()) { + printf("associated dept [%s] (%s) with server repository " + "source [%s] (%s)\n", modifiedDepotInfo.Name().String(), + modifiedDepotInfo.BaseURL().String(), + repositorySourceCode->String(), + repositoryAndRepositorySource->repositorySource->Url()->String()); + } else { + printf("associated depot [%s] with server repository source [%s]\n", + modifiedDepotInfo.Name().String(), repositorySourceCode->String()); + } + + return modifiedDepotInfo; } bool -DepotMatchingRepositoryListener::IsUnassociatedDepotByUrl( - const DepotInfo& depotInfo, const BString& urlStr) const -{ - if (depotInfo.BaseURL().Length() > 0 - && depotInfo.WebAppRepositorySourceCode().Length() == 0) { - BUrl depotInfoBaseUrl(depotInfo.BaseURL()); - BUrl url(urlStr); - - NormalizeUrl(depotInfoBaseUrl); - NormalizeUrl(url); - - if (depotInfoBaseUrl == url) - return true; - } - - return false; -} - - -int32 -DepotMatchingRepositoryListener::IndexOfUnassociatedDepotByUrl( - const BString& url) const -{ - int32 i; - - for (i = 0; i < fDepotList->CountItems(); i++) { - const DepotInfo& depot = fDepotList->ItemAt(i); - - if (IsUnassociatedDepotByUrl(depot, url)) - return i; - } - - return -1; -} - - -void DepotMatchingRepositoryListener::Handle(DumpExportRepository* repository) { int32 i; for (i = 0; i < repository->CountRepositorySources(); i++) { - DumpExportRepositorySource *repositorySource = + repository_and_repository_source repositoryAndRepositorySource; + repositoryAndRepositorySource.repository = repository; + repositoryAndRepositorySource.repositorySource = repository->RepositorySourcesItemAt(i); - int32 depotIndex = IndexOfUnassociatedDepotByUrl( - *(repositorySource->Url())); - if (depotIndex >= 0) { - DepotInfo modifiedDepotInfo(fDepotList->ItemAt(depotIndex)); - modifiedDepotInfo.SetWebAppRepositoryCode( - BString(*(repository->Code()))); - modifiedDepotInfo.SetWebAppRepositorySourceCode( - BString(*(repositorySource->Code()))); - fDepotList->Replace(depotIndex, modifiedDepotInfo); + // TODO; replace with the repo info url + BString* url = repositoryAndRepositorySource.repositorySource->Url(); - printf("associated depot [%s] with server" - " repository source [%s]\n", modifiedDepotInfo.Name().String(), - repositorySource->Code()->String()); + if (url->Length() > 0) { + fModel->ReplaceDepotByUrl(*url, this, + &repositoryAndRepositorySource); } } + + return !fStoppable->WasStopped(); } void DepotMatchingRepositoryListener::Complete() { - int32 i; - - for (i = 0; i < fDepotList->CountItems(); i++) { - const DepotInfo& depot = fDepotList->ItemAt(i); - - if (depot.WebAppRepositoryCode().Length() == 0) { - printf("depot [%s]", depot.Name().String()); - - if (depot.BaseURL().Length() > 0) - printf(" (%s)", depot.BaseURL().String()); - - printf(" correlates with no repository in the haiku" - "depot server system\n"); - } - } } RepositoryDataUpdateProcess::RepositoryDataUpdateProcess( + AbstractServerProcessListener* listener, const BPath& localFilePath, - DepotList* depotList) + Model* model, + uint32 options) + : + AbstractSingleFileServerProcess(listener, options), + fLocalFilePath(localFilePath), + fModel(model) { - fLocalFilePath = localFilePath; - fDepotList = depotList; } @@ -172,46 +153,32 @@ RepositoryDataUpdateProcess::~RepositoryDataUpdateProcess() } -status_t -RepositoryDataUpdateProcess::Run() +const char* +RepositoryDataUpdateProcess::Name() { - printf("will fetch repositories data\n"); + return "RepositoryDataUpdateProcess"; +} - // TODO: add language ISO code to the path; just 'en' for now. - status_t result = DownloadToLocalFile(fLocalFilePath, - ServerSettings::CreateFullUrl("/__repository/all-en.json.gz"), - 0, 0); - if (result == B_OK || result == APP_ERR_NOT_MODIFIED) { - printf("did fetch repositories data\n"); +BString +RepositoryDataUpdateProcess::UrlPathComponent() +{ + return BString("/__repository/all-en.json.gz"); +} - // now load the data in and process it. - printf("will process repository data and match to depots\n"); - result = PopulateDataToDepots(); - - switch (result) { - case B_OK: - printf("did process repository data and match to depots\n"); - break; - default: - MoveDamagedFileAside(fLocalFilePath); - break; - } - - } else { - printf("an error has arisen downloading the repositories' data\n"); - } - - return result; +BPath& +RepositoryDataUpdateProcess::LocalPath() +{ + return fLocalFilePath; } status_t -RepositoryDataUpdateProcess::PopulateDataToDepots() +RepositoryDataUpdateProcess::ProcessLocalData() { DepotMatchingRepositoryListener* itemListener = - new DepotMatchingRepositoryListener(fDepotList); + new DepotMatchingRepositoryListener(fModel, this); BulkContainerDumpExportRepositoryJsonListener* listener = new BulkContainerDumpExportRepositoryJsonListener(itemListener); @@ -238,10 +205,3 @@ RepositoryDataUpdateProcess::GetStandardMetaDataJsonPath( { jsonPath.SetTo("$.info"); } - - -const char* -RepositoryDataUpdateProcess::LoggingName() const -{ - return "repo-data-update"; -} \ No newline at end of file diff --git a/src/apps/haikudepot/server/RepositoryDataUpdateProcess.h b/src/apps/haikudepot/server/RepositoryDataUpdateProcess.h index 1226a2aff4..5bc48900c3 100644 --- a/src/apps/haikudepot/server/RepositoryDataUpdateProcess.h +++ b/src/apps/haikudepot/server/RepositoryDataUpdateProcess.h @@ -7,8 +7,9 @@ #define REPOSITORY_DATA_UPDATE_PROCESS_H -#include "AbstractServerProcess.h" +#include "AbstractSingleFileServerProcess.h" +#include "Model.h" #include "PackageInfo.h" #include @@ -17,27 +18,29 @@ #include -class RepositoryDataUpdateProcess : public AbstractServerProcess { +class RepositoryDataUpdateProcess : public AbstractSingleFileServerProcess { public: RepositoryDataUpdateProcess( + AbstractServerProcessListener* listener, const BPath& localFilePath, - DepotList* depotList); + Model* model, uint32 options); virtual ~RepositoryDataUpdateProcess(); - status_t Run(); + const char* Name(); protected: void GetStandardMetaDataPath(BPath& path) const; void GetStandardMetaDataJsonPath( BString& jsonPath) const; - const char* LoggingName() const; + + BString UrlPathComponent(); + status_t ProcessLocalData(); + BPath& LocalPath(); private: - status_t PopulateDataToDepots(); - BPath fLocalFilePath; - DepotList* fDepotList; + Model* fModel; }; diff --git a/src/apps/haikudepot/server/ServerIconExportUpdateProcess.cpp b/src/apps/haikudepot/server/ServerIconExportUpdateProcess.cpp index af74cbf46b..5d434c9a35 100644 --- a/src/apps/haikudepot/server/ServerIconExportUpdateProcess.cpp +++ b/src/apps/haikudepot/server/ServerIconExportUpdateProcess.cpp @@ -9,9 +9,12 @@ #include #include +#include #include +#include #include +#include "Logger.h" #include "ServerSettings.h" #include "StorageUtils.h" #include "TarArchiveService.h" @@ -20,9 +23,17 @@ /*! This constructor will locate the cached data in a standardized location */ ServerIconExportUpdateProcess::ServerIconExportUpdateProcess( - const BPath& localStorageDirectoryPath) + AbstractServerProcessListener* listener, + const BPath& localStorageDirectoryPath, + Model* model, + uint32 options) + : + AbstractServerProcess(listener, options), + fLocalStorageDirectoryPath(localStorageDirectoryPath), + fModel(model), + fLocalIconStore(LocalIconStore(localStorageDirectoryPath)), + fCountIconsSet(0) { - fLocalStorageDirectoryPath = localStorageDirectoryPath; } @@ -31,8 +42,106 @@ ServerIconExportUpdateProcess::~ServerIconExportUpdateProcess() } +const char* +ServerIconExportUpdateProcess::Name() +{ + return "ServerIconExportUpdateProcess"; +} + + status_t -ServerIconExportUpdateProcess::Run() +ServerIconExportUpdateProcess::RunInternal() +{ + status_t result = B_OK; + + if (IsSuccess(result) && HasOption(SERVER_PROCESS_DROP_CACHE)) { + result = StorageUtils::RemoveDirectoryContents( + fLocalStorageDirectoryPath); + } + + if (IsSuccess(result)) { + bool hasData; + + result = HasLocalData(&hasData); + + if (IsSuccess(result) && ShouldAttemptNetworkDownload(hasData)) + result = DownloadAndUnpack(); + + if (IsSuccess(result)) { + status_t hasDataResult = HasLocalData(&hasData); + + if (IsSuccess(hasDataResult) && !hasData) + result = APP_ERR_NO_DATA; + } + } + + if (IsSuccess(result) && !WasStopped()) + result = Populate(); + + return result; +} + + +status_t +ServerIconExportUpdateProcess::PopulateForPkg(const PackageInfoRef& package) +{ + BPath bestIconPath; + + if ( fLocalIconStore.TryFindIconPath( + package->Name(), bestIconPath) == B_OK) { + + BFile bestIconFile(bestIconPath.Path(), O_RDONLY); + BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(bestIconFile), true); + // TODO; somehow handle the locking! + //BAutolock locker(&fLock); + package->SetIcon(bitmapRef); + + if (Logger::IsDebugEnabled()) { + fprintf(stdout, "have set the package icon for [%s] from [%s]\n", + package->Name().String(), bestIconPath.Path()); + } + + fCountIconsSet++; + + return B_OK; + } + + if (Logger::IsDebugEnabled()) { + fprintf(stdout, "did not set the package icon for [%s]; no data\n", + package->Name().String()); + } + + return B_FILE_NOT_FOUND; +} + + +bool +ServerIconExportUpdateProcess::ConsumePackage( + const PackageInfoRef& packageInfoRef, void* context) +{ + PopulateForPkg(packageInfoRef); + return !WasStopped(); +} + + +status_t +ServerIconExportUpdateProcess::Populate() +{ + BStopWatch watch("ServerIconExportUpdateProcess::Populate", true); + fModel->ForAllPackages(this, NULL); + + if (Logger::IsInfoEnabled()) { + double secs = watch.ElapsedTime() / 1000000.0; + fprintf(stdout, "did populate %" B_PRId32 " packages' icons" + " (%6.3g secs)\n", fCountIconsSet, secs); + } + + return B_OK; +} + + +status_t +ServerIconExportUpdateProcess::DownloadAndUnpack() { BPath tarGzFilePath(tmpnam(NULL)); status_t result = B_OK; @@ -59,10 +168,15 @@ ServerIconExportUpdateProcess::Run() zlibDecompressionParameters, tarIn); if (result == B_OK) { + BStopWatch watch("ServerIconExportUpdateProcess::DownloadAndUnpack_Unpack", true); + result = TarArchiveService::Unpack(*tarIn, - fLocalStorageDirectoryPath); + fLocalStorageDirectoryPath, NULL); if (result == B_OK) { + double secs = watch.ElapsedTime() / 1000000.0; + fprintf(stdout, "did unpack icon tgz in (%6.3g secs)\n", secs); + if (0 != remove(tarGzFilePath.Path())) { fprintf(stdout, "unable to delete the temporary tgz path; " "%s\n", tarGzFilePath.Path()); @@ -79,6 +193,17 @@ ServerIconExportUpdateProcess::Run() } +status_t +ServerIconExportUpdateProcess::HasLocalData(bool* result) const +{ + BPath path; + off_t size; + GetStandardMetaDataPath(path); + return StorageUtils::ExistsObject(path, result, NULL, &size) + && size > 0; +} + + void ServerIconExportUpdateProcess::GetStandardMetaDataPath(BPath& path) const { @@ -96,16 +221,9 @@ ServerIconExportUpdateProcess::GetStandardMetaDataJsonPath( } -const char* -ServerIconExportUpdateProcess::LoggingName() const -{ - return "icon-export-update"; -} - - status_t ServerIconExportUpdateProcess::Download(BPath& tarGzFilePath) { - return DownloadToLocalFile(tarGzFilePath, - ServerSettings::CreateFullUrl("/__pkgicon/all.tar.gz"), 0, 0); + return DownloadToLocalFileAtomically(tarGzFilePath, + ServerSettings::CreateFullUrl("/__pkgicon/all.tar.gz")); } \ No newline at end of file diff --git a/src/apps/haikudepot/server/ServerIconExportUpdateProcess.h b/src/apps/haikudepot/server/ServerIconExportUpdateProcess.h index f91c806801..ceb9c83058 100644 --- a/src/apps/haikudepot/server/ServerIconExportUpdateProcess.h +++ b/src/apps/haikudepot/server/ServerIconExportUpdateProcess.h @@ -8,6 +8,8 @@ #include "AbstractServerProcess.h" +#include "LocalIconStore.h" +#include "Model.h" #include #include @@ -15,26 +17,37 @@ #include -class ServerIconExportUpdateProcess : public AbstractServerProcess { +class ServerIconExportUpdateProcess : + public AbstractServerProcess, public PackageConsumer { public: ServerIconExportUpdateProcess( - const BPath& localStorageDirectoryPath); + AbstractServerProcessListener* listener, + const BPath& localStorageDirectoryPath, + Model* model, uint32 options); virtual ~ServerIconExportUpdateProcess(); - status_t Run(); + const char* Name(); + status_t RunInternal(); + virtual bool ConsumePackage( + const PackageInfoRef& packageInfoRef, + void *context); protected: + status_t PopulateForPkg(const PackageInfoRef& package); + status_t Populate(); + status_t DownloadAndUnpack(); + status_t HasLocalData(bool* result) const; void GetStandardMetaDataPath(BPath& path) const; void GetStandardMetaDataJsonPath( BString& jsonPath) const; - const char* LoggingName() const; - - private: status_t Download(BPath& tarGzFilePath); BPath fLocalStorageDirectoryPath; + Model* fModel; + LocalIconStore fLocalIconStore; + int32 fCountIconsSet; }; diff --git a/src/apps/haikudepot/server/ServerSettings.cpp b/src/apps/haikudepot/server/ServerSettings.cpp index c3009bdb2f..043fee4b48 100644 --- a/src/apps/haikudepot/server/ServerSettings.cpp +++ b/src/apps/haikudepot/server/ServerSettings.cpp @@ -21,6 +21,9 @@ BUrl ServerSettings::sBaseUrl = BUrl(BASEURL_DEFAULT); BString ServerSettings::sUserAgent = BString(); pthread_once_t ServerSettings::sUserAgentInitOnce = PTHREAD_ONCE_INIT; +bool ServerSettings::sPreferCache = false; +bool ServerSettings::sDropCache = false; +bool ServerSettings::sForceNoNetwork = false; status_t @@ -102,6 +105,7 @@ ServerSettings::_GetUserAgentVersionString() return result; } + void ServerSettings::AugmentHeaders(BHttpHeaders& headers) { @@ -109,3 +113,43 @@ ServerSettings::AugmentHeaders(BHttpHeaders& headers) } +bool +ServerSettings::PreferCache() +{ + return sPreferCache; +} + + +void +ServerSettings::SetPreferCache(bool value) +{ + sPreferCache = value; +} + + +bool +ServerSettings::DropCache() +{ + return sDropCache; +} + + +void +ServerSettings::SetDropCache(bool value) +{ + sDropCache = value; +} + + +bool +ServerSettings::ForceNoNetwork() +{ + return sForceNoNetwork; +} + + +void +ServerSettings::SetForceNoNetwork(bool value) +{ + sForceNoNetwork = value; +} \ No newline at end of file diff --git a/src/apps/haikudepot/server/ServerSettings.h b/src/apps/haikudepot/server/ServerSettings.h index f882c10f93..63fe40ec57 100644 --- a/src/apps/haikudepot/server/ServerSettings.h +++ b/src/apps/haikudepot/server/ServerSettings.h @@ -20,6 +20,13 @@ public: static BUrl CreateFullUrl( const BString urlPathComponents); + static bool PreferCache(); + static void SetPreferCache(bool value); + static bool DropCache(); + static void SetDropCache(bool value); + static bool ForceNoNetwork(); + static void SetForceNoNetwork(bool value); + private: static void _InitUserAgent(); static const BString _GetUserAgentVersionString(); @@ -27,6 +34,9 @@ private: static BUrl sBaseUrl; static BString sUserAgent; static pthread_once_t sUserAgentInitOnce; + static bool sPreferCache; + static bool sDropCache; + static bool sForceNoNetwork; }; #endif // SERVER_SETTINGS_H diff --git a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkg.cpp b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkg.cpp index 1cdf2d912f..68108afb1d 100644 --- a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkg.cpp +++ b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkg.cpp @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-05T22:30:10.254264 + * generated at : 2017-12-07T23:22:17.116794 */ #include "DumpExportPkg.h" diff --git a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkg.h b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkg.h index c3b6648ed6..4d0a97edbc 100644 --- a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkg.h +++ b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkg.h @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-05T22:30:10.253178 + * generated at : 2017-12-07T23:22:17.115160 */ #ifndef GEN_JSON_SCHEMA_MODEL__DUMPEXPORTPKG_H diff --git a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgCategory.cpp b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgCategory.cpp index d60355df2c..dc42713917 100644 --- a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgCategory.cpp +++ b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgCategory.cpp @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-05T22:30:10.260503 + * generated at : 2017-12-07T23:22:17.118616 */ #include "DumpExportPkgCategory.h" diff --git a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgCategory.h b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgCategory.h index 77dacb3899..bef12f0bd4 100644 --- a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgCategory.h +++ b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgCategory.h @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-05T22:30:10.259170 + * generated at : 2017-12-07T23:22:17.118521 */ #ifndef GEN_JSON_SCHEMA_MODEL__DUMPEXPORTPKGCATEGORY_H diff --git a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgJsonListener.cpp b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgJsonListener.cpp index 555b545fb1..4af8f45994 100644 --- a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgJsonListener.cpp +++ b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgJsonListener.cpp @@ -1,7 +1,7 @@ /* * Generated Listener Object * source json-schema : dumpexport.json - * generated at : 2017-11-11T14:09:03.498648 + * generated at : 2017-12-17T20:45:25.516772 */ #include "DumpExportPkgJsonListener.h" #include "List.h" @@ -10,11 +10,11 @@ // #pragma mark - private interfaces for the stacked listeners - + /*! This class is the top level of the stacked listeners. The stack structure is maintained in a linked list and sub-classes implement specific behaviors depending where in the parse tree the stacked listener is working at. -*/ +*/ class AbstractStackedDumpExportPkgJsonListener : public BJsonEventListener { public: AbstractStackedDumpExportPkgJsonListener( @@ -29,14 +29,14 @@ public: AbstractStackedDumpExportPkgJsonListener* Parent(); - virtual void WillPop(); + virtual bool WillPop(); protected: AbstractMainDumpExportPkgJsonListener* fMainListener; - void Pop(); + bool Pop(); void Push(AbstractStackedDumpExportPkgJsonListener* stackedListener); - + private: AbstractStackedDumpExportPkgJsonListener* fParent; }; @@ -47,7 +47,7 @@ public: AbstractMainDumpExportPkgJsonListener* mainListener, AbstractStackedDumpExportPkgJsonListener* parent); ~GeneralArrayStackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); }; @@ -57,7 +57,7 @@ public: AbstractMainDumpExportPkgJsonListener* mainListener, AbstractStackedDumpExportPkgJsonListener* parent); ~GeneralObjectStackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); }; @@ -67,11 +67,11 @@ public: AbstractMainDumpExportPkgJsonListener* mainListener, AbstractStackedDumpExportPkgJsonListener* parent); ~DumpExportPkg_StackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); - + DumpExportPkg* Target(); - + protected: DumpExportPkg* fTarget; BString fNextItemName; @@ -83,11 +83,11 @@ public: AbstractMainDumpExportPkgJsonListener* mainListener, AbstractStackedDumpExportPkgJsonListener* parent); ~DumpExportPkg_List_StackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); - + List* Target(); // list of %s pointers - + private: List* fTarget; }; @@ -98,11 +98,11 @@ public: AbstractMainDumpExportPkgJsonListener* mainListener, AbstractStackedDumpExportPkgJsonListener* parent); ~DumpExportPkgVersion_StackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); - + DumpExportPkgVersion* Target(); - + protected: DumpExportPkgVersion* fTarget; BString fNextItemName; @@ -114,11 +114,11 @@ public: AbstractMainDumpExportPkgJsonListener* mainListener, AbstractStackedDumpExportPkgJsonListener* parent); ~DumpExportPkgVersion_List_StackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); - + List* Target(); // list of %s pointers - + private: List* fTarget; }; @@ -129,11 +129,11 @@ public: AbstractMainDumpExportPkgJsonListener* mainListener, AbstractStackedDumpExportPkgJsonListener* parent); ~DumpExportPkgScreenshot_StackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); - + DumpExportPkgScreenshot* Target(); - + protected: DumpExportPkgScreenshot* fTarget; BString fNextItemName; @@ -145,11 +145,11 @@ public: AbstractMainDumpExportPkgJsonListener* mainListener, AbstractStackedDumpExportPkgJsonListener* parent); ~DumpExportPkgScreenshot_List_StackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); - + List* Target(); // list of %s pointers - + private: List* fTarget; }; @@ -160,11 +160,11 @@ public: AbstractMainDumpExportPkgJsonListener* mainListener, AbstractStackedDumpExportPkgJsonListener* parent); ~DumpExportPkgCategory_StackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); - + DumpExportPkgCategory* Target(); - + protected: DumpExportPkgCategory* fTarget; BString fNextItemName; @@ -176,11 +176,11 @@ public: AbstractMainDumpExportPkgJsonListener* mainListener, AbstractStackedDumpExportPkgJsonListener* parent); ~DumpExportPkgCategory_List_StackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); - + List* Target(); // list of %s pointers - + private: List* fTarget; }; @@ -192,9 +192,9 @@ public: AbstractStackedDumpExportPkgJsonListener* parent, DumpExportPkgListener* itemListener); ~ItemEmittingStackedDumpExportPkgJsonListener(); - - void WillPop(); - + + bool WillPop(); + private: DumpExportPkgListener* fItemListener; }; @@ -207,9 +207,9 @@ public: AbstractStackedDumpExportPkgJsonListener* parent, DumpExportPkgListener* itemListener); ~BulkContainerStackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); - + private: BString fNextItemName; DumpExportPkgListener* fItemListener; @@ -223,10 +223,10 @@ public: AbstractStackedDumpExportPkgJsonListener* parent, DumpExportPkgListener* itemListener); ~BulkContainerItemsStackedDumpExportPkgJsonListener(); - + bool Handle(const BJsonEvent& event); - void WillPop(); - + bool WillPop(); + private: DumpExportPkgListener* fItemListener; }; @@ -275,16 +275,18 @@ AbstractStackedDumpExportPkgJsonListener::Push(AbstractStackedDumpExportPkgJsonL fMainListener->SetStackedListener(stackedListener); } -void +bool AbstractStackedDumpExportPkgJsonListener::WillPop() { + return true; } -void +bool AbstractStackedDumpExportPkgJsonListener::Pop() { - WillPop(); + bool result = WillPop(); fMainListener->SetStackedListener(fParent); + return result; } GeneralObjectStackedDumpExportPkgJsonListener::GeneralObjectStackedDumpExportPkgJsonListener( @@ -312,29 +314,28 @@ GeneralObjectStackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) case B_JSON_NULL: // ignore break; - + case B_JSON_OBJECT_START: Push(new GeneralObjectStackedDumpExportPkgJsonListener(fMainListener, this)); break; - + case B_JSON_ARRAY_START: Push(new GeneralArrayStackedDumpExportPkgJsonListener(fMainListener, this)); break; - + case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected end of array"); break; - + case B_JSON_OBJECT_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + } - + return ErrorStatus() == B_OK; } @@ -363,29 +364,28 @@ GeneralArrayStackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) case B_JSON_NULL: // ignore break; - + case B_JSON_OBJECT_START: Push(new GeneralObjectStackedDumpExportPkgJsonListener(fMainListener, this)); break; - + case B_JSON_ARRAY_START: Push(new GeneralArrayStackedDumpExportPkgJsonListener(fMainListener, this)); break; - + case B_JSON_OBJECT_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected end of object"); break; - + case B_JSON_ARRAY_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + } - + return ErrorStatus() == B_OK; } @@ -415,19 +415,18 @@ bool DumpExportPkg_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; - + case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; - + case B_JSON_OBJECT_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } @@ -436,7 +435,7 @@ DumpExportPkg_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) if (fNextItemName == "pkgChangelogContent") fTarget->SetPkgChangelogContent(new BString(event.Content())); - + if (fNextItemName == "name") fTarget->SetName(new BString(event.Content())); fNextItemName.SetTo(""); @@ -452,16 +451,16 @@ DumpExportPkg_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) if (fNextItemName == "pkgChangelogContent") fTarget->SetPkgChangelogContentNull(); - + if (fNextItemName == "name") fTarget->SetNameNull(); - + if (fNextItemName == "derivedRating") fTarget->SetDerivedRatingNull(); - + if (fNextItemName == "prominenceOrdering") fTarget->SetProminenceOrderingNull(); - + if (fNextItemName == "modifyTimestamp") fTarget->SetModifyTimestampNull(); fNextItemName.SetTo(""); @@ -472,10 +471,10 @@ DumpExportPkg_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) if (fNextItemName == "derivedRating") fTarget->SetDerivedRating(event.ContentDouble()); - + if (fNextItemName == "prominenceOrdering") fTarget->SetProminenceOrdering(event.ContentInteger()); - + if (fNextItemName == "modifyTimestamp") fTarget->SetModifyTimestamp(event.ContentInteger()); fNextItemName.SetTo(""); @@ -516,7 +515,7 @@ DumpExportPkg_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) } } - + return ErrorStatus() == B_OK; } @@ -546,15 +545,14 @@ bool DumpExportPkg_List_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + case B_JSON_OBJECT_START: { DumpExportPkg_StackedDumpExportPkgJsonListener* nextListener = @@ -563,13 +561,13 @@ DumpExportPkg_List_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& ev Push(nextListener); break; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing an array of DumpExportPkg"); break; } - + return ErrorStatus() == B_OK; } @@ -599,19 +597,18 @@ bool DumpExportPkgVersion_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; - + case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; - + case B_JSON_OBJECT_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } @@ -620,25 +617,25 @@ DumpExportPkgVersion_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& if (fNextItemName == "major") fTarget->SetMajor(new BString(event.Content())); - + if (fNextItemName == "description") fTarget->SetDescription(new BString(event.Content())); - + if (fNextItemName == "title") fTarget->SetTitle(new BString(event.Content())); - + if (fNextItemName == "summary") fTarget->SetSummary(new BString(event.Content())); - + if (fNextItemName == "micro") fTarget->SetMicro(new BString(event.Content())); - + if (fNextItemName == "preRelease") fTarget->SetPreRelease(new BString(event.Content())); - + if (fNextItemName == "architectureCode") fTarget->SetArchitectureCode(new BString(event.Content())); - + if (fNextItemName == "minor") fTarget->SetMinor(new BString(event.Content())); fNextItemName.SetTo(""); @@ -654,31 +651,31 @@ DumpExportPkgVersion_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& if (fNextItemName == "major") fTarget->SetMajorNull(); - + if (fNextItemName == "payloadLength") fTarget->SetPayloadLengthNull(); - + if (fNextItemName == "description") fTarget->SetDescriptionNull(); - + if (fNextItemName == "title") fTarget->SetTitleNull(); - + if (fNextItemName == "summary") fTarget->SetSummaryNull(); - + if (fNextItemName == "micro") fTarget->SetMicroNull(); - + if (fNextItemName == "preRelease") fTarget->SetPreReleaseNull(); - + if (fNextItemName == "architectureCode") fTarget->SetArchitectureCodeNull(); - + if (fNextItemName == "minor") fTarget->SetMinorNull(); - + if (fNextItemName == "revision") fTarget->SetRevisionNull(); fNextItemName.SetTo(""); @@ -689,7 +686,7 @@ DumpExportPkgVersion_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& if (fNextItemName == "payloadLength") fTarget->SetPayloadLength(event.ContentInteger()); - + if (fNextItemName == "revision") fTarget->SetRevision(event.ContentInteger()); fNextItemName.SetTo(""); @@ -715,7 +712,7 @@ DumpExportPkgVersion_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& } } - + return ErrorStatus() == B_OK; } @@ -745,15 +742,14 @@ bool DumpExportPkgVersion_List_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + case B_JSON_OBJECT_START: { DumpExportPkgVersion_StackedDumpExportPkgJsonListener* nextListener = @@ -762,13 +758,13 @@ DumpExportPkgVersion_List_StackedDumpExportPkgJsonListener::Handle(const BJsonEv Push(nextListener); break; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing an array of DumpExportPkgVersion"); break; } - + return ErrorStatus() == B_OK; } @@ -798,19 +794,18 @@ bool DumpExportPkgScreenshot_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; - + case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; - + case B_JSON_OBJECT_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } @@ -832,16 +827,16 @@ DumpExportPkgScreenshot_StackedDumpExportPkgJsonListener::Handle(const BJsonEven if (fNextItemName == "ordering") fTarget->SetOrderingNull(); - + if (fNextItemName == "width") fTarget->SetWidthNull(); - + if (fNextItemName == "length") fTarget->SetLengthNull(); - + if (fNextItemName == "code") fTarget->SetCodeNull(); - + if (fNextItemName == "height") fTarget->SetHeightNull(); fNextItemName.SetTo(""); @@ -852,13 +847,13 @@ DumpExportPkgScreenshot_StackedDumpExportPkgJsonListener::Handle(const BJsonEven if (fNextItemName == "ordering") fTarget->SetOrdering(event.ContentInteger()); - + if (fNextItemName == "width") fTarget->SetWidth(event.ContentInteger()); - + if (fNextItemName == "length") fTarget->SetLength(event.ContentInteger()); - + if (fNextItemName == "height") fTarget->SetHeight(event.ContentInteger()); fNextItemName.SetTo(""); @@ -884,7 +879,7 @@ DumpExportPkgScreenshot_StackedDumpExportPkgJsonListener::Handle(const BJsonEven } } - + return ErrorStatus() == B_OK; } @@ -914,15 +909,14 @@ bool DumpExportPkgScreenshot_List_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + case B_JSON_OBJECT_START: { DumpExportPkgScreenshot_StackedDumpExportPkgJsonListener* nextListener = @@ -931,13 +925,13 @@ DumpExportPkgScreenshot_List_StackedDumpExportPkgJsonListener::Handle(const BJso Push(nextListener); break; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing an array of DumpExportPkgScreenshot"); break; } - + return ErrorStatus() == B_OK; } @@ -967,19 +961,18 @@ bool DumpExportPkgCategory_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; - + case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; - + case B_JSON_OBJECT_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } @@ -1029,7 +1022,7 @@ DumpExportPkgCategory_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& } } - + return ErrorStatus() == B_OK; } @@ -1059,15 +1052,14 @@ bool DumpExportPkgCategory_List_StackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + case B_JSON_OBJECT_START: { DumpExportPkgCategory_StackedDumpExportPkgJsonListener* nextListener = @@ -1076,13 +1068,13 @@ DumpExportPkgCategory_List_StackedDumpExportPkgJsonListener::Handle(const BJsonE Push(nextListener); break; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing an array of DumpExportPkgCategory"); break; } - + return ErrorStatus() == B_OK; } @@ -1101,11 +1093,13 @@ ItemEmittingStackedDumpExportPkgJsonListener::~ItemEmittingStackedDumpExportPkgJ } -void +bool ItemEmittingStackedDumpExportPkgJsonListener::WillPop() { - fItemListener->Handle(fTarget); + bool result = fItemListener->Handle(fTarget); delete fTarget; + fTarget = NULL; + return result; } @@ -1128,39 +1122,38 @@ bool BulkContainerStackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; - + case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; - + case B_JSON_OBJECT_START: Push(new GeneralObjectStackedDumpExportPkgJsonListener(fMainListener, this)); break; - + case B_JSON_ARRAY_START: if (fNextItemName == "items") Push(new BulkContainerItemsStackedDumpExportPkgJsonListener(fMainListener, this, fItemListener)); else Push(new GeneralArrayStackedDumpExportPkgJsonListener(fMainListener, this)); break; - + case B_JSON_OBJECT_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + default: // ignore break; } - + return ErrorStatus() == B_OK; } @@ -1184,32 +1177,32 @@ bool BulkContainerItemsStackedDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_OBJECT_START: Push(new ItemEmittingStackedDumpExportPkgJsonListener(fMainListener, this, fItemListener)); break; - + case B_JSON_ARRAY_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event"); break; } - + return ErrorStatus() == B_OK; } -void +bool BulkContainerItemsStackedDumpExportPkgJsonListener::WillPop() { fItemListener->Complete(); + return true; } @@ -1278,12 +1271,12 @@ SingleDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { if (fErrorStatus != B_OK) return false; - + if (fStackedListener != NULL) return fStackedListener->Handle(event); - + switch (event.EventType()) { - + case B_JSON_OBJECT_START: { DumpExportPkg_StackedDumpExportPkgJsonListener* nextListener = new DumpExportPkg_StackedDumpExportPkgJsonListener( @@ -1292,13 +1285,13 @@ SingleDumpExportPkgJsonListener::Handle(const BJsonEvent& event) SetStackedListener(nextListener); break; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing top level for DumpExportPkg"); break; } - + return ErrorStatus() == B_OK; } @@ -1327,12 +1320,12 @@ BulkContainerDumpExportPkgJsonListener::Handle(const BJsonEvent& event) { if (fErrorStatus != B_OK) return false; - + if (fStackedListener != NULL) return fStackedListener->Handle(event); - + switch (event.EventType()) { - + case B_JSON_OBJECT_START: { BulkContainerStackedDumpExportPkgJsonListener* nextListener = @@ -1342,13 +1335,13 @@ BulkContainerDumpExportPkgJsonListener::Handle(const BJsonEvent& event) return true; break; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing top level for BulkContainerDumpExportPkgJsonListener"); break; } - + return ErrorStatus() == B_OK; } diff --git a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgJsonListener.h b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgJsonListener.h index ea778c994e..f9166b65f9 100644 --- a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgJsonListener.h +++ b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgJsonListener.h @@ -1,7 +1,7 @@ /* * Generated Listener Object * source json-schema : dumpexport.json - * generated at : 2017-11-11T14:09:03.498089 + * generated at : 2017-12-17T20:45:25.514143 */ #ifndef GEN_JSON_SCHEMA_PARSER__SINGLEDUMPEXPORTPKGJSONLISTENER_H @@ -60,7 +60,7 @@ private: */ class DumpExportPkgListener { public: - virtual void Handle(DumpExportPkg* item) = 0; + virtual bool Handle(DumpExportPkg* item) = 0; virtual void Complete() = 0; }; diff --git a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgScreenshot.cpp b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgScreenshot.cpp index 34aa25ac88..66ead56d24 100644 --- a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgScreenshot.cpp +++ b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgScreenshot.cpp @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-05T22:30:10.257444 + * generated at : 2017-12-07T23:22:17.118221 */ #include "DumpExportPkgScreenshot.h" diff --git a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgScreenshot.h b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgScreenshot.h index 251ed55bd7..823746a04b 100644 --- a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgScreenshot.h +++ b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgScreenshot.h @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-05T22:30:10.256842 + * generated at : 2017-12-07T23:22:17.118049 */ #ifndef GEN_JSON_SCHEMA_MODEL__DUMPEXPORTPKGSCREENSHOT_H diff --git a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgVersion.cpp b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgVersion.cpp index f8703ce2bc..94d7ae67f5 100644 --- a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgVersion.cpp +++ b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgVersion.cpp @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-05T22:30:10.255929 + * generated at : 2017-12-07T23:22:17.117543 */ #include "DumpExportPkgVersion.h" diff --git a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgVersion.h b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgVersion.h index 8d71cbd906..331e3b0efd 100644 --- a/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgVersion.h +++ b/src/apps/haikudepot/server/dumpexportpkg/DumpExportPkgVersion.h @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-05T22:30:10.255268 + * generated at : 2017-12-07T23:22:17.117333 */ #ifndef GEN_JSON_SCHEMA_MODEL__DUMPEXPORTPKGVERSION_H diff --git a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepository.cpp b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepository.cpp index a921f10e77..c572f22580 100644 --- a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepository.cpp +++ b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepository.cpp @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-11T13:59:22.553529 + * generated at : 2017-12-07T23:22:33.021497 */ #include "DumpExportRepository.h" diff --git a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepository.h b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepository.h index 0121403412..c337a27e8d 100644 --- a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepository.h +++ b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepository.h @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-11T13:59:22.550365 + * generated at : 2017-12-07T23:22:33.020747 */ #ifndef GEN_JSON_SCHEMA_MODEL__DUMPEXPORTREPOSITORY_H diff --git a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositoryJsonListener.cpp b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositoryJsonListener.cpp index 2b4774f56c..68b4002147 100644 --- a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositoryJsonListener.cpp +++ b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositoryJsonListener.cpp @@ -1,19 +1,20 @@ /* * Generated Listener Object * source json-schema : dumpexport.json - * generated at : 2017-11-11T14:08:39.276778 + * generated at : 2017-12-18T23:07:02.401765 */ #include "DumpExportRepositoryJsonListener.h" #include "List.h" + #include // #pragma mark - private interfaces for the stacked listeners - + /*! This class is the top level of the stacked listeners. The stack structure is maintained in a linked list and sub-classes implement specific behaviors depending where in the parse tree the stacked listener is working at. -*/ +*/ class AbstractStackedDumpExportRepositoryJsonListener : public BJsonEventListener { public: AbstractStackedDumpExportRepositoryJsonListener( @@ -28,14 +29,14 @@ public: AbstractStackedDumpExportRepositoryJsonListener* Parent(); - virtual void WillPop(); + virtual bool WillPop(); protected: AbstractMainDumpExportRepositoryJsonListener* fMainListener; - void Pop(); + bool Pop(); void Push(AbstractStackedDumpExportRepositoryJsonListener* stackedListener); - + private: AbstractStackedDumpExportRepositoryJsonListener* fParent; }; @@ -46,7 +47,7 @@ public: AbstractMainDumpExportRepositoryJsonListener* mainListener, AbstractStackedDumpExportRepositoryJsonListener* parent); ~GeneralArrayStackedDumpExportRepositoryJsonListener(); - + bool Handle(const BJsonEvent& event); }; @@ -56,7 +57,7 @@ public: AbstractMainDumpExportRepositoryJsonListener* mainListener, AbstractStackedDumpExportRepositoryJsonListener* parent); ~GeneralObjectStackedDumpExportRepositoryJsonListener(); - + bool Handle(const BJsonEvent& event); }; @@ -66,11 +67,11 @@ public: AbstractMainDumpExportRepositoryJsonListener* mainListener, AbstractStackedDumpExportRepositoryJsonListener* parent); ~DumpExportRepository_StackedDumpExportRepositoryJsonListener(); - + bool Handle(const BJsonEvent& event); - + DumpExportRepository* Target(); - + protected: DumpExportRepository* fTarget; BString fNextItemName; @@ -82,11 +83,11 @@ public: AbstractMainDumpExportRepositoryJsonListener* mainListener, AbstractStackedDumpExportRepositoryJsonListener* parent); ~DumpExportRepository_List_StackedDumpExportRepositoryJsonListener(); - + bool Handle(const BJsonEvent& event); - + List* Target(); // list of %s pointers - + private: List* fTarget; }; @@ -97,11 +98,11 @@ public: AbstractMainDumpExportRepositoryJsonListener* mainListener, AbstractStackedDumpExportRepositoryJsonListener* parent); ~DumpExportRepositorySource_StackedDumpExportRepositoryJsonListener(); - + bool Handle(const BJsonEvent& event); - + DumpExportRepositorySource* Target(); - + protected: DumpExportRepositorySource* fTarget; BString fNextItemName; @@ -113,11 +114,11 @@ public: AbstractMainDumpExportRepositoryJsonListener* mainListener, AbstractStackedDumpExportRepositoryJsonListener* parent); ~DumpExportRepositorySource_List_StackedDumpExportRepositoryJsonListener(); - + bool Handle(const BJsonEvent& event); - + List* Target(); // list of %s pointers - + private: List* fTarget; }; @@ -129,9 +130,9 @@ public: AbstractStackedDumpExportRepositoryJsonListener* parent, DumpExportRepositoryListener* itemListener); ~ItemEmittingStackedDumpExportRepositoryJsonListener(); - - void WillPop(); - + + bool WillPop(); + private: DumpExportRepositoryListener* fItemListener; }; @@ -144,9 +145,9 @@ public: AbstractStackedDumpExportRepositoryJsonListener* parent, DumpExportRepositoryListener* itemListener); ~BulkContainerStackedDumpExportRepositoryJsonListener(); - + bool Handle(const BJsonEvent& event); - + private: BString fNextItemName; DumpExportRepositoryListener* fItemListener; @@ -160,10 +161,10 @@ public: AbstractStackedDumpExportRepositoryJsonListener* parent, DumpExportRepositoryListener* itemListener); ~BulkContainerItemsStackedDumpExportRepositoryJsonListener(); - + bool Handle(const BJsonEvent& event); - void WillPop(); - + bool WillPop(); + private: DumpExportRepositoryListener* fItemListener; }; @@ -212,16 +213,18 @@ AbstractStackedDumpExportRepositoryJsonListener::Push(AbstractStackedDumpExportR fMainListener->SetStackedListener(stackedListener); } -void +bool AbstractStackedDumpExportRepositoryJsonListener::WillPop() { + return true; } -void +bool AbstractStackedDumpExportRepositoryJsonListener::Pop() { - WillPop(); + bool result = WillPop(); fMainListener->SetStackedListener(fParent); + return result; } GeneralObjectStackedDumpExportRepositoryJsonListener::GeneralObjectStackedDumpExportRepositoryJsonListener( @@ -249,28 +252,28 @@ GeneralObjectStackedDumpExportRepositoryJsonListener::Handle(const BJsonEvent& e case B_JSON_NULL: // ignore break; - + case B_JSON_OBJECT_START: Push(new GeneralObjectStackedDumpExportRepositoryJsonListener(fMainListener, this)); break; - + case B_JSON_ARRAY_START: Push(new GeneralArrayStackedDumpExportRepositoryJsonListener(fMainListener, this)); break; - + case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected end of array"); break; - + case B_JSON_OBJECT_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } + } - + return ErrorStatus() == B_OK; } @@ -299,28 +302,28 @@ GeneralArrayStackedDumpExportRepositoryJsonListener::Handle(const BJsonEvent& ev case B_JSON_NULL: // ignore break; - + case B_JSON_OBJECT_START: Push(new GeneralObjectStackedDumpExportRepositoryJsonListener(fMainListener, this)); break; - + case B_JSON_ARRAY_START: Push(new GeneralArrayStackedDumpExportRepositoryJsonListener(fMainListener, this)); break; - + case B_JSON_OBJECT_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected end of object"); break; - + case B_JSON_ARRAY_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } + } - + return ErrorStatus() == B_OK; } @@ -350,19 +353,18 @@ bool DumpExportRepository_StackedDumpExportRepositoryJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; - + case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; - + case B_JSON_OBJECT_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } @@ -371,13 +373,13 @@ DumpExportRepository_StackedDumpExportRepositoryJsonListener::Handle(const BJson if (fNextItemName == "informationUrl") fTarget->SetInformationUrl(new BString(event.Content())); - + if (fNextItemName == "code") fTarget->SetCode(new BString(event.Content())); - + if (fNextItemName == "name") fTarget->SetName(new BString(event.Content())); - + if (fNextItemName == "description") fTarget->SetDescription(new BString(event.Content())); fNextItemName.SetTo(""); @@ -393,13 +395,13 @@ DumpExportRepository_StackedDumpExportRepositoryJsonListener::Handle(const BJson if (fNextItemName == "informationUrl") fTarget->SetInformationUrlNull(); - + if (fNextItemName == "code") fTarget->SetCodeNull(); - + if (fNextItemName == "name") fTarget->SetNameNull(); - + if (fNextItemName == "description") fTarget->SetDescriptionNull(); fNextItemName.SetTo(""); @@ -435,7 +437,7 @@ DumpExportRepository_StackedDumpExportRepositoryJsonListener::Handle(const BJson } } - + return ErrorStatus() == B_OK; } @@ -465,15 +467,14 @@ bool DumpExportRepository_List_StackedDumpExportRepositoryJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + case B_JSON_OBJECT_START: { DumpExportRepository_StackedDumpExportRepositoryJsonListener* nextListener = @@ -482,13 +483,13 @@ DumpExportRepository_List_StackedDumpExportRepositoryJsonListener::Handle(const Push(nextListener); break; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing an array of DumpExportRepository"); break; } - + return ErrorStatus() == B_OK; } @@ -518,19 +519,18 @@ bool DumpExportRepositorySource_StackedDumpExportRepositoryJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; - + case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; - + case B_JSON_OBJECT_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } @@ -539,7 +539,10 @@ DumpExportRepositorySource_StackedDumpExportRepositoryJsonListener::Handle(const if (fNextItemName == "url") fTarget->SetUrl(new BString(event.Content())); - + + if (fNextItemName == "repoInfoUrl") + fTarget->SetRepoInfoUrl(new BString(event.Content())); + if (fNextItemName == "code") fTarget->SetCode(new BString(event.Content())); fNextItemName.SetTo(""); @@ -555,7 +558,10 @@ DumpExportRepositorySource_StackedDumpExportRepositoryJsonListener::Handle(const if (fNextItemName == "url") fTarget->SetUrlNull(); - + + if (fNextItemName == "repoInfoUrl") + fTarget->SetRepoInfoUrlNull(); + if (fNextItemName == "code") fTarget->SetCodeNull(); fNextItemName.SetTo(""); @@ -586,7 +592,7 @@ DumpExportRepositorySource_StackedDumpExportRepositoryJsonListener::Handle(const } } - + return ErrorStatus() == B_OK; } @@ -616,15 +622,14 @@ bool DumpExportRepositorySource_List_StackedDumpExportRepositoryJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + case B_JSON_OBJECT_START: { DumpExportRepositorySource_StackedDumpExportRepositoryJsonListener* nextListener = @@ -633,13 +638,13 @@ DumpExportRepositorySource_List_StackedDumpExportRepositoryJsonListener::Handle( Push(nextListener); break; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing an array of DumpExportRepositorySource"); break; } - + return ErrorStatus() == B_OK; } @@ -658,11 +663,13 @@ ItemEmittingStackedDumpExportRepositoryJsonListener::~ItemEmittingStackedDumpExp } -void +bool ItemEmittingStackedDumpExportRepositoryJsonListener::WillPop() { - fItemListener->Handle(fTarget); + bool result = fItemListener->Handle(fTarget); delete fTarget; + fTarget = NULL; + return result; } @@ -685,39 +692,38 @@ bool BulkContainerStackedDumpExportRepositoryJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; - + case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; - + case B_JSON_OBJECT_START: Push(new GeneralObjectStackedDumpExportRepositoryJsonListener(fMainListener, this)); break; - + case B_JSON_ARRAY_START: if (fNextItemName == "items") Push(new BulkContainerItemsStackedDumpExportRepositoryJsonListener(fMainListener, this, fItemListener)); else Push(new GeneralArrayStackedDumpExportRepositoryJsonListener(fMainListener, this)); break; - + case B_JSON_OBJECT_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + default: // ignore break; } - + return ErrorStatus() == B_OK; } @@ -741,32 +747,32 @@ bool BulkContainerItemsStackedDumpExportRepositoryJsonListener::Handle(const BJsonEvent& event) { switch (event.EventType()) { - + case B_JSON_OBJECT_START: Push(new ItemEmittingStackedDumpExportRepositoryJsonListener(fMainListener, this, fItemListener)); break; - + case B_JSON_ARRAY_END: { - Pop(); - bool status = (ErrorStatus() == B_OK); + bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event"); break; } - + return ErrorStatus() == B_OK; } -void +bool BulkContainerItemsStackedDumpExportRepositoryJsonListener::WillPop() { fItemListener->Complete(); + return true; } @@ -835,12 +841,12 @@ SingleDumpExportRepositoryJsonListener::Handle(const BJsonEvent& event) { if (fErrorStatus != B_OK) return false; - + if (fStackedListener != NULL) return fStackedListener->Handle(event); - + switch (event.EventType()) { - + case B_JSON_OBJECT_START: { DumpExportRepository_StackedDumpExportRepositoryJsonListener* nextListener = new DumpExportRepository_StackedDumpExportRepositoryJsonListener( @@ -849,13 +855,13 @@ SingleDumpExportRepositoryJsonListener::Handle(const BJsonEvent& event) SetStackedListener(nextListener); break; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing top level for DumpExportRepository"); break; } - + return ErrorStatus() == B_OK; } @@ -884,29 +890,28 @@ BulkContainerDumpExportRepositoryJsonListener::Handle(const BJsonEvent& event) { if (fErrorStatus != B_OK) return false; - + if (fStackedListener != NULL) return fStackedListener->Handle(event); - + switch (event.EventType()) { - + case B_JSON_OBJECT_START: { BulkContainerStackedDumpExportRepositoryJsonListener* nextListener = new BulkContainerStackedDumpExportRepositoryJsonListener( this, NULL, fItemListener); - SetStackedListener(nextListener); return true; break; } - + default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing top level for BulkContainerDumpExportRepositoryJsonListener"); break; } - + return ErrorStatus() == B_OK; } diff --git a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositoryJsonListener.h b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositoryJsonListener.h index cd8edde79a..f79ef0b572 100644 --- a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositoryJsonListener.h +++ b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositoryJsonListener.h @@ -1,7 +1,7 @@ /* * Generated Listener Object * source json-schema : dumpexport.json - * generated at : 2017-11-11T14:08:39.274913 + * generated at : 2017-12-18T23:07:02.399681 */ #ifndef GEN_JSON_SCHEMA_PARSER__SINGLEDUMPEXPORTREPOSITORYJSONLISTENER_H @@ -60,7 +60,7 @@ private: */ class DumpExportRepositoryListener { public: - virtual void Handle(DumpExportRepository* item) = 0; + virtual bool Handle(DumpExportRepository* item) = 0; virtual void Complete() = 0; }; diff --git a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositorySource.cpp b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositorySource.cpp index e0e5998a74..d5fef59a26 100644 --- a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositorySource.cpp +++ b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositorySource.cpp @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-11T13:59:22.559632 + * generated at : 2017-12-07T23:22:33.022114 */ #include "DumpExportRepositorySource.h" @@ -9,6 +9,7 @@ DumpExportRepositorySource::DumpExportRepositorySource() { fUrl = NULL; + fRepoInfoUrl = NULL; fCode = NULL; } @@ -19,6 +20,10 @@ DumpExportRepositorySource::~DumpExportRepositorySource() delete fUrl; } + if (fRepoInfoUrl != NULL) { + delete fRepoInfoUrl; + } + if (fCode != NULL) { delete fCode; } @@ -56,6 +61,37 @@ DumpExportRepositorySource::UrlIsNull() } +BString* +DumpExportRepositorySource::RepoInfoUrl() +{ + return fRepoInfoUrl; +} + + +void +DumpExportRepositorySource::SetRepoInfoUrl(BString* value) +{ + fRepoInfoUrl = value; +} + + +void +DumpExportRepositorySource::SetRepoInfoUrlNull() +{ + if (!RepoInfoUrlIsNull()) { + delete fRepoInfoUrl; + fRepoInfoUrl = NULL; + } +} + + +bool +DumpExportRepositorySource::RepoInfoUrlIsNull() +{ + return fRepoInfoUrl == NULL; +} + + BString* DumpExportRepositorySource::Code() { diff --git a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositorySource.h b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositorySource.h index 470c5d85a8..a6be61264a 100644 --- a/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositorySource.h +++ b/src/apps/haikudepot/server/dumpexportrepository/DumpExportRepositorySource.h @@ -1,7 +1,7 @@ /* * Generated Model Object * source json-schema : dumpexport.json - * generated at : 2017-11-11T13:59:22.559237 + * generated at : 2017-12-07T23:22:33.021952 */ #ifndef GEN_JSON_SCHEMA_MODEL__DUMPEXPORTREPOSITORYSOURCE_H @@ -21,6 +21,11 @@ public: void SetUrlNull(); bool UrlIsNull(); + BString* RepoInfoUrl(); + void SetRepoInfoUrl(BString* value); + void SetRepoInfoUrlNull(); + bool RepoInfoUrlIsNull(); + BString* Code(); void SetCode(BString* value); void SetCodeNull(); @@ -28,6 +33,7 @@ public: private: BString* fUrl; + BString* fRepoInfoUrl; BString* fCode; }; diff --git a/src/apps/haikudepot/tar/TarArchiveService.cpp b/src/apps/haikudepot/tar/TarArchiveService.cpp index 64f4505249..c645003cfa 100644 --- a/src/apps/haikudepot/tar/TarArchiveService.cpp +++ b/src/apps/haikudepot/tar/TarArchiveService.cpp @@ -19,7 +19,8 @@ status_t -TarArchiveService::Unpack(BDataIO& tarDataIo, BPath& targetDirectory) +TarArchiveService::Unpack(BDataIO& tarDataIo, BPath& targetDirectory, + Stoppable* stoppable) { uint8 buffer[LENGTH_BLOCK]; uint8 zero_buffer[LENGTH_BLOCK]; @@ -30,8 +31,9 @@ TarArchiveService::Unpack(BDataIO& tarDataIo, BPath& targetDirectory) memset(zero_buffer, 0, sizeof zero_buffer); - while (B_OK == result && B_OK == (result = tarDataIo.ReadExactly(buffer, - LENGTH_BLOCK))) { + while (B_OK == result + && (NULL == stoppable || !stoppable->WasStopped()) + && B_OK == (result = tarDataIo.ReadExactly(buffer, LENGTH_BLOCK))) { count_items_read++; diff --git a/src/apps/haikudepot/tar/TarArchiveService.h b/src/apps/haikudepot/tar/TarArchiveService.h index a8cf706ae3..b49e6da3b6 100644 --- a/src/apps/haikudepot/tar/TarArchiveService.h +++ b/src/apps/haikudepot/tar/TarArchiveService.h @@ -7,6 +7,7 @@ #define TAR_ARCHIVE_SERVICE_H #include "AbstractServerProcess.h" +#include "Stoppable.h" #include "TarArchiveHeader.h" #include @@ -16,7 +17,8 @@ class TarArchiveService { public: static status_t Unpack(BDataIO& tarDataIo, - BPath& targetDirectoryPath); + BPath& targetDirectoryPath, + Stoppable* stoppable); private: static status_t _EnsurePathToTarItemFile( diff --git a/src/apps/haikudepot/ui/App.cpp b/src/apps/haikudepot/ui/App.cpp index e12fb26b33..e7ede8a8f4 100644 --- a/src/apps/haikudepot/ui/App.cpp +++ b/src/apps/haikudepot/ui/App.cpp @@ -1,5 +1,6 @@ /* * Copyright 2013, Stephan Aßmus . + * Copyright 2017, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ @@ -127,6 +128,9 @@ enum arg_switch { HELP_SWITCH, WEB_APP_BASE_URL_SWITCH, VERBOSITY_SWITCH, + FORCE_NO_NETWORKING_SWITCH, + PREFER_CACHE_SWITCH, + DROP_CACHE_SWITCH }; @@ -134,13 +138,24 @@ static void app_print_help() { fprintf(stdout, "HaikuDepot "); - fprintf(stdout, "[-u|--webappbaseurl ] "); - fprintf(stdout, "[-v|--verbosity [off|info|debug|trace] "); - fprintf(stdout, "[-h|--help]\n\n"); + fprintf(stdout, "[-u|--webappbaseurl ]\n"); + fprintf(stdout, "[-v|--verbosity [off|info|debug|trace]\n"); + fprintf(stdout, "[--nonetworking]\n"); + fprintf(stdout, "[--prefercache]\n"); + fprintf(stdout, "[--dropcache]\n"); + fprintf(stdout, "[-h|--help]\n"); + fprintf(stdout, "\n"); fprintf(stdout, "'-h' : causes this help text to be printed out.\n"); fprintf(stdout, "'-v' : allows for the verbosity level to be set.\n"); - fprintf(stdout, "'-u' : allows for the haiku depot server to be\n"); - fprintf(stdout, " configured."); + fprintf(stdout, "'-u' : allows for the haiku depot server url to be\n"); + fprintf(stdout, " configured.\n"); + fprintf(stdout, "'--nonetworking' : prevents network access.**\n"); + fprintf(stdout, "'--prefercache' : prefer to get data from cache rather\n"); + fprintf(stdout, " then obtain data from the network.**\n"); + fprintf(stdout, "'--dropcache' : drop cached data before performing\n"); + fprintf(stdout, " bulk operations.**\n"); + fprintf(stdout, "\n"); + fprintf(stdout, "** = only applies to bulk operations.\n"); } @@ -160,6 +175,15 @@ app_resolve_switch(char *arg) if (0 == strcmp(&arg[2], "verbosity")) return VERBOSITY_SWITCH; + + if (0 == strcmp(&arg[2], "nonetworking")) + return FORCE_NO_NETWORKING_SWITCH; + + if (0 == strcmp(&arg[2], "prefercache")) + return PREFER_CACHE_SWITCH; + + if (0 == strcmp(&arg[2], "dropcache")) + return DROP_CACHE_SWITCH; } else { if (arglen == 2) { // short form switch (arg[1]) { @@ -237,6 +261,18 @@ App::ArgvReceived(int32 argc, char* argv[]) break; + case FORCE_NO_NETWORKING_SWITCH: + ServerSettings::SetForceNoNetwork(true); + break; + + case PREFER_CACHE_SWITCH: + ServerSettings::SetPreferCache(true); + break; + + case DROP_CACHE_SWITCH: + ServerSettings::SetDropCache(true); + break; + case NOT_SWITCH: { BEntry entry(argv[i], true); diff --git a/src/apps/haikudepot/ui/MainWindow.cpp b/src/apps/haikudepot/ui/MainWindow.cpp index f094cb9a22..3a8fdd1193 100644 --- a/src/apps/haikudepot/ui/MainWindow.cpp +++ b/src/apps/haikudepot/ui/MainWindow.cpp @@ -132,6 +132,7 @@ MainWindow::MainWindow(const BMessage& settings) fLogInItem(NULL), fLogOutItem(NULL), fModelListener(new MessageModelListener(BMessenger(this)), true), + fBulkLoadStateMachine(&fModel), fTerminating(false), fSinglePackageMode(false), fModelWorker(B_BAD_THREAD_ID) @@ -245,6 +246,7 @@ MainWindow::MainWindow(const BMessage& settings, const PackageInfoRef& package) fLogInItem(NULL), fLogOutItem(NULL), fModelListener(new MessageModelListener(BMessenger(this)), true), + fBulkLoadStateMachine(&fModel), fTerminating(false), fSinglePackageMode(true), fModelWorker(B_BAD_THREAD_ID) @@ -1062,7 +1064,7 @@ MainWindow::_RefreshPackageList(bool force) bool wasEmpty = fModel.Depots().IsEmpty(); if (force || wasEmpty) - fModel.StopPopulatingAllPackages(); + fBulkLoadStateMachine.Stop(); BAutolock lock(fModel.Lock()); @@ -1094,11 +1096,10 @@ MainWindow::_RefreshPackageList(bool force) fModel.AddDepot(it->second); } - fModel.PopulateWebAppRepositoryCodes(); - // start retrieving package icons and average ratings - if (force || wasEmpty) - fModel.PopulateAllPackages(); + if (force || wasEmpty) { + fBulkLoadStateMachine.Start(); + } // compute the OS package dependencies try { diff --git a/src/apps/haikudepot/ui/MainWindow.h b/src/apps/haikudepot/ui/MainWindow.h index 6f7d95c18a..152b46c1c3 100644 --- a/src/apps/haikudepot/ui/MainWindow.h +++ b/src/apps/haikudepot/ui/MainWindow.h @@ -2,6 +2,7 @@ * Copyright 2013-2014, Stephan Aßmus . * Copyright 2013, Rene Gollent . * Copyright 2017, Julian Harnath . + * Copyright 2017, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ #ifndef MAIN_WINDOW_H @@ -9,6 +10,7 @@ #include +#include "BulkLoadStateMachine.h" #include "Model.h" #include "PackageAction.h" #include "PackageActionHandler.h" @@ -119,6 +121,8 @@ private: Model fModel; ModelListenerRef fModelListener; PackageList fVisiblePackages; + BulkLoadStateMachine + fBulkLoadStateMachine; bool fTerminating; bool fSinglePackageMode; diff --git a/src/apps/haikudepot/util/StorageUtils.cpp b/src/apps/haikudepot/util/StorageUtils.cpp index 35e102b921..020004577f 100644 --- a/src/apps/haikudepot/util/StorageUtils.cpp +++ b/src/apps/haikudepot/util/StorageUtils.cpp @@ -5,13 +5,15 @@ #include "StorageUtils.h" +#include +#include + #include #include #include #include -#include -#include +#include "Logger.h" #define FILE_TO_STRING_BUFFER_LEN 64 @@ -51,23 +53,27 @@ StorageUtils::RemoveDirectoryContents(BPath& path) bool exists = false; bool isDirectory = false; - BPath directroyEntryPath; + BPath directoryEntryPath; - result = directoryEntry.GetPath(&directroyEntryPath); + result = directoryEntry.GetPath(&directoryEntryPath); - if (result == B_OK) - result = ExistsDirectory(directroyEntryPath, &exists, &isDirectory); + if (result == B_OK) { + result = ExistsObject(directoryEntryPath, &exists, &isDirectory, + NULL); + } if (result == B_OK) { if (isDirectory) - RemoveDirectoryContents(directroyEntryPath); + RemoveDirectoryContents(directoryEntryPath); - if (remove(directroyEntryPath.Path()) == 0) { - fprintf(stdout, "did delete [%s]\n", - directroyEntryPath.Path()); + if (remove(directoryEntryPath.Path()) == 0) { + if (Logger::IsDebugEnabled()) { + fprintf(stdout, "did delete [%s]\n", + directoryEntryPath.Path()); + } } else { fprintf(stderr, "unable to delete [%s]\n", - directroyEntryPath.Path()); + directoryEntryPath.Path()); result = B_ERROR; } } @@ -84,21 +90,34 @@ StorageUtils::RemoveDirectoryContents(BPath& path) */ status_t -StorageUtils::ExistsDirectory(BPath& directory, +StorageUtils::ExistsObject(BPath& path, bool* exists, - bool* isDirectory) + bool* isDirectory, + off_t* size) { struct stat s; - *exists = false; - *isDirectory = false; + if (exists != NULL) + *exists = false; - if (-1 == stat(directory.Path(), &s)) { + if (isDirectory != NULL) + *isDirectory = false; + + if (size != NULL) + *size = 0; + + if (-1 == stat(path.Path(), &s)) { if (ENOENT != errno) return B_ERROR; } else { - *exists = true; - *isDirectory = S_ISDIR(s.st_mode); + if (exists != NULL) + *exists = true; + + if (isDirectory != NULL) + *isDirectory = S_ISDIR(s.st_mode); + + if (size != NULL) + *size = s.st_size; } return B_OK; diff --git a/src/apps/haikudepot/util/StorageUtils.h b/src/apps/haikudepot/util/StorageUtils.h index e17778350f..45c025f494 100644 --- a/src/apps/haikudepot/util/StorageUtils.h +++ b/src/apps/haikudepot/util/StorageUtils.h @@ -2,7 +2,6 @@ * Copyright 2017, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ - #ifndef PATH_UTILS_H #define PATH_UTILS_H @@ -13,9 +12,10 @@ class StorageUtils { public: static status_t RemoveDirectoryContents(BPath& path); static status_t AppendToString(BPath& path, BString& result); - static status_t ExistsDirectory(BPath& directory, + static status_t ExistsObject(BPath& directory, bool* exists, - bool* isDirectory); + bool* isDirectory, + off_t* size); }; #endif // PATH_UTILS_H diff --git a/src/apps/haikudepot/util/ToFileUrlProtocolListener.cpp b/src/apps/haikudepot/util/ToFileUrlProtocolListener.cpp index e7e68b68ce..6188d8dd35 100644 --- a/src/apps/haikudepot/util/ToFileUrlProtocolListener.cpp +++ b/src/apps/haikudepot/util/ToFileUrlProtocolListener.cpp @@ -18,6 +18,7 @@ ToFileUrlProtocolListener::ToFileUrlProtocolListener(BPath path, fTraceLoggingIdentifier = traceLoggingIdentifier; fTraceLogging = traceLogging; fShouldDownload = true; + fContentLength = 0; } @@ -70,6 +71,8 @@ void ToFileUrlProtocolListener::DataReceived(BUrlRequest* caller, const char* data, off_t position, ssize_t size) { + fContentLength += size; + if (fShouldDownload && fDownloadIO != NULL && size > 0) { size_t remaining = size; size_t written = 0; @@ -116,3 +119,9 @@ ToFileUrlProtocolListener::DebugMessage(BUrlRequest* caller, } } + +ssize_t +ToFileUrlProtocolListener::ContentLength() +{ + return fContentLength; +} diff --git a/src/apps/haikudepot/util/ToFileUrlProtocolListener.h b/src/apps/haikudepot/util/ToFileUrlProtocolListener.h index 3744a1983f..a65b29b0d4 100644 --- a/src/apps/haikudepot/util/ToFileUrlProtocolListener.h +++ b/src/apps/haikudepot/util/ToFileUrlProtocolListener.h @@ -13,6 +13,8 @@ public: bool traceLogging); virtual ~ToFileUrlProtocolListener(); + ssize_t ContentLength(); + void ConnectionOpened(BUrlRequest* caller); void HostnameResolved(BUrlRequest* caller, const char* ip); @@ -37,6 +39,7 @@ private: bool fTraceLogging; BString fTraceLoggingIdentifier; BPositionIO* fDownloadIO; + ssize_t fContentLength; }; diff --git a/src/tests/apps/haikudepot/DumpExportRepositoryJsonListenerTest.cpp b/src/tests/apps/haikudepot/DumpExportRepositoryJsonListenerTest.cpp index 22050f249e..bdbcc24fd0 100644 --- a/src/tests/apps/haikudepot/DumpExportRepositoryJsonListenerTest.cpp +++ b/src/tests/apps/haikudepot/DumpExportRepositoryJsonListenerTest.cpp @@ -122,7 +122,7 @@ public: TestBulkContainerItemListener(); virtual ~TestBulkContainerItemListener(); - void Handle(DumpExportRepository* item); + bool Handle(DumpExportRepository* item); void Complete(); BString ConcatenatedCodes(); @@ -261,7 +261,7 @@ TestBulkContainerItemListener::~TestBulkContainerItemListener() for this. */ -void +bool TestBulkContainerItemListener::Handle(DumpExportRepository* item) { int32 i; @@ -278,6 +278,8 @@ TestBulkContainerItemListener::Handle(DumpExportRepository* item) fConcatenatedSourcesUrl.Append( item->RepositorySourcesItemAt(i)->Url()->String()); } + + return true; } diff --git a/src/tests/apps/haikudepot/HaikuDepotTestAddon.cpp b/src/tests/apps/haikudepot/HaikuDepotTestAddon.cpp index c2af027417..7dd58757c6 100644 --- a/src/tests/apps/haikudepot/HaikuDepotTestAddon.cpp +++ b/src/tests/apps/haikudepot/HaikuDepotTestAddon.cpp @@ -8,6 +8,7 @@ #include "StandardMetaDataJsonEventListenerTest.h" #include "DumpExportRepositoryJsonListenerTest.h" +#include "ListTest.h" BTestSuite* getTestSuite() @@ -16,6 +17,7 @@ getTestSuite() StandardMetaDataJsonEventListenerTest::AddTests(*suite); DumpExportRepositoryJsonListenerTest::AddTests(*suite); + ListTest::AddTests(*suite); return suite; } diff --git a/src/tests/apps/haikudepot/Jamfile b/src/tests/apps/haikudepot/Jamfile index a8cbe67ec9..8b48efb43a 100644 --- a/src/tests/apps/haikudepot/Jamfile +++ b/src/tests/apps/haikudepot/Jamfile @@ -9,6 +9,16 @@ SubDirHdrs [ FDirName $(HAIKU_TOP) src apps haikudepot server dumpexportreposito UsePrivateHeaders shared ; +local sourceDirs = + server + server/dumpexportrepository +; + +local sourceDir ; +for sourceDir in $(sourceDirs) { + SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps haikudepot $(sourceDir) ] ; +} + UnitTestLib haikudepottest.so : HaikuDepotTestAddon.cpp @@ -17,15 +27,11 @@ UnitTestLib haikudepottest.so : DumpExportRepositoryJsonListener.cpp DumpExportRepositoryJsonListenerTest.cpp + ListTest.cpp + StandardMetaData.cpp StandardMetaDataJsonEventListener.cpp StandardMetaDataJsonEventListenerTest.cpp - : be shared bnetapi [ TargetLibstdc++ ] [ TargetLibsupc++ ] -; - -SEARCH on [ FGristFiles StandardMetaData.cpp StandardMetaDataJsonEventListener.cpp ] - = [ FDirName $(HAIKU_TOP) src apps haikudepot server ] ; - -SEARCH on [ FGristFiles DumpExportRepositorySource.cpp DumpExportRepository.cpp DumpExportRepositoryJsonListener.cpp ] - = [ FDirName $(HAIKU_TOP) src apps haikudepot server dumpexportrepository ] ; \ No newline at end of file + : be shared bnetapi package [ TargetLibstdc++ ] [ TargetLibsupc++ ] +; \ No newline at end of file