diff options
-rw-r--r-- | common/makefile | 20 | ||||
-rw-r--r-- | common/schema/driver.cxx | 43 | ||||
-rw-r--r-- | common/schema/makefile | 82 | ||||
-rw-r--r-- | common/schema/test.hxx | 58 | ||||
-rw-r--r-- | common/schema/test.std | 1 | ||||
-rw-r--r-- | common/template/driver.cxx | 43 | ||||
-rw-r--r-- | common/template/makefile | 82 | ||||
-rw-r--r-- | common/template/test.hxx | 44 | ||||
-rw-r--r-- | common/template/test.std | 1 | ||||
-rw-r--r-- | libcommon/common.cxx | 45 | ||||
-rw-r--r-- | libcommon/common.hxx | 16 | ||||
-rw-r--r-- | libcommon/makefile | 82 | ||||
-rw-r--r-- | libcommon/options.cli | 58 | ||||
-rw-r--r-- | libcommon/options.cxx | 794 | ||||
-rw-r--r-- | libcommon/options.hxx | 396 | ||||
-rw-r--r-- | libcommon/options.ixx | 256 | ||||
-rw-r--r-- | makefile | 32 | ||||
-rw-r--r-- | tracer/makefile | 20 | ||||
-rw-r--r-- | tracer/object/driver.cxx | 78 | ||||
-rw-r--r-- | tracer/object/makefile | 81 | ||||
-rw-r--r-- | tracer/object/test.hxx | 44 | ||||
-rw-r--r-- | tracer/object/test.std | 32 | ||||
-rw-r--r-- | tracer/transaction/driver.cxx | 100 | ||||
-rw-r--r-- | tracer/transaction/makefile | 65 | ||||
-rw-r--r-- | tracer/transaction/test.std | 25 |
25 files changed, 2498 insertions, 0 deletions
diff --git a/common/makefile b/common/makefile new file mode 100644 index 0000000..b81fd58 --- /dev/null +++ b/common/makefile @@ -0,0 +1,20 @@ +# file : common/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +# license : GNU GPL; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make + +tests := \ +schema \ +template + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/common/schema/driver.cxx b/common/schema/driver.cxx new file mode 100644 index 0000000..4d27e81 --- /dev/null +++ b/common/schema/driver.cxx @@ -0,0 +1,43 @@ +// file : common/schema/driver.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <memory> // std::auto_ptr +#include <cassert> +#include <iostream> + +#include <odb/database.hxx> +#include <odb/transaction.hxx> + +#include <common.hxx> + +#include "test.hxx" +#include "test-odb.hxx" + +using namespace std; +using namespace odb; + +using odb::shared_ptr; + +int +main (int argc, char* argv[]) +{ + try + { + auto_ptr<database> db (create_database (argc, argv)); + + // + // + cout << "test 001" << endl; + { + transaction t (db->begin_transaction ()); + t.commit (); + } + } + catch (const odb::exception& e) + { + cerr << e.what () << endl; + return 1; + } +} diff --git a/common/schema/makefile b/common/schema/makefile new file mode 100644 index 0000000..29cca5f --- /dev/null +++ b/common/schema/makefile @@ -0,0 +1,82 @@ +# file : common/schema/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make + +cxx_tun := driver.cxx +odb_hdr := test.hxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o) $(odb_hdr:.hxx=-odb.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +common.l := $(out_root)/libcommon/common.l +common.l.cpp-options := $(out_root)/libcommon/common.l.cpp-options + +driver := $(out_base)/driver +test := $(out_base)/.test +clean := $(out_base)/.clean + +# Import. +# +$(call import,\ + $(scf_root)/import/odb/stub.make,\ + odb: odb,odb-rules: odb_rules) + +# Build. +# +$(driver): $(cxx_obj) $(common.l) +$(cxx_obj) $(cxx_od): cpp_options := -I$(out_base) +$(cxx_obj) $(cxx_od): $(common.l.cpp-options) + +genf := $(addprefix $(odb_hdr:.hxx=-odb),.hxx .ixx .cxx) $(odb_hdr:.hxx=.sql) +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): $(odb) +$(gen): odb := $(odb) +$(gen): odb_options += --database $(db_id) --generate-schema +$(gen): cpp_options := -I$(out_base) +$(gen): $(common.l.cpp-options) + +$(call include-dep,$(cxx_od),$(cxx_obj),$(gen)) + +# Alias for default target. +# +$(out_base)/: $(driver) + +# Test. +# +$(test): $(driver) $(src_base)/test.std + $(call message,sql $$1,$(dcf_root)/db-driver $$1, $(src_base)/test.sql) + $(call message,test $<,$< --options-file $(dcf_root)/db.options \ +| diff -u $(src_base)/test.std -) + +# Clean. +# +$(clean): \ + $(driver).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) \ + $(addprefix $(out_base)/,$(odb_hdr:.hxx=-odb.cxx.hxx.clean)) + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + +# How to. +# +$(call include,$(odb_rules)) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/o-e.make) + +# Dependencies. +# +$(call import,$(src_root)/libcommon/makefile) diff --git a/common/schema/test.hxx b/common/schema/test.hxx new file mode 100644 index 0000000..471d27b --- /dev/null +++ b/common/schema/test.hxx @@ -0,0 +1,58 @@ +// file : common/schema/test.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TEST_HXX +#define TEST_HXX + +#include <string> +#include <odb/core.hxx> + +// Table names. +// +#pragma odb object table ("TABLE_EXPLICIT") +struct table_explicit +{ + #pragma odb id + unsigned long id_; +}; + +#pragma odb object +struct table_implicit +{ + #pragma odb id + unsigned long id_; +}; + +// Column names. +// +#pragma odb object +struct column +{ + #pragma odb id + int m1; + + #pragma odb column ("foo") + int m2; + + int m_m3; + int _m4; + int m5_; + int m_; + int m__; +}; + +// Column types. +// +#pragma odb object +struct type +{ + #pragma odb id + int id; + + #pragma odb type ("INTEGER") + bool m1; +}; + +#endif // TEST_HXX diff --git a/common/schema/test.std b/common/schema/test.std new file mode 100644 index 0000000..af8d8e7 --- /dev/null +++ b/common/schema/test.std @@ -0,0 +1 @@ +test 001 diff --git a/common/template/driver.cxx b/common/template/driver.cxx new file mode 100644 index 0000000..0361c13 --- /dev/null +++ b/common/template/driver.cxx @@ -0,0 +1,43 @@ +// file : common/template/driver.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <memory> // std::auto_ptr +#include <cassert> +#include <iostream> + +#include <odb/database.hxx> +#include <odb/transaction.hxx> + +#include <common.hxx> + +#include "test.hxx" +#include "test-odb.hxx" + +using namespace std; +using namespace odb; + +using odb::shared_ptr; + +int +main (int argc, char* argv[]) +{ + try + { + auto_ptr<database> db (create_database (argc, argv)); + + // + // + cout << "test 001" << endl; + { + transaction t (db->begin_transaction ()); + t.commit (); + } + } + catch (const odb::exception& e) + { + cerr << e.what () << endl; + return 1; + } +} diff --git a/common/template/makefile b/common/template/makefile new file mode 100644 index 0000000..c963659 --- /dev/null +++ b/common/template/makefile @@ -0,0 +1,82 @@ +# file : common/template/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make + +cxx_tun := driver.cxx +odb_hdr := test.hxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o) $(odb_hdr:.hxx=-odb.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +common.l := $(out_root)/libcommon/common.l +common.l.cpp-options := $(out_root)/libcommon/common.l.cpp-options + +driver := $(out_base)/driver +test := $(out_base)/.test +clean := $(out_base)/.clean + +# Import. +# +$(call import,\ + $(scf_root)/import/odb/stub.make,\ + odb: odb,odb-rules: odb_rules) + +# Build. +# +$(driver): $(cxx_obj) $(common.l) +$(cxx_obj) $(cxx_od): cpp_options := -I$(out_base) +$(cxx_obj) $(cxx_od): $(common.l.cpp-options) + +genf := $(addprefix $(odb_hdr:.hxx=-odb),.hxx .ixx .cxx) $(odb_hdr:.hxx=.sql) +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): $(odb) +$(gen): odb := $(odb) +$(gen): odb_options += --database $(db_id) --generate-schema +$(gen): cpp_options := -I$(out_base) +$(gen): $(common.l.cpp-options) + +$(call include-dep,$(cxx_od),$(cxx_obj),$(gen)) + +# Alias for default target. +# +$(out_base)/: $(driver) + +# Test. +# +$(test): $(driver) $(src_base)/test.std + $(call message,sql $$1,$(dcf_root)/db-driver $$1, $(src_base)/test.sql) + $(call message,test $<,$< --options-file $(dcf_root)/db.options \ +| diff -u $(src_base)/test.std -) + +# Clean. +# +$(clean): \ + $(driver).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) \ + $(addprefix $(out_base)/,$(odb_hdr:.hxx=-odb.cxx.hxx.clean)) + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + +# How to. +# +$(call include,$(odb_rules)) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/o-e.make) + +# Dependencies. +# +$(call import,$(src_root)/libcommon/makefile) diff --git a/common/template/test.hxx b/common/template/test.hxx new file mode 100644 index 0000000..48acd44 --- /dev/null +++ b/common/template/test.hxx @@ -0,0 +1,44 @@ +// file : common/template/test.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TEST_HXX +#define TEST_HXX + +#include <string> +#include <odb/core.hxx> + +#pragma odb object +struct object1 +{ + object1 (unsigned long id) + : id_ (id) + { + } + + object1 () + { + } + + #pragma odb id + unsigned long id_; +}; + +#pragma odb object +struct object2 +{ + object2 (const std::string& id) + : id_ (id) + { + } + + object2 () + { + } + + #pragma odb id + std::string id_; +}; + +#endif // TEST_HXX diff --git a/common/template/test.std b/common/template/test.std new file mode 100644 index 0000000..af8d8e7 --- /dev/null +++ b/common/template/test.std @@ -0,0 +1 @@ +test 001 diff --git a/libcommon/common.cxx b/libcommon/common.cxx new file mode 100644 index 0000000..bfc3482 --- /dev/null +++ b/libcommon/common.cxx @@ -0,0 +1,45 @@ +// file : libcommon/common.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cstdlib> // std::exit +#include <iostream> + +#ifdef DB_ID_MYSQL +# include <odb/mysql/database.hxx> +#endif + +#include "common.hxx" +#include "options.hxx" + +using namespace std; +using namespace odb; + +auto_ptr<database> +create_database (int argc, char* argv[]) +{ +#ifdef DB_ID_MYSQL + cli::argv_file_scanner scan (argc, argv, "--options-file"); + cli::mysql_options ops (scan); + + if (ops.help ()) + { + cerr << "Usage: " << argv[0] << " [options]" << endl + << "Options:" << endl; + cli::mysql_options::print_usage (cerr); + exit (0); + } + + return auto_ptr<database> ( + new mysql::database ( + ops.user (), + ops.passwd_specified () ? &ops.passwd () : 0, + ops.db_name (), + ops.host (), + ops.port (), + ops.socket_specified () ? &ops.socket () : 0)); +#else + return auto_ptr<database> (0); +#endif +} diff --git a/libcommon/common.hxx b/libcommon/common.hxx new file mode 100644 index 0000000..8e5bd4d --- /dev/null +++ b/libcommon/common.hxx @@ -0,0 +1,16 @@ +// file : libcommon/common.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef LIBCOMMON_COMMON_HXX +#define LIBCOMMON_COMMON_HXX + +#include <memory> // std::auto_ptr + +#include <odb/database.hxx> + +std::auto_ptr<odb::database> +create_database (int argc, char* argv[]); + +#endif // LIBCOMMON_COMMON_HXX diff --git a/libcommon/makefile b/libcommon/makefile new file mode 100644 index 0000000..44c789a --- /dev/null +++ b/libcommon/makefile @@ -0,0 +1,82 @@ +# file : libcommon/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make + +# Options file. +# +cli_tun := options.cli +cxx_tun := common.cxx + +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o) $(cli_tun:.cli=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +common.l := $(out_base)/common.l +common.l.cpp-options := $(out_base)/common.l.cpp-options + +default := $(out_base)/ +clean := $(out_base)/.clean + +# Import. +# +$(call import,\ + $(scf_root)/import/cli/stub.make,\ + cli: cli,cli-rules: cli_rules) + +$(call import,\ + $(scf_root)/import/libodb/stub.make,\ + l: odb.l,cpp-options: odb.l.cpp-options) + +ifdef db_id +$(call import,\ + $(scf_root)/import/libodb-$(db_id)/stub.make,\ + l: odb_db.l,cpp-options: odb_db.l.cpp-options) +endif + +ifeq ($(odb_db.l.cpp-options),) +odb_db.l.cpp-options := $(out_base)/.unbuildable +endif + +# Build. +# +$(common.l): $(cxx_obj) $(odb.l) $(odb_db.l) + +$(cxx_obj) $(cxx_od): $(common.l.cpp-options) +$(common.l.cpp-options): value := -I$(src_base) +$(common.l.cpp-options): $(odb_db.l.cpp-options) $(odb.l.cpp-options) + +ifeq ($(db_id),mysql) +$(cxx_obj): cpp_options += -DDB_ID_MYSQL +endif + +genf := $(cli_tun:.cli=.hxx) $(cli_tun:.cli=.ixx) $(cli_tun:.cli=.cxx) +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): $(cli) +$(gen): cli := $(cli) +$(gen): cli_options += \ +--generate-specifier \ +--generate-file-scanner \ +--guard-prefix LIBCOMMON + +$(call include-dep,$(cxx_od),$(cxx_obj),$(gen)) + +# Convenience alias for default target. +# +$(out_base)/: $(common.l) + +# Clean. +# +$(clean): $(common.l).o.clean \ + $(common.l.cpp-options).clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + +# How to. +# +$(call include,$(cli_rules)) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/o-l.make) diff --git a/libcommon/options.cli b/libcommon/options.cli new file mode 100644 index 0000000..a16c5b0 --- /dev/null +++ b/libcommon/options.cli @@ -0,0 +1,58 @@ +// file : libcommon/options.cli +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +include <string>; + +namespace cli +{ + class mysql_options + { + bool --help {"Print usage information and exit."}; + + std::string --user + { + "<name>", + "MySQL database user." + }; + + std::string --passwd + { + "<str>", + "MySQL database password" + }; + + std::string --db-name + { + "<name>", + "MySQL database name." + }; + + std::string --host + { + "<addr>", + "MySQL database host name or address (localhost by default)." + }; + + unsigned int --port = 0 + { + "<integer>", + "MySQL database port number." + }; + + std::string --socket + { + "<name>", + "MySQL database socket name." + }; + + std::string --options-file + { + "<file>", + "Read additional options from <file>. Each option appearing on a separate + line optionally followed by space and an option value. Empty lines and + lines starting with \cb{#} are ignored." + }; + }; +} diff --git a/libcommon/options.cxx b/libcommon/options.cxx new file mode 100644 index 0000000..2a2280d --- /dev/null +++ b/libcommon/options.cxx @@ -0,0 +1,794 @@ +// This code was generated by CLI, a command line interface +// compiler for C++. +// + +#include "options.hxx" + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <ostream> +#include <sstream> +#include <cstring> +#include <fstream> + +namespace cli +{ + // unknown_option + // + unknown_option:: + ~unknown_option () throw () + { + } + + void unknown_option:: + print (std::ostream& os) const + { + os << "unknown option '" << option () << "'"; + } + + const char* unknown_option:: + what () const throw () + { + return "unknown option"; + } + + // unknown_argument + // + unknown_argument:: + ~unknown_argument () throw () + { + } + + void unknown_argument:: + print (std::ostream& os) const + { + os << "unknown argument '" << argument () << "'"; + } + + const char* unknown_argument:: + what () const throw () + { + return "unknown argument"; + } + + // missing_value + // + missing_value:: + ~missing_value () throw () + { + } + + void missing_value:: + print (std::ostream& os) const + { + os << "missing value for option '" << option () << "'"; + } + + const char* missing_value:: + what () const throw () + { + return "missing option value"; + } + + // invalid_value + // + invalid_value:: + ~invalid_value () throw () + { + } + + void invalid_value:: + print (std::ostream& os) const + { + os << "invalid value '" << value () << "' for option '" + << option () << "'"; + } + + const char* invalid_value:: + what () const throw () + { + return "invalid option value"; + } + + // eos_reached + // + void eos_reached:: + print (std::ostream& os) const + { + os << what (); + } + + const char* eos_reached:: + what () const throw () + { + return "end of argument stream reached"; + } + + // file_io_failure + // + file_io_failure:: + ~file_io_failure () throw () + { + } + + void file_io_failure:: + print (std::ostream& os) const + { + os << "unable to open file '" << file () << "' or read failure"; + } + + const char* file_io_failure:: + what () const throw () + { + return "unable to open file or read failure"; + } + + // unmatched_quote + // + unmatched_quote:: + ~unmatched_quote () throw () + { + } + + void unmatched_quote:: + print (std::ostream& os) const + { + os << "unmatched quote in argument '" << argument () << "'"; + } + + const char* unmatched_quote:: + what () const throw () + { + return "unmatched quote"; + } + + // scanner + // + scanner:: + ~scanner () + { + } + + // argv_scanner + // + bool argv_scanner:: + more () + { + return i_ < argc_; + } + + const char* argv_scanner:: + peek () + { + if (i_ < argc_) + return argv_[i_]; + else + throw eos_reached (); + } + + const char* argv_scanner:: + next () + { + if (i_ < argc_) + { + const char* r (argv_[i_]); + + if (erase_) + { + for (int i (i_ + 1); i < argc_; ++i) + argv_[i - 1] = argv_[i]; + + --argc_; + argv_[argc_] = 0; + } + else + ++i_; + + return r; + } + else + throw eos_reached (); + } + + void argv_scanner:: + skip () + { + if (i_ < argc_) + ++i_; + else + throw eos_reached (); + } + + // argv_file_scanner + // + bool argv_file_scanner:: + more () + { + if (!args_.empty ()) + return true; + + while (base::more ()) + { + // See if the next argument is the file option. + // + const char* a (base::peek ()); + + if (!skip_ && a == option_) + { + base::next (); + + if (!base::more ()) + throw missing_value (option_); + + load (base::next ()); + + if (!args_.empty ()) + return true; + } + else + { + if (!skip_) + skip_ = (std::strcmp (a, "--") == 0); + + return true; + } + } + + return false; + } + + const char* argv_file_scanner:: + peek () + { + if (!more ()) + throw eos_reached (); + + return args_.empty () ? base::peek () : args_.front ().c_str (); + } + + const char* argv_file_scanner:: + next () + { + if (!more ()) + throw eos_reached (); + + if (args_.empty ()) + return base::next (); + else + { + hold_.swap (args_.front ()); + args_.pop_front (); + return hold_.c_str (); + } + } + + void argv_file_scanner:: + skip () + { + if (!more ()) + throw eos_reached (); + + if (args_.empty ()) + return base::skip (); + else + args_.pop_front (); + } + + void argv_file_scanner:: + load (const char* file) + { + using namespace std; + + ifstream is (file); + + if (!is.is_open ()) + throw file_io_failure (file); + + while (!is.eof ()) + { + string line; + getline (is, line); + + if (is.fail () && !is.eof ()) + throw file_io_failure (file); + + string::size_type n (line.size ()); + + // Trim the line from leading and trailing whitespaces. + // + if (n != 0) + { + const char* f (line.c_str ()); + const char* l (f + n); + + const char* of (f); + while (f < l && (*f == ' ' || *f == '\t' || *f == '\r')) + ++f; + + --l; + + const char* ol (l); + while (l > f && (*l == ' ' || *l == '\t' || *l == '\r')) + --l; + + if (f != of || l != ol) + line = f <= l ? string (f, l - f + 1) : string (); + } + + // Ignore empty lines, those that start with #. + // + if (line.empty () || line[0] == '#') + continue; + + string::size_type p (line.find (' ')); + + if (p == string::npos) + { + if (!skip_) + skip_ = (line == "--"); + + args_.push_back (line); + } + else + { + string s1 (line, 0, p); + + // Skip leading whitespaces in the argument. + // + n = line.size (); + for (++p; p < n; ++p) + { + char c (line[p]); + + if (c != ' ' && c != '\t' && c != '\r') + break; + } + + string s2 (line, p); + + // If the string is wrapped in quotes, remove them. + // + n = s2.size (); + char cf (s2[0]), cl (s2[n - 1]); + + if (cf == '"' || cf == '\'' || cl == '"' || cl == '\'') + { + if (n == 1 || cf != cl) + throw unmatched_quote (s2); + + s2 = string (s2, 1, n - 2); + } + + if (!skip_ && s1 == option_) + load (s2.c_str ()); + else + { + args_.push_back (s1); + args_.push_back (s2); + } + } + } + } + + template <typename X> + struct parser + { + static void + parse (X& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + std::istringstream is (v); + if (!(is >> x && is.eof ())) + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + }; + + template <> + struct parser<bool> + { + static void + parse (bool& x, scanner& s) + { + s.next (); + x = true; + } + }; + + template <> + struct parser<std::string> + { + static void + parse (std::string& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + x = s.next (); + else + throw missing_value (o); + + xs = true; + } + }; + + template <typename X> + struct parser<std::vector<X> > + { + static void + parse (std::vector<X>& c, bool& xs, scanner& s) + { + X x; + parser<X>::parse (x, s); + c.push_back (x); + xs = true; + } + }; + + template <typename X> + struct parser<std::set<X> > + { + static void + parse (std::set<X>& c, bool& xs, scanner& s) + { + X x; + parser<X>::parse (x, s); + c.insert (x); + xs = true; + } + }; + + template <typename K, typename V> + struct parser<std::map<K, V> > + { + static void + parse (std::map<K, V>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + if (p == std::string::npos) + { + K k = K (); + + if (!ov.empty ()) + { + std::istringstream ks (ov); + + if (!(ks >> k && ks.eof ())) + throw invalid_value (o, ov); + } + + m[k] = V (); + } + else + { + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, p + 1); + + if (!kstr.empty ()) + { + std::istringstream ks (kstr); + + if (!(ks >> k && ks.eof ())) + throw invalid_value (o, ov); + } + + if (!vstr.empty ()) + { + std::istringstream vs (vstr); + + if (!(vs >> v && vs.eof ())) + throw invalid_value (o, ov); + } + + m[k] = v; + } + } + else + throw missing_value (o); + + xs = true; + } + }; + + template <typename X, typename T, T X::*M> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, s); + } + + template <typename X, typename T, T X::*M, bool X::*S> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, x.*S, s); + } +} + +#include <map> +#include <cstring> + +namespace cli +{ + // mysql_options + // + + mysql_options:: + mysql_options (int& argc, + char** argv, + bool erase, + ::cli::unknown_mode opt, + ::cli::unknown_mode arg) + : help_ (), + user_ (), + user_specified_ (false), + passwd_ (), + passwd_specified_ (false), + db_name_ (), + db_name_specified_ (false), + host_ (), + host_specified_ (false), + port_ (0), + port_specified_ (false), + socket_ (), + socket_specified_ (false), + options_file_ (), + options_file_specified_ (false) + { + ::cli::argv_scanner s (argc, argv, erase); + _parse (s, opt, arg); + } + + mysql_options:: + mysql_options (int start, + int& argc, + char** argv, + bool erase, + ::cli::unknown_mode opt, + ::cli::unknown_mode arg) + : help_ (), + user_ (), + user_specified_ (false), + passwd_ (), + passwd_specified_ (false), + db_name_ (), + db_name_specified_ (false), + host_ (), + host_specified_ (false), + port_ (0), + port_specified_ (false), + socket_ (), + socket_specified_ (false), + options_file_ (), + options_file_specified_ (false) + { + ::cli::argv_scanner s (start, argc, argv, erase); + _parse (s, opt, arg); + } + + mysql_options:: + mysql_options (int& argc, + char** argv, + int& end, + bool erase, + ::cli::unknown_mode opt, + ::cli::unknown_mode arg) + : help_ (), + user_ (), + user_specified_ (false), + passwd_ (), + passwd_specified_ (false), + db_name_ (), + db_name_specified_ (false), + host_ (), + host_specified_ (false), + port_ (0), + port_specified_ (false), + socket_ (), + socket_specified_ (false), + options_file_ (), + options_file_specified_ (false) + { + ::cli::argv_scanner s (argc, argv, erase); + _parse (s, opt, arg); + end = s.end (); + } + + mysql_options:: + mysql_options (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::cli::unknown_mode opt, + ::cli::unknown_mode arg) + : help_ (), + user_ (), + user_specified_ (false), + passwd_ (), + passwd_specified_ (false), + db_name_ (), + db_name_specified_ (false), + host_ (), + host_specified_ (false), + port_ (0), + port_specified_ (false), + socket_ (), + socket_specified_ (false), + options_file_ (), + options_file_specified_ (false) + { + ::cli::argv_scanner s (start, argc, argv, erase); + _parse (s, opt, arg); + end = s.end (); + } + + mysql_options:: + mysql_options (::cli::scanner& s, + ::cli::unknown_mode opt, + ::cli::unknown_mode arg) + : help_ (), + user_ (), + user_specified_ (false), + passwd_ (), + passwd_specified_ (false), + db_name_ (), + db_name_specified_ (false), + host_ (), + host_specified_ (false), + port_ (0), + port_specified_ (false), + socket_ (), + socket_specified_ (false), + options_file_ (), + options_file_specified_ (false) + { + _parse (s, opt, arg); + } + + void mysql_options:: + print_usage (::std::ostream& os) + { + os << "--help Print usage information and exit." << ::std::endl; + + os << "--user <name> MySQL database user." << ::std::endl; + + os << "--passwd <str> MySQL database password" << ::std::endl; + + os << "--db-name <name> MySQL database name." << ::std::endl; + + os << "--host <addr> MySQL database host name or address (localhost by" << ::std::endl + << " default)." << ::std::endl; + + os << "--port <integer> MySQL database port number." << ::std::endl; + + os << "--socket <name> MySQL database socket name." << ::std::endl; + + os << "--options-file <file> Read additional options from <file>." << ::std::endl; + } + + typedef + std::map<std::string, void (*) (mysql_options&, ::cli::scanner&)> + _cli_mysql_options_map; + + static _cli_mysql_options_map _cli_mysql_options_map_; + + struct _cli_mysql_options_map_init + { + _cli_mysql_options_map_init () + { + _cli_mysql_options_map_["--help"] = + &::cli::thunk< mysql_options, bool, &mysql_options::help_ >; + _cli_mysql_options_map_["--user"] = + &::cli::thunk< mysql_options, std::string, &mysql_options::user_, + &mysql_options::user_specified_ >; + _cli_mysql_options_map_["--passwd"] = + &::cli::thunk< mysql_options, std::string, &mysql_options::passwd_, + &mysql_options::passwd_specified_ >; + _cli_mysql_options_map_["--db-name"] = + &::cli::thunk< mysql_options, std::string, &mysql_options::db_name_, + &mysql_options::db_name_specified_ >; + _cli_mysql_options_map_["--host"] = + &::cli::thunk< mysql_options, std::string, &mysql_options::host_, + &mysql_options::host_specified_ >; + _cli_mysql_options_map_["--port"] = + &::cli::thunk< mysql_options, unsigned int, &mysql_options::port_, + &mysql_options::port_specified_ >; + _cli_mysql_options_map_["--socket"] = + &::cli::thunk< mysql_options, std::string, &mysql_options::socket_, + &mysql_options::socket_specified_ >; + _cli_mysql_options_map_["--options-file"] = + &::cli::thunk< mysql_options, std::string, &mysql_options::options_file_, + &mysql_options::options_file_specified_ >; + } + } _cli_mysql_options_map_init_; + + void mysql_options:: + _parse (::cli::scanner& s, + ::cli::unknown_mode opt_mode, + ::cli::unknown_mode arg_mode) + { + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + s.skip (); + opt = false; + continue; + } + + _cli_mysql_options_map::const_iterator i ( + opt ? _cli_mysql_options_map_.find (o) : _cli_mysql_options_map_.end ()); + + if (i != _cli_mysql_options_map_.end ()) + { + (*(i->second)) (*this, s); + } + else if (opt && std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + switch (opt_mode) + { + case ::cli::unknown_mode::skip: + { + s.skip (); + continue; + } + case ::cli::unknown_mode::stop: + { + break; + } + case ::cli::unknown_mode::fail: + { + throw ::cli::unknown_option (o); + } + } + + break; + } + else + { + switch (arg_mode) + { + case ::cli::unknown_mode::skip: + { + s.skip (); + continue; + } + case ::cli::unknown_mode::stop: + { + break; + } + case ::cli::unknown_mode::fail: + { + throw ::cli::unknown_argument (o); + } + } + + break; + } + } + } +} + diff --git a/libcommon/options.hxx b/libcommon/options.hxx new file mode 100644 index 0000000..d9e3ab8 --- /dev/null +++ b/libcommon/options.hxx @@ -0,0 +1,396 @@ +// This code was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef LIBCOMMON_OPTIONS_HXX +#define LIBCOMMON_OPTIONS_HXX + +#include <deque> +#include <iosfwd> +#include <string> +#include <exception> + +namespace cli +{ + class unknown_mode + { + public: + enum value + { + skip, + stop, + fail + }; + + unknown_mode (value v); + + operator value () const + { + return v_; + } + + private: + value v_; + }; + + // Exceptions. + // + + class exception: public std::exception + { + public: + virtual void + print (std::ostream&) const = 0; + }; + + std::ostream& + operator<< (std::ostream&, const exception&); + + class unknown_option: public exception + { + public: + virtual + ~unknown_option () throw (); + + unknown_option (const std::string& option); + + const std::string& + option () const; + + virtual void + print (std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string option_; + }; + + class unknown_argument: public exception + { + public: + virtual + ~unknown_argument () throw (); + + unknown_argument (const std::string& argument); + + const std::string& + argument () const; + + virtual void + print (std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string argument_; + }; + + class missing_value: public exception + { + public: + virtual + ~missing_value () throw (); + + missing_value (const std::string& option); + + const std::string& + option () const; + + virtual void + print (std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string option_; + }; + + class invalid_value: public exception + { + public: + virtual + ~invalid_value () throw (); + + invalid_value (const std::string& option, + const std::string& value); + + const std::string& + option () const; + + const std::string& + value () const; + + virtual void + print (std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string option_; + std::string value_; + }; + + class eos_reached: public exception + { + public: + virtual void + print (std::ostream&) const; + + virtual const char* + what () const throw (); + }; + + class file_io_failure: public exception + { + public: + virtual + ~file_io_failure () throw (); + + file_io_failure (const std::string& file); + + const std::string& + file () const; + + virtual void + print (std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string file_; + }; + + class unmatched_quote: public exception + { + public: + virtual + ~unmatched_quote () throw (); + + unmatched_quote (const std::string& argument); + + const std::string& + argument () const; + + virtual void + print (std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string argument_; + }; + + class scanner + { + public: + virtual + ~scanner (); + + virtual bool + more () = 0; + + virtual const char* + peek () = 0; + + virtual const char* + next () = 0; + + virtual void + skip () = 0; + }; + + class argv_scanner: public scanner + { + public: + argv_scanner (int& argc, char** argv, bool erase = false); + argv_scanner (int start, int& argc, char** argv, bool erase = false); + + int + end () const; + + virtual bool + more (); + + virtual const char* + peek (); + + virtual const char* + next (); + + virtual void + skip (); + + private: + int i_; + int& argc_; + char** argv_; + bool erase_; + }; + + class argv_file_scanner: public argv_scanner + { + public: + argv_file_scanner (int& argc, + char** argv, + const std::string& file_option, + bool erase = false); + + argv_file_scanner (int start, + int& argc, + char** argv, + const std::string& file_option, + bool erase = false); + + virtual bool + more (); + + virtual const char* + peek (); + + virtual const char* + next (); + + virtual void + skip (); + + private: + void + load (const char* file); + + typedef argv_scanner base; + + const std::string option_; + std::string hold_; + std::deque<std::string> args_; + bool skip_; + }; +} + +#include <string> + +namespace cli +{ + class mysql_options + { + public: + + mysql_options (int& argc, + char** argv, + bool erase = false, + ::cli::unknown_mode option = ::cli::unknown_mode::fail, + ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + + mysql_options (int start, + int& argc, + char** argv, + bool erase = false, + ::cli::unknown_mode option = ::cli::unknown_mode::fail, + ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + + mysql_options (int& argc, + char** argv, + int& end, + bool erase = false, + ::cli::unknown_mode option = ::cli::unknown_mode::fail, + ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + + mysql_options (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::cli::unknown_mode option = ::cli::unknown_mode::fail, + ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + + mysql_options (::cli::scanner&, + ::cli::unknown_mode option = ::cli::unknown_mode::fail, + ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + + // Option accessors. + // + + const bool& + help () const; + + const std::string& + user () const; + + bool + user_specified () const; + + const std::string& + passwd () const; + + bool + passwd_specified () const; + + const std::string& + db_name () const; + + bool + db_name_specified () const; + + const std::string& + host () const; + + bool + host_specified () const; + + const unsigned int& + port () const; + + bool + port_specified () const; + + const std::string& + socket () const; + + bool + socket_specified () const; + + const std::string& + options_file () const; + + bool + options_file_specified () const; + + // Print usage information. + // + static void + print_usage (::std::ostream&); + + private: + void + _parse (::cli::scanner&, + ::cli::unknown_mode option, + ::cli::unknown_mode argument); + + public: + bool help_; + std::string user_; + bool user_specified_; + std::string passwd_; + bool passwd_specified_; + std::string db_name_; + bool db_name_specified_; + std::string host_; + bool host_specified_; + unsigned int port_; + bool port_specified_; + std::string socket_; + bool socket_specified_; + std::string options_file_; + bool options_file_specified_; + }; +} + +#include "options.ixx" + +#endif // LIBCOMMON_OPTIONS_HXX diff --git a/libcommon/options.ixx b/libcommon/options.ixx new file mode 100644 index 0000000..0fa60e5 --- /dev/null +++ b/libcommon/options.ixx @@ -0,0 +1,256 @@ +// This code was generated by CLI, a command line interface +// compiler for C++. +// + +namespace cli +{ + // unknown_mode + // + inline unknown_mode:: + unknown_mode (value v) + : v_ (v) + { + } + + // exception + // + inline std::ostream& + operator<< (std::ostream& os, const exception& e) + { + e.print (os); + return os; + } + + // unknown_option + // + inline unknown_option:: + unknown_option (const std::string& option) + : option_ (option) + { + } + + inline const std::string& unknown_option:: + option () const + { + return option_; + } + + // unknown_argument + // + inline unknown_argument:: + unknown_argument (const std::string& argument) + : argument_ (argument) + { + } + + inline const std::string& unknown_argument:: + argument () const + { + return argument_; + } + + // missing_value + // + inline missing_value:: + missing_value (const std::string& option) + : option_ (option) + { + } + + inline const std::string& missing_value:: + option () const + { + return option_; + } + + // invalid_value + // + inline invalid_value:: + invalid_value (const std::string& option, + const std::string& value) + : option_ (option), value_ (value) + { + } + + inline const std::string& invalid_value:: + option () const + { + return option_; + } + + inline const std::string& invalid_value:: + value () const + { + return value_; + } + + // file_io_failure + // + inline file_io_failure:: + file_io_failure (const std::string& file) + : file_ (file) + { + } + + inline const std::string& file_io_failure:: + file () const + { + return file_; + } + + // unmatched_quote + // + inline unmatched_quote:: + unmatched_quote (const std::string& argument) + : argument_ (argument) + { + } + + inline const std::string& unmatched_quote:: + argument () const + { + return argument_; + } + + // argv_scanner + // + inline argv_scanner:: + argv_scanner (int& argc, char** argv, bool erase) + : i_ (1), argc_ (argc), argv_ (argv), erase_ (erase) + { + } + + inline argv_scanner:: + argv_scanner (int start, int& argc, char** argv, bool erase) + : i_ (start), argc_ (argc), argv_ (argv), erase_ (erase) + { + } + + inline int argv_scanner:: + end () const + { + return i_; + } + + // argv_file_scanner + // + inline argv_file_scanner:: + argv_file_scanner (int& argc, + char** argv, + const std::string& option, + bool erase) + : argv_scanner (argc, argv, erase), + option_ (option), + skip_ (false) + { + } + + inline argv_file_scanner:: + argv_file_scanner (int start, + int& argc, + char** argv, + const std::string& option, + bool erase) + : argv_scanner (start, argc, argv, erase), + option_ (option), + skip_ (false) + { + } +} + +namespace cli +{ + // mysql_options + // + + inline const bool& mysql_options:: + help () const + { + return this->help_; + } + + inline const std::string& mysql_options:: + user () const + { + return this->user_; + } + + inline bool mysql_options:: + user_specified () const + { + return this->user_specified_; + } + + inline const std::string& mysql_options:: + passwd () const + { + return this->passwd_; + } + + inline bool mysql_options:: + passwd_specified () const + { + return this->passwd_specified_; + } + + inline const std::string& mysql_options:: + db_name () const + { + return this->db_name_; + } + + inline bool mysql_options:: + db_name_specified () const + { + return this->db_name_specified_; + } + + inline const std::string& mysql_options:: + host () const + { + return this->host_; + } + + inline bool mysql_options:: + host_specified () const + { + return this->host_specified_; + } + + inline const unsigned int& mysql_options:: + port () const + { + return this->port_; + } + + inline bool mysql_options:: + port_specified () const + { + return this->port_specified_; + } + + inline const std::string& mysql_options:: + socket () const + { + return this->socket_; + } + + inline bool mysql_options:: + socket_specified () const + { + return this->socket_specified_; + } + + inline const std::string& mysql_options:: + options_file () const + { + return this->options_file_; + } + + inline bool mysql_options:: + options_file_specified () const + { + return this->options_file_specified_; + } +} + diff --git a/makefile b/makefile new file mode 100644 index 0000000..fc5718f --- /dev/null +++ b/makefile @@ -0,0 +1,32 @@ +# file : makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))build/bootstrap.make + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +# Build. +# +$(default): \ +$(out_base)/tracer/ \ +$(out_base)/common/ \ +$(out_base)/libcommon/ + +# Test. +# +$(test): $(out_base)/tracer/.test $(out_base)/common/.test + +# Clean. +# +$(clean): \ +$(out_base)/tracer/.clean \ +$(out_base)/common/.clean \ +$(out_base)/libcommon/.clean + +$(call import,$(src_base)/tracer/makefile) +$(call import,$(src_base)/common/makefile) +$(call import,$(src_base)/libcommon/makefile) diff --git a/tracer/makefile b/tracer/makefile new file mode 100644 index 0000000..41368ea --- /dev/null +++ b/tracer/makefile @@ -0,0 +1,20 @@ +# file : tracer/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +# license : GNU GPL; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make + +tests := \ +object \ +transaction + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tracer/object/driver.cxx b/tracer/object/driver.cxx new file mode 100644 index 0000000..8680b0a --- /dev/null +++ b/tracer/object/driver.cxx @@ -0,0 +1,78 @@ +// file : tracer/object/driver.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cassert> +#include <iostream> + +#include <odb/transaction.hxx> +#include <odb/tracer/database.hxx> + +#include "test.hxx" +#include "test-odb.hxx" + +using namespace std; +using namespace odb; + +using odb::shared_ptr; + +int +main () +{ + tracer::database db; + + // transient -> persistent in transaction + // + cout << "test 001" << endl; + { + shared_ptr<object1> o1 (new (shared) object1 (1)); + transaction t (db.begin_transaction ()); + cout << "s 1" << endl; + db.persist (o1); + cout << "s 2" << endl; + t.commit (); + cout << "s 3" << endl; + } + + // persistent -> transient in transaction + // + cout << "test 002" << endl; + { + shared_ptr<object1> o1 (new (shared) object1 (1)); + transaction t (db.begin_transaction ()); + cout << "s 1" << endl; + db.persist (o1); + cout << "s 2" << endl; + db.erase (o1); + cout << "s 3" << endl; + t.commit (); + cout << "s 4" << endl; + } + + // load in transaction + // + cout << "test 003" << endl; + { + transaction t (db.begin_transaction ()); + cout << "s 1" << endl; + shared_ptr<object1> o1 (db.load<object1> (1)); + cout << "s 2" << endl; + t.commit (); + cout << "s 3" << endl; + } + + // persistent/clean -> persistent/dirty in transaction + // + cout << "test 004" << endl; + { + transaction t (db.begin_transaction ()); + cout << "s 1" << endl; + shared_ptr<object1> o1 (db.load<object1> (1)); + cout << "s 2" << endl; + db.modified (o1); + cout << "s 3" << endl; + t.commit (); + cout << "s 4" << endl; + } +} diff --git a/tracer/object/makefile b/tracer/object/makefile new file mode 100644 index 0000000..ed7c562 --- /dev/null +++ b/tracer/object/makefile @@ -0,0 +1,81 @@ +# file : tracer/object/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make + +cxx_tun := driver.cxx +odb_hdr := test.hxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o) $(odb_hdr:.hxx=-odb.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +driver := $(out_base)/driver +test := $(out_base)/.test +clean := $(out_base)/.clean + +# Import. +# +$(call import,\ + $(scf_root)/import/odb/stub.make,\ + odb: odb,odb-rules: odb_rules) + +$(call import,\ + $(scf_root)/import/libodb/stub.make,\ + l: odb.l,cpp-options: odb.l.cpp-options) + +$(call import,\ + $(scf_root)/import/libodb-tracer/stub.make,\ + l: odb_tracer.l,cpp-options: odb_tracer.l.cpp-options) + +# Build. +# +$(driver): $(cxx_obj) $(odb_tracer.l) $(odb.l) +$(cxx_obj) $(cxx_od): cpp_options := -I$(out_base) +$(cxx_obj) $(cxx_od): $(odb_tracer.l.cpp-options) $(odb.l.cpp-options) + +genf := $(addprefix $(odb_hdr:.hxx=-odb),.hxx .ixx .cxx) +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): $(odb) +$(gen): odb := $(odb) +$(gen): odb_options += --database tracer +$(gen): cpp_options := -I$(out_base) +$(gen): $(odb_tracer.l.cpp-options) $(odb.l.cpp-options) + +$(call include-dep,$(cxx_od),$(cxx_obj),$(gen)) + +# Alias for default target. +# +$(out_base)/: $(driver) + +# Test. +# +$(test): $(driver) $(src_base)/test.std + $(call message,test $<,$< | diff -u $(src_base)/test.std -) + +# Clean. +# +$(clean): \ + $(driver).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) \ + $(addprefix $(out_base)/,$(odb_hdr:.hxx=-odb.cxx.hxx.clean)) + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + +# How to. +# +$(call include,$(odb_rules)) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/o-e.make) diff --git a/tracer/object/test.hxx b/tracer/object/test.hxx new file mode 100644 index 0000000..a988411 --- /dev/null +++ b/tracer/object/test.hxx @@ -0,0 +1,44 @@ +// file : tracer/object/test.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TEST_HXX +#define TEST_HXX + +#include <iostream> +#include <odb/core.hxx> + +#pragma odb object +struct object1 +{ + object1 (unsigned long id) + : id_ (id) + { + } + + object1 () + { + } + + #pragma odb id + unsigned long id_; +}; + +#pragma odb object +struct object2 +{ + object2 (const std::string& id) + : id_ (id) + { + } + + object2 () + { + } + + #pragma odb id + std::string id_; +}; + +#endif // TEST_HXX diff --git a/tracer/object/test.std b/tracer/object/test.std new file mode 100644 index 0000000..c7e458c --- /dev/null +++ b/tracer/object/test.std @@ -0,0 +1,32 @@ +test 001 +begin transaction +s 1 +insert ::object1 id 1 +s 2 +commit transaction +s 3 +test 002 +begin transaction +s 1 +insert ::object1 id 1 +s 2 +s 3 +delete ::object1 id 1 +commit transaction +s 4 +test 003 +begin transaction +s 1 +select ::object1 id 1 +s 2 +commit transaction +s 3 +test 004 +begin transaction +s 1 +select ::object1 id 1 +s 2 +s 3 +update ::object1 id 1 +commit transaction +s 4 diff --git a/tracer/transaction/driver.cxx b/tracer/transaction/driver.cxx new file mode 100644 index 0000000..164b9a0 --- /dev/null +++ b/tracer/transaction/driver.cxx @@ -0,0 +1,100 @@ +// file : tracer/transaction/driver.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cassert> +#include <iostream> + +#include <odb/exceptions.hxx> +#include <odb/session.hxx> +#include <odb/transaction.hxx> +#include <odb/tracer/database.hxx> +#include <odb/tracer/transaction.hxx> + +using namespace std; +using namespace odb; + +int +main () +{ + tracer::database db; + + assert (!transaction::has_current ()); + + // Current and db accessors. + // + cout << "test 001" << endl; + { + transaction t (db.begin_transaction ()); + assert (&t.database () == &db); + assert (transaction::has_current ()); + assert (&transaction::current () == &t); + } + + // Commit. + // + cout << "test 002" << endl; + { + transaction t (db.begin_transaction ()); + t.commit (); + } + + // Rollback. + // + cout << "test 003" << endl; + { + transaction t (db.begin_transaction ()); + t.rollback (); + } + + // Auto rollback. + // + cout << "test 004" << endl; + { + transaction t (db.begin_transaction ()); + } + + // Nested transaction. + // + cout << "test 005" << endl; + { + transaction t (db.begin_transaction ()); + try + { + transaction n (db.begin_transaction ()); + } + catch (const already_in_transaction&) + { + cout << "already_in_transaction" << endl; + } + } + + // Existing session via current. + // + cout << "test 006" << endl; + { + session s; + transaction t (db.begin_transaction ()); + assert (&t.session () == &s); + } + + // Existing session passed explicitly. + // + cout << "test 007" << endl; + { + session s; + transaction t (db.begin_transaction (s)); + assert (&t.session () == &s); + } + + // Concrete transaction type. + // + cout << "test 008" << endl; + { + assert (sizeof (tracer::transaction) == sizeof (transaction)); + + tracer::transaction t (db.begin_transaction ()); + tracer::transaction& r (tracer::transaction::current ()); + } +} diff --git a/tracer/transaction/makefile b/tracer/transaction/makefile new file mode 100644 index 0000000..5919e6e --- /dev/null +++ b/tracer/transaction/makefile @@ -0,0 +1,65 @@ +# file : tracer/transaction/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make + +cxx_tun := driver.cxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +driver := $(out_base)/driver +test := $(out_base)/.test +clean := $(out_base)/.clean + +# Import. +# +$(call import,\ + $(scf_root)/import/libodb/stub.make,\ + l: odb.l,cpp-options: odb.l.cpp-options) + +$(call import,\ + $(scf_root)/import/libodb-tracer/stub.make,\ + l: odb_tracer.l,cpp-options: odb_tracer.l.cpp-options) + +# Build. +# +$(driver): $(cxx_obj) $(odb_tracer.l) $(odb.l) +$(cxx_obj) $(cxx_od): cpp_options := -I$(out_base) +$(cxx_obj) $(cxx_od): $(odb_tracer.l.cpp-options) $(odb.l.cpp-options) + +$(call include-dep,$(cxx_od)) + +# Alias for default target. +# +$(out_base)/: $(driver) + +# Test. +# +$(test): $(driver) $(src_base)/test.std + $(call message,test $<,$< | diff -u $(src_base)/test.std -) + +# Clean. +# +$(clean): \ + $(driver).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + +# How to. +# +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/o-e.make) diff --git a/tracer/transaction/test.std b/tracer/transaction/test.std new file mode 100644 index 0000000..8f962ef --- /dev/null +++ b/tracer/transaction/test.std @@ -0,0 +1,25 @@ +test 001 +begin transaction +rollback transaction +test 002 +begin transaction +commit transaction +test 003 +begin transaction +rollback transaction +test 004 +begin transaction +rollback transaction +test 005 +begin transaction +already_in_transaction +rollback transaction +test 006 +begin transaction +rollback transaction +test 007 +begin transaction +rollback transaction +test 008 +begin transaction +rollback transaction |