* Finished ProgressReporter

* Integrated ProgressReporter into CopyEngine and UnzipEngine.
* Integrated unzipping to main installer engine. Since there are currently no
  .zip files in the _packages_ folder (and not even a _packages_ folder
  itself), this is completely invisible, but it works.

TODO: Adjust the build system to optionally copy packages into _packages_
instead of extracting them. Like for the CD build profile mode.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32967 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2009-09-06 17:23:31 +00:00
parent c12764b812
commit 72586154d7
9 changed files with 185 additions and 152 deletions

View File

@ -22,19 +22,22 @@
#include "InstallerWindow.h"
// TODO: For PACKAGES_DIRECTORY and VAR_DIRECTORY, not so nice...
#include "SemaphoreLocker.h"
#include "ProgressReporter.h"
using std::nothrow;
CopyEngine::CopyEngine(const BMessenger& messenger, BMessage* message)
CopyEngine::CopyEngine(ProgressReporter* reporter)
:
fBufferQueue(),
fWriterThread(-1),
fQuitting(false),
fBytesRead(0),
fLastBytesRead(0),
fItemsCopied(0),
fLastItemsCopied(0),
fTimeRead(0),
fBytesWritten(0),
@ -46,8 +49,7 @@ CopyEngine::CopyEngine(const BMessenger& messenger, BMessage* message)
fCurrentTargetFolder(NULL),
fCurrentItem(NULL),
fMessenger(messenger),
fMessage(message)
fProgressReporter(reporter)
{
fWriterThread = spawn_thread(_WriteThreadEntry, "buffer writer",
B_NORMAL_PRIORITY, this);
@ -73,16 +75,19 @@ CopyEngine::~CopyEngine()
int32 exitValue;
wait_for_thread(fWriterThread, &exitValue);
}
delete fMessage;
}
void
CopyEngine::ResetTargets()
{
// TODO: One could subtract the bytes/items which were added to the
// ProgressReporter before resetting them...
fBytesRead = 0;
fLastBytesRead = 0;
fItemsCopied = 0;
fLastItemsCopied = 0;
fTimeRead = 0;
fBytesWritten = 0;
@ -93,12 +98,6 @@ CopyEngine::ResetTargets()
fCurrentTargetFolder = NULL;
fCurrentItem = NULL;
if (fMessage) {
BMessage message(*fMessage);
message.AddString("status", "Collecting copy information.");
fMessenger.SendMessage(&message);
}
}
@ -106,7 +105,10 @@ status_t
CopyEngine::CollectTargets(const char* source, sem_id cancelSemaphore)
{
int32 level = 0;
return _CollectCopyInfo(source, level, cancelSemaphore);
status_t ret = _CollectCopyInfo(source, level, cancelSemaphore);
if (ret == B_OK && fProgressReporter != NULL)
fProgressReporter->AddItems(fItemsToCopy, fBytesToCopy);
return ret;
}
@ -114,14 +116,6 @@ status_t
CopyEngine::CopyFolder(const char* source, const char* destination,
sem_id cancelSemaphore)
{
printf("%lld bytes to read in %lld files\n", fBytesToCopy, fItemsToCopy);
if (fMessage) {
BMessage message(*fMessage);
message.AddString("status", "Performing installation.");
fMessenger.SendMessage(&message);
}
int32 level = 0;
return _CopyFolder(source, destination, level, cancelSemaphore);
}
@ -475,16 +469,23 @@ CopyEngine::_RemoveFolder(BEntry& entry)
void
CopyEngine::_UpdateProgress()
{
if (fMessage != NULL) {
BMessage message(*fMessage);
float progress = 100.0 * fBytesRead / fBytesToCopy;
message.AddFloat("progress", progress);
message.AddInt32("current", fItemsCopied);
message.AddInt32("maximum", fItemsToCopy);
message.AddString("item", fCurrentItem);
message.AddString("folder", fCurrentTargetFolder);
fMessenger.SendMessage(&message);
if (fProgressReporter == NULL)
return;
uint64 items = 0;
if (fLastItemsCopied < fItemsCopied) {
items = fItemsCopied - fLastItemsCopied;
fLastItemsCopied = fItemsCopied;
}
off_t bytes = 0;
if (fLastBytesRead < fBytesRead) {
bytes = fBytesRead - fLastBytesRead;
fLastBytesRead = fBytesRead;
}
fProgressReporter->ItemsWritten(items, bytes, fCurrentItem,
fCurrentTargetFolder);
}

View File

@ -15,14 +15,12 @@
#include "BlockingQueue.h"
class BFile;
class BMessage;
class BMessenger;
class ProgressReporter;
class CopyEngine {
public:
CopyEngine(const BMessenger& messenger,
BMessage* message);
CopyEngine(ProgressReporter* reporter);
virtual ~CopyEngine();
void ResetTargets();
@ -93,7 +91,9 @@ private:
volatile bool fQuitting;
off_t fBytesRead;
uint64 fLastBytesRead;
uint64 fItemsCopied;
uint64 fLastItemsCopied;
bigtime_t fTimeRead;
off_t fBytesWritten;
@ -105,8 +105,7 @@ private:
const char* fCurrentTargetFolder;
const char* fCurrentItem;
BMessenger fMessenger;
BMessage* fMessage;
ProgressReporter* fProgressReporter;
};

View File

@ -9,6 +9,7 @@ Application Installer :
InstallerWindow.cpp
PackageViews.cpp
PartitionMenuItem.cpp
ProgressReporter.cpp
UnzipEngine.cpp
WorkerThread.cpp
: be tracker translation libshared.a $(TARGET_LIBSTDC++)

View File

@ -5,28 +5,19 @@
#include "ProgressReporter.h"
#include <new>
#include <math.h>
#include <stdio.h>
#include <string.h>
using std::nothrow;
ProgressReporter::ProgressReporter(const BMessenger& messenger,
BMessage* message)
:
fBytesRead(0),
fItemsCopied(0),
fTimeRead(0),
fStartTime(0),
fBytesToWrite(0),
fBytesWritten(0),
fTimeWritten(0),
fBytesToCopy(0),
fItemsToCopy(0),
fItemsToWrite(0),
fItemsWritten(0),
fMessenger(messenger),
fMessage(message)
@ -43,15 +34,11 @@ ProgressReporter::~ProgressReporter()
void
ProgressReporter::Reset()
{
fBytesRead = 0;
fItemsCopied = 0;
fTimeRead = 0;
fBytesToWrite = 0;
fBytesWritten = 0;
fTimeWritten = 0;
fBytesToCopy = 0;
fItemsToCopy = 0;
fItemsToWrite = 0;
fItemsWritten = 0;
if (fMessage) {
BMessage message(*fMessage);
@ -64,22 +51,35 @@ ProgressReporter::Reset()
void
ProgressReporter::AddItems(uint64 count, off_t bytes)
{
// TODO ...
fBytesToWrite += bytes;
fItemsToWrite += count;
}
void
ProgressReporter::StartTimer()
{
// TODO ...
fStartTime = system_time();
printf("%lld bytes to write in %lld files\n", fBytesToWrite,
fItemsToWrite);
if (fMessage) {
BMessage message(*fMessage);
message.AddString("status", "Performing installation.");
fMessenger.SendMessage(&message);
}
}
void
ProgressReporter::ItemsCopied(uint64 items, off_t bytes, const char* itemName,
const char* targetFolder)
ProgressReporter::ItemsWritten(uint64 items, off_t bytes,
const char* itemName, const char* targetFolder)
{
// TODO ...
fItemsWritten += items;
fBytesWritten += bytes;
_UpdateProgress(itemName, targetFolder);
}
@ -87,14 +87,17 @@ void
ProgressReporter::_UpdateProgress(const char* itemName,
const char* targetFolder)
{
if (fMessage != NULL) {
BMessage message(*fMessage);
float progress = 100.0 * fBytesRead / fBytesToCopy;
message.AddFloat("progress", progress);
message.AddInt32("current", fItemsCopied);
message.AddInt32("maximum", fItemsToCopy);
message.AddString("item", itemName);
message.AddString("folder", targetFolder);
fMessenger.SendMessage(&message);
}
if (fMessage == NULL)
return;
// TODO: Could add time to finish calculation here...
BMessage message(*fMessage);
float progress = 100.0 * fBytesWritten / fBytesToWrite;
message.AddFloat("progress", progress);
message.AddInt32("current", fItemsWritten);
message.AddInt32("maximum", fItemsToWrite);
message.AddString("item", itemName);
message.AddString("folder", targetFolder);
fMessenger.SendMessage(&message);
}

View File

@ -21,24 +21,24 @@ public:
void StartTimer();
void ItemsCopied(uint64 items, off_t bytes,
void ItemsWritten(uint64 items, off_t bytes,
const char* itemName,
const char* targetFolder);
// TODO: Perhaps move cancelling here as well...
private:
void _UpdateProgress(const char* itemName,
const char* targetFolder);
private:
off_t fBytesRead;
uint64 fItemsCopied;
bigtime_t fTimeRead;
bigtime_t fStartTime;
off_t fBytesToWrite;
off_t fBytesWritten;
bigtime_t fTimeWritten;
off_t fBytesToCopy;
uint64 fItemsToCopy;
uint64 fItemsToWrite;
uint64 fItemsWritten;
BMessenger fMessenger;
BMessage* fMessage;

View File

@ -21,12 +21,13 @@
#include "CommandPipe.h"
#include "SemaphoreLocker.h"
#include "ProgressReporter.h"
using std::nothrow;
UnzipEngine::UnzipEngine(const BMessenger& messenger, BMessage* message,
UnzipEngine::UnzipEngine(ProgressReporter* reporter,
sem_id cancelSemaphore)
:
fPackage(""),
@ -34,11 +35,12 @@ UnzipEngine::UnzipEngine(const BMessenger& messenger, BMessage* message,
fBytesToUncompress(0),
fBytesUncompressed(0),
fLastBytesUncompressed(0),
fItemsToUncompress(0),
fItemsUncompressed(0),
fLastItemsUncompressed(0),
fMessenger(messenger),
fMessage(message),
fProgressReporter(reporter),
fCancelSemaphore(cancelSemaphore)
{
}
@ -46,7 +48,6 @@ UnzipEngine::UnzipEngine(const BMessenger& messenger, BMessage* message,
UnzipEngine::~UnzipEngine()
{
delete fMessage;
}
@ -60,8 +61,10 @@ UnzipEngine::SetTo(const char* pathToPackage, const char* destinationFolder)
fBytesToUncompress = 0;
fBytesUncompressed = 0;
fLastBytesUncompressed = 0;
fItemsToUncompress = 0;
fItemsUncompressed = 0;
fLastItemsUncompressed = 0;
BPrivate::BCommandPipe commandPipe;
status_t ret = commandPipe.AddArg("unzip");
@ -95,12 +98,6 @@ UnzipEngine::UnzipPackage()
if (fItemsToUncompress == 0)
return B_NO_INIT;
if (fMessage) {
BMessage message(*fMessage);
message.AddString("status", "Extracting package.");
fMessenger.SendMessage(&message);
}
BPrivate::BCommandPipe commandPipe;
status_t ret = commandPipe.AddArg("unzip");
if (ret == B_OK)
@ -155,19 +152,6 @@ UnzipEngine::ReadLine(const BString& line)
status_t
UnzipEngine::_ReadLineListing(const BString& line)
{
// static const char* kListingFormat = "%llu files, %llu bytes uncompressed, "
// "%llu bytes compressed: %f%%";
//
// uint64 bytesCompressed;
// float compresssionRatio;
// if (sscanf(line.String(), kListingFormat, &fItemsToUncompress,
// &fBytesToUncompress, &bytesCompressed, &compresssionRatio) != 4) {
// fBytesToUncompress = 0;
// fItemsToUncompress = 0;
// fprintf(stderr, "error reading command output: %s\n", line.String());
// return B_ERROR;
// }
static const char* kListingFormat = "%llu %s %s %s\n";
const char* string = line.String();
@ -197,7 +181,7 @@ UnzipEngine::_ReadLineListing(const BString& line)
if (destination.Append(itemPath.String()) == B_OK) {
BEntry test(destination.Path());
if (test.Exists() && test.IsDirectory()) {
printf("ignoring %s\n", itemPath.String());
// printf("ignoring %s\n", itemPath.String());
itemCount = 0;
}
}
@ -205,8 +189,8 @@ UnzipEngine::_ReadLineListing(const BString& line)
fItemsToUncompress += itemCount;
printf("item %s with %llu bytes to %s\n", itemName.String(),
bytes, itemPath.String());
// printf("item %s with %llu bytes to %s\n", itemName.String(),
// bytes, itemPath.String());
fEntrySizeMap.Put(itemName.String(), bytes);
} else {
@ -243,8 +227,8 @@ UnzipEngine::_ReadLineExtract(const BString& line)
fBytesUncompressed += bytes;
}
printf("%llu extracted %s to %s (%llu)\n", fItemsUncompressed,
itemName.String(), itemPath.String(), bytes);
// printf("%llu extracted %s to %s (%llu)\n", fItemsUncompressed,
// itemName.String(), itemPath.String(), bytes);
_UpdateProgress(itemName.String(), itemPath.String());
} else {
@ -258,14 +242,20 @@ UnzipEngine::_ReadLineExtract(const BString& line)
void
UnzipEngine::_UpdateProgress(const char* item, const char* targetFolder)
{
if (fMessage != NULL) {
BMessage message(*fMessage);
float progress = 100.0 * fBytesUncompressed / fBytesToUncompress;
message.AddFloat("progress", progress);
message.AddInt32("current", fItemsUncompressed);
message.AddInt32("maximum", fItemsToUncompress);
message.AddString("item", item);
message.AddString("folder", targetFolder);
fMessenger.SendMessage(&message);
if (fProgressReporter == NULL)
return;
uint64 items = 0;
if (fLastItemsUncompressed < fItemsUncompressed) {
items = fItemsUncompressed - fLastItemsUncompressed;
fLastItemsUncompressed = fItemsUncompressed;
}
off_t bytes = 0;
if (fLastBytesUncompressed < fBytesUncompressed) {
bytes = fBytesUncompressed - fLastBytesUncompressed;
fLastBytesUncompressed = fBytesUncompressed;
}
fProgressReporter->ItemsWritten(items, bytes, item, targetFolder);
}

View File

@ -15,14 +15,12 @@
#include "HashMap.h"
#include "HashString.h"
class BMessage;
class BMessenger;
class ProgressReporter;
class UnzipEngine : private BCommandPipe::LineReader {
public:
UnzipEngine(const BMessenger& messenger,
BMessage* message,
UnzipEngine(ProgressReporter* reporter,
sem_id cancelSemaphore = -1);
virtual ~UnzipEngine();
@ -59,11 +57,12 @@ private:
off_t fBytesToUncompress;
off_t fBytesUncompressed;
off_t fLastBytesUncompressed;
uint64 fItemsToUncompress;
uint64 fItemsUncompressed;
uint64 fLastItemsUncompressed;
BMessenger fMessenger;
BMessage* fMessage;
ProgressReporter* fProgressReporter;
sem_id fCancelSemaphore;
};

View File

@ -27,6 +27,7 @@
#include "InstallerWindow.h"
#include "PackageViews.h"
#include "PartitionMenuItem.h"
#include "ProgressReporter.h"
#include "UnzipEngine.h"
@ -251,7 +252,9 @@ WorkerThread::_PerformInstall(BMenu* srcMenu, BMenu* targetMenu)
entry_ref testRef;
BMessenger messenger(fWindow);
CopyEngine engine(messenger, new BMessage(MSG_STATUS_MESSAGE));
ProgressReporter reporter(messenger, new BMessage(MSG_STATUS_MESSAGE));
CopyEngine engine(&reporter);
BList unzipEngines;
PartitionMenuItem* targetItem = (PartitionMenuItem*)targetMenu->FindMarked();
PartitionMenuItem* srcItem = (PartitionMenuItem*)srcMenu->FindMarked();
@ -397,6 +400,7 @@ WorkerThread::_PerformInstall(BMenu* srcMenu, BMenu* targetMenu)
goto error;
}
// Begin actuall installation
_LaunchInitScript(targetDirectory);
@ -419,6 +423,14 @@ WorkerThread::_PerformInstall(BMenu* srcMenu, BMenu* targetMenu)
}
}
// collect information about all zip packages
err = _ProcessZipPackages(srcDirectory.Path(), targetDirectory.Path(),
&reporter, unzipEngines);
if (err != B_OK)
goto error;
reporter.StartTimer();
// copy source volume
err = engine.CopyFolder(srcDirectory.Path(), targetDirectory.Path(),
fCancelSemaphore);
@ -439,37 +451,17 @@ WorkerThread::_PerformInstall(BMenu* srcMenu, BMenu* targetMenu)
}
}
#if 0
// extract zip packages
// TODO: Put those in the optional packages list view
// TODO: Implement mechanism to handle dependencies between these
// packages. (Selecting one will auto-select others.)
{
BPath pkgRootDir(srcDirectory.Path(), PACKAGES_DIRECTORY);
BDirectory directory(pkgRootDir.Path());
BEntry entry;
while (directory.GetNextEntry(&entry) == B_OK) {
char name[B_FILE_NAME_LENGTH];
if (entry.GetName(name) != B_OK)
continue;
int nameLength = strlen(name);
if (nameLength <= 0)
continue;
char* nameExtension = name + nameLength - 4;
printf("inspecting %s (%s)\n", name, nameExtension);
if (strcasecmp(nameExtension, ".zip") != 0)
continue;
printf("found .zip package: %s\n", name);
UnzipEngine unzipEngine(messenger, new BMessage(MSG_STATUS_MESSAGE),
fCancelSemaphore);
BPath path;
entry.GetPath(&path);
unzipEngine.SetTo(path.Path(), targetDirectory.Path());
unzipEngine.UnzipPackage();
}
// Extract all zip packages. If an error occured, delete the rest of
// the engines, but stop extracting.
for (int32 i = 0; i < unzipEngines.CountItems(); i++) {
UnzipEngine* engine = reinterpret_cast<UnzipEngine*>(
unzipEngines.ItemAtFast(i));
if (err == B_OK)
err = engine->UnzipPackage();
delete engine;
}
#endif
if (err != B_OK)
goto error;
_LaunchFinishScript(targetDirectory);
@ -487,6 +479,48 @@ error:
}
status_t
WorkerThread::_ProcessZipPackages(const char* sourcePath,
const char* targetPath, ProgressReporter* reporter, BList& unzipEngines)
{
// TODO: Put those in the optional packages list view
// TODO: Implement mechanism to handle dependencies between these
// packages. (Selecting one will auto-select others.)
BPath pkgRootDir(sourcePath, PACKAGES_DIRECTORY);
BDirectory directory(pkgRootDir.Path());
BEntry entry;
while (directory.GetNextEntry(&entry) == B_OK) {
char name[B_FILE_NAME_LENGTH];
if (entry.GetName(name) != B_OK)
continue;
int nameLength = strlen(name);
if (nameLength <= 0)
continue;
char* nameExtension = name + nameLength - 4;
if (strcasecmp(nameExtension, ".zip") != 0)
continue;
printf("found .zip package: %s\n", name);
UnzipEngine* unzipEngine = new(std::nothrow) UnzipEngine(reporter,
fCancelSemaphore);
if (unzipEngine == NULL || !unzipEngines.AddItem(unzipEngine)) {
delete unzipEngine;
return B_NO_MEMORY;
}
BPath path;
entry.GetPath(&path);
status_t ret = unzipEngine->SetTo(path.Path(), targetPath);
if (ret != B_OK)
return ret;
reporter->AddItems(unzipEngine->ItemsToUncompress(),
unzipEngine->BytesToUncompress());
}
return B_OK;
}
void
WorkerThread::_SetStatusMessage(const char *status)
{

View File

@ -16,6 +16,7 @@
class BList;
class BMenu;
class InstallerWindow;
class ProgressReporter;
class WorkerThread : public BLooper {
public:
@ -41,7 +42,12 @@ private:
void _LaunchInitScript(BPath& path);
void _LaunchFinishScript(BPath& path);
void _PerformInstall(BMenu* srcMenu, BMenu* dstMenu);
void _PerformInstall(BMenu* srcMenu,
BMenu* dstMenu);
status_t _ProcessZipPackages(const char* sourcePath,
const char* targetPath,
ProgressReporter* reporter,
BList& unzipEngines);
void _SetStatusMessage(const char* status);