Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/bareos/bareos.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Rogge <andreas.rogge@bareos.com>2022-10-05 15:05:49 +0300
committerAndreas Rogge <andreas.rogge@bareos.com>2022-11-07 19:37:29 +0300
commit529ff83cfe47ee3c6bb434a717dfcfb25c541d48 (patch)
tree5f28789b78eab8a6c7a5f999b7f71d3d6ed227a7
parent49cc107f05e7c87af1292eab4c63dea4397bd4af (diff)
stored: register backends in plugin-registry
This patch introduces a plugin regsitry that contains all loaded backends. Storage backends will self-register their factory either at startup (in case the backend is statically linked into the SD) or when the backend is loaded. From the backend's perspective, there's no difference if it is statically or dynamically loaded anymore. Finally, the loading of the backends is done right after loading the configuration, so for every device we check the presence of its backend and fail if it is missing or cannot be loaded.
-rw-r--r--core/src/lib/plugin_registry.h75
-rw-r--r--core/src/stored/CMakeLists.txt4
-rw-r--r--core/src/stored/backends/CMakeLists.txt25
-rw-r--r--core/src/stored/backends/droplet_device.cc8
-rw-r--r--core/src/stored/backends/gfapi_device.cc10
-rw-r--r--core/src/stored/backends/unix_fifo_device.cc10
-rw-r--r--core/src/stored/backends/unix_file_device.cc10
-rw-r--r--core/src/stored/backends/unix_tape_device.cc9
-rw-r--r--core/src/stored/backends/win32_fifo_device.cc (renamed from core/src/win32/stored/backends/win32_fifo_device.cc)3
-rw-r--r--core/src/stored/backends/win32_fifo_device.h (renamed from core/src/win32/stored/backends/win32_fifo_device.h)8
-rw-r--r--core/src/stored/backends/win32_file_device.cc (renamed from core/src/win32/stored/backends/win32_file_device.cc)3
-rw-r--r--core/src/stored/backends/win32_file_device.h (renamed from core/src/win32/stored/backends/win32_file_device.h)8
-rw-r--r--core/src/stored/backends/win32_tape_device.cc (renamed from core/src/win32/stored/backends/win32_tape_device.cc)3
-rw-r--r--core/src/stored/backends/win32_tape_device.h (renamed from core/src/win32/stored/backends/win32_tape_device.h)8
-rw-r--r--core/src/stored/dev.cc88
-rw-r--r--core/src/stored/sd_backends.h17
-rw-r--r--core/src/stored/sd_backends_dynamic.cc78
-rw-r--r--core/src/stored/stored_conf.cc30
18 files changed, 250 insertions, 147 deletions
diff --git a/core/src/lib/plugin_registry.h b/core/src/lib/plugin_registry.h
new file mode 100644
index 000000000..3b01a3c59
--- /dev/null
+++ b/core/src/lib/plugin_registry.h
@@ -0,0 +1,75 @@
+/*
+ BAREOS® - Backup Archiving REcovery Open Sourced
+
+ Copyright (C) 2022-2022 Bareos GmbH & Co. KG
+
+ This program is Free Software; you can redistribute it and/or
+ modify it under the terms of version three of the GNU Affero General Public
+ License as published by the Free Software Foundation and included
+ in the file LICENSE.
+
+ 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
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+/*
+ * generic plugin registry where you can register factory functions based
+ * on a name. The registry is templated on the plugin's interface, thus the
+ * naming is automatically per plugin interface.
+ */
+
+#ifndef BAREOS_LIB_PLUGIN_REGISTRY_H_
+#define BAREOS_LIB_PLUGIN_REGISTRY_H_
+
+#include <memory>
+#include <functional>
+#include <unordered_map>
+
+template <typename T> class PluginRegistry {
+ using Factory = std::function<T*()>;
+ using Map = std::unordered_map<std::string, Factory>;
+
+ static Map& GetMap()
+ {
+ // this ensures thread-safe initialization (Meyers' singleton)
+ static Map plugin_map;
+ return plugin_map;
+ }
+
+ public:
+ static bool Add(const std::string& plugin_name, Factory plugin_factory)
+ {
+ GetMap().insert({plugin_name, plugin_factory});
+ return true;
+ }
+
+ static bool IsRegistered(const std::string& plugin_name)
+ {
+ auto m = GetMap();
+ return m.find(plugin_name) != m.end();
+ }
+
+ static T* Create(const std::string& plugin_name)
+ {
+ Dmsg0(100, "Creating Instance for '%s'\n", plugin_name.c_str());
+ return GetMap().at(plugin_name)();
+ }
+
+ static void DumpDbg()
+ {
+ Dmsg0(100, "Start plugin registry dump\n");
+ for (auto const& [plugin_name, plugin_factory] : GetMap()) {
+ auto type = plugin_factory.target_type().name();
+ Dmsg0(100, "Plugin name %s with factory %s\n", plugin_name.c_str(), type);
+ }
+ Dmsg0(100, "end plugin registry dump\n");
+ }
+};
+#endif // BAREOS_LIB_PLUGIN_REGISTRY_H_
diff --git a/core/src/stored/CMakeLists.txt b/core/src/stored/CMakeLists.txt
index 3a5e11291..0555c150a 100644
--- a/core/src/stored/CMakeLists.txt
+++ b/core/src/stored/CMakeLists.txt
@@ -155,7 +155,9 @@ set_target_properties(
SOVERSION "${BAREOS_VERSION_MAJOR}"
)
-if(NOT ${HAVE_DYNAMIC_SD_BACKENDS})
+if(${HAVE_DYNAMIC_SD_BACKENDS})
+ target_sources(bareossd PRIVATE sd_backends_dynamic.cc)
+else()
target_link_libraries(bareossd PRIVATE ${LIBBAREOSSD_LIBRARIES})
endif()
diff --git a/core/src/stored/backends/CMakeLists.txt b/core/src/stored/backends/CMakeLists.txt
index 0f4733c31..b2304f3bc 100644
--- a/core/src/stored/backends/CMakeLists.txt
+++ b/core/src/stored/backends/CMakeLists.txt
@@ -26,7 +26,7 @@ macro(add_sd_backend backend_name)
add_library(${backend_name} MODULE)
install(TARGETS ${backend_name} DESTINATION ${backenddir})
else()
- add_library(${backend_name} STATIC)
+ add_library(${backend_name} OBJECT)
target_link_libraries(bareossd PRIVATE ${backend_name})
endif()
set_property(TARGET ${backend_name} PROPERTY POSITION_INDEPENDENT_CODE ON)
@@ -56,14 +56,20 @@ if(TARGET droplet)
endif()
+add_sd_backend(bareossd-file)
add_sd_backend(bareossd-fifo)
-target_sources(bareossd-fifo PRIVATE unix_fifo_device.cc)
-if(HAVE_DARWIN_OS)
- target_link_libraries(bareossd-fifo bareos bareossd)
-endif()
-
add_sd_backend(bareossd-tape)
-target_sources(bareossd-tape PRIVATE unix_tape_device.cc)
+if(HAVE_WIN32)
+ target_sources(bareossd-file PRIVATE win32_file_device.cc)
+ target_sources(bareossd-fifo PRIVATE win32_fifo_device.cc)
+ target_sources(bareossd-tape PRIVATE win32_tape_device.cc)
+
+ target_link_libraries(bareossd-file PRIVATE bareos)
+else()
+ target_sources(bareossd-file PRIVATE unix_file_device.cc)
+ target_sources(bareossd-fifo PRIVATE unix_fifo_device.cc)
+ target_sources(bareossd-tape PRIVATE unix_tape_device.cc)
+endif()
if(HAVE_DYNAMIC_SD_BACKENDS)
add_library(bareossd-gentape SHARED generic_tape_device.cc)
@@ -76,7 +82,6 @@ else()
target_sources(bareossd-tape PRIVATE generic_tape_device.cc)
endif()
-if(NOT HAVE_WIN32)
- add_sd_backend(bareossd-file)
- target_sources(bareossd-file PRIVATE unix_file_device.cc)
+if(HAVE_DARWIN_OS)
+ target_link_libraries(bareossd-fifo bareos bareossd)
endif()
diff --git a/core/src/stored/backends/droplet_device.cc b/core/src/stored/backends/droplet_device.cc
index b3d3bd0ce..0aaf6beaf 100644
--- a/core/src/stored/backends/droplet_device.cc
+++ b/core/src/stored/backends/droplet_device.cc
@@ -1027,12 +1027,6 @@ DropletDevice::~DropletDevice()
unlock_mutex(mutex);
}
-class Backend : public BackendInterface {
- public:
- Device* GetDevice() override { return new DropletDevice; }
-};
+REGISTER_SD_BACKEND(droplet, DropletDevice)
-#ifdef HAVE_DYNAMIC_SD_BACKENDS
-extern "C" BackendInterface* GetBackend(void) { return new Backend; }
-#endif
} /* namespace storagedaemon */
diff --git a/core/src/stored/backends/gfapi_device.cc b/core/src/stored/backends/gfapi_device.cc
index 7b866eb5c..0497c9278 100644
--- a/core/src/stored/backends/gfapi_device.cc
+++ b/core/src/stored/backends/gfapi_device.cc
@@ -575,15 +575,7 @@ gfapi_device::gfapi_device()
virtual_filename_ = GetPoolMemory(PM_FNAME);
}
-class Backend : public BackendInterface {
- public:
- Device* GetDevice() override { return new gfapi_device; }
-};
-
-# ifdef HAVE_DYNAMIC_SD_BACKENDS
-extern "C" BackendInterface* GetBackend(void) { return new Backend; }
-# endif
-
+REGISTER_SD_BACKEND(gfapi, gfapi_device);
} /* namespace storagedaemon */
#endif /* HAVE_GFAPI */
diff --git a/core/src/stored/backends/unix_fifo_device.cc b/core/src/stored/backends/unix_fifo_device.cc
index 612b52291..558d1e56d 100644
--- a/core/src/stored/backends/unix_fifo_device.cc
+++ b/core/src/stored/backends/unix_fifo_device.cc
@@ -315,14 +315,6 @@ boffset_t unix_fifo_device::d_lseek(DeviceControlRecord*, boffset_t, int)
bool unix_fifo_device::d_truncate(DeviceControlRecord*) { return true; }
-class Backend : public BackendInterface {
- public:
- Device* GetDevice() override { return new unix_fifo_device; }
-};
-
-#ifdef HAVE_DYNAMIC_SD_BACKENDS
-extern "C" BackendInterface* GetBackend(void) { return new Backend; }
-#endif
-
+REGISTER_SD_BACKEND(fifo, unix_fifo_device);
} /* namespace storagedaemon */
diff --git a/core/src/stored/backends/unix_file_device.cc b/core/src/stored/backends/unix_file_device.cc
index 5bf95f40d..f866c203e 100644
--- a/core/src/stored/backends/unix_file_device.cc
+++ b/core/src/stored/backends/unix_file_device.cc
@@ -37,6 +37,7 @@
#include "unix_file_device.h"
#include "lib/berrno.h"
#include "lib/util.h"
+#include "lib/plugin_registry.h"
namespace storagedaemon {
@@ -311,13 +312,6 @@ bail_out:
return true;
}
-class Backend : public BackendInterface {
- public:
- Device* GetDevice() override { return new unix_file_device; }
-};
-
-#ifdef HAVE_DYNAMIC_SD_BACKENDS
-extern "C" BackendInterface* GetBackend(void) { return new Backend; }
-#endif
+REGISTER_SD_BACKEND(file, unix_file_device);
} /* namespace storagedaemon */
diff --git a/core/src/stored/backends/unix_tape_device.cc b/core/src/stored/backends/unix_tape_device.cc
index b7b62f771..b196b0f09 100644
--- a/core/src/stored/backends/unix_tape_device.cc
+++ b/core/src/stored/backends/unix_tape_device.cc
@@ -59,13 +59,6 @@ unix_tape_device::unix_tape_device()
SetCap(CAP_ADJWRITESIZE); /* Adjust write size to min/max */
}
-class Backend : public BackendInterface {
- public:
- Device* GetDevice() override { return new unix_tape_device; }
-};
-
-#ifdef HAVE_DYNAMIC_SD_BACKENDS
-extern "C" BackendInterface* GetBackend(void) { return new Backend; }
-#endif
+REGISTER_SD_BACKEND(tape, unix_tape_device)
} /* namespace storagedaemon */
diff --git a/core/src/win32/stored/backends/win32_fifo_device.cc b/core/src/stored/backends/win32_fifo_device.cc
index 373ea5224..cb4ad27fa 100644
--- a/core/src/win32/stored/backends/win32_fifo_device.cc
+++ b/core/src/stored/backends/win32_fifo_device.cc
@@ -36,6 +36,7 @@
#include "stored/device_control_record.h"
#include "stored/stored.h"
#include "stored/autochanger.h"
+#include "stored/sd_backends.h"
namespace storagedaemon {
@@ -318,4 +319,6 @@ boffset_t win32_fifo_device::d_lseek(DeviceControlRecord*, boffset_t, int)
bool win32_fifo_device::d_truncate(DeviceControlRecord*) { return true; }
+REGISTER_SD_BACKEND(fifo, win32_fifo_device);
+
} /* namespace storagedaemon */
diff --git a/core/src/win32/stored/backends/win32_fifo_device.h b/core/src/stored/backends/win32_fifo_device.h
index 744cb06f8..a1f7716ff 100644
--- a/core/src/win32/stored/backends/win32_fifo_device.h
+++ b/core/src/stored/backends/win32_fifo_device.h
@@ -2,7 +2,7 @@
BAREOS® - Backup Archiving REcovery Open Sourced
Copyright (C) 2015-2015 Planets Communications B.V.
- Copyright (C) 2015-2021 Bareos GmbH & Co. KG
+ Copyright (C) 2015-2022 Bareos GmbH & Co. KG
This program is Free Software; you can redistribute it and/or
modify it under the terms of version three of the GNU Affero General Public
@@ -25,8 +25,8 @@
* Marco van Wieringen, June 2014
*/
-#ifndef BAREOS_WIN32_STORED_BACKENDS_WIN32_FIFO_DEVICE_H_
-#define BAREOS_WIN32_STORED_BACKENDS_WIN32_FIFO_DEVICE_H_
+#ifndef BAREOS_STORED_BACKENDS_WIN32_FIFO_DEVICE_H_
+#define BAREOS_STORED_BACKENDS_WIN32_FIFO_DEVICE_H_
#include "stored/dev.h"
#include "lib/btimers.h"
@@ -61,4 +61,4 @@ class win32_fifo_device : public Device {
};
} /* namespace storagedaemon */
-#endif // BAREOS_WIN32_STORED_BACKENDS_WIN32_FIFO_DEVICE_H_
+#endif // BAREOS_STORED_BACKENDS_WIN32_FIFO_DEVICE_H_
diff --git a/core/src/win32/stored/backends/win32_file_device.cc b/core/src/stored/backends/win32_file_device.cc
index e0b8bd1e2..07510845f 100644
--- a/core/src/win32/stored/backends/win32_file_device.cc
+++ b/core/src/stored/backends/win32_file_device.cc
@@ -30,6 +30,7 @@
#include "lib/berrno.h"
#include "stored/device_control_record.h"
#include "stored/stored.h"
+#include "stored/sd_backends.h"
#include "win32_file_device.h"
namespace storagedaemon {
@@ -290,4 +291,6 @@ bool win32_file_device::d_truncate(DeviceControlRecord* dcr)
win32_file_device::win32_file_device() {}
+REGISTER_SD_BACKEND(file, win32_file_device);
+
} /* namespace storagedaemon */
diff --git a/core/src/win32/stored/backends/win32_file_device.h b/core/src/stored/backends/win32_file_device.h
index 07ac30049..31a87fa98 100644
--- a/core/src/win32/stored/backends/win32_file_device.h
+++ b/core/src/stored/backends/win32_file_device.h
@@ -2,7 +2,7 @@
BAREOS® - Backup Archiving REcovery Open Sourced
Copyright (C) 2013-2014 Planets Communications B.V.
- Copyright (C) 2013-2021 Bareos GmbH & Co. KG
+ Copyright (C) 2013-2022 Bareos GmbH & Co. KG
This program is Free Software; you can redistribute it and/or
modify it under the terms of version three of the GNU Affero General Public
@@ -25,8 +25,8 @@
* Marco van Wieringen, December 2013
*/
-#ifndef BAREOS_WIN32_STORED_BACKENDS_WIN32_FILE_DEVICE_H_
-#define BAREOS_WIN32_STORED_BACKENDS_WIN32_FILE_DEVICE_H_
+#ifndef BAREOS_STORED_BACKENDS_WIN32_FILE_DEVICE_H_
+#define BAREOS_STORED_BACKENDS_WIN32_FILE_DEVICE_H_
#include "lib/util.h"
namespace storagedaemon {
@@ -51,4 +51,4 @@ class win32_file_device : public Device {
};
} /* namespace storagedaemon */
-#endif // BAREOS_WIN32_STORED_BACKENDS_WIN32_FILE_DEVICE_H_
+#endif // BAREOS_STORED_BACKENDS_WIN32_FILE_DEVICE_H_
diff --git a/core/src/win32/stored/backends/win32_tape_device.cc b/core/src/stored/backends/win32_tape_device.cc
index 35e6954a2..6f666217e 100644
--- a/core/src/win32/stored/backends/win32_tape_device.cc
+++ b/core/src/stored/backends/win32_tape_device.cc
@@ -43,6 +43,7 @@
#include "include/bareos.h"
#include "stored/stored.h"
+#include "stored/sd_backends.h"
#include "generic_tape_device.h"
#include "win32_tape_device.h"
@@ -1110,4 +1111,6 @@ win32_tape_device::win32_tape_device()
SetCap(CAP_ADJWRITESIZE); /* Adjust write size to min/max */
}
+REGISTER_SD_BACKEND(tape, win32_tape_device)
+
} /* namespace storagedaemon */
diff --git a/core/src/win32/stored/backends/win32_tape_device.h b/core/src/stored/backends/win32_tape_device.h
index a62d07dce..b5aad9609 100644
--- a/core/src/win32/stored/backends/win32_tape_device.h
+++ b/core/src/stored/backends/win32_tape_device.h
@@ -1,7 +1,7 @@
/*
BAREOS® - Backup Archiving REcovery Open Sourced
- Copyright (C) 2013-2021 Bareos GmbH & Co. KG
+ Copyright (C) 2013-2022 Bareos GmbH & Co. KG
Copyright (C) 2013-2014 Planets Communications B.V.
This program is Free Software; you can redistribute it and/or
@@ -25,8 +25,8 @@
* Marco van Wieringen, December 2013
*/
-#ifndef BAREOS_WIN32_STORED_BACKENDS_WIN32_TAPE_DEVICE_H_
-#define BAREOS_WIN32_STORED_BACKENDS_WIN32_TAPE_DEVICE_H_
+#ifndef BAREOS_STORED_BACKENDS_WIN32_TAPE_DEVICE_H_
+#define BAREOS_STORED_BACKENDS_WIN32_TAPE_DEVICE_H_
namespace storagedaemon {
@@ -46,4 +46,4 @@ class win32_tape_device : public generic_tape_device {
};
} /* namespace storagedaemon */
-#endif // BAREOS_WIN32_STORED_BACKENDS_WIN32_TAPE_DEVICE_H_
+#endif // BAREOS_STORED_BACKENDS_WIN32_TAPE_DEVICE_H_
diff --git a/core/src/stored/dev.cc b/core/src/stored/dev.cc
index 90c91acf5..285396764 100644
--- a/core/src/stored/dev.cc
+++ b/core/src/stored/dev.cc
@@ -82,26 +82,6 @@
#include "include/jcr.h"
#include "lib/berrno.h"
-#ifndef HAVE_DYNAMIC_SD_BACKENDS
-# ifdef HAVE_GFAPI
-# include "backends/gfapi_device.h"
-# endif
-# ifdef HAVE_BAREOSSD_DROPLET_DEVICE
-# include "backends/chunked_device.h"
-# include "backends/droplet_device.h"
-# endif
-# include "backends/generic_tape_device.h"
-# ifdef HAVE_WIN32
-# include "backends/win32_file_device.h"
-# include "backends/win32_tape_device.h"
-# include "backends/win32_fifo_device.h"
-# else
-# include "backends/unix_file_device.h"
-# include "backends/unix_tape_device.h"
-# include "backends/unix_fifo_device.h"
-# endif
-#endif /* HAVE_DYNAMIC_SD_BACKENDS */
-
#ifndef O_NONBLOCK
# define O_NONBLOCK 0
#endif
@@ -142,77 +122,27 @@ Device* FactoryCreateDevice(JobControlRecord* jcr,
Dmsg1(400, "max_block_size in device_resource res is %u\n",
device_resource->max_block_size);
- // If no device type specified, try to guess
- if (device_resource->dev_type == DeviceType::B_UNKNOWN_DEV) {
+ if (!PluginRegistry<BackendInterface>::IsRegistered(
+ device_resource->dev_type)) {
Jmsg2(jcr, M_ERROR, 0, _("%s has an unknown device type %s\n"),
device_resource->archive_device_string,
device_resource->dev_type.c_str());
return nullptr;
}
- Device* dev = nullptr;
-
-/*
- * When using dynamic loading use the InitBackendDevice() function
- * for any type of device.
- */
-#if !defined(HAVE_DYNAMIC_SD_BACKENDS)
-# ifdef HAVE_WIN32
- if (device_resource->dev_type == DeviceType::B_FILE_DEV) {
- dev = new win32_file_device;
- } else if (device_resource->dev_type == DeviceType::B_TAPE_DEV) {
- dev = new win32_tape_device;
- } else if (device_resource->dev_type == DeviceType::B_FIFO_DEV) {
- dev = new win32_fifo_device;
- } else
-# else
- if (device_resource->dev_type == DeviceType::B_FILE_DEV) {
- dev = new unix_file_device;
- } else if (device_resource->dev_type == DeviceType::B_TAPE_DEV) {
- dev = new unix_tape_device;
- } else if (device_resource->dev_type == DeviceType::B_FIFO_DEV) {
- dev = new unix_fifo_device;
- } else
-# endif
-# ifdef HAVE_GFAPI
- if (device_resource->dev_type == DeviceType::B_GFAPI_DEV) {
- dev = new gfapi_device;
- } else
-# endif
-# ifdef HAVE_BAREOSSD_DROPLET_DEVICE
- if (device_resource->dev_type == DeviceType::B_DROPLET_DEV) {
- dev = new DropletDevice;
- } else
-# endif
- {
- Jmsg2(jcr, M_ERROR, 0, _("%s has unsupported device type %s\n"),
- device_resource->archive_device_string,
- device_resource->dev_type.c_str());
- return nullptr;
- }
-#else
- dev = InitBackendDevice(jcr, device_resource->dev_type);
- if (!dev) {
- try {
- Jmsg2(jcr, M_ERROR, 0,
- _("Initialization of dynamic %s device \"%s\" with archive "
- "device \"%s\" failed. Backend "
- "library might be missing or backend directory incorrect.\n"),
- device_resource->dev_type.c_str(), device_resource->resource_name_,
- device_resource->archive_device_string);
- } catch (const std::out_of_range&) {
- // device_resource->dev_type could exceed limits of map
- }
- return nullptr;
- }
-#endif // !defined(HAVE_DYNAMIC_SD_BACKENDS)
+ // FIXME: the PluginRegistry should return the device instead of the factory
+ // so we save one call and a delete.
+ auto factory
+ = PluginRegistry<BackendInterface>::Create(device_resource->dev_type);
+ Device* dev = factory->GetDevice();
+ delete factory;
dev->device_resource = device_resource;
device_resource->dev = dev;
InitiateDevice(jcr, dev);
return dev;
-} // namespace storagedaemon
+}
static void InitiateDevice(JobControlRecord* jcr, Device* dev)
{
diff --git a/core/src/stored/sd_backends.h b/core/src/stored/sd_backends.h
index 72896cc53..2ecc69e6a 100644
--- a/core/src/stored/sd_backends.h
+++ b/core/src/stored/sd_backends.h
@@ -28,6 +28,8 @@
#ifndef BAREOS_STORED_SD_BACKENDS_H_
#define BAREOS_STORED_SD_BACKENDS_H_
+#include <lib/plugin_registry.h>
+
namespace storagedaemon {
class BackendInterface {
@@ -36,6 +38,12 @@ class BackendInterface {
virtual Device* GetDevice() = 0;
};
+template <typename T> class Backend : public BackendInterface {
+ public:
+ Device* GetDevice(void) override { return new T(); }
+};
+
+template <typename T> BackendInterface* BackendFactory(void) { return new T(); }
extern "C" {
typedef BackendInterface* (*t_backend_base)(void);
@@ -52,7 +60,6 @@ BackendInterface* GetBackend(void);
# define DYN_LIB_EXTENSION ".so"
#endif
-
#if defined(HAVE_DYNAMIC_SD_BACKENDS)
# include <map>
void SetBackendDeviceDirectories(std::vector<std::string>&& new_backend_dirs);
@@ -60,7 +67,15 @@ Device* InitBackendDevice(JobControlRecord* jcr,
const std::string& device_type);
void FlushAndCloseBackendDevices();
+bool LoadStorageBackend(const std::string& dev_type,
+ const std::vector<std::string>& backend_directories);
#endif
+
+#define REGISTER_SD_BACKEND(backend_name, backend_class) \
+ [[maybe_unused]] static bool backend_name##_backend_ \
+ = PluginRegistry<BackendInterface>::Add( \
+ #backend_name, BackendFactory<Backend<backend_class>>);
+
} /* namespace storagedaemon */
#endif // BAREOS_STORED_SD_BACKENDS_H_
diff --git a/core/src/stored/sd_backends_dynamic.cc b/core/src/stored/sd_backends_dynamic.cc
new file mode 100644
index 000000000..4917f08b9
--- /dev/null
+++ b/core/src/stored/sd_backends_dynamic.cc
@@ -0,0 +1,78 @@
+/*
+ BAREOS® - Backup Archiving REcovery Open Sourced
+
+ Copyright (C) 2022-2022 Bareos GmbH & Co. KG
+
+ This program is Free Software; you can redistribute it and/or
+ modify it under the terms of version three of the GNU Affero General Public
+ License as published by the Free Software Foundation and included
+ in the file LICENSE.
+
+ 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
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+/**
+ * @file
+ * Dynamic loading of SD backend plugins.
+ */
+
+#include "include/bareos.h"
+
+#include "stored/stored.h"
+#include "sd_backends.h"
+#include <dlfcn.h>
+
+namespace storagedaemon {
+
+#if defined(HAVE_WIN32)
+static const char* kDynLibExtension = ".dll";
+#else
+static const char* kDynLibExtension = ".so";
+#endif
+
+static bool LoadDynamicLibrary(
+ const std::string& library_file,
+ const std::vector<std::string>& library_directories)
+{
+ for (const auto& library_dir : library_directories) {
+ if (dlopen((library_dir + "/" + library_file).c_str(), RTLD_NOW)) {
+ Dmsg0(50, "Loaded dynamic library %s/%s\n", library_dir.c_str(),
+ library_file.c_str());
+ return true;
+ }
+ Dmsg0(50, "Could not load library %s/%s: %s\n", library_dir.c_str(),
+ library_file.c_str(), dlerror());
+ }
+ return false;
+}
+
+bool LoadStorageBackend(const std::string& dev_type,
+ const std::vector<std::string>& backend_directories)
+{
+ using namespace std::string_literals;
+
+ if (dev_type.empty() || backend_directories.empty()) { return false; }
+
+ if (!LoadDynamicLibrary("libbareossd-"s + dev_type + kDynLibExtension,
+ backend_directories)) {
+ return false;
+ }
+
+ if (!PluginRegistry<BackendInterface>::IsRegistered(dev_type)) {
+ Jmsg(nullptr, M_ERROR_TERM, 0,
+ "Loaded backend library for %s did not register its backend. This is "
+ "probably a bug in the backend library.\n",
+ dev_type.c_str());
+ }
+
+ return true;
+}
+
+} /* namespace storagedaemon */
diff --git a/core/src/stored/stored_conf.cc b/core/src/stored/stored_conf.cc
index 38fc5fd3c..4e00244ef 100644
--- a/core/src/stored/stored_conf.cc
+++ b/core/src/stored/stored_conf.cc
@@ -43,6 +43,7 @@
#define NEED_JANSSON_NAMESPACE 1
#include "lib/output_formatter.h"
#include "lib/output_formatter_resource.h"
+#include "lib/plugin_registry.h"
#include "include/auth_types.h"
#include "include/jcr.h"
@@ -544,18 +545,40 @@ static void GuessMissingDeviceTypes(ConfigurationParser& my_config)
}
}
-static void CheckDeviceBackends(ConfigurationParser& my_config)
+static void CheckAndLoadDeviceBackends(ConfigurationParser& my_config)
{
PluginRegistry<BackendInterface>::DumpDbg();
+#if defined(HAVE_DYNAMIC_SD_BACKENDS)
+ auto storage_res
+ = dynamic_cast<StorageResource*>(my_config.GetNextRes(R_STORAGE, NULL));
+#endif
+
BareosResource* p = nullptr;
while ((p = my_config.GetNextRes(R_DEVICE, p)) != nullptr) {
DeviceResource* d = dynamic_cast<DeviceResource*>(p);
if (d) {
to_lower(d->dev_type);
- Dmsg0(50, "device %s has dev_type %s\n", d->resource_name_,
- d->dev_type.c_str());
+ if (!PluginRegistry<BackendInterface>::IsRegistered(d->dev_type)) {
+#if defined(HAVE_DYNAMIC_SD_BACKENDS)
+ if (!storage_res || storage_res->backend_directories.empty()) {
+ Jmsg2(nullptr, M_ERROR_TERM, 0,
+ "Backend Directory not set. Cannot load dynamic backend %s\n",
+ d->dev_type.c_str());
+ }
+ if (!LoadStorageBackend(d->dev_type,
+ storage_res->backend_directories)) {
+ Jmsg2(nullptr, M_ERROR_TERM, 0,
+ "Could not load storage backend %s for device %s.\n",
+ d->dev_type.c_str(), d->resource_name_);
+ }
+#else
+ Jmsg2(nullptr, M_ERROR_TERM, 0,
+ "Backend %s for device %s not available.\n", d->dev_type.c_str(),
+ d->resource_name_);
+#endif
+ }
}
}
}
@@ -564,6 +587,7 @@ static void ConfigReadyCallback(ConfigurationParser& my_config)
{
MultiplyConfiguredDevices(my_config);
GuessMissingDeviceTypes(my_config);
+ CheckAndLoadDeviceBackends(my_config);
CheckDropletDevices(my_config);
}