summaryrefslogtreecommitdiff
path: root/accel-pppd/backup/backup.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/backup/backup.c')
-rw-r--r--accel-pppd/backup/backup.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/accel-pppd/backup/backup.c b/accel-pppd/backup/backup.c
new file mode 100644
index 0000000..d045f0c
--- /dev/null
+++ b/accel-pppd/backup/backup.c
@@ -0,0 +1,245 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "triton.h"
+#include "events.h"
+#include "ap_session.h"
+#include "backup.h"
+
+#ifdef USE_BACKUP
+
+static LIST_HEAD(storage_list);
+static LIST_HEAD(module_list);
+
+struct backup_tag __export *backup_add_tag(struct backup_mod *m, uint8_t id, int internal, const void *data, size_t size)
+{
+ struct backup_tag *t;
+
+ t = m->data->storage->alloc_tag(m->data, size);
+ if (!t)
+ return NULL;
+
+ t->id = id;
+ t->internal = internal;
+ t->size = size;
+ memcpy(t->data, data, size);
+
+ list_add_tail(&t->entry, &m->tag_list);
+
+ return t;
+}
+
+void backup_add_fd(struct backup_mod *m, int fd)
+{
+ if (m->data->storage->add_fd)
+ m->data->storage->add_fd(m->data, fd);
+}
+
+struct backup_mod __export *backup_find_mod(struct backup_data *d, uint8_t mod_id)
+{
+ struct backup_mod *m;
+
+ list_for_each_entry(m, &d->mod_list, entry) {
+ if (m->id == mod_id)
+ return m;
+ }
+
+ return NULL;
+}
+
+struct backup_tag __export *backup_find_tag(struct backup_data *d, uint8_t mod_id, uint8_t tag_id, int internal)
+{
+ struct backup_mod *m = backup_find_mod(d, mod_id);
+ struct backup_tag *t;
+
+ if (!m)
+ return NULL;
+
+ list_for_each_entry(t, &m->tag_list, entry) {
+ if (t->id == tag_id && t->internal == internal)
+ return t;
+ }
+
+ return NULL;
+}
+
+void __export backup_free(struct backup_data *data)
+{
+ struct backup_mod *m;
+ struct backup_tag *t;
+
+ while (!list_empty(&data->mod_list)) {
+ m = list_entry(data->mod_list.next, typeof(*m), entry);
+ while (!list_empty(&m->tag_list)) {
+ t = list_entry(m->tag_list.next, typeof(*t), entry);
+ list_del(&t->entry);
+ data->storage->free_tag(data, t);
+ }
+ list_del(&m->entry);
+ data->storage->free_mod(m);
+ }
+ data->storage->free(data);
+}
+
+int __export backup_save_session(struct ap_session *ses)
+{
+ struct backup_storage *storage;
+ struct backup_module *module;
+ struct backup_data *d;
+ struct backup_mod *m;
+ int r, f1 = 0, f2;
+
+ list_for_each_entry(storage, &storage_list, entry) {
+ d = storage->create(ses);
+ if (!d)
+ continue;
+
+ //d->ses = ses;
+
+ f2 = 0;
+
+ list_for_each_entry(module, &module_list, entry) {
+ if (!module->save)
+ continue;
+
+ m = storage->alloc_mod(d);
+ if (!m) {
+ f2 = 1;
+ break;
+ }
+
+ m->data = d;
+ m->id = module->id;
+ r = module->save(ses, m);
+ if (r == -2) {
+ storage->free_mod(m);
+ continue;
+ }
+
+ list_add_tail(&m->entry, &d->mod_list);
+
+ if (r == -1) {
+ f2 = 1;
+ break;
+ }
+ }
+
+ if (f2)
+ backup_free(d);
+ else {
+ f1 = 1;
+ if (storage->commit)
+ storage->commit(d);
+ ses->backup = d;
+ }
+ }
+
+ return !f1;
+}
+
+/*int backup_restore_internal(void)
+{
+ struct backup_storage *storage;
+
+ list_for_each_entry(storage, &storage_list, entry) {
+ if (storage->restore_internal) {
+ if (storage->check_integrity())
+ continue;
+ storage->restore_internal();
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+void backup_restore_external(void)
+{
+ struct backup_storage *storage;
+
+ list_for_each_entry(storage, &storage_list, entry) {
+ if (storage->restore_external) {
+ if (storage->check_integrity())
+ continue;
+ storage->restore_external();
+ return;
+ }
+ }
+}*/
+
+static void __restore_session(struct ap_session *ses)
+{
+ struct backup_module *module;
+ struct backup_mod *m;
+ struct backup_module *ctrl = NULL;
+
+ list_for_each_entry(module, &module_list, entry) {
+ if (module->ctrl_start)
+ ctrl = module;
+ if (module->restore) {
+ m = backup_find_mod(ses->backup, module->id);
+ if (!m)
+ continue;
+ module->restore(ses, m);
+ }
+ }
+
+ if (ctrl)
+ ctrl->ctrl_start(ses);
+ else {
+ triton_event_fire(EV_CTRL_STARTING, ses);
+ triton_event_fire(EV_CTRL_STARTED, ses);
+
+ ap_session_starting(ses);
+ ap_session_activate(ses);
+ }
+}
+
+void __export backup_restore_session(struct backup_data *d)
+{
+ struct backup_module *module;
+ struct backup_mod *m;
+ struct ap_session *ses;
+
+ list_for_each_entry(module, &module_list, entry) {
+ if (module->ctrl_restore) {
+ m = backup_find_mod(d, module->id);
+ if (!m)
+ continue;
+ ses = module->ctrl_restore(m);
+ ses->backup = d;
+ d->ses = ses;
+ ses->state = AP_STATE_RESTORE;
+ triton_context_call(ses->ctrl->ctx, (triton_event_func)__restore_session, ses);
+ break;
+ }
+ }
+}
+
+
+void __export backup_register_module(struct backup_module *m)
+{
+ list_add_tail(&m->entry, &module_list);
+}
+
+void __export backup_register_storage(struct backup_storage *s)
+{
+ list_add_tail(&s->entry, &storage_list);
+}
+
+void backup_restore_fd()
+{
+
+}
+
+void backup_restore(int internal)
+{
+ struct backup_storage *storage;
+
+ list_for_each_entry(storage, &storage_list, entry) {
+ if (storage->restore)
+ storage->restore(internal);
+ }
+}
+
+#endif