Skip to content

Commit

Permalink
Refactor|FS: Continued refactoring remote file repository classes
Browse files Browse the repository at this point in the history
The different types of repositories form a class hierarchy, and
the application (DoomsdayApp) can register its own repository type(s).
libcore just provides access to the serverside files.
  • Loading branch information
skyjake committed Oct 25, 2017
1 parent 7f0dc93 commit ef9d6f9
Show file tree
Hide file tree
Showing 18 changed files with 237 additions and 122 deletions.
10 changes: 5 additions & 5 deletions doomsday/apps/client/src/network/packagedownloader.cpp
Expand Up @@ -240,15 +240,15 @@ void PackageDownloader::mountFileRepository(shell::ServerInfo const &info)
// The remote repository feature was added in 2.1. Trying to send a RemoteFeed
// request to an older server would just result in us getting immediately
// disconnected.

if (info.version() > Version(2, 1, 0, 2484))
{
d->fileRepository = info.address().asText();
d->fileRepository = "doomsday:" + info.address().asText();
d->isCancelled = false;
FS::get().makeFolderWithFeed
(PATH_REMOTE_SERVER,
RemoteFeedRelay::get().addRepository(RemoteFeedRelay::Server,
d->fileRepository,
PATH_SERVER_REPOSITORY_ROOT),
filesys::RemoteFeedRelay::get().addRepository(d->fileRepository,
PATH_SERVER_REPOSITORY_ROOT),
Folder::PopulateAsyncFullTree);
}
}
Expand All @@ -261,7 +261,7 @@ void PackageDownloader::unmountFileRepository()
{
trash(remoteFiles);
}
RemoteFeedRelay::get().removeRepository(d->fileRepository);
filesys::RemoteFeedRelay::get().removeRepository(d->fileRepository);
d->fileRepository.clear();
d->isCancelled = false;
}
Expand Down
Expand Up @@ -27,6 +27,8 @@ class IdgamesLink : public de::filesys::WebHostedLink
IdgamesLink(de::String const &address);

void parseRepositoryIndex(QByteArray data) override;

static de::filesys::Link *construct(de::String const &address);
};

#endif // LIBDOOMSDAY_FILESYS_IDGAMESLINK_H
7 changes: 5 additions & 2 deletions doomsday/apps/libdoomsday/src/doomsdayapp.cpp
Expand Up @@ -28,6 +28,7 @@
#include "doomsday/filesys/datafile.h"
#include "doomsday/filesys/datafolder.h"
#include "doomsday/filesys/virtualmappings.h"
#include "doomsday/filesys/idgameslink.h"
#include "doomsday/busymode.h"
#include "doomsday/world/world.h"
#include "doomsday/world/entitydef.h"
Expand Down Expand Up @@ -151,6 +152,9 @@ DENG2_PIMPL(DoomsdayApp)
}
});
configSaveTimer.start();

// File system extensions.
filesys::RemoteFeedRelay::get().defineLink(IdgamesLink::construct);
}

~Impl()
Expand Down Expand Up @@ -389,8 +393,7 @@ DENG2_PIMPL(DoomsdayApp)
void initRemoteRepositories()
{
FS::get().makeFolderWithFeed("/remote/idgames",
RemoteFeedRelay::get().addRepository(RemoteFeedRelay::IdgamesFileTree,
"http://www.gamers.org/pub/idgames/"),
filesys::RemoteFeedRelay::get().addRepository("http://www.gamers.org/pub/idgames/"),
Folder::PopulateAsyncFullTree);
}

Expand Down
12 changes: 11 additions & 1 deletion doomsday/apps/libdoomsday/src/filesys/idgameslink.cpp
Expand Up @@ -108,5 +108,15 @@ void IdgamesLink::parseRepositoryIndex(QByteArray data)
handleError("Failed to parse directory listing: " + errorMessage);
wasDisconnected();
}
});
});
}

filesys::Link *IdgamesLink::construct(String const &address)
{
if ((address.startsWith("http:") || address.startsWith("https:")) &&
!address.contains("dengine.net"))
{
return new IdgamesLink(address);
}
return nullptr;
}
4 changes: 2 additions & 2 deletions doomsday/sdk/libcore/include/de/core/app.h
Expand Up @@ -48,11 +48,11 @@ class Module;
class Path;
class NativePath;
class PackageLoader;
class RemoteFeedRelay;
class ScriptSystem;
class System;
class UnixInfo;

namespace filesys { class RemoteFeedRelay; }
namespace game { class Game; }

/**
Expand Down Expand Up @@ -296,7 +296,7 @@ class DENG2_PUBLIC App : DENG2_OBSERVES(Clock, TimeChange)
/**
* Returns the remote feed relay that manages connections to remote file repositories.
*/
static RemoteFeedRelay &remoteFeedRelay();
static filesys::RemoteFeedRelay &remoteFeedRelay();

/**
* Returns the application's package loader.
Expand Down
2 changes: 2 additions & 0 deletions doomsday/sdk/libcore/include/de/filesys/Query
@@ -0,0 +1,2 @@
#include "remote/query.h"

44 changes: 16 additions & 28 deletions doomsday/sdk/libcore/include/de/filesys/remote/link.h
Expand Up @@ -21,8 +21,8 @@

#include "../../DictionaryValue"
#include "../../IdentifiedPacket"
#include "../../RemoteFeedRelay"
#include "../../String"
#include "../Query"

namespace de {

Expand All @@ -31,49 +31,31 @@ class AsyncScope;
namespace filesys {

/**
* Active connection to a remote repository. One link is shared by all
* RemoteFeed instances accessing the same repository.
* Base class for an active connection to a remote repository. Specialized subclasses
* handle specific types of repositories. One link instance is shared by all RemoteFeed
* instances accessing the same repository.
*
* @ingroup fs
*/
class DENG2_PUBLIC Link
{
public:
enum State { Deinitialized, Initializing, Ready };

using QueryId = IdentifiedPacket::Id;

struct DENG2_PUBLIC Query
{
QueryId id;
String path;
RemoteFeedRelay::FileListRequest fileList;
RemoteFeedRelay::FileContentsRequest fileContents;
duint64 receivedBytes = 0;
duint64 fileSize = 0;

Query(RemoteFeedRelay::FileListRequest req, String path);
Query(RemoteFeedRelay::FileContentsRequest req, String path);
bool isValid() const;
void cancel();
};
typedef std::function<Link * (String const &address)> Constructor;

public:
Link(String const &address);

virtual ~Link();

String address() const;

State state() const;

virtual void wasConnected();

virtual void wasDisconnected();

virtual void handleError(QString errorMessage);

void sendQuery(Query query);

protected:
Link(String const &address);

AsyncScope &scope();

Query *findQuery(QueryId id);
Expand All @@ -86,6 +68,12 @@ class DENG2_PUBLIC Link

void chunkReceived(QueryId id, duint64 startOffset, Block const &chunk, duint64 fileSize);

virtual void wasConnected();

virtual void wasDisconnected();

virtual void handleError(QString errorMessage);

virtual void transmit(Query const &query) = 0;

private:
Expand All @@ -95,4 +83,4 @@ class DENG2_PUBLIC Link
} // namespace filesys
} // namespace de

#endif // DENG2_REMOTE_REPOSITORYLINK_H
#endif // DENG2_FILESYS_LINK_H
4 changes: 3 additions & 1 deletion doomsday/sdk/libcore/include/de/filesys/remote/nativelink.h
Expand Up @@ -30,9 +30,11 @@ namespace filesys {
class DENG2_PUBLIC NativeLink : public Link
{
public:
NativeLink(String const &address);
static Link *construct(String const &address);

protected:
NativeLink(String const &address);

void wasConnected() override;
void transmit(Query const &query) override;

Expand Down
66 changes: 66 additions & 0 deletions doomsday/sdk/libcore/include/de/filesys/remote/query.h
@@ -0,0 +1,66 @@
/** @file remote/query.h
*
* @authors Copyright (c) 2017 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* LGPL: http://www.gnu.org/licenses/lgpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy of
* the GNU Lesser General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#ifndef DENG2_FILESYS_QUERY_H
#define DENG2_FILESYS_QUERY_H

#include "../../AsyncCallback"
#include "../../DictionaryValue"
#include "../../IdentifiedPacket"

namespace de {
namespace filesys {

typedef DictionaryValue FileList;

typedef std::function<void (FileList const &)> FileListFunc;
typedef std::function<void (duint64 startOffset, Block const &, duint64 remainingBytes)> DataReceivedFunc;

typedef std::shared_ptr<AsyncCallback<FileListFunc>> FileListRequest;
typedef std::shared_ptr<AsyncCallback<DataReceivedFunc>> FileContentsRequest;

using QueryId = IdentifiedPacket::Id;

/**
* Query about information stored in the remote repository. The callbacks will
* be called when a reply is received.
*/
struct DENG2_PUBLIC Query
{
// Query parameters:
QueryId id;
String path;

// Callbacks:
FileListRequest fileList;
FileContentsRequest fileContents;

// Internal status:
duint64 receivedBytes = 0;
duint64 fileSize = 0;

Query(FileListRequest req, String path);
Query(FileContentsRequest req, String path);
bool isValid() const;
void cancel();
};

} // namespace filesys
} // namespace de

#endif // DENG2_FILESYS_QUERY_H
33 changes: 19 additions & 14 deletions doomsday/sdk/libcore/include/de/filesys/remote/remotefeedrelay.h
Expand Up @@ -23,10 +23,13 @@
#include "../../Record"
#include "../../DictionaryValue"
#include "../../AsyncCallback"
#include "../Query"
#include "../Link"

#include <QNetworkAccessManager>

namespace de {
namespace filesys {

/**
* Connects to one or more remote file repositories and provides metadata and file
Expand All @@ -35,21 +38,13 @@ namespace de {
class DENG2_PUBLIC RemoteFeedRelay
{
public:
typedef DictionaryValue FileList;

typedef std::function<void (FileList const &)> FileListFunc;
typedef std::function<void (duint64 startOffset, Block const &, duint64 remainingBytes)> DataReceivedFunc;

typedef std::shared_ptr<AsyncCallback<FileListFunc>> FileListRequest;
typedef std::shared_ptr<AsyncCallback<DataReceivedFunc>> FileContentsRequest;

static RemoteFeedRelay &get();

enum RepositoryType {
Server,
NativePackages,
IdgamesFileTree,
};
// enum RepositoryType {
// Server,
// NativePackages,
// IdgamesFileTree,
// };

enum Status { Disconnected, Connected };

Expand All @@ -58,7 +53,16 @@ class DENG2_PUBLIC RemoteFeedRelay
public:
RemoteFeedRelay();

RemoteFeed *addRepository(RepositoryType type, String const &address, String const &remoteRoot = "/");
/**
* Defines a new type of remote repository link. The defined links are each
* offered a remote repository address, and the first one to create a Link instance
* based on the address will be used to communicate with the repository.
*
* @param linkConstructor Constructor method.
*/
void defineLink(Link::Constructor linkConstructor);

RemoteFeed *addRepository(String const &address, String const &remoteRoot = "/");

void removeRepository(String const &address);

Expand All @@ -80,6 +84,7 @@ class DENG2_PUBLIC RemoteFeedRelay
DENG2_PRIVATE(d)
};

} // namespace filesys
} // namespace de

#endif // LIBDENG2_REMOTEFEEDRELAY_H
4 changes: 2 additions & 2 deletions doomsday/sdk/libcore/src/core/app.cpp
Expand Up @@ -101,7 +101,7 @@ DENG2_PIMPL(App)

std::unique_ptr<UnixInfo> unixInfo;

RemoteFeedRelay remoteFeedRelay;
filesys::RemoteFeedRelay remoteFeedRelay;

/// The configuration.
Path configPath;
Expand Down Expand Up @@ -892,7 +892,7 @@ Folder &App::homeFolder()
return rootFolder().locate<Folder>("home");
}

RemoteFeedRelay &App::remoteFeedRelay()
filesys::RemoteFeedRelay &App::remoteFeedRelay()
{
return DENG2_APP->d->remoteFeedRelay;
}
Expand Down

0 comments on commit ef9d6f9

Please sign in to comment.