2026-02-27 15:15:25 -03:00
|
|
|
// This file contains the basic skeleton for a Logos Storage CLI application.
|
|
|
|
|
// It implements basic module initialization and startup, and provides simple
|
|
|
|
|
// synchronization primitives.
|
|
|
|
|
|
2026-02-24 20:57:59 +04:00
|
|
|
#include "logos_manager.h"
|
|
|
|
|
|
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
#include <QDir>
|
2026-02-26 16:15:48 -03:00
|
|
|
#include <QEventLoop>
|
|
|
|
|
#include <QTimer>
|
2026-02-24 20:57:59 +04:00
|
|
|
#include <iostream>
|
|
|
|
|
|
2026-02-27 15:15:25 -03:00
|
|
|
// Default timeout for operations, in milliseconds. It is in general
|
|
|
|
|
// not a good idea to use the same timeout for all operations, but
|
|
|
|
|
// fine for an example.
|
2026-02-26 16:15:48 -03:00
|
|
|
#define DEFAULT_TIMEOUT 10000
|
|
|
|
|
|
2026-02-27 15:15:25 -03:00
|
|
|
// The main function for the app. This is where application logic
|
|
|
|
|
// should go.
|
2026-02-26 16:15:48 -03:00
|
|
|
int app_main(LogosModules* modules, int argc, char* argv[]);
|
|
|
|
|
|
2026-02-27 15:15:25 -03:00
|
|
|
|
|
|
|
|
// The storage module runs operations asynchronously, and we'd often
|
|
|
|
|
// like to wait for such operations to complete before we do something
|
|
|
|
|
// else; e.g., wait for the module to initialize before we upload a file.
|
|
|
|
|
//
|
|
|
|
|
// Since Logos Core is Qt-based, we provide two simple synchronization
|
|
|
|
|
// primitives which are friendly to Qt's event loop: an `await` call,
|
|
|
|
|
// which can be invoked by the main thread to block and wait for an
|
|
|
|
|
// operation, and a `notify` call, which can be invoked by the
|
|
|
|
|
// operation's signal handler to "wake up" the main thread when it
|
|
|
|
|
// completes.
|
|
|
|
|
|
|
|
|
|
// "Blocks" the main thread until `notify` is called on the
|
|
|
|
|
// corresponding signal handler.
|
2026-02-26 16:15:48 -03:00
|
|
|
bool await(QEventLoop* loop, int timeoutMs) {
|
|
|
|
|
QTimer::singleShot(timeoutMs, loop, [loop]() {
|
|
|
|
|
std::cerr << "Call timed out." << std::endl;
|
|
|
|
|
loop->exit(1);
|
|
|
|
|
});
|
|
|
|
|
return loop->exec() == 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-27 15:15:25 -03:00
|
|
|
// "Wakes up" the main thread, signalling that an operation
|
|
|
|
|
// has completed. Typically called by a signal handler.
|
2026-02-26 16:15:48 -03:00
|
|
|
void notify(QEventLoop* loop, bool successValue) {
|
|
|
|
|
loop->exit(successValue ? 0 : 1);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-24 20:57:59 +04:00
|
|
|
int main(int argc, char* argv[]) {
|
|
|
|
|
QCoreApplication app(argc, argv);
|
|
|
|
|
QCoreApplication::setOrganizationName("Logos");
|
2026-02-27 14:10:19 -03:00
|
|
|
QCoreApplication::setApplicationName("LogosUploader");
|
2026-02-24 20:57:59 +04:00
|
|
|
|
2026-02-26 10:39:27 -03:00
|
|
|
Logos logos(QCoreApplication::applicationDirPath() + "/../modules");
|
2026-02-27 14:10:19 -03:00
|
|
|
if (!logos.init("LogosUploader")) {
|
2026-02-24 20:57:59 +04:00
|
|
|
std::cerr << "Failed to initialize Logos" << std::endl;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-26 10:39:27 -03:00
|
|
|
int result = app_main(logos.modules(), argc, argv);
|
2026-02-24 21:04:18 +04:00
|
|
|
logos.cleanup();
|
2026-02-26 10:39:27 -03:00
|
|
|
return result;
|
|
|
|
|
}
|
2026-02-24 21:04:18 +04:00
|
|
|
|
2026-02-26 10:39:27 -03:00
|
|
|
int app_main(LogosModules* modules, int argc, char* argv[]) {
|
2026-02-26 11:55:31 -03:00
|
|
|
|
2026-02-27 15:15:25 -03:00
|
|
|
// See https://github.com/logos-co/logos-storage-module/blob/7512d6745f9f412220e0c589e3f82fe454405e6d/storage_module_interface.h#L13
|
|
|
|
|
// for a full list of options.
|
2026-02-26 11:55:31 -03:00
|
|
|
const QString jsonConfig = "{"
|
2026-02-27 14:10:19 -03:00
|
|
|
"\"listen-addrs\": [\"/ip4/0.0.0.0/tcp/8000\"],"
|
|
|
|
|
"\"disc-port\": 9000,"
|
|
|
|
|
"\"data-dir\": \"./app-data\","
|
|
|
|
|
"\"nat\": \"none\""
|
2026-02-26 11:55:31 -03:00
|
|
|
"}";
|
|
|
|
|
|
|
|
|
|
if (!modules->storage_module.init(jsonConfig)) {
|
|
|
|
|
std::cerr << "Failed to initialize storage module" << std::endl;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-27 15:15:25 -03:00
|
|
|
// This showcases the use of await/notify. Each await/notify pair requires the use of
|
|
|
|
|
// a distinct, scoped event loop.
|
2026-02-26 16:15:48 -03:00
|
|
|
{
|
|
|
|
|
QEventLoop loop;
|
|
|
|
|
modules->storage_module.on("storageStart", [&loop](const QVariantList& data) {
|
|
|
|
|
bool success = data[0].toBool();
|
|
|
|
|
if (!success) {
|
|
|
|
|
std::cerr << "Failed to start storage module: " << data[1].toString().toStdString() << std::endl;
|
|
|
|
|
}
|
|
|
|
|
notify(&loop, success);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
modules->storage_module.start();
|
|
|
|
|
|
|
|
|
|
if (!await(&loop, DEFAULT_TIMEOUT)) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-27 14:10:19 -03:00
|
|
|
std::cerr << "Storage module started successfully" << std::endl;
|
2026-02-26 16:15:48 -03:00
|
|
|
}
|
|
|
|
|
|
2026-02-27 14:10:19 -03:00
|
|
|
// Rest of the app goes here.
|
|
|
|
|
|
|
|
|
|
std::cerr << "Exiting..." << std::endl;
|
2026-02-24 20:57:59 +04:00
|
|
|
return 0;
|
2026-02-27 14:10:19 -03:00
|
|
|
}
|