Added persist_manager class to handle saving,
...loading, caching and (not yet implemented) atomic transactions of data.
This commit is contained in:
parent
bd60de7140
commit
55f1280b07
14 changed files with 179 additions and 75 deletions
|
@ -553,7 +553,7 @@
|
|||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\persist_manager.hpp"
|
||||
RelativePath="..\..\src\persist_manager.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
|
@ -6735,6 +6735,10 @@
|
|||
RelativePath="..\..\src\persist_context.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\persist_manager.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\persist_var.hpp"
|
||||
>
|
||||
|
|
|
@ -425,6 +425,7 @@ set(wesnoth-main_SRC
|
|||
multiplayer_create.cpp
|
||||
${network_implementation_files} # network.cpp and network_worker.cpp are included by default (without USE_ANA_NETWORK)
|
||||
persist_context.cpp
|
||||
persist_manager.cpp
|
||||
persist_var.cpp
|
||||
playcampaign.cpp
|
||||
play_controller.cpp
|
||||
|
|
|
@ -241,6 +241,7 @@ wesnoth_source = \
|
|||
$(network_core) \
|
||||
pathfind/pathfind.cpp \
|
||||
persist_context.cpp \
|
||||
persist_manager.cpp \
|
||||
persist_var.cpp \
|
||||
playcampaign.cpp \
|
||||
play_controller.cpp \
|
||||
|
|
|
@ -225,6 +225,7 @@ wesnoth_sources = Split("""
|
|||
multiplayer_connect.cpp
|
||||
pathfind/pathfind.cpp
|
||||
persist_context.cpp
|
||||
persist_manager.cpp
|
||||
persist_var.cpp
|
||||
playcampaign.cpp
|
||||
play_controller.cpp
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2003 - 2010 by David White <dave@whitevine.net>
|
||||
Copyright (C) 2010 by Jody Northup
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -14,68 +14,11 @@
|
|||
|
||||
#include "global.hpp"
|
||||
|
||||
#include "filesystem.hpp"
|
||||
#include "util.hpp"
|
||||
#include "log.hpp"
|
||||
#include "persist_context.hpp"
|
||||
#include "persist_manager.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "serialization/binary_or_text.hpp"
|
||||
|
||||
static std::string get_persist_cfg_name(const std::string &name_space) {
|
||||
return (get_dir(get_user_data_dir() + "/persist/") + name_space + ".cfg");
|
||||
}
|
||||
|
||||
static bool load_persist_data(const std::string &name_space, config &cfg, const bool create_if_missing = true)
|
||||
{
|
||||
bool success = false;
|
||||
std::string cfg_dir = get_dir(get_user_data_dir() + "/persist");
|
||||
create_directory_if_missing(cfg_dir);
|
||||
|
||||
std::string cfg_name = get_persist_cfg_name(name_space);
|
||||
if (!cfg_name.empty()) {
|
||||
scoped_istream file_stream = istream_file(cfg_name);
|
||||
if (file_stream->fail()) {
|
||||
if (create_if_missing) {
|
||||
success = true;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
detect_format_and_read(cfg,*file_stream);
|
||||
success = true;
|
||||
} catch (config::error &err) {
|
||||
LOG_SAVE << err.message;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool save_persist_data(const std::string &name_space, config &cfg)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
std::string cfg_name = get_persist_cfg_name(name_space);
|
||||
if (!cfg_name.empty()) {
|
||||
if (cfg.empty()) {
|
||||
success = delete_directory(cfg_name);
|
||||
} else {
|
||||
scoped_ostream out = ostream_file(cfg_name);
|
||||
if (!out->fail())
|
||||
{
|
||||
config_writer writer(*out,false);
|
||||
try {
|
||||
writer.write(cfg);
|
||||
success = true;
|
||||
} catch(config::error &err) {
|
||||
LOG_SAVE << err.message;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
#include "util.hpp"
|
||||
|
||||
config pack_scalar(const std::string &name, const t_string &val)
|
||||
{
|
||||
|
@ -89,12 +32,12 @@ persist_context &persist_context::add_child(const std::string& /*key*/) {
|
|||
return *this;//(children_[key]);
|
||||
}
|
||||
void persist_context::load() {
|
||||
load_persist_data(namespace_.root_,cfg_,false);
|
||||
resources::persist->load_data(namespace_.root_,cfg_,false);
|
||||
}
|
||||
|
||||
persist_context::persist_context(const std::string &name_space)
|
||||
: cfg_()
|
||||
, namespace_(name_space)
|
||||
, namespace_(name_space,true)
|
||||
, root_node_(namespace_.root_,this,cfg_)
|
||||
, active_(&root_node_)
|
||||
, valid_(namespace_.valid())
|
||||
|
@ -142,7 +85,6 @@ bool persist_context::clear_var(std::string &global)
|
|||
active_->cfg_.clear_children("variables");
|
||||
active_->cfg_.remove_attribute("variables");
|
||||
}
|
||||
namespace_ = namespace_.prev();
|
||||
}
|
||||
}
|
||||
// dirty_ = true;
|
||||
|
@ -174,7 +116,7 @@ config persist_context::get_var(const std::string &global) const
|
|||
return ret;
|
||||
}
|
||||
bool persist_context::save_context() {
|
||||
return save_persist_data(namespace_.root_,cfg_);
|
||||
return resources::persist->save_data(namespace_.root_,cfg_);
|
||||
}
|
||||
bool persist_context::set_var(const std::string &global,const config &val)
|
||||
{
|
||||
|
@ -191,3 +133,20 @@ bool persist_context::set_var(const std::string &global,const config &val)
|
|||
// dirty_ = true;
|
||||
return save_context();
|
||||
}
|
||||
void persist_context::set_node(const std::string &name) {
|
||||
active_ = &(root_node_.child(name));
|
||||
}
|
||||
std::string persist_context::get_node() {
|
||||
std::vector<std::string> layers;
|
||||
node *ptr = active_;
|
||||
while (ptr != NULL) {
|
||||
layers.push_back(ptr->name_);
|
||||
ptr = ptr->parent_;
|
||||
}
|
||||
std::string ret;
|
||||
for (int i = layers.size() - 1; i >= 0; i--) {
|
||||
ret += layers[i];
|
||||
if (i != 0) ret += ".";
|
||||
}
|
||||
return ret;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2003 - 2010 by David White <dave@whitevine.net>
|
||||
Copyright (C) 2010 by Jody Northup
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -22,7 +22,7 @@ static lg::log_domain log_persist("engine/persistence");
|
|||
#define ERR_SAVE LOG_STREAM(err, log_persist)
|
||||
config pack_scalar(const std::string &,const t_string &);
|
||||
class persist_context {
|
||||
private:
|
||||
public:
|
||||
struct name_space {
|
||||
std::string namespace_;
|
||||
std::string root_;
|
||||
|
@ -76,7 +76,7 @@ private:
|
|||
{
|
||||
}
|
||||
|
||||
name_space(const std::string &ns)
|
||||
name_space(const std::string &ns, bool doParse = false)
|
||||
: namespace_(ns)
|
||||
, root_()
|
||||
, node_()
|
||||
|
@ -84,7 +84,8 @@ private:
|
|||
, descendants_()
|
||||
, valid_(false)
|
||||
{
|
||||
parse();
|
||||
if (doParse)
|
||||
parse();
|
||||
valid_ = ((namespace_.find_first_not_of("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_.") > namespace_.length()) && !namespace_.empty());
|
||||
root_ = namespace_.substr(0,namespace_.find_first_of("."));
|
||||
node_ = namespace_.substr(namespace_.find_last_of(".") + 1);
|
||||
|
@ -94,6 +95,7 @@ private:
|
|||
descendants_ = namespace_.substr(namespace_.find_first_of(".") + 1);
|
||||
}
|
||||
};
|
||||
private:
|
||||
struct node {
|
||||
typedef std::map<std::string,node*> child_map;
|
||||
|
||||
|
@ -166,6 +168,8 @@ public:
|
|||
bool clear_var(std::string &);
|
||||
config get_var(const std::string &) const;
|
||||
bool set_var(const std::string &, const config &);
|
||||
std::string get_node();
|
||||
void set_node(const std::string &);
|
||||
bool valid() const { return valid_; };
|
||||
bool dirty() const {
|
||||
return true;
|
||||
|
|
85
src/persist_manager.cpp
Normal file
85
src/persist_manager.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* $Id: persist_manager.cpp 43488 2010-06-16 13:47:53Z upthorn $ */
|
||||
/*
|
||||
Copyright (C) 2010 by Jody Northup
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include "filesystem.hpp"
|
||||
#include "persist_context.hpp"
|
||||
#include "persist_manager.hpp"
|
||||
#include "serialization/binary_or_text.hpp"
|
||||
|
||||
static std::string get_persist_cfg_name(const std::string &name_space) {
|
||||
return (get_dir(get_user_data_dir() + "/persist/") + name_space + ".cfg");
|
||||
}
|
||||
|
||||
bool persist_manager::save_data(const std::string &name_space, config &cfg) {
|
||||
bool success = false;
|
||||
|
||||
std::string cfg_name = get_persist_cfg_name(name_space);
|
||||
if (!cfg_name.empty()) {
|
||||
if (cfg.empty()) {
|
||||
success = delete_directory(cfg_name);
|
||||
} else {
|
||||
scoped_ostream out = ostream_file(cfg_name);
|
||||
if (!out->fail())
|
||||
{
|
||||
config_writer writer(*out,false);
|
||||
try {
|
||||
writer.write(cfg);
|
||||
success = true;
|
||||
} catch(config::error &err) {
|
||||
LOG_SAVE << err.message;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool persist_manager::load_data(const std::string &name_space, config &cfg, const bool create_if_missing) {
|
||||
bool success = false;
|
||||
std::string cfg_dir = get_dir(get_user_data_dir() + "/persist");
|
||||
create_directory_if_missing(cfg_dir);
|
||||
|
||||
std::string cfg_name = get_persist_cfg_name(name_space);
|
||||
if (!cfg_name.empty()) {
|
||||
scoped_istream file_stream = istream_file(cfg_name);
|
||||
if (file_stream->fail()) {
|
||||
if (create_if_missing) {
|
||||
success = true;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
detect_format_and_read(cfg,*file_stream);
|
||||
success = true;
|
||||
} catch (config::error &err) {
|
||||
LOG_SAVE << err.message;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
persist_context &persist_manager::get_context(const std::string &ns)
|
||||
{
|
||||
persist_context::name_space name(ns,true);
|
||||
std::string key(name.root_);
|
||||
context_map::iterator i = contexts_.find(key);
|
||||
if (i == contexts_.end()) {
|
||||
contexts_[key] = new persist_context(key);
|
||||
}
|
||||
persist_context *ret = contexts_[key];
|
||||
if (ret->get_node() != ns)
|
||||
ret->set_node(name.descendants_);
|
||||
return *ret;
|
||||
};
|
40
src/persist_manager.hpp
Normal file
40
src/persist_manager.hpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2010 by Jody Northup
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include "config.hpp"
|
||||
#include "persist_context.hpp"
|
||||
|
||||
class persist_manager {
|
||||
protected:
|
||||
typedef std::map<std::string,persist_context *> context_map;
|
||||
|
||||
bool in_transaction_;
|
||||
context_map contexts_;
|
||||
public:
|
||||
persist_manager() : in_transaction_(false),contexts_() {}
|
||||
~persist_manager() {
|
||||
for (context_map::iterator i = contexts_.begin(); i != contexts_.end(); i++)
|
||||
delete (i->second);
|
||||
}
|
||||
persist_context &get_context(const std::string &ns);
|
||||
|
||||
//Allow for derived types to save/load from other types of storage
|
||||
virtual bool save_data(const std::string &name_space, config &cfg);
|
||||
virtual bool load_data(const std::string &name_space, config &cfg, const bool create_if_missing = true);
|
||||
|
||||
//TODO - Transactions
|
||||
bool start_transaction();
|
||||
bool end_transaction();
|
||||
bool cancel_transaction();
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2003 - 2010 by David White <dave@whitevine.net>
|
||||
Copyright (C) 2010 by Jody Northup
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -17,6 +17,7 @@
|
|||
#include "gamestatus.hpp"
|
||||
#include "log.hpp"
|
||||
#include "persist_context.hpp"
|
||||
#include "persist_manager.hpp"
|
||||
#include "persist_var.hpp"
|
||||
#include "resources.hpp"
|
||||
|
||||
|
@ -78,7 +79,7 @@ void verify_and_get_global_variable(const vconfig &pcfg)
|
|||
// TODO: determine single or multiplayer and check for side=, depending.
|
||||
if (valid)
|
||||
{
|
||||
persist_context ctx(pcfg["namespace"]);
|
||||
persist_context &ctx = resources::persist->get_context((pcfg["namespace"]));
|
||||
if (ctx.valid()) {
|
||||
get_global_variable(ctx,pcfg);
|
||||
} else {
|
||||
|
@ -104,7 +105,7 @@ void verify_and_set_global_variable(const vconfig &pcfg)
|
|||
// TODO: determine single or multiplayer and check for side=, depending.
|
||||
if (valid)
|
||||
{
|
||||
persist_context ctx(pcfg["namespace"]);
|
||||
persist_context &ctx = resources::persist->get_context((pcfg["namespace"]));
|
||||
if (ctx.valid()) {
|
||||
set_global_variable(ctx,pcfg);
|
||||
} else {
|
||||
|
@ -126,7 +127,7 @@ void verify_and_clear_global_variable(const vconfig &pcfg)
|
|||
// TODO: determine single or multiplayer and check for side=, depending.
|
||||
if (valid)
|
||||
{
|
||||
persist_context ctx(pcfg["namespace"]);
|
||||
persist_context &ctx = resources::persist->get_context((pcfg["namespace"]));
|
||||
if (ctx.valid()) {
|
||||
clear_global_variable(ctx,pcfg);
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2003 - 2010 by David White <dave@whitevine.net>
|
||||
Copyright (C) 2010 by Jody Northup
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
|
|
@ -62,7 +62,8 @@ playsingle_controller::playsingle_controller(const config& level,
|
|||
replaying_(false),
|
||||
turn_over_(false),
|
||||
skip_next_turn_(false),
|
||||
level_result_(NONE)
|
||||
level_result_(NONE),
|
||||
persist_()
|
||||
{
|
||||
// game may need to start in linger mode
|
||||
if (state_of_game.classification().completion == "victory" || state_of_game.classification().completion == "defeat")
|
||||
|
@ -74,12 +75,14 @@ playsingle_controller::playsingle_controller(const config& level,
|
|||
ai::game_info ai_info;
|
||||
ai::manager::set_ai_info(ai_info);
|
||||
ai::manager::add_observer(this) ;
|
||||
resources::persist = &persist_;
|
||||
}
|
||||
|
||||
playsingle_controller::~playsingle_controller()
|
||||
{
|
||||
ai::manager::remove_observer(this) ;
|
||||
ai::manager::clear_ais() ;
|
||||
resources::persist = NULL;
|
||||
}
|
||||
|
||||
void playsingle_controller::init_gui(){
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "global.hpp"
|
||||
|
||||
#include "cursor.hpp"
|
||||
#include "persist_manager.hpp"
|
||||
#include "play_controller.hpp"
|
||||
#include "replay.hpp"
|
||||
|
||||
|
@ -96,6 +97,7 @@ protected:
|
|||
bool turn_over_;
|
||||
bool skip_next_turn_;
|
||||
LEVEL_RESULT level_result_;
|
||||
persist_manager persist_;
|
||||
private:
|
||||
void report_victory(std::ostringstream &report, int player_gold,
|
||||
int remaining_gold, int finishing_bonus_per_turn,
|
||||
|
|
|
@ -28,4 +28,5 @@ namespace resources
|
|||
wb::manager *whiteboard;
|
||||
std::vector<undo_action> *undo_stack;
|
||||
std::vector<undo_action> *redo_stack;
|
||||
persist_manager *persist;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ class play_controller;
|
|||
class team;
|
||||
class tod_manager;
|
||||
class unit_map;
|
||||
class persist_manager;
|
||||
struct undo_action;
|
||||
|
||||
namespace soundsource { class manager; }
|
||||
|
@ -48,6 +49,7 @@ namespace resources
|
|||
extern wb::manager *whiteboard;
|
||||
extern std::vector<undo_action> *undo_stack;
|
||||
extern std::vector<undo_action> *redo_stack;
|
||||
extern persist_manager *persist;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue