From d2e0ef5cfec96b68437c54cf9f6e7befb5ac19db Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 20 Jan 2014 14:00:08 -0500 Subject: [PATCH 01/84] generate protobuf for c bindings. --- binding-c/Makefile | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 binding-c/Makefile diff --git a/binding-c/Makefile b/binding-c/Makefile new file mode 100644 index 0000000..5123637 --- /dev/null +++ b/binding-c/Makefile @@ -0,0 +1,14 @@ +# TODO(monnand): Check protoc-c is installed +PROTOC_C = protoc-c + + +# The directory where this Makefile resides +PWD = $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) + +LMCTFY_ROOT = $(shell dirname ${PWD}) + +INCLUDE= ${PWD}/include + +${INCLUDE}/lmctfy.pb-c.h: ${LMCTFY_ROOT}/include/lmctfy.proto + ${PROTOC_C} --c_out=${INCLUDE} --proto_path=${LMCTFY_ROOT}/include $< + From ff14b001f0b6d17bb12627015e17fa136062ab1a Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 20 Jan 2014 16:00:31 -0500 Subject: [PATCH 02/84] status --- binding-c/Makefile | 10 ++++++++++ binding-c/include/lmctfy-c.h | 5 +++++ binding-c/include/status.h | 16 ++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 binding-c/include/lmctfy-c.h create mode 100644 binding-c/include/status.h diff --git a/binding-c/Makefile b/binding-c/Makefile index 5123637..7cbebe1 100644 --- a/binding-c/Makefile +++ b/binding-c/Makefile @@ -9,6 +9,16 @@ LMCTFY_ROOT = $(shell dirname ${PWD}) INCLUDE= ${PWD}/include +all: ${INCLUDE}/codes.pb-c.h ${INCLUDE}/lmctfy.pb-c.h + +${INCLUDE}/codes.pb-c.h: ${LMCTFY_ROOT}/util/task/codes.proto + ${PROTOC_C} --c_out=${INCLUDE} --proto_path=${LMCTFY_ROOT}/util/task $< + ${INCLUDE}/lmctfy.pb-c.h: ${LMCTFY_ROOT}/include/lmctfy.proto ${PROTOC_C} --c_out=${INCLUDE} --proto_path=${LMCTFY_ROOT}/include $< +clean: + rm -f ${INCLUDE}/*.pb-c.[ch] + +.PHONY: clean all + diff --git a/binding-c/include/lmctfy-c.h b/binding-c/include/lmctfy-c.h new file mode 100644 index 0000000..9156a99 --- /dev/null +++ b/binding-c/include/lmctfy-c.h @@ -0,0 +1,5 @@ +#include "lmctfy.pb-c.h" + +extern "C" { + +} diff --git a/binding-c/include/status.h b/binding-c/include/status.h new file mode 100644 index 0000000..628c3b4 --- /dev/null +++ b/binding-c/include/status.h @@ -0,0 +1,16 @@ +#ifndef LMCTFY_C_BINDING_H_ +#define LMCTFY_C_BINDING_H_ + +#include "codes.pb-c.h" + +extern "C" { + +struct status; + +int status_is_ok(struct status *); +int status_get_code(struct status *); +const char *status_get_message(struct status *); + +} + +#endif // LMCTFY_C_BINDING_H_ From 2e19a44890bc39e8898d186161cbafe77d0f1a0c Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 21 Jan 2014 13:18:20 -0500 Subject: [PATCH 03/84] container and container api. --- binding-c/include/lmctfy-c.h | 5 --- {binding-c => c}/Makefile | 12 ++++- c/include/lmctfy-c.h | 20 +++++++++ .../include/status.h => c/include/status-c.h | 5 +++ c/lmctfy-c.cc | 20 +++++++++ c/status-c.cc | 44 +++++++++++++++++++ c/status-internal.h | 16 +++++++ 7 files changed, 115 insertions(+), 7 deletions(-) delete mode 100644 binding-c/include/lmctfy-c.h rename {binding-c => c}/Makefile (64%) create mode 100644 c/include/lmctfy-c.h rename binding-c/include/status.h => c/include/status-c.h (69%) create mode 100644 c/lmctfy-c.cc create mode 100644 c/status-c.cc create mode 100644 c/status-internal.h diff --git a/binding-c/include/lmctfy-c.h b/binding-c/include/lmctfy-c.h deleted file mode 100644 index 9156a99..0000000 --- a/binding-c/include/lmctfy-c.h +++ /dev/null @@ -1,5 +0,0 @@ -#include "lmctfy.pb-c.h" - -extern "C" { - -} diff --git a/binding-c/Makefile b/c/Makefile similarity index 64% rename from binding-c/Makefile rename to c/Makefile index 7cbebe1..8e0f126 100644 --- a/binding-c/Makefile +++ b/c/Makefile @@ -7,9 +7,16 @@ PWD = $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) LMCTFY_ROOT = $(shell dirname ${PWD}) -INCLUDE= ${PWD}/include +INCLUDE = ${PWD}/include -all: ${INCLUDE}/codes.pb-c.h ${INCLUDE}/lmctfy.pb-c.h +CXX = g++ + +CXXFLAGS = -I${INCLUDE} -I${LMCTFY_ROOT}/include -I${LMCTFY_ROOT} + +all: status-c.o ${INCLUDE}/lmctfy.pb-c.h + +status-c.o: ${PWD}/status-c.cc ${INCLUDE}/status-c.h ${INCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h + ${CXX} ${CXXFLAGS} -c -o $@ $< ${INCLUDE}/codes.pb-c.h: ${LMCTFY_ROOT}/util/task/codes.proto ${PROTOC_C} --c_out=${INCLUDE} --proto_path=${LMCTFY_ROOT}/util/task $< @@ -19,6 +26,7 @@ ${INCLUDE}/lmctfy.pb-c.h: ${LMCTFY_ROOT}/include/lmctfy.proto clean: rm -f ${INCLUDE}/*.pb-c.[ch] + rm -f *.o .PHONY: clean all diff --git a/c/include/lmctfy-c.h b/c/include/lmctfy-c.h new file mode 100644 index 0000000..a565416 --- /dev/null +++ b/c/include/lmctfy-c.h @@ -0,0 +1,20 @@ +#ifndef LMCTFY_C_BINDING_LMCTFY_C_H_ +#define LMCTFY_C_BINDING_LMCTFY_C_H_ +#include "lmctfy.pb-c.h" +#include "status-c.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +struct container; +struct container_api; + +struct status *lmctfy_init_machine_raw(void *spec, int spec_size); +struct status *lmctfy_init_machine(Containers__Lmctfy__InitSpec *spec); +struct statuc *lmctfy_new_container_api(struct container_api **api); + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // LMCTFY_C_BINDING_LMCTFY_C_H_ diff --git a/binding-c/include/status.h b/c/include/status-c.h similarity index 69% rename from binding-c/include/status.h rename to c/include/status-c.h index 628c3b4..5d0a025 100644 --- a/binding-c/include/status.h +++ b/c/include/status-c.h @@ -3,14 +3,19 @@ #include "codes.pb-c.h" +#ifdef __cplusplus extern "C" { +#endif // __cplusplus struct status; int status_is_ok(struct status *); int status_get_code(struct status *); const char *status_get_message(struct status *); +void status_release(struct status *); +#ifdef __cplusplus } +#endif // __cplusplus #endif // LMCTFY_C_BINDING_H_ diff --git a/c/lmctfy-c.cc b/c/lmctfy-c.cc new file mode 100644 index 0000000..9baaacb --- /dev/null +++ b/c/lmctfy-c.cc @@ -0,0 +1,20 @@ +#include "lmctfy-c.h" +#include "lmctfy.h" +#include "status-internal.h" +#include "lmctfy.pb.h" + +using ::containers::lmctfy::Container; +using ::containers::lmctfy::ContainerApi; +using ::util::internal::status_new; + +struct container { + Container *container_; +}; + +struct container_api { + ContainerApi *container_api_; +}; + +struct status *lmctfy_init_machine_raw(void *spec, int spec_size) { +} + diff --git a/c/status-c.cc b/c/status-c.cc new file mode 100644 index 0000000..b04f8c1 --- /dev/null +++ b/c/status-c.cc @@ -0,0 +1,44 @@ +#include "status-c.h" +#include "status-internal.h" +#include "util/task/status.h" + +using ::util::Status; + +struct status { + Status status_; +}; + +int status_is_ok(struct status *s) { + if (s->status_.ok()) { + return 1; + } + return 0; +} + +int status_get_code(struct status *s) { + return s->status_.error_code(); +} + +const char *status_get_message(struct status *s) { + return s->status_.error_message().c_str(); +} + +void status_release(struct status *s) { + if (s != NULL) { + delete s; + } +} + +namespace util { +namespace internal { + +// TODO(monnand): We may want to use a memory pool for status stucture. +struct status *status_new(Status &s) { + struct status *ret = new status(); + ret->status_ = s; + return ret; +} + +} // namespace internal +} // namespace util + diff --git a/c/status-internal.h b/c/status-internal.h new file mode 100644 index 0000000..c4f466f --- /dev/null +++ b/c/status-internal.h @@ -0,0 +1,16 @@ +#ifndef LMCTFY_C_BINDING_STATUS_INTERNAL_H_ +#define LMCTFY_C_BINDING_STATUS_INTERNAL_H_ + +#include "status-c.h" +#include "util/task/status.h" + +namespace util { +namespace internal { + +// We don't want users to instantiate the status structure. +struct status *status_new(Status &s); + +} // namespace internal +} // namespace util + +#endif // LMCTFY_C_BINDING_STATUS_INTERNAL_H_ From dc2e4aa8337fb806374050fe877037f0dea4ece8 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 21 Jan 2014 14:56:32 -0500 Subject: [PATCH 04/84] Basic structure of C binding. --- c/Makefile | 9 ++++++--- c/include/lmctfy-c.h | 6 +++--- c/include/status-c.h | 6 +++--- c/lmctfy-c.cc | 31 ++++++++++++++++++++++++++++--- c/status-c.cc | 12 +++++------- c/status-internal.h | 17 ++++++++++++++++- 6 files changed, 61 insertions(+), 20 deletions(-) diff --git a/c/Makefile b/c/Makefile index 8e0f126..e3b5331 100644 --- a/c/Makefile +++ b/c/Makefile @@ -11,11 +11,14 @@ INCLUDE = ${PWD}/include CXX = g++ -CXXFLAGS = -I${INCLUDE} -I${LMCTFY_ROOT}/include -I${LMCTFY_ROOT} +CXXFLAGS = -I${INCLUDE} -I${LMCTFY_ROOT}/include -I${LMCTFY_ROOT} -I${PWD} +CXXFLAGS += -std=c++0x -fpermissive -all: status-c.o ${INCLUDE}/lmctfy.pb-c.h +all: lmctfy-c.o status-c.o ${INCLUDE}/lmctfy.pb-c.h -status-c.o: ${PWD}/status-c.cc ${INCLUDE}/status-c.h ${INCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h +lmctfy-c.o: ${PWD}/lmctfy-c.cc ${INCLUDE}/lmctfy-c.h ${PWD}/status-internal.h ${INCLUDE}/status-c.h + ${CXX} ${CXXFLAGS} -c -o $@ $< +status-c.o: ${PWD}/status-c.cc ${INCLUDE}/status-c.h ${INCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h ${PWD}/status-internal.h ${CXX} ${CXXFLAGS} -c -o $@ $< ${INCLUDE}/codes.pb-c.h: ${LMCTFY_ROOT}/util/task/codes.proto diff --git a/c/include/lmctfy-c.h b/c/include/lmctfy-c.h index a565416..b1594ac 100644 --- a/c/include/lmctfy-c.h +++ b/c/include/lmctfy-c.h @@ -10,9 +10,9 @@ extern "C" { struct container; struct container_api; -struct status *lmctfy_init_machine_raw(void *spec, int spec_size); -struct status *lmctfy_init_machine(Containers__Lmctfy__InitSpec *spec); -struct statuc *lmctfy_new_container_api(struct container_api **api); +struct status *lmctfy_init_machine_raw(const void *spec, const int spec_size); +struct status *lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec); +struct status *lmctfy_new_container_api(struct container_api **api); #ifdef __cplusplus } diff --git a/c/include/status-c.h b/c/include/status-c.h index 5d0a025..ed7c005 100644 --- a/c/include/status-c.h +++ b/c/include/status-c.h @@ -9,9 +9,9 @@ extern "C" { struct status; -int status_is_ok(struct status *); -int status_get_code(struct status *); -const char *status_get_message(struct status *); +int status_is_ok(const struct status *); +int status_get_code(const struct status *); +const char *status_get_message(const struct status *); void status_release(struct status *); #ifdef __cplusplus diff --git a/c/lmctfy-c.cc b/c/lmctfy-c.cc index 9baaacb..558d15f 100644 --- a/c/lmctfy-c.cc +++ b/c/lmctfy-c.cc @@ -1,11 +1,15 @@ +#include + #include "lmctfy-c.h" #include "lmctfy.h" +#include "util/task/statusor.h" #include "status-internal.h" #include "lmctfy.pb.h" -using ::containers::lmctfy::Container; -using ::containers::lmctfy::ContainerApi; +using namespace ::containers::lmctfy; using ::util::internal::status_new; +using ::util::Status; +using ::util::StatusOr; struct container { Container *container_; @@ -15,6 +19,27 @@ struct container_api { ContainerApi *container_api_; }; -struct status *lmctfy_init_machine_raw(void *spec, int spec_size) { +struct status *lmctfy_init_machine_raw(const void *spec, const int spec_size) { + InitSpec init_spec; + init_spec.ParseFromArray(spec, spec_size); + Status s = ContainerApi::InitMachine(init_spec); + return status_new(s); +} + +struct status *lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec) { + size_t sz = containers__lmctfy__init_spec__get_packed_size(spec); + void *buf = malloc(sz); + containers__lmctfy__init_spec__pack(spec, (uint8_t *)buf); + struct status *s = lmctfy_init_machine_raw(buf, sz); + free(buf); + return s; +} + +struct status *lmctfy_new_container_api(struct container_api **api) { + *api = new container_api(); + (*api)->container_api_ = NULL; + StatusOr statusor_container_api = ContainerApi::New(); + RETURN_IF_ERROR_PTR(statusor_container_api, &((*api)->container_api_)); + return &status_ok; } diff --git a/c/status-c.cc b/c/status-c.cc index b04f8c1..04b7590 100644 --- a/c/status-c.cc +++ b/c/status-c.cc @@ -4,22 +4,20 @@ using ::util::Status; -struct status { - Status status_; -}; +struct status status_ok = { Status::OK }; -int status_is_ok(struct status *s) { +int status_is_ok(const struct status *s) { if (s->status_.ok()) { return 1; } return 0; } -int status_get_code(struct status *s) { +int status_get_code(const struct status *s) { return s->status_.error_code(); } -const char *status_get_message(struct status *s) { +const char *status_get_message(const struct status *s) { return s->status_.error_message().c_str(); } @@ -33,7 +31,7 @@ namespace util { namespace internal { // TODO(monnand): We may want to use a memory pool for status stucture. -struct status *status_new(Status &s) { +struct status *status_new(const Status &s) { struct status *ret = new status(); ret->status_ = s; return ret; diff --git a/c/status-internal.h b/c/status-internal.h index c4f466f..f7a8a26 100644 --- a/c/status-internal.h +++ b/c/status-internal.h @@ -1,14 +1,29 @@ #ifndef LMCTFY_C_BINDING_STATUS_INTERNAL_H_ #define LMCTFY_C_BINDING_STATUS_INTERNAL_H_ +#include "util/errors.h" #include "status-c.h" #include "util/task/status.h" +#include "util/task/statusor.h" + +struct status { + ::util::Status status_; +}; + +extern struct status status_ok; + +#define RETURN_IF_ERROR_PTR(...) \ + do { \ + const ::util::Status _status = \ + ::util::errors_internal::PerformSideEffects(__VA_ARGS__); \ + if (PREDICT_FALSE(!_status.ok())) return status_new(_status); \ + } while (0) namespace util { namespace internal { // We don't want users to instantiate the status structure. -struct status *status_new(Status &s); +struct status *status_new(const Status &s); } // namespace internal } // namespace util From 6028583f31681c0cb40ce80cd84b954d94fa5e9e Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 21 Jan 2014 15:14:07 -0500 Subject: [PATCH 05/84] lmctfy-c.o depends on lmctfy.pb-c.h --- c/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/Makefile b/c/Makefile index e3b5331..2c2f8cb 100644 --- a/c/Makefile +++ b/c/Makefile @@ -16,7 +16,7 @@ CXXFLAGS += -std=c++0x -fpermissive all: lmctfy-c.o status-c.o ${INCLUDE}/lmctfy.pb-c.h -lmctfy-c.o: ${PWD}/lmctfy-c.cc ${INCLUDE}/lmctfy-c.h ${PWD}/status-internal.h ${INCLUDE}/status-c.h +lmctfy-c.o: ${PWD}/lmctfy-c.cc ${INCLUDE}/lmctfy-c.h ${PWD}/status-internal.h ${INCLUDE}/status-c.h ${INCLUDE}/lmctfy.pb-c.h ${INCLUDE}/codes.pb-c.h ${CXX} ${CXXFLAGS} -c -o $@ $< status-c.o: ${PWD}/status-c.cc ${INCLUDE}/status-c.h ${INCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h ${PWD}/status-internal.h ${CXX} ${CXXFLAGS} -c -o $@ $< From cb69f013101c9ef013e52eeed4c86686a3f5bd09 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 21 Jan 2014 15:15:35 -0500 Subject: [PATCH 06/84] release container api --- c/include/lmctfy-c.h | 2 ++ c/lmctfy-c.cc | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/c/include/lmctfy-c.h b/c/include/lmctfy-c.h index b1594ac..99c21f2 100644 --- a/c/include/lmctfy-c.h +++ b/c/include/lmctfy-c.h @@ -14,6 +14,8 @@ struct status *lmctfy_init_machine_raw(const void *spec, const int spec_size); struct status *lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec); struct status *lmctfy_new_container_api(struct container_api **api); +void lmctfy_release_container_api(struct container_api *api); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/c/lmctfy-c.cc b/c/lmctfy-c.cc index 558d15f..d393ac3 100644 --- a/c/lmctfy-c.cc +++ b/c/lmctfy-c.cc @@ -43,3 +43,12 @@ struct status *lmctfy_new_container_api(struct container_api **api) { return &status_ok; } +void lmctfy_release_container_api(struct container_api *api) { + if (api != NULL) { + if (api->container_api_ != NULL) { + // TODO(monnand): delete api->container_api_? + } + delete api; + } +} + From 9daa43b3b79add8c6931651fd7d4d8379e46934a Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 21 Jan 2014 15:26:43 -0500 Subject: [PATCH 07/84] get container. --- c/include/lmctfy-c.h | 3 +++ c/lmctfy-c.cc | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/c/include/lmctfy-c.h b/c/include/lmctfy-c.h index 99c21f2..bfcf887 100644 --- a/c/include/lmctfy-c.h +++ b/c/include/lmctfy-c.h @@ -13,6 +13,9 @@ struct container_api; struct status *lmctfy_init_machine_raw(const void *spec, const int spec_size); struct status *lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec); struct status *lmctfy_new_container_api(struct container_api **api); +struct status *lmctfy_get_container(struct container_api *api, + struct container **container, + const char *container_name); void lmctfy_release_container_api(struct container_api *api); diff --git a/c/lmctfy-c.cc b/c/lmctfy-c.cc index d393ac3..b246bba 100644 --- a/c/lmctfy-c.cc +++ b/c/lmctfy-c.cc @@ -36,7 +36,7 @@ struct status *lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec) { } struct status *lmctfy_new_container_api(struct container_api **api) { - *api = new container_api(); + *api = (struct container_api *)malloc(sizeof(struct container_api)); (*api)->container_api_ = NULL; StatusOr statusor_container_api = ContainerApi::New(); RETURN_IF_ERROR_PTR(statusor_container_api, &((*api)->container_api_)); @@ -48,7 +48,17 @@ void lmctfy_release_container_api(struct container_api *api) { if (api->container_api_ != NULL) { // TODO(monnand): delete api->container_api_? } - delete api; + free(api); } } +struct status *lmctfy_get_container(struct container_api *api, + struct container **container, + const char *container_name) { + *container = (struct container *)malloc(sizeof(struct container)); + (*container)->container_ = NULL; + + StatusOr statusor = api->container_api_->Get(container_name); + RETURN_IF_ERROR_PTR(statusor, &((*container)->container_)); + return &status_ok; +} From cdb501311fb3eeca3f4ebd4c1324accdd4234226 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 21 Jan 2014 15:54:13 -0500 Subject: [PATCH 08/84] get container --- c/include/lmctfy-c.h | 9 +++++---- c/lmctfy-c.cc | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/c/include/lmctfy-c.h b/c/include/lmctfy-c.h index bfcf887..f4f6a36 100644 --- a/c/include/lmctfy-c.h +++ b/c/include/lmctfy-c.h @@ -12,12 +12,13 @@ struct container_api; struct status *lmctfy_init_machine_raw(const void *spec, const int spec_size); struct status *lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec); -struct status *lmctfy_new_container_api(struct container_api **api); -struct status *lmctfy_get_container(struct container_api *api, - struct container **container, - const char *container_name); +struct status *lmctfy_new_container_api(struct container_api **api); void lmctfy_release_container_api(struct container_api *api); +struct status *lmctfy_container_api_get_container( + const struct container_api *api, + struct container **container, + const char *container_name); #ifdef __cplusplus } diff --git a/c/lmctfy-c.cc b/c/lmctfy-c.cc index b246bba..f292ae1 100644 --- a/c/lmctfy-c.cc +++ b/c/lmctfy-c.cc @@ -52,9 +52,9 @@ void lmctfy_release_container_api(struct container_api *api) { } } -struct status *lmctfy_get_container(struct container_api *api, - struct container **container, - const char *container_name) { +struct status *lmctfy_container_api_get_container(const struct container_api *api, + struct container **container, + const char *container_name) { *container = (struct container *)malloc(sizeof(struct container)); (*container)->container_ = NULL; From 740c6bbe0bbe1647a79eff14587e626a853aa38f Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 22 Jan 2014 14:07:10 -0500 Subject: [PATCH 09/84] status_new() --- c/include/status-c.h | 2 ++ c/lmctfy-c.cc | 4 ++-- c/status-c.cc | 21 +++++++++++++++++---- c/status-internal.h | 4 ++-- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/c/include/status-c.h b/c/include/status-c.h index ed7c005..4c001a6 100644 --- a/c/include/status-c.h +++ b/c/include/status-c.h @@ -9,6 +9,8 @@ extern "C" { struct status; +struct status *status_new_success(); +struct status *status_new(int code, const char *msg); int status_is_ok(const struct status *); int status_get_code(const struct status *); const char *status_get_message(const struct status *); diff --git a/c/lmctfy-c.cc b/c/lmctfy-c.cc index f292ae1..ddc3a8a 100644 --- a/c/lmctfy-c.cc +++ b/c/lmctfy-c.cc @@ -7,7 +7,7 @@ #include "lmctfy.pb.h" using namespace ::containers::lmctfy; -using ::util::internal::status_new; +using ::util::internal::status_copy; using ::util::Status; using ::util::StatusOr; @@ -23,7 +23,7 @@ struct status *lmctfy_init_machine_raw(const void *spec, const int spec_size) { InitSpec init_spec; init_spec.ParseFromArray(spec, spec_size); Status s = ContainerApi::InitMachine(init_spec); - return status_new(s); + return status_copy(s); } struct status *lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec) { diff --git a/c/status-c.cc b/c/status-c.cc index 04b7590..893544e 100644 --- a/c/status-c.cc +++ b/c/status-c.cc @@ -6,6 +6,19 @@ using ::util::Status; struct status status_ok = { Status::OK }; +struct status *status_new_success() { + struct status *ok = (struct status *)malloc(sizeof(struct status)); + ok->status_ = Status::OK; + return ok; +} + +struct status *status_new(int code, const char *msg) { + struct status *s = (struct status *)malloc(sizeof(struct status)); + Status st((::util::error::Code)code, msg); + s->status_ = st; + return s; +} + int status_is_ok(const struct status *s) { if (s->status_.ok()) { return 1; @@ -22,8 +35,8 @@ const char *status_get_message(const struct status *s) { } void status_release(struct status *s) { - if (s != NULL) { - delete s; + if (s != NULL && s != &status_ok) { + free(s); } } @@ -31,8 +44,8 @@ namespace util { namespace internal { // TODO(monnand): We may want to use a memory pool for status stucture. -struct status *status_new(const Status &s) { - struct status *ret = new status(); +struct status *status_copy(const Status &s) { + struct status *ret = (struct status *)malloc(sizeof(struct status)); ret->status_ = s; return ret; } diff --git a/c/status-internal.h b/c/status-internal.h index f7a8a26..ccde1ed 100644 --- a/c/status-internal.h +++ b/c/status-internal.h @@ -16,14 +16,14 @@ extern struct status status_ok; do { \ const ::util::Status _status = \ ::util::errors_internal::PerformSideEffects(__VA_ARGS__); \ - if (PREDICT_FALSE(!_status.ok())) return status_new(_status); \ + if (PREDICT_FALSE(!_status.ok())) return status_copy(_status); \ } while (0) namespace util { namespace internal { // We don't want users to instantiate the status structure. -struct status *status_new(const Status &s); +struct status *status_copy(const Status &s); } // namespace internal } // namespace util From 2e2b8b4d740cb858f8fa62722e5093ccf731b353 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 22 Jan 2014 14:19:31 -0500 Subject: [PATCH 10/84] status is no longer a return value. --- c/include/lmctfy-c.h | 25 +++++++++++++++++++++++-- c/lmctfy-c.cc | 16 ++++++++++------ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/c/include/lmctfy-c.h b/c/include/lmctfy-c.h index f4f6a36..9233845 100644 --- a/c/include/lmctfy-c.h +++ b/c/include/lmctfy-c.h @@ -10,8 +10,29 @@ extern "C" { struct container; struct container_api; -struct status *lmctfy_init_machine_raw(const void *spec, const int spec_size); -struct status *lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec); +// InitMachine +// +// Arguments: +// - s: s will be used as output. It contains the error code/message. +// - spec: Serialized data (protobuf format) containing the specification. +// - spec_size: Size of the serialized data. +// +// Returns: +// Returns the error code. 0 on success. The return code is same as +// status_get_code(s). +int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_size); + + +// InitMachine +// +// Arguments: +// - s: s will be used as output. It contains the error code/message. +// - spec: The specification. +// +// Returns: +// Returns the error code. 0 on success. The return code is same as +// status_get_code(s). +int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec); struct status *lmctfy_new_container_api(struct container_api **api); void lmctfy_release_container_api(struct container_api *api); diff --git a/c/lmctfy-c.cc b/c/lmctfy-c.cc index ddc3a8a..caef4c9 100644 --- a/c/lmctfy-c.cc +++ b/c/lmctfy-c.cc @@ -19,20 +19,24 @@ struct container_api { ContainerApi *container_api_; }; -struct status *lmctfy_init_machine_raw(const void *spec, const int spec_size) { +int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_size) { InitSpec init_spec; init_spec.ParseFromArray(spec, spec_size); - Status s = ContainerApi::InitMachine(init_spec); - return status_copy(s); + Status v = ContainerApi::InitMachine(init_spec); + if (s != NULL) { + s->status_ = v; + } + return v.error_code(); } -struct status *lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec) { +int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec) { size_t sz = containers__lmctfy__init_spec__get_packed_size(spec); void *buf = malloc(sz); + int ret = 0; containers__lmctfy__init_spec__pack(spec, (uint8_t *)buf); - struct status *s = lmctfy_init_machine_raw(buf, sz); + ret = lmctfy_init_machine_raw(s, buf, sz); free(buf); - return s; + return ret; } struct status *lmctfy_new_container_api(struct container_api **api) { From b74b9a80184e9674e7f4f13740ddc4557ef87ab3 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 22 Jan 2014 14:27:15 -0500 Subject: [PATCH 11/84] status is an argument. --- c/include/lmctfy-c.h | 7 ++++--- c/lmctfy-c.cc | 20 ++++++++++++-------- c/status-internal.h | 7 +++++-- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/c/include/lmctfy-c.h b/c/include/lmctfy-c.h index 9233845..fa948cc 100644 --- a/c/include/lmctfy-c.h +++ b/c/include/lmctfy-c.h @@ -22,7 +22,6 @@ struct container_api; // status_get_code(s). int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_size); - // InitMachine // // Arguments: @@ -34,9 +33,11 @@ int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_s // status_get_code(s). int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec); -struct status *lmctfy_new_container_api(struct container_api **api); +int lmctfy_new_container_api(struct status *s, struct container_api **api); void lmctfy_release_container_api(struct container_api *api); -struct status *lmctfy_container_api_get_container( + +int lmctfy_container_api_get_container( + struct status *s, const struct container_api *api, struct container **container, const char *container_name); diff --git a/c/lmctfy-c.cc b/c/lmctfy-c.cc index caef4c9..7166076 100644 --- a/c/lmctfy-c.cc +++ b/c/lmctfy-c.cc @@ -5,6 +5,9 @@ #include "util/task/statusor.h" #include "status-internal.h" #include "lmctfy.pb.h" +#include "codes.pb-c.h" + +#define STATUS_OK UTIL__ERROR__CODE__OK using namespace ::containers::lmctfy; using ::util::internal::status_copy; @@ -39,12 +42,12 @@ int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *sp return ret; } -struct status *lmctfy_new_container_api(struct container_api **api) { +int lmctfy_new_container_api(struct status *s, struct container_api **api) { *api = (struct container_api *)malloc(sizeof(struct container_api)); (*api)->container_api_ = NULL; StatusOr statusor_container_api = ContainerApi::New(); - RETURN_IF_ERROR_PTR(statusor_container_api, &((*api)->container_api_)); - return &status_ok; + RETURN_IF_ERROR_PTR(s, statusor_container_api, &((*api)->container_api_)); + return STATUS_OK; } void lmctfy_release_container_api(struct container_api *api) { @@ -56,13 +59,14 @@ void lmctfy_release_container_api(struct container_api *api) { } } -struct status *lmctfy_container_api_get_container(const struct container_api *api, - struct container **container, - const char *container_name) { +int lmctfy_container_api_get_container(struct status *s, + const struct container_api *api, + struct container **container, + const char *container_name) { *container = (struct container *)malloc(sizeof(struct container)); (*container)->container_ = NULL; StatusOr statusor = api->container_api_->Get(container_name); - RETURN_IF_ERROR_PTR(statusor, &((*container)->container_)); - return &status_ok; + RETURN_IF_ERROR_PTR(s, statusor, &((*container)->container_)); + return STATUS_OK; } diff --git a/c/status-internal.h b/c/status-internal.h index ccde1ed..17da217 100644 --- a/c/status-internal.h +++ b/c/status-internal.h @@ -12,11 +12,14 @@ struct status { extern struct status status_ok; -#define RETURN_IF_ERROR_PTR(...) \ +#define RETURN_IF_ERROR_PTR(s, ...) \ do { \ const ::util::Status _status = \ ::util::errors_internal::PerformSideEffects(__VA_ARGS__); \ - if (PREDICT_FALSE(!_status.ok())) return status_copy(_status); \ + if (PREDICT_FALSE(!_status.ok())) { \ + if (s != NULL) s->status_ = _status; \ + return _status.error_code(); \ + } \ } while (0) namespace util { From 4abc0f7a80819b9ffd7842875b7ddd3fc2971ff7 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 22 Jan 2014 15:29:46 -0500 Subject: [PATCH 12/84] comments. --- c/include/lmctfy-c.h | 35 ++++++++++++++++++++++++++++++----- c/lmctfy-c.cc | 2 +- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/c/include/lmctfy-c.h b/c/include/lmctfy-c.h index fa948cc..c8acf03 100644 --- a/c/include/lmctfy-c.h +++ b/c/include/lmctfy-c.h @@ -10,10 +10,10 @@ extern "C" { struct container; struct container_api; -// InitMachine +// Initializes the machine to start being able to create containers. // // Arguments: -// - s: s will be used as output. It contains the error code/message. +// - s: [output] s will be used as output. It contains the error code/message. // - spec: Serialized data (protobuf format) containing the specification. // - spec_size: Size of the serialized data. // @@ -22,10 +22,10 @@ struct container_api; // status_get_code(s). int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_size); -// InitMachine +// Initializes the machine to start being able to create containers. // // Arguments: -// - s: s will be used as output. It contains the error code/message. +// - s: [output] s will be used as output. It contains the error code/message. // - spec: The specification. // // Returns: @@ -33,13 +33,38 @@ int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_s // status_get_code(s). int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec); +// Create a new container_api. +// +// Arguments: +// - s: [output] s will be used as output. It contains the error code/message. +// - api: [output] The address of a pointer to struct container_api. The +// pointer of the container api will be stored in this address. +// +// Returns: +// Returns the error code. 0 on success. The return code is same as +// status_get_code(s). int lmctfy_new_container_api(struct status *s, struct container_api **api); + +// Release the container api. void lmctfy_release_container_api(struct container_api *api); +// Get a container +// +// Arguments: +// +// - s: [output] s will be used as output. It contains the error code/message. +// - container: [output] The address of a pointer to struct container. It will +// be used to store the pointer to the container. +// - api: A container api. +// - container_name: the container name. +// +// Returns: +// Returns the error code. 0 on success. The return code is same as +// status_get_code(s). int lmctfy_container_api_get_container( struct status *s, - const struct container_api *api, struct container **container, + const struct container_api *api, const char *container_name); #ifdef __cplusplus diff --git a/c/lmctfy-c.cc b/c/lmctfy-c.cc index 7166076..2dac9f2 100644 --- a/c/lmctfy-c.cc +++ b/c/lmctfy-c.cc @@ -60,8 +60,8 @@ void lmctfy_release_container_api(struct container_api *api) { } int lmctfy_container_api_get_container(struct status *s, - const struct container_api *api, struct container **container, + const struct container_api *api, const char *container_name) { *container = (struct container *)malloc(sizeof(struct container)); (*container)->container_ = NULL; From 795c4e9a67c03e3a94624c602e42dc7d565f7c93 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 22 Jan 2014 15:39:08 -0500 Subject: [PATCH 13/84] create_container() --- c/include/lmctfy-c.h | 7 +++++++ c/lmctfy-c.cc | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/c/include/lmctfy-c.h b/c/include/lmctfy-c.h index c8acf03..23d71d2 100644 --- a/c/include/lmctfy-c.h +++ b/c/include/lmctfy-c.h @@ -67,6 +67,13 @@ int lmctfy_container_api_get_container( const struct container_api *api, const char *container_name); +int lmctfy_container_api_create_container_raw( + struct status *s, + struct container **container, + const struct container_api *api, + const char *container_name, + const void *spec, + const int spec_size); #ifdef __cplusplus } #endif // __cplusplus diff --git a/c/lmctfy-c.cc b/c/lmctfy-c.cc index 2dac9f2..3f36926 100644 --- a/c/lmctfy-c.cc +++ b/c/lmctfy-c.cc @@ -70,3 +70,19 @@ int lmctfy_container_api_get_container(struct status *s, RETURN_IF_ERROR_PTR(s, statusor, &((*container)->container_)); return STATUS_OK; } + +int lmctfy_container_api_create_container_raw(struct status *s, + struct container **container, + const struct container_api *api, + const char *container_name, + const void *spec, + const int spec_size) { + ContainerSpec container_spec; + *container = (struct container *)malloc(sizeof(struct container)); + (*container)->container_ = NULL; + container_spec.ParseFromArray(spec, spec_size); + + StatusOr statusor = api->container_api_->Create(container_name, container_spec); + RETURN_IF_ERROR_PTR(s, statusor, &((*container)->container_)); + return STATUS_OK; +} From e0815528175d1b7a04aae352661e7cd9d53896d3 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 22 Jan 2014 16:43:54 -0500 Subject: [PATCH 14/84] create_container() --- c/include/lmctfy-c.h | 2 +- c/lmctfy-c.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/c/include/lmctfy-c.h b/c/include/lmctfy-c.h index 23d71d2..84f95aa 100644 --- a/c/include/lmctfy-c.h +++ b/c/include/lmctfy-c.h @@ -70,7 +70,7 @@ int lmctfy_container_api_get_container( int lmctfy_container_api_create_container_raw( struct status *s, struct container **container, - const struct container_api *api, + struct container_api *api, const char *container_name, const void *spec, const int spec_size); diff --git a/c/lmctfy-c.cc b/c/lmctfy-c.cc index 3f36926..7bc261e 100644 --- a/c/lmctfy-c.cc +++ b/c/lmctfy-c.cc @@ -73,7 +73,7 @@ int lmctfy_container_api_get_container(struct status *s, int lmctfy_container_api_create_container_raw(struct status *s, struct container **container, - const struct container_api *api, + struct container_api *api, const char *container_name, const void *spec, const int spec_size) { From b53059703249abb1e72bc47bbf46569d9994304a Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 24 Jan 2014 23:25:15 -0500 Subject: [PATCH 15/84] rename --- {c => clmctfy}/Makefile | 4 ++-- c/lmctfy-c.cc => clmctfy/clmctfy.cc | 2 +- c/include/lmctfy-c.h => clmctfy/include/clmctfy.h | 0 {c => clmctfy}/include/status-c.h | 0 {c => clmctfy}/status-c.cc | 0 {c => clmctfy}/status-internal.h | 0 6 files changed, 3 insertions(+), 3 deletions(-) rename {c => clmctfy}/Makefile (81%) rename c/lmctfy-c.cc => clmctfy/clmctfy.cc (99%) rename c/include/lmctfy-c.h => clmctfy/include/clmctfy.h (100%) rename {c => clmctfy}/include/status-c.h (100%) rename {c => clmctfy}/status-c.cc (100%) rename {c => clmctfy}/status-internal.h (100%) diff --git a/c/Makefile b/clmctfy/Makefile similarity index 81% rename from c/Makefile rename to clmctfy/Makefile index 2c2f8cb..64a32e6 100644 --- a/c/Makefile +++ b/clmctfy/Makefile @@ -14,9 +14,9 @@ CXX = g++ CXXFLAGS = -I${INCLUDE} -I${LMCTFY_ROOT}/include -I${LMCTFY_ROOT} -I${PWD} CXXFLAGS += -std=c++0x -fpermissive -all: lmctfy-c.o status-c.o ${INCLUDE}/lmctfy.pb-c.h +all: clmctfy.o status-c.o ${INCLUDE}/lmctfy.pb-c.h -lmctfy-c.o: ${PWD}/lmctfy-c.cc ${INCLUDE}/lmctfy-c.h ${PWD}/status-internal.h ${INCLUDE}/status-c.h ${INCLUDE}/lmctfy.pb-c.h ${INCLUDE}/codes.pb-c.h +clmctfy.o: ${PWD}/clmctfy.cc ${INCLUDE}/clmctfy.h ${PWD}/status-internal.h ${INCLUDE}/status-c.h ${INCLUDE}/lmctfy.pb-c.h ${INCLUDE}/codes.pb-c.h ${CXX} ${CXXFLAGS} -c -o $@ $< status-c.o: ${PWD}/status-c.cc ${INCLUDE}/status-c.h ${INCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h ${PWD}/status-internal.h ${CXX} ${CXXFLAGS} -c -o $@ $< diff --git a/c/lmctfy-c.cc b/clmctfy/clmctfy.cc similarity index 99% rename from c/lmctfy-c.cc rename to clmctfy/clmctfy.cc index 7bc261e..b5e1a4a 100644 --- a/c/lmctfy-c.cc +++ b/clmctfy/clmctfy.cc @@ -1,6 +1,6 @@ #include -#include "lmctfy-c.h" +#include "clmctfy.h" #include "lmctfy.h" #include "util/task/statusor.h" #include "status-internal.h" diff --git a/c/include/lmctfy-c.h b/clmctfy/include/clmctfy.h similarity index 100% rename from c/include/lmctfy-c.h rename to clmctfy/include/clmctfy.h diff --git a/c/include/status-c.h b/clmctfy/include/status-c.h similarity index 100% rename from c/include/status-c.h rename to clmctfy/include/status-c.h diff --git a/c/status-c.cc b/clmctfy/status-c.cc similarity index 100% rename from c/status-c.cc rename to clmctfy/status-c.cc diff --git a/c/status-internal.h b/clmctfy/status-internal.h similarity index 100% rename from c/status-internal.h rename to clmctfy/status-internal.h From 8ea9a41da375489c414bb82b1cfb924f6960a097 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 24 Jan 2014 23:42:18 -0500 Subject: [PATCH 16/84] make status as simple as possible --- clmctfy/clmctfy.cc | 5 +--- clmctfy/include/clmctfy.h | 6 ++++- clmctfy/include/status-c.h | 9 ------- clmctfy/status-c.cc | 54 +++++++++----------------------------- clmctfy/status-internal.h | 15 +++-------- 5 files changed, 22 insertions(+), 67 deletions(-) diff --git a/clmctfy/clmctfy.cc b/clmctfy/clmctfy.cc index b5e1a4a..2ab5ef2 100644 --- a/clmctfy/clmctfy.cc +++ b/clmctfy/clmctfy.cc @@ -26,10 +26,7 @@ int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_s InitSpec init_spec; init_spec.ParseFromArray(spec, spec_size); Status v = ContainerApi::InitMachine(init_spec); - if (s != NULL) { - s->status_ = v; - } - return v.error_code(); + return status_copy(s, v); } int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec) { diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 84f95aa..846bf5b 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -1,12 +1,16 @@ #ifndef LMCTFY_C_BINDING_LMCTFY_C_H_ #define LMCTFY_C_BINDING_LMCTFY_C_H_ #include "lmctfy.pb-c.h" -#include "status-c.h" #ifdef __cplusplus extern "C" { #endif // __cplusplus +struct status { + int error_code; + char *message; +}; + struct container; struct container_api; diff --git a/clmctfy/include/status-c.h b/clmctfy/include/status-c.h index 4c001a6..6b22e8c 100644 --- a/clmctfy/include/status-c.h +++ b/clmctfy/include/status-c.h @@ -7,15 +7,6 @@ extern "C" { #endif // __cplusplus -struct status; - -struct status *status_new_success(); -struct status *status_new(int code, const char *msg); -int status_is_ok(const struct status *); -int status_get_code(const struct status *); -const char *status_get_message(const struct status *); -void status_release(struct status *); - #ifdef __cplusplus } #endif // __cplusplus diff --git a/clmctfy/status-c.cc b/clmctfy/status-c.cc index 893544e..f25b6d7 100644 --- a/clmctfy/status-c.cc +++ b/clmctfy/status-c.cc @@ -1,53 +1,23 @@ -#include "status-c.h" +#include // to use strdup + +#include "clmctfy.h" #include "status-internal.h" #include "util/task/status.h" using ::util::Status; -struct status status_ok = { Status::OK }; - -struct status *status_new_success() { - struct status *ok = (struct status *)malloc(sizeof(struct status)); - ok->status_ = Status::OK; - return ok; -} - -struct status *status_new(int code, const char *msg) { - struct status *s = (struct status *)malloc(sizeof(struct status)); - Status st((::util::error::Code)code, msg); - s->status_ = st; - return s; -} - -int status_is_ok(const struct status *s) { - if (s->status_.ok()) { - return 1; - } - return 0; -} - -int status_get_code(const struct status *s) { - return s->status_.error_code(); -} - -const char *status_get_message(const struct status *s) { - return s->status_.error_message().c_str(); -} - -void status_release(struct status *s) { - if (s != NULL && s != &status_ok) { - free(s); - } -} - namespace util { namespace internal { -// TODO(monnand): We may want to use a memory pool for status stucture. -struct status *status_copy(const Status &s) { - struct status *ret = (struct status *)malloc(sizeof(struct status)); - ret->status_ = s; - return ret; +int status_copy(struct status *dst, const Status &src) { + if (dst == NULL) { + return (int)src.error_code(); + } + dst->error_code = src.error_code(); + if (!src.ok() && src.error_message() != "") { + dst->message = strdup(src.error_message().c_str()); + } + return (int)src.error_code(); } } // namespace internal diff --git a/clmctfy/status-internal.h b/clmctfy/status-internal.h index 17da217..9533667 100644 --- a/clmctfy/status-internal.h +++ b/clmctfy/status-internal.h @@ -2,31 +2,24 @@ #define LMCTFY_C_BINDING_STATUS_INTERNAL_H_ #include "util/errors.h" -#include "status-c.h" +#include "clmctfy.h" #include "util/task/status.h" #include "util/task/statusor.h" -struct status { - ::util::Status status_; -}; - -extern struct status status_ok; - #define RETURN_IF_ERROR_PTR(s, ...) \ do { \ const ::util::Status _status = \ ::util::errors_internal::PerformSideEffects(__VA_ARGS__); \ if (PREDICT_FALSE(!_status.ok())) { \ - if (s != NULL) s->status_ = _status; \ - return _status.error_code(); \ + if (s != NULL) status_copy(s, _status); \ + return (int)_status.error_code(); \ } \ } while (0) namespace util { namespace internal { -// We don't want users to instantiate the status structure. -struct status *status_copy(const Status &s); +int status_copy(struct status *dst, const Status &src); } // namespace internal } // namespace util From e9145f62d2a13dca1686cb8e0356391c17426da8 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 24 Jan 2014 23:43:18 -0500 Subject: [PATCH 17/84] removed status-c.h --- clmctfy/Makefile | 4 ++-- clmctfy/include/status-c.h | 14 -------------- 2 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 clmctfy/include/status-c.h diff --git a/clmctfy/Makefile b/clmctfy/Makefile index 64a32e6..bc14f9c 100644 --- a/clmctfy/Makefile +++ b/clmctfy/Makefile @@ -16,9 +16,9 @@ CXXFLAGS += -std=c++0x -fpermissive all: clmctfy.o status-c.o ${INCLUDE}/lmctfy.pb-c.h -clmctfy.o: ${PWD}/clmctfy.cc ${INCLUDE}/clmctfy.h ${PWD}/status-internal.h ${INCLUDE}/status-c.h ${INCLUDE}/lmctfy.pb-c.h ${INCLUDE}/codes.pb-c.h +clmctfy.o: ${PWD}/clmctfy.cc ${INCLUDE}/clmctfy.h ${PWD}/status-internal.h ${INCLUDE}/lmctfy.pb-c.h ${INCLUDE}/codes.pb-c.h ${CXX} ${CXXFLAGS} -c -o $@ $< -status-c.o: ${PWD}/status-c.cc ${INCLUDE}/status-c.h ${INCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h ${PWD}/status-internal.h +status-c.o: ${PWD}/status-c.cc ${INCLUDE}/clmctfy.h ${INCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h ${PWD}/status-internal.h ${CXX} ${CXXFLAGS} -c -o $@ $< ${INCLUDE}/codes.pb-c.h: ${LMCTFY_ROOT}/util/task/codes.proto diff --git a/clmctfy/include/status-c.h b/clmctfy/include/status-c.h deleted file mode 100644 index 6b22e8c..0000000 --- a/clmctfy/include/status-c.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LMCTFY_C_BINDING_H_ -#define LMCTFY_C_BINDING_H_ - -#include "codes.pb-c.h" - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // LMCTFY_C_BINDING_H_ From 54e65727df19ca6360aa17302bc83c7390da30af Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 24 Jan 2014 23:46:13 -0500 Subject: [PATCH 18/84] comment. --- clmctfy/include/clmctfy.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 846bf5b..c3cdd34 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -8,6 +8,9 @@ extern "C" { struct status { int error_code; + + // Null-terminated string allocated on heap. + // Needs to be free()'ed. char *message; }; From 10bc74840c8048f053a2c0707c75c82b6bfa1f31 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 24 Jan 2014 23:51:07 -0500 Subject: [PATCH 19/84] use new instead of malloc() in C++ code. --- clmctfy/clmctfy.cc | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/clmctfy/clmctfy.cc b/clmctfy/clmctfy.cc index 2ab5ef2..33add27 100644 --- a/clmctfy/clmctfy.cc +++ b/clmctfy/clmctfy.cc @@ -31,16 +31,16 @@ int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_s int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec) { size_t sz = containers__lmctfy__init_spec__get_packed_size(spec); - void *buf = malloc(sz); + uint8_t *buf = new uint8_t[sz]; int ret = 0; - containers__lmctfy__init_spec__pack(spec, (uint8_t *)buf); + containers__lmctfy__init_spec__pack(spec, buf); ret = lmctfy_init_machine_raw(s, buf, sz); - free(buf); + delete []buf; return ret; } int lmctfy_new_container_api(struct status *s, struct container_api **api) { - *api = (struct container_api *)malloc(sizeof(struct container_api)); + *api = new container_api(); (*api)->container_api_ = NULL; StatusOr statusor_container_api = ContainerApi::New(); RETURN_IF_ERROR_PTR(s, statusor_container_api, &((*api)->container_api_)); @@ -52,34 +52,34 @@ void lmctfy_release_container_api(struct container_api *api) { if (api->container_api_ != NULL) { // TODO(monnand): delete api->container_api_? } - free(api); + delete api; } } int lmctfy_container_api_get_container(struct status *s, - struct container **container, + struct container **c, const struct container_api *api, const char *container_name) { - *container = (struct container *)malloc(sizeof(struct container)); - (*container)->container_ = NULL; + *c = new container(); + (*c)->container_ = NULL; StatusOr statusor = api->container_api_->Get(container_name); - RETURN_IF_ERROR_PTR(s, statusor, &((*container)->container_)); + RETURN_IF_ERROR_PTR(s, statusor, &((*c)->container_)); return STATUS_OK; } int lmctfy_container_api_create_container_raw(struct status *s, - struct container **container, + struct container **c, struct container_api *api, const char *container_name, const void *spec, const int spec_size) { ContainerSpec container_spec; - *container = (struct container *)malloc(sizeof(struct container)); - (*container)->container_ = NULL; + *c = new container(); + (*c)->container_ = NULL; container_spec.ParseFromArray(spec, spec_size); StatusOr statusor = api->container_api_->Create(container_name, container_spec); - RETURN_IF_ERROR_PTR(s, statusor, &((*container)->container_)); + RETURN_IF_ERROR_PTR(s, statusor, &((*c)->container_)); return STATUS_OK; } From be902eb2329d0287998cfc8b39dcd13cea800053 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 24 Jan 2014 23:51:47 -0500 Subject: [PATCH 20/84] rename a function. --- clmctfy/clmctfy.cc | 2 +- clmctfy/include/clmctfy.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clmctfy/clmctfy.cc b/clmctfy/clmctfy.cc index 33add27..445a8b5 100644 --- a/clmctfy/clmctfy.cc +++ b/clmctfy/clmctfy.cc @@ -47,7 +47,7 @@ int lmctfy_new_container_api(struct status *s, struct container_api **api) { return STATUS_OK; } -void lmctfy_release_container_api(struct container_api *api) { +void lmctfy_delete_container_api(struct container_api *api) { if (api != NULL) { if (api->container_api_ != NULL) { // TODO(monnand): delete api->container_api_? diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index c3cdd34..85811f9 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -53,7 +53,7 @@ int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *sp int lmctfy_new_container_api(struct status *s, struct container_api **api); // Release the container api. -void lmctfy_release_container_api(struct container_api *api); +void lmctfy_delete_container_api(struct container_api *api); // Get a container // From e5e566c15b537b92944d2451d8f493dc81c3e89e Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 24 Jan 2014 23:57:41 -0500 Subject: [PATCH 21/84] delete api. --- clmctfy/clmctfy.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clmctfy/clmctfy.cc b/clmctfy/clmctfy.cc index 445a8b5..8bea9ad 100644 --- a/clmctfy/clmctfy.cc +++ b/clmctfy/clmctfy.cc @@ -50,7 +50,7 @@ int lmctfy_new_container_api(struct status *s, struct container_api **api) { void lmctfy_delete_container_api(struct container_api *api) { if (api != NULL) { if (api->container_api_ != NULL) { - // TODO(monnand): delete api->container_api_? + delete api->container_api_; } delete api; } From c62b720ec8f363779cc7df53b2e08f592e29cec6 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Sat, 25 Jan 2014 13:16:36 -0500 Subject: [PATCH 22/84] put *_raw functions into a separate header. --- clmctfy/Makefile | 23 ++++++++++++----------- clmctfy/clmctfy.cc | 1 + clmctfy/include/clmctfy-raw.h | 34 ++++++++++++++++++++++++++++++++++ clmctfy/include/clmctfy.h | 19 ------------------- 4 files changed, 47 insertions(+), 30 deletions(-) create mode 100644 clmctfy/include/clmctfy-raw.h diff --git a/clmctfy/Makefile b/clmctfy/Makefile index bc14f9c..f0e6769 100644 --- a/clmctfy/Makefile +++ b/clmctfy/Makefile @@ -7,28 +7,29 @@ PWD = $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) LMCTFY_ROOT = $(shell dirname ${PWD}) -INCLUDE = ${PWD}/include +CINCLUDE = ${PWD}/include -CXX = g++ +CXX ?= g++ +AR ?= ar -CXXFLAGS = -I${INCLUDE} -I${LMCTFY_ROOT}/include -I${LMCTFY_ROOT} -I${PWD} +CXXFLAGS = -I${CINCLUDE} -I${LMCTFY_ROOT}/include -I${LMCTFY_ROOT} -I${PWD} CXXFLAGS += -std=c++0x -fpermissive -all: clmctfy.o status-c.o ${INCLUDE}/lmctfy.pb-c.h +all: clmctfy.o status-c.o -clmctfy.o: ${PWD}/clmctfy.cc ${INCLUDE}/clmctfy.h ${PWD}/status-internal.h ${INCLUDE}/lmctfy.pb-c.h ${INCLUDE}/codes.pb-c.h +clmctfy.o: ${PWD}/clmctfy.cc ${CINCLUDE}/clmctfy.h ${PWD}/status-internal.h ${CINCLUDE}/lmctfy.pb-c.h ${CINCLUDE}/codes.pb-c.h ${CINCLUDE}/clmctfy-raw.h ${CXX} ${CXXFLAGS} -c -o $@ $< -status-c.o: ${PWD}/status-c.cc ${INCLUDE}/clmctfy.h ${INCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h ${PWD}/status-internal.h +status-c.o: ${PWD}/status-c.cc ${CINCLUDE}/clmctfy.h ${CINCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h ${PWD}/status-internal.h ${CXX} ${CXXFLAGS} -c -o $@ $< -${INCLUDE}/codes.pb-c.h: ${LMCTFY_ROOT}/util/task/codes.proto - ${PROTOC_C} --c_out=${INCLUDE} --proto_path=${LMCTFY_ROOT}/util/task $< +${CINCLUDE}/codes.pb-c.h: ${LMCTFY_ROOT}/util/task/codes.proto + ${PROTOC_C} --c_out=${CINCLUDE} --proto_path=${LMCTFY_ROOT}/util/task $< -${INCLUDE}/lmctfy.pb-c.h: ${LMCTFY_ROOT}/include/lmctfy.proto - ${PROTOC_C} --c_out=${INCLUDE} --proto_path=${LMCTFY_ROOT}/include $< +${CINCLUDE}/lmctfy.pb-c.h: ${LMCTFY_ROOT}/include/lmctfy.proto + ${PROTOC_C} --c_out=${CINCLUDE} --proto_path=${LMCTFY_ROOT}/include $< clean: - rm -f ${INCLUDE}/*.pb-c.[ch] + rm -f ${CINCLUDE}/*.pb-c.[ch] rm -f *.o .PHONY: clean all diff --git a/clmctfy/clmctfy.cc b/clmctfy/clmctfy.cc index 8bea9ad..636f932 100644 --- a/clmctfy/clmctfy.cc +++ b/clmctfy/clmctfy.cc @@ -1,6 +1,7 @@ #include #include "clmctfy.h" +#include "clmctfy-raw.h" #include "lmctfy.h" #include "util/task/statusor.h" #include "status-internal.h" diff --git a/clmctfy/include/clmctfy-raw.h b/clmctfy/include/clmctfy-raw.h new file mode 100644 index 0000000..5babbe7 --- /dev/null +++ b/clmctfy/include/clmctfy-raw.h @@ -0,0 +1,34 @@ +#ifndef LMCTFY_C_BINDING_CLMCTFY_RAW_H_ +#define LMCTFY_C_BINDING_CLMCTFY_RAW_H_ + +#include "clmctfy.h" +#include "lmctfy.pb-c.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Initializes the machine to start being able to create containers. +// +// Arguments: +// - s: [output] s will be used as output. It contains the error code/message. +// - spec: Serialized data (protobuf format) containing the specification. +// - spec_size: Size of the serialized data. +// +// Returns: +// Returns the error code. 0 on success. The return code is same as +// status_get_code(s). +int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_size); + +int lmctfy_container_api_create_container_raw( + struct status *s, + struct container **container, + struct container_api *api, + const char *container_name, + const void *spec, + const int spec_size); + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // LMCTFY_C_BINDING_CLMCTFY_RAW_H_ diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 85811f9..29d647e 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -17,18 +17,6 @@ struct status { struct container; struct container_api; -// Initializes the machine to start being able to create containers. -// -// Arguments: -// - s: [output] s will be used as output. It contains the error code/message. -// - spec: Serialized data (protobuf format) containing the specification. -// - spec_size: Size of the serialized data. -// -// Returns: -// Returns the error code. 0 on success. The return code is same as -// status_get_code(s). -int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_size); - // Initializes the machine to start being able to create containers. // // Arguments: @@ -74,13 +62,6 @@ int lmctfy_container_api_get_container( const struct container_api *api, const char *container_name); -int lmctfy_container_api_create_container_raw( - struct status *s, - struct container **container, - struct container_api *api, - const char *container_name, - const void *spec, - const int spec_size); #ifdef __cplusplus } #endif // __cplusplus From fdf3ca6b3dcc73009adc998aa9f6e2288a6ec640 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 01:21:31 -0500 Subject: [PATCH 23/84] Rename some variables. Output to bin/ --- clmctfy/Makefile | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/clmctfy/Makefile b/clmctfy/Makefile index f0e6769..9046d82 100644 --- a/clmctfy/Makefile +++ b/clmctfy/Makefile @@ -3,33 +3,41 @@ PROTOC_C = protoc-c # The directory where this Makefile resides -PWD = $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) +CLMCTFY_ROOT = $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) -LMCTFY_ROOT = $(shell dirname ${PWD}) +LMCTFY_ROOT = $(shell dirname ${CLMCTFY_ROOT}) -CINCLUDE = ${PWD}/include +CLMCTFY_INCLUDE = ${CLMCTFY_ROOT}/include CXX ?= g++ AR ?= ar -CXXFLAGS = -I${CINCLUDE} -I${LMCTFY_ROOT}/include -I${LMCTFY_ROOT} -I${PWD} +# Where to place the binary outputs. +OUT_DIR = ${CLMCTFY_ROOT}/bin + +# Function for ensuring the output directory has been created. +create_bin = mkdir -p $(dir $(OUT_DIR)/$@) + +CXXFLAGS = -I${CLMCTFY_INCLUDE} -I${LMCTFY_ROOT}/include -I${LMCTFY_ROOT} -I${CLMCTFY_ROOT} CXXFLAGS += -std=c++0x -fpermissive all: clmctfy.o status-c.o -clmctfy.o: ${PWD}/clmctfy.cc ${CINCLUDE}/clmctfy.h ${PWD}/status-internal.h ${CINCLUDE}/lmctfy.pb-c.h ${CINCLUDE}/codes.pb-c.h ${CINCLUDE}/clmctfy-raw.h - ${CXX} ${CXXFLAGS} -c -o $@ $< -status-c.o: ${PWD}/status-c.cc ${CINCLUDE}/clmctfy.h ${CINCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h ${PWD}/status-internal.h - ${CXX} ${CXXFLAGS} -c -o $@ $< +clmctfy.o: ${CLMCTFY_ROOT}/clmctfy.cc ${CLMCTFY_INCLUDE}/clmctfy.h ${CLMCTFY_ROOT}/status-internal.h ${CLMCTFY_INCLUDE}/lmctfy.pb-c.h ${CLMCTFY_INCLUDE}/codes.pb-c.h ${CLMCTFY_INCLUDE}/clmctfy-raw.h + $(create_bin) + ${CXX} ${CXXFLAGS} -c -o $(OUT_DIR)/$@ $< +status-c.o: ${CLMCTFY_ROOT}/status-c.cc ${CLMCTFY_INCLUDE}/clmctfy.h ${CLMCTFY_INCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h ${CLMCTFY_ROOT}/status-internal.h + $(create_bin) + ${CXX} ${CXXFLAGS} -c -o $(OUT_DIR)/$@ $< -${CINCLUDE}/codes.pb-c.h: ${LMCTFY_ROOT}/util/task/codes.proto - ${PROTOC_C} --c_out=${CINCLUDE} --proto_path=${LMCTFY_ROOT}/util/task $< +${CLMCTFY_INCLUDE}/codes.pb-c.h: ${LMCTFY_ROOT}/util/task/codes.proto + ${PROTOC_C} --c_out=${CLMCTFY_INCLUDE} --proto_path=${LMCTFY_ROOT}/util/task $< -${CINCLUDE}/lmctfy.pb-c.h: ${LMCTFY_ROOT}/include/lmctfy.proto - ${PROTOC_C} --c_out=${CINCLUDE} --proto_path=${LMCTFY_ROOT}/include $< +${CLMCTFY_INCLUDE}/lmctfy.pb-c.h: ${LMCTFY_ROOT}/include/lmctfy.proto + ${PROTOC_C} --c_out=${CLMCTFY_INCLUDE} --proto_path=${LMCTFY_ROOT}/include $< clean: - rm -f ${CINCLUDE}/*.pb-c.[ch] + rm -f ${CLMCTFY_INCLUDE}/*.pb-c.[ch] rm -f *.o .PHONY: clean all From c109cba303e94f947601c73cab95083abce12ff2 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 01:29:08 -0500 Subject: [PATCH 24/84] create gtest.a in Makefile. --- clmctfy/Makefile | 67 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/clmctfy/Makefile b/clmctfy/Makefile index 9046d82..c044222 100644 --- a/clmctfy/Makefile +++ b/clmctfy/Makefile @@ -15,18 +15,34 @@ AR ?= ar # Where to place the binary outputs. OUT_DIR = ${CLMCTFY_ROOT}/bin +# Location of gTest and gMock. +GTEST_DIR = ${LMCTFY_ROOT}/gmock/gtest +GMOCK_DIR = ${LMCTFY_ROOT}/gmock + # Function for ensuring the output directory has been created. create_bin = mkdir -p $(dir $(OUT_DIR)/$@) +# Function that archives all input's bin/ output into an archive. +archive_all = $(AR) $(ARFLAGS) $(OUT_DIR)/$@ $(addprefix $(OUT_DIR)/,$^) + CXXFLAGS = -I${CLMCTFY_INCLUDE} -I${LMCTFY_ROOT}/include -I${LMCTFY_ROOT} -I${CLMCTFY_ROOT} CXXFLAGS += -std=c++0x -fpermissive all: clmctfy.o status-c.o -clmctfy.o: ${CLMCTFY_ROOT}/clmctfy.cc ${CLMCTFY_INCLUDE}/clmctfy.h ${CLMCTFY_ROOT}/status-internal.h ${CLMCTFY_INCLUDE}/lmctfy.pb-c.h ${CLMCTFY_INCLUDE}/codes.pb-c.h ${CLMCTFY_INCLUDE}/clmctfy-raw.h +clmctfy.o: ${CLMCTFY_ROOT}/clmctfy.cc \ + ${CLMCTFY_INCLUDE}/clmctfy.h \ + ${CLMCTFY_ROOT}/status-internal.h \ + ${CLMCTFY_INCLUDE}/lmctfy.pb-c.h \ + ${CLMCTFY_INCLUDE}/codes.pb-c.h \ + ${CLMCTFY_INCLUDE}/clmctfy-raw.h $(create_bin) ${CXX} ${CXXFLAGS} -c -o $(OUT_DIR)/$@ $< -status-c.o: ${CLMCTFY_ROOT}/status-c.cc ${CLMCTFY_INCLUDE}/clmctfy.h ${CLMCTFY_INCLUDE}/codes.pb-c.h ${LMCTFY_ROOT}/util/task/status.h ${CLMCTFY_ROOT}/status-internal.h +status-c.o: ${CLMCTFY_ROOT}/status-c.cc \ + ${CLMCTFY_INCLUDE}/clmctfy.h \ + ${CLMCTFY_INCLUDE}/codes.pb-c.h \ + ${LMCTFY_ROOT}/util/task/status.h \ + ${CLMCTFY_ROOT}/status-internal.h $(create_bin) ${CXX} ${CXXFLAGS} -c -o $(OUT_DIR)/$@ $< @@ -39,6 +55,53 @@ ${CLMCTFY_INCLUDE}/lmctfy.pb-c.h: ${LMCTFY_ROOT}/include/lmctfy.proto clean: rm -f ${CLMCTFY_INCLUDE}/*.pb-c.[ch] rm -f *.o + rm -rf ${OUT_DIR} .PHONY: clean all +# Rules for Building Google Test and Google Mock (based on gmock's example). + +# All Google Test headers. Usually you shouldn't change this definition. +GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ + $(GTEST_DIR)/include/gtest/internal/*.h + +# All Google Mock headers. Note that all Google Test headers are +# included here too, as they are #included by Google Mock headers. +# Usually you shouldn't change this definition. +GMOCK_HEADERS = $(GMOCK_DIR)/include/gmock/*.h \ + $(GMOCK_DIR)/include/gmock/internal/*.h \ + $(GTEST_HEADERS) + +GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) +GMOCK_SRCS_ = $(GMOCK_DIR)/src/*.cc $(GMOCK_HEADERS) + +# For simplicity and to avoid depending on Google Test's +# implementation details, the dependencies specified below are +# conservative and not optimized. This is fine as Google Test +# compiles fast and for ordinary users its source rarely changes. +gtest-all.o : $(GTEST_SRCS_) + $(create_bin) + $(CXX) -I$(GTEST_DIR) \ + -I$(GMOCK_DIR)/include -I$(GTEST_DIR)/include \ + $(CXXFLAGS) \ + -c $(GTEST_DIR)/src/gtest-all.cc -o $(OUT_DIR)/$@ + +gmock-all.o : $(GMOCK_SRCS_) + $(create_bin) + $(CXX) -I$(GTEST_DIR) -I$(GMOCK_DIR) \ + -I$(GMOCK_DIR)/include -I$(GTEST_DIR)/include \ + $(CXXFLAGS) \ + -c $(GMOCK_DIR)/src/gmock-all.cc -o $(OUT_DIR)/$@ + +gmock_main.o : $(GMOCK_SRCS_) + $(create_bin) + $(CXX) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \ + -c $(GMOCK_DIR)/src/gmock_main.cc -o $(OUT_DIR)/$@ + +gtest.a : gmock-all.o gtest-all.o + $(create_bin) + $(archive_all) + +gtest_main.a : gmock-all.o gtest-all.o gmock_main.o + $(create_bin) + $(archive_all) From 04b3c09071c2855a8d5ae4824d217a38e23831fd Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 13:52:12 -0500 Subject: [PATCH 25/84] working on unit tests. --- clmctfy/Makefile | 29 ++++++++++++++++++++++++++--- clmctfy/clmctfy_test.cc | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 clmctfy/clmctfy_test.cc diff --git a/clmctfy/Makefile b/clmctfy/Makefile index c044222..875a326 100644 --- a/clmctfy/Makefile +++ b/clmctfy/Makefile @@ -25,8 +25,16 @@ create_bin = mkdir -p $(dir $(OUT_DIR)/$@) # Function that archives all input's bin/ output into an archive. archive_all = $(AR) $(ARFLAGS) $(OUT_DIR)/$@ $(addprefix $(OUT_DIR)/,$^) +# Gets all *_test.cc files in lmtcfy/. +TESTS = $(basename $(shell find ./ -name \*_test.cc)) + CXXFLAGS = -I${CLMCTFY_INCLUDE} -I${LMCTFY_ROOT}/include -I${LMCTFY_ROOT} -I${CLMCTFY_ROOT} +CXXFLAGS += -I${LMCTFY_ROOT}/base -I${LMCTFY_ROOT}/lmctfy -I${GTEST_DIR}/include \ + -I${GMOCK_DIR}/include -I/usr/local/include -L/usr/local/lib \ + -I/usr/include -L/usr/lib CXXFLAGS += -std=c++0x -fpermissive +# Add libraries to link in. +CXXFLAGS += -pthread -lrt -lre2 -lgflags all: clmctfy.o status-c.o @@ -52,12 +60,27 @@ ${CLMCTFY_INCLUDE}/codes.pb-c.h: ${LMCTFY_ROOT}/util/task/codes.proto ${CLMCTFY_INCLUDE}/lmctfy.pb-c.h: ${LMCTFY_ROOT}/include/lmctfy.proto ${PROTOC_C} --c_out=${CLMCTFY_INCLUDE} --proto_path=${LMCTFY_ROOT}/include $< +%_test: gtest_main.a + $(create_bin) + $(CXX) ${CXXFLAGS} -o $(OUT_DIR)/$@ $*.cc $*_test.cc $(addprefix $(OUT_DIR)/,$^) + +TEST_TMPDIR = "clmctfy_test.$$" +check: $(TESTS) + for t in $(addprefix $(OUT_DIR)/,$^); \ + do \ + echo "***** Running $$t"; \ + rm -rf $(TEST_TMPDIR); \ + mkdir $(TEST_TMPDIR); \ + ./$$t --test_tmpdir=$(TEST_TMPDIR); \ + done; \ + #rm -rf $(TEST_TMPDIR) + clean: rm -f ${CLMCTFY_INCLUDE}/*.pb-c.[ch] rm -f *.o rm -rf ${OUT_DIR} -.PHONY: clean all +.PHONY: clean all check # Rules for Building Google Test and Google Mock (based on gmock's example). @@ -89,13 +112,13 @@ gtest-all.o : $(GTEST_SRCS_) gmock-all.o : $(GMOCK_SRCS_) $(create_bin) $(CXX) -I$(GTEST_DIR) -I$(GMOCK_DIR) \ - -I$(GMOCK_DIR)/include -I$(GTEST_DIR)/include \ + -I$(GMOCK_DIR)/include \ $(CXXFLAGS) \ -c $(GMOCK_DIR)/src/gmock-all.cc -o $(OUT_DIR)/$@ gmock_main.o : $(GMOCK_SRCS_) $(create_bin) - $(CXX) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \ + $(CXX) -I$(GTEST_DIR) $(CXXFLAGS) \ -c $(GMOCK_DIR)/src/gmock_main.cc -o $(OUT_DIR)/$@ gtest.a : gmock-all.o gtest-all.o diff --git a/clmctfy/clmctfy_test.cc b/clmctfy/clmctfy_test.cc new file mode 100644 index 0000000..6b3f5af --- /dev/null +++ b/clmctfy/clmctfy_test.cc @@ -0,0 +1,41 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include "lmctfy_mock.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "clmctfy.h" +#include "util/task/statusor.h" + +using ::util::Status; +using ::util::StatusOr; + +namespace containers { +namespace lmctfy { + +StatusOr ContainerApi::New() { + return new StrictMockContainerApi(); +} + +namespace { + +TEST(ClmctfyTest, NewContainerApi) { + EXPECT_EQ(1, 1); +} + +} // namespace +} // namespace lmctfy +} // namespace containers + From ada5231a64ff327d98bed555a2ca618ffb9663f7 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 13:55:07 -0500 Subject: [PATCH 26/84] Use () instead of {} in Makefile --- clmctfy/Makefile | 56 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/clmctfy/Makefile b/clmctfy/Makefile index 875a326..8097b3d 100644 --- a/clmctfy/Makefile +++ b/clmctfy/Makefile @@ -5,19 +5,19 @@ PROTOC_C = protoc-c # The directory where this Makefile resides CLMCTFY_ROOT = $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) -LMCTFY_ROOT = $(shell dirname ${CLMCTFY_ROOT}) +LMCTFY_ROOT = $(shell dirname $(CLMCTFY_ROOT)) -CLMCTFY_INCLUDE = ${CLMCTFY_ROOT}/include +CLMCTFY_INCLUDE = $(CLMCTFY_ROOT)/include CXX ?= g++ AR ?= ar # Where to place the binary outputs. -OUT_DIR = ${CLMCTFY_ROOT}/bin +OUT_DIR = $(CLMCTFY_ROOT)/bin # Location of gTest and gMock. -GTEST_DIR = ${LMCTFY_ROOT}/gmock/gtest -GMOCK_DIR = ${LMCTFY_ROOT}/gmock +GTEST_DIR = $(LMCTFY_ROOT)/gmock/gtest +GMOCK_DIR = $(LMCTFY_ROOT)/gmock # Function for ensuring the output directory has been created. create_bin = mkdir -p $(dir $(OUT_DIR)/$@) @@ -28,9 +28,9 @@ archive_all = $(AR) $(ARFLAGS) $(OUT_DIR)/$@ $(addprefix $(OUT_DIR)/,$^) # Gets all *_test.cc files in lmtcfy/. TESTS = $(basename $(shell find ./ -name \*_test.cc)) -CXXFLAGS = -I${CLMCTFY_INCLUDE} -I${LMCTFY_ROOT}/include -I${LMCTFY_ROOT} -I${CLMCTFY_ROOT} -CXXFLAGS += -I${LMCTFY_ROOT}/base -I${LMCTFY_ROOT}/lmctfy -I${GTEST_DIR}/include \ - -I${GMOCK_DIR}/include -I/usr/local/include -L/usr/local/lib \ +CXXFLAGS = -I$(CLMCTFY_INCLUDE) -I$(LMCTFY_ROOT)/include -I$(LMCTFY_ROOT) -I$(CLMCTFY_ROOT) +CXXFLAGS += -I$(LMCTFY_ROOT)/base -I$(LMCTFY_ROOT)/lmctfy -I$(GTEST_DIR)/include \ + -I$(GMOCK_DIR)/include -I/usr/local/include -L/usr/local/lib \ -I/usr/include -L/usr/lib CXXFLAGS += -std=c++0x -fpermissive # Add libraries to link in. @@ -38,31 +38,31 @@ CXXFLAGS += -pthread -lrt -lre2 -lgflags all: clmctfy.o status-c.o -clmctfy.o: ${CLMCTFY_ROOT}/clmctfy.cc \ - ${CLMCTFY_INCLUDE}/clmctfy.h \ - ${CLMCTFY_ROOT}/status-internal.h \ - ${CLMCTFY_INCLUDE}/lmctfy.pb-c.h \ - ${CLMCTFY_INCLUDE}/codes.pb-c.h \ - ${CLMCTFY_INCLUDE}/clmctfy-raw.h +clmctfy.o: $(CLMCTFY_ROOT)/clmctfy.cc \ + $(CLMCTFY_INCLUDE)/clmctfy.h \ + $(CLMCTFY_ROOT)/status-internal.h \ + $(CLMCTFY_INCLUDE)/lmctfy.pb-c.h \ + $(CLMCTFY_INCLUDE)/codes.pb-c.h \ + $(CLMCTFY_INCLUDE)/clmctfy-raw.h $(create_bin) - ${CXX} ${CXXFLAGS} -c -o $(OUT_DIR)/$@ $< -status-c.o: ${CLMCTFY_ROOT}/status-c.cc \ - ${CLMCTFY_INCLUDE}/clmctfy.h \ - ${CLMCTFY_INCLUDE}/codes.pb-c.h \ - ${LMCTFY_ROOT}/util/task/status.h \ - ${CLMCTFY_ROOT}/status-internal.h + $(CXX) $(CXXFLAGS) -c -o $(OUT_DIR)/$@ $< +status-c.o: $(CLMCTFY_ROOT)/status-c.cc \ + $(CLMCTFY_INCLUDE)/clmctfy.h \ + $(CLMCTFY_INCLUDE)/codes.pb-c.h \ + $(LMCTFY_ROOT)/util/task/status.h \ + $(CLMCTFY_ROOT)/status-internal.h $(create_bin) - ${CXX} ${CXXFLAGS} -c -o $(OUT_DIR)/$@ $< + $(CXX) $(CXXFLAGS) -c -o $(OUT_DIR)/$@ $< -${CLMCTFY_INCLUDE}/codes.pb-c.h: ${LMCTFY_ROOT}/util/task/codes.proto - ${PROTOC_C} --c_out=${CLMCTFY_INCLUDE} --proto_path=${LMCTFY_ROOT}/util/task $< +$(CLMCTFY_INCLUDE)/codes.pb-c.h: $(LMCTFY_ROOT)/util/task/codes.proto + $(PROTOC_C) --c_out=$(CLMCTFY_INCLUDE) --proto_path=$(LMCTFY_ROOT)/util/task $< -${CLMCTFY_INCLUDE}/lmctfy.pb-c.h: ${LMCTFY_ROOT}/include/lmctfy.proto - ${PROTOC_C} --c_out=${CLMCTFY_INCLUDE} --proto_path=${LMCTFY_ROOT}/include $< +$(CLMCTFY_INCLUDE)/lmctfy.pb-c.h: $(LMCTFY_ROOT)/include/lmctfy.proto + $(PROTOC_C) --c_out=$(CLMCTFY_INCLUDE) --proto_path=$(LMCTFY_ROOT)/include $< %_test: gtest_main.a $(create_bin) - $(CXX) ${CXXFLAGS} -o $(OUT_DIR)/$@ $*.cc $*_test.cc $(addprefix $(OUT_DIR)/,$^) + $(CXX) $(CXXFLAGS) -o $(OUT_DIR)/$@ $*.cc $*_test.cc $(addprefix $(OUT_DIR)/,$^) TEST_TMPDIR = "clmctfy_test.$$" check: $(TESTS) @@ -76,9 +76,9 @@ check: $(TESTS) #rm -rf $(TEST_TMPDIR) clean: - rm -f ${CLMCTFY_INCLUDE}/*.pb-c.[ch] + rm -f $(CLMCTFY_INCLUDE)/*.pb-c.[ch] rm -f *.o - rm -rf ${OUT_DIR} + rm -rf $(OUT_DIR) .PHONY: clean all check From 820b9bca557b512294e9dba42ba227a49e26469e Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 17:09:19 -0500 Subject: [PATCH 27/84] A better Makefile. --- clmctfy/Makefile | 32 +++++++++++++------------------- clmctfy/clmctfy.cc | 2 +- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/clmctfy/Makefile b/clmctfy/Makefile index 8097b3d..50c39b5 100644 --- a/clmctfy/Makefile +++ b/clmctfy/Makefile @@ -1,6 +1,6 @@ # TODO(monnand): Check protoc-c is installed PROTOC_C = protoc-c - +PROTOC = protoc # The directory where this Makefile resides CLMCTFY_ROOT = $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) @@ -15,6 +15,9 @@ AR ?= ar # Where to place the binary outputs. OUT_DIR = $(CLMCTFY_ROOT)/bin +INCLUDE_PROTOS = $(LMCTFY_ROOT)/include/lmctfy +UTIL_PROTOS = $(LMCTFY_ROOT)/util/task/codes + # Location of gTest and gMock. GTEST_DIR = $(LMCTFY_ROOT)/gmock/gtest GMOCK_DIR = $(LMCTFY_ROOT)/gmock @@ -38,27 +41,18 @@ CXXFLAGS += -pthread -lrt -lre2 -lgflags all: clmctfy.o status-c.o -clmctfy.o: $(CLMCTFY_ROOT)/clmctfy.cc \ - $(CLMCTFY_INCLUDE)/clmctfy.h \ - $(CLMCTFY_ROOT)/status-internal.h \ - $(CLMCTFY_INCLUDE)/lmctfy.pb-c.h \ - $(CLMCTFY_INCLUDE)/codes.pb-c.h \ - $(CLMCTFY_INCLUDE)/clmctfy-raw.h - $(create_bin) - $(CXX) $(CXXFLAGS) -c -o $(OUT_DIR)/$@ $< -status-c.o: $(CLMCTFY_ROOT)/status-c.cc \ - $(CLMCTFY_INCLUDE)/clmctfy.h \ - $(CLMCTFY_INCLUDE)/codes.pb-c.h \ - $(LMCTFY_ROOT)/util/task/status.h \ - $(CLMCTFY_ROOT)/status-internal.h +%.o: gen_protos %.cc $(create_bin) - $(CXX) $(CXXFLAGS) -c -o $(OUT_DIR)/$@ $< + $(CXX) -c $*.cc -o $(OUT_DIR)/$@ $(CXXFLAGS) -$(CLMCTFY_INCLUDE)/codes.pb-c.h: $(LMCTFY_ROOT)/util/task/codes.proto - $(PROTOC_C) --c_out=$(CLMCTFY_INCLUDE) --proto_path=$(LMCTFY_ROOT)/util/task $< +gen_protos: $(addsuffix _proto,$(INCLUDE_PROTOS) $(UTIL_PROTOS)) -$(CLMCTFY_INCLUDE)/lmctfy.pb-c.h: $(LMCTFY_ROOT)/include/lmctfy.proto - $(PROTOC_C) --c_out=$(CLMCTFY_INCLUDE) --proto_path=$(LMCTFY_ROOT)/include $< +%_proto: %.proto + $(PROTOC_C) $^ --c_out=$(dir $^) --proto_path=$(dir $^) + +%.pb-c.o: %_proto + $(create_bin) + $(CXX) -c $*.pb-c.c -o $(OUT_DIR)/$@ $(CXXFLAGS) %_test: gtest_main.a $(create_bin) diff --git a/clmctfy/clmctfy.cc b/clmctfy/clmctfy.cc index 636f932..a0b52d5 100644 --- a/clmctfy/clmctfy.cc +++ b/clmctfy/clmctfy.cc @@ -6,7 +6,7 @@ #include "util/task/statusor.h" #include "status-internal.h" #include "lmctfy.pb.h" -#include "codes.pb-c.h" +#include "util/task/codes.pb-c.h" #define STATUS_OK UTIL__ERROR__CODE__OK From a53a34242a6e421ef0f5ba248524880bb7cb202b Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 17:57:12 -0500 Subject: [PATCH 28/84] merge clmctfy Makefile into the top-level Makefile. --- Makefile | 48 +++++++++++++++++++ clmctfy/Makefile | 6 +++ clmctfy/{clmctfy_test.cc => clmctfy_ctest.cc} | 4 ++ 3 files changed, 58 insertions(+) rename clmctfy/{clmctfy_test.cc => clmctfy_ctest.cc} (92%) diff --git a/Makefile b/Makefile index 6523170..0f18291 100755 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ VERSION = "\"0.4.5\"" # TODO(vmarmol): Ensure our dependencies are installed PROTOC = protoc +PROTOC_C = protoc-c # Function for getting a set of source files. get_srcs = $(shell find $(1) -name \*.cc -a ! -name \*_test.cc | tr "\n" " ") @@ -37,6 +38,8 @@ LIBLMCTFY_SOURCES =$(shell find lmctfy/ -name \*.cc -a ! -name \*_test.cc \ CLI_SOURCES = $(call get_srcs,lmctfy/cli/) NSINIT_SOURCES = nscon/init.cc nscon/init_impl.cc NSCON_SOURCES = $(filter-out $(NSINIT_SOURCES),$(call get_srcs,nscon/)) +CPROTOS_SOURCES = $(addsuffix .pb-c.c,$(INCLUDE_PROTOS)) $(addsuffix .pb.cc,$(UTIL_PROTOS)) +LIBCLMCTFY_SOURCES = $(call get_srcs,clmctfy/) $(CPROTOS_SOURCES) # The objects for the system API (both release and test versions). SYSTEM_API_OBJS = global_utils/mount_utils.o \ @@ -61,6 +64,7 @@ SYSTEM_API_TEST_OBJS = global_utils/mount_utils_test_util.o \ # Gets all *_test.cc files in lmtcfy/. TESTS = $(basename $(shell find lmctfy/ nscon/ -name \*_test.cc \ -a ! -name \*_integration_test.cc)) +CLMCTFY_TESTS = $(basename $(shell find clmctfy/ -name \*_ctest.cc)) # Where to place the binary outputs. OUT_DIR = bin @@ -96,15 +100,21 @@ CXXFLAGS += -pthread -lrt -lre2 -lgflags CXXFLAGS += -I. -I./include -I./base -I./lmctfy -I$(GTEST_DIR)/include \ -I$(GMOCK_DIR)/include -I/usr/local/include -L/usr/local/lib \ -I/usr/include -L/usr/lib +# Add include for c binding +CXXFLAGS += -I./clmctfy/include -I./clmctfy # Add proto flags. CXXFLAGS += `pkg-config --cflags --libs protobuf` +# Add proto-c flags. +CXXFLAGS += -lprotobuf-c + CLI = lmctfy NSCON = lmctfy-nscon NSINIT = lmctfy-nsinit LIBRARY = liblmctfy.a CREAPER = lmctfy-creaper +CLIBRARY = libclmctfy.a # Function for ensuring the output directory has been created. create_bin = mkdir -p $(dir $(OUT_DIR)/$@) @@ -128,6 +138,8 @@ install: all chmod +x /usr/local/bin/$(NSINIT) cp ./bin/$(CREAPER) /usr/local/bin chmod +x /usr/local/bin/$(CREAPER) + +cbinding: $(CLIBRARY) checkc TEST_TMPDIR = "/tmp/lmctfy_test.$$" check: $(TESTS) @@ -141,6 +153,16 @@ check: $(TESTS) rm -rf $(TEST_TMPDIR) echo "All tests pass!" +checkc: $(CLMCTFY_TESTS) + for t in $(addprefix $(OUT_DIR)/,$^); \ + do \ + echo "***** Running $$t"; \ + rm -rf $(TEST_TMPDIR); \ + mkdir $(TEST_TMPDIR); \ + ./$$t --test_tmpdir=$(TEST_TMPDIR); \ + done; \ + rm -rf $(TEST_TMPDIR) + clean: -rm -rf $(OUT_DIR) -rm -f `find . -type f -name '*.pb.*'` @@ -155,6 +177,10 @@ COMMON_SOURCES = $(INCLUDE_SOURCES) $(BASE_SOURCES) $(STRINGS_SOURCES) \ # All sources needed by the library (minus the system API). LIBRARY_SOURCES = $(COMMON_SOURCES) $(LIBLMCTFY_SOURCES) $(NSCON_SOURCES) +CLIBRARY_ONLY_SOURCES = $(INCLUDE_SOURCES) $(BASE_SOURCES) $(LIBCLMCTFY_SOURCES) \ + $(STRINGS_SOURCES) $(FILE_SOURCES) $(THREAD_SOURCES) \ + $(UTIL_SOURCES) +CLIBRARY_SOURCES = $(LIBRARY_SOURCES) $(LIBCLMCTFY_SOURCES) # The lmctfy library without the system API. This is primarily an internal @@ -163,11 +189,19 @@ lmctfy_no_system_api.a: $(call source_to_object,$(LIBRARY_SOURCES)) $(create_bin) $(archive_all) +clmctfy_only_api.a: $(call source_to_object,$(CLIBRARY_ONLY_SOURCES)) + $(create_bin) + $(archive_all) + # The lmctfy library with the real system API. $(LIBRARY): $(call source_to_object,$(LIBRARY_SOURCES)) $(SYSTEM_API_OBJS) $(create_bin) $(archive_all) +$(CLIBRARY): $(call source_to_object,$(CLIBRARY_SOURCES)) $(SYSTEM_API_OBJS) + $(create_bin) + $(archive_all) + # Objects of the lmctfy CLI. lmctfy_cli.a: $(call source_to_object,$(CLI_SOURCES)) $(create_bin) @@ -204,19 +238,33 @@ $(CREAPER): lmctfy-creaper.go $(CXX) -o $(OUT_DIR)/$@ $*.cc $*_test.cc $(addprefix $(OUT_DIR)/,$^) \ $(CXXFLAGS) +%_ctest: gtest_main.a $(SYSTEM_API_TEST_OBJS) clmctfy_only_api.a + $(create_bin) + $(CXX) -o $(OUT_DIR)/$@ $*.cc $*_ctest.cc $(addprefix $(OUT_DIR)/,$^) \ + $(CXXFLAGS) + %_proto: %.proto $(PROTOC) $^ --cpp_out=. + $(PROTOC_C) $^ --c_out=$(dir $^) --proto_path=$(dir $^) %.pb.o: %_proto $(create_bin) $(CXX) -c $*.pb.cc -o $(OUT_DIR)/$@ $(CXXFLAGS) +%.pb-c.o: %_proto + $(create_bin) + $(CXX) -c $*.pb-c.c -o $(OUT_DIR)/$@ $(CXXFLAGS) + gen_protos: $(addsuffix _proto,$(INCLUDE_PROTOS) $(UTIL_PROTOS)) %.o: gen_protos %.cc $(create_bin) $(CXX) -c $*.cc -o $(OUT_DIR)/$@ $(CXXFLAGS) +%.o: %.pb-c.c + $(create_bin) + $(CXX) -c $*.c -o $(OUT_DIR)/$@ $(CXXFLAGS) + # Rules for Building Google Test and Google Mock (based on gmock's example). # All Google Test headers. Usually you shouldn't change this definition. diff --git a/clmctfy/Makefile b/clmctfy/Makefile index 50c39b5..8bb60b4 100644 --- a/clmctfy/Makefile +++ b/clmctfy/Makefile @@ -28,6 +28,12 @@ create_bin = mkdir -p $(dir $(OUT_DIR)/$@) # Function that archives all input's bin/ output into an archive. archive_all = $(AR) $(ARFLAGS) $(OUT_DIR)/$@ $(addprefix $(OUT_DIR)/,$^) +# Function for getting a set of source files. +get_srcs = $(shell find $(1) -name \*.cc -a ! -name \*_test.cc | tr "\n" " ") + +BASE_SOURCES = $(call get_srcs,$(LMCTFY_ROOT)/base/) +FILE_SOURCES = $(call get_srcs,$(LMCTFY_ROOT)/file/) + # Gets all *_test.cc files in lmtcfy/. TESTS = $(basename $(shell find ./ -name \*_test.cc)) diff --git a/clmctfy/clmctfy_test.cc b/clmctfy/clmctfy_ctest.cc similarity index 92% rename from clmctfy/clmctfy_test.cc rename to clmctfy/clmctfy_ctest.cc index 6b3f5af..2c33838 100644 --- a/clmctfy/clmctfy_test.cc +++ b/clmctfy/clmctfy_ctest.cc @@ -29,6 +29,10 @@ StatusOr ContainerApi::New() { return new StrictMockContainerApi(); } +Status ContainerApi::InitMachine(const InitSpec &spec) { + return Status::OK; +} + namespace { TEST(ClmctfyTest, NewContainerApi) { From bb4b213b524da2d49041ec014faadf5777ea6df5 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 17:58:22 -0500 Subject: [PATCH 29/84] remove old Makefile in clmctfy --- clmctfy/Makefile | 130 ----------------------------------------------- 1 file changed, 130 deletions(-) delete mode 100644 clmctfy/Makefile diff --git a/clmctfy/Makefile b/clmctfy/Makefile deleted file mode 100644 index 8bb60b4..0000000 --- a/clmctfy/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -# TODO(monnand): Check protoc-c is installed -PROTOC_C = protoc-c -PROTOC = protoc - -# The directory where this Makefile resides -CLMCTFY_ROOT = $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) - -LMCTFY_ROOT = $(shell dirname $(CLMCTFY_ROOT)) - -CLMCTFY_INCLUDE = $(CLMCTFY_ROOT)/include - -CXX ?= g++ -AR ?= ar - -# Where to place the binary outputs. -OUT_DIR = $(CLMCTFY_ROOT)/bin - -INCLUDE_PROTOS = $(LMCTFY_ROOT)/include/lmctfy -UTIL_PROTOS = $(LMCTFY_ROOT)/util/task/codes - -# Location of gTest and gMock. -GTEST_DIR = $(LMCTFY_ROOT)/gmock/gtest -GMOCK_DIR = $(LMCTFY_ROOT)/gmock - -# Function for ensuring the output directory has been created. -create_bin = mkdir -p $(dir $(OUT_DIR)/$@) - -# Function that archives all input's bin/ output into an archive. -archive_all = $(AR) $(ARFLAGS) $(OUT_DIR)/$@ $(addprefix $(OUT_DIR)/,$^) - -# Function for getting a set of source files. -get_srcs = $(shell find $(1) -name \*.cc -a ! -name \*_test.cc | tr "\n" " ") - -BASE_SOURCES = $(call get_srcs,$(LMCTFY_ROOT)/base/) -FILE_SOURCES = $(call get_srcs,$(LMCTFY_ROOT)/file/) - -# Gets all *_test.cc files in lmtcfy/. -TESTS = $(basename $(shell find ./ -name \*_test.cc)) - -CXXFLAGS = -I$(CLMCTFY_INCLUDE) -I$(LMCTFY_ROOT)/include -I$(LMCTFY_ROOT) -I$(CLMCTFY_ROOT) -CXXFLAGS += -I$(LMCTFY_ROOT)/base -I$(LMCTFY_ROOT)/lmctfy -I$(GTEST_DIR)/include \ - -I$(GMOCK_DIR)/include -I/usr/local/include -L/usr/local/lib \ - -I/usr/include -L/usr/lib -CXXFLAGS += -std=c++0x -fpermissive -# Add libraries to link in. -CXXFLAGS += -pthread -lrt -lre2 -lgflags - -all: clmctfy.o status-c.o - -%.o: gen_protos %.cc - $(create_bin) - $(CXX) -c $*.cc -o $(OUT_DIR)/$@ $(CXXFLAGS) - -gen_protos: $(addsuffix _proto,$(INCLUDE_PROTOS) $(UTIL_PROTOS)) - -%_proto: %.proto - $(PROTOC_C) $^ --c_out=$(dir $^) --proto_path=$(dir $^) - -%.pb-c.o: %_proto - $(create_bin) - $(CXX) -c $*.pb-c.c -o $(OUT_DIR)/$@ $(CXXFLAGS) - -%_test: gtest_main.a - $(create_bin) - $(CXX) $(CXXFLAGS) -o $(OUT_DIR)/$@ $*.cc $*_test.cc $(addprefix $(OUT_DIR)/,$^) - -TEST_TMPDIR = "clmctfy_test.$$" -check: $(TESTS) - for t in $(addprefix $(OUT_DIR)/,$^); \ - do \ - echo "***** Running $$t"; \ - rm -rf $(TEST_TMPDIR); \ - mkdir $(TEST_TMPDIR); \ - ./$$t --test_tmpdir=$(TEST_TMPDIR); \ - done; \ - #rm -rf $(TEST_TMPDIR) - -clean: - rm -f $(CLMCTFY_INCLUDE)/*.pb-c.[ch] - rm -f *.o - rm -rf $(OUT_DIR) - -.PHONY: clean all check - -# Rules for Building Google Test and Google Mock (based on gmock's example). - -# All Google Test headers. Usually you shouldn't change this definition. -GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ - $(GTEST_DIR)/include/gtest/internal/*.h - -# All Google Mock headers. Note that all Google Test headers are -# included here too, as they are #included by Google Mock headers. -# Usually you shouldn't change this definition. -GMOCK_HEADERS = $(GMOCK_DIR)/include/gmock/*.h \ - $(GMOCK_DIR)/include/gmock/internal/*.h \ - $(GTEST_HEADERS) - -GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) -GMOCK_SRCS_ = $(GMOCK_DIR)/src/*.cc $(GMOCK_HEADERS) - -# For simplicity and to avoid depending on Google Test's -# implementation details, the dependencies specified below are -# conservative and not optimized. This is fine as Google Test -# compiles fast and for ordinary users its source rarely changes. -gtest-all.o : $(GTEST_SRCS_) - $(create_bin) - $(CXX) -I$(GTEST_DIR) \ - -I$(GMOCK_DIR)/include -I$(GTEST_DIR)/include \ - $(CXXFLAGS) \ - -c $(GTEST_DIR)/src/gtest-all.cc -o $(OUT_DIR)/$@ - -gmock-all.o : $(GMOCK_SRCS_) - $(create_bin) - $(CXX) -I$(GTEST_DIR) -I$(GMOCK_DIR) \ - -I$(GMOCK_DIR)/include \ - $(CXXFLAGS) \ - -c $(GMOCK_DIR)/src/gmock-all.cc -o $(OUT_DIR)/$@ - -gmock_main.o : $(GMOCK_SRCS_) - $(create_bin) - $(CXX) -I$(GTEST_DIR) $(CXXFLAGS) \ - -c $(GMOCK_DIR)/src/gmock_main.cc -o $(OUT_DIR)/$@ - -gtest.a : gmock-all.o gtest-all.o - $(create_bin) - $(archive_all) - -gtest_main.a : gmock-all.o gtest-all.o gmock_main.o - $(create_bin) - $(archive_all) From c8070dc6f261b2dc5b3b7a93eb8446ac886ce727 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 20:48:17 -0500 Subject: [PATCH 30/84] 1st unit test passed. --- .../{clmctfy.cc => clmctfy_container_api.cc} | 14 +++- clmctfy/clmctfy_container_api_ctest.cc | 74 +++++++++++++++++++ clmctfy/clmctfy_ctest.cc | 45 ----------- .../{status-internal.h => clmctfy_internal.h} | 11 +++ clmctfy/status-c.cc | 2 +- 5 files changed, 99 insertions(+), 47 deletions(-) rename clmctfy/{clmctfy.cc => clmctfy_container_api.cc} (91%) create mode 100644 clmctfy/clmctfy_container_api_ctest.cc delete mode 100644 clmctfy/clmctfy_ctest.cc rename clmctfy/{status-internal.h => clmctfy_internal.h} (83%) diff --git a/clmctfy/clmctfy.cc b/clmctfy/clmctfy_container_api.cc similarity index 91% rename from clmctfy/clmctfy.cc rename to clmctfy/clmctfy_container_api.cc index a0b52d5..48faa60 100644 --- a/clmctfy/clmctfy.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -4,7 +4,7 @@ #include "clmctfy-raw.h" #include "lmctfy.h" #include "util/task/statusor.h" -#include "status-internal.h" +#include "clmctfy_internal.h" #include "lmctfy.pb.h" #include "util/task/codes.pb-c.h" @@ -84,3 +84,15 @@ int lmctfy_container_api_create_container_raw(struct status *s, RETURN_IF_ERROR_PTR(s, statusor, &((*c)->container_)); return STATUS_OK; } + +namespace containers { +namespace lmctfy { +namespace internal { + +ContainerApi *lmctfy_container_api_strip(struct container_api *api) { + return api->container_api_; +} + +} // internal +} // lmctfy +} // containers diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc new file mode 100644 index 0000000..a834e5e --- /dev/null +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -0,0 +1,74 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "clmctfy.h" + +#include "lmctfy_mock.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "util/task/statusor.h" +#include "clmctfy_internal.h" + +using ::testing::NotNull; +using ::testing::Return; +using ::testing::SetArgPointee; +using ::testing::StrictMock; +using ::testing::_; +using ::util::Status; +using ::util::StatusOr; + +namespace containers { +namespace lmctfy { + +StatusOr ContainerApi::New() { + return new StrictMockContainerApi(); +} + +Status ContainerApi::InitMachine(const InitSpec &spec) { + return Status::OK; +} + +class ClmctfyContainerApiTest : public ::testing::Test { + public: + virtual void SetUp() { + container_api_ = NULL; + lmctfy_new_container_api(NULL, &container_api_); + } + + virtual void TearDown() { + lmctfy_delete_container_api(container_api_); + } + protected: + struct container_api *container_api_; + StrictMockContainerApi *GetMockApi(); +}; + +StrictMockContainerApi *ClmctfyContainerApiTest::GetMockApi() { + ContainerApi *capi = internal::lmctfy_container_api_strip(container_api_); + StrictMockContainerApi *mock_api = dynamic_cast(capi); + return mock_api; +} + +TEST_F(ClmctfyContainerApiTest, NewContainerApi) { + StrictMockContainerApi *mock_api = GetMockApi(); + StatusOr statusor_container = StatusOr(new StrictMockContainer("test")); + EXPECT_CALL(*mock_api, Get(_)).WillOnce(Return(statusor_container)); + struct container *c = NULL; + int ret = lmctfy_container_api_get_container(NULL, &c, container_api_, "test"); + EXPECT_EQ(ret, 0); +} + +} // namespace lmctfy +} // namespace containers + diff --git a/clmctfy/clmctfy_ctest.cc b/clmctfy/clmctfy_ctest.cc deleted file mode 100644 index 2c33838..0000000 --- a/clmctfy/clmctfy_ctest.cc +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -#include "lmctfy_mock.h" -#include "gtest/gtest.h" -#include "gmock/gmock.h" -#include "clmctfy.h" -#include "util/task/statusor.h" - -using ::util::Status; -using ::util::StatusOr; - -namespace containers { -namespace lmctfy { - -StatusOr ContainerApi::New() { - return new StrictMockContainerApi(); -} - -Status ContainerApi::InitMachine(const InitSpec &spec) { - return Status::OK; -} - -namespace { - -TEST(ClmctfyTest, NewContainerApi) { - EXPECT_EQ(1, 1); -} - -} // namespace -} // namespace lmctfy -} // namespace containers - diff --git a/clmctfy/status-internal.h b/clmctfy/clmctfy_internal.h similarity index 83% rename from clmctfy/status-internal.h rename to clmctfy/clmctfy_internal.h index 9533667..294f0f8 100644 --- a/clmctfy/status-internal.h +++ b/clmctfy/clmctfy_internal.h @@ -5,6 +5,7 @@ #include "clmctfy.h" #include "util/task/status.h" #include "util/task/statusor.h" +#include "lmctfy.h" #define RETURN_IF_ERROR_PTR(s, ...) \ do { \ @@ -24,4 +25,14 @@ int status_copy(struct status *dst, const Status &src); } // namespace internal } // namespace util +namespace containers { +namespace lmctfy { +namespace internal { + +ContainerApi *lmctfy_container_api_strip(struct container_api *api); + +} // internal +} // lmctfy +} // containers + #endif // LMCTFY_C_BINDING_STATUS_INTERNAL_H_ diff --git a/clmctfy/status-c.cc b/clmctfy/status-c.cc index f25b6d7..1fc3599 100644 --- a/clmctfy/status-c.cc +++ b/clmctfy/status-c.cc @@ -1,7 +1,7 @@ #include // to use strdup #include "clmctfy.h" -#include "status-internal.h" +#include "clmctfy_internal.h" #include "util/task/status.h" using ::util::Status; From f71c51859ad2bfa874505be541f1de9e6494ebc5 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 20:59:11 -0500 Subject: [PATCH 31/84] refined the test case. --- clmctfy/clmctfy_container_api.cc | 4 ++++ clmctfy/clmctfy_container_api_ctest.cc | 10 +++++++--- clmctfy/clmctfy_internal.h | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index 48faa60..1a7024a 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -93,6 +93,10 @@ ContainerApi *lmctfy_container_api_strip(struct container_api *api) { return api->container_api_; } +Container *lmctfy_container_strip(struct container *c) { + return c->container_; +} + } // internal } // lmctfy } // containers diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index a834e5e..ec1a0e6 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -60,13 +60,17 @@ StrictMockContainerApi *ClmctfyContainerApiTest::GetMockApi() { return mock_api; } -TEST_F(ClmctfyContainerApiTest, NewContainerApi) { +TEST_F(ClmctfyContainerApiTest, GetContainer) { StrictMockContainerApi *mock_api = GetMockApi(); - StatusOr statusor_container = StatusOr(new StrictMockContainer("test")); + const char *container_name = "test"; + Container *ctnr = new StrictMockContainer(container_name); + StatusOr statusor_container = StatusOr(ctnr); EXPECT_CALL(*mock_api, Get(_)).WillOnce(Return(statusor_container)); struct container *c = NULL; - int ret = lmctfy_container_api_get_container(NULL, &c, container_api_, "test"); + int ret = lmctfy_container_api_get_container(NULL, &c, container_api_, container_name); EXPECT_EQ(ret, 0); + Container *ctnr_2 = internal::lmctfy_container_strip(c); + EXPECT_EQ(ctnr_2, ctnr); } } // namespace lmctfy diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index 294f0f8..c094b09 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -30,6 +30,7 @@ namespace lmctfy { namespace internal { ContainerApi *lmctfy_container_api_strip(struct container_api *api); +Container *lmctfy_container_strip(struct container *container); } // internal } // lmctfy From aed27270e89fe96a204362b5c311c2508bd4a964 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 21:19:15 -0500 Subject: [PATCH 32/84] unit test for create_container() --- clmctfy/clmctfy_container_api.cc | 19 +++++++++++++++++++ clmctfy/clmctfy_container_api_ctest.cc | 14 ++++++++++++++ clmctfy/include/clmctfy.h | 7 +++++++ 3 files changed, 40 insertions(+) diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index 1a7024a..42af220 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -32,6 +32,7 @@ int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_s int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec) { size_t sz = containers__lmctfy__init_spec__get_packed_size(spec); + // TODO(monnand) Can we use alloca(3) here, so that we don't need to use heap? uint8_t *buf = new uint8_t[sz]; int ret = 0; containers__lmctfy__init_spec__pack(spec, buf); @@ -85,6 +86,24 @@ int lmctfy_container_api_create_container_raw(struct status *s, return STATUS_OK; } +int lmctfy_container_api_create_container(struct status *s, + struct container **c, + struct container_api *api, + const char *container_name, + const Containers__Lmctfy__ContainerSpec *spec) { + *c = new container(); + (*c)->container_ = NULL; + + size_t sz = containers__lmctfy__container_spec__get_packed_size(spec); + uint8_t *buf = new uint8_t[sz]; + + int ret = 0; + containers__lmctfy__container_spec__pack(spec, buf); + ret = lmctfy_container_api_create_container_raw(s, c, api, container_name, buf, sz); + delete []buf; + return ret; +} + namespace containers { namespace lmctfy { namespace internal { diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index ec1a0e6..01379ae 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -73,6 +73,20 @@ TEST_F(ClmctfyContainerApiTest, GetContainer) { EXPECT_EQ(ctnr_2, ctnr); } +TEST_F(ClmctfyContainerApiTest, CreateContainer) { + StrictMockContainerApi *mock_api = GetMockApi(); + const char *container_name = "test"; + Container *ctnr = new StrictMockContainer(container_name); + StatusOr statusor_container = StatusOr(ctnr); + EXPECT_CALL(*mock_api, Create(_, _)).WillOnce(Return(statusor_container)); + struct container *c = NULL; + Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; + int ret = lmctfy_container_api_create_container(NULL, &c, container_api_, container_name, &spec); + EXPECT_EQ(ret, 0); + Container *ctnr_2 = internal::lmctfy_container_strip(c); + EXPECT_EQ(ctnr_2, ctnr); +} + } // namespace lmctfy } // namespace containers diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 29d647e..26310bc 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -62,6 +62,13 @@ int lmctfy_container_api_get_container( const struct container_api *api, const char *container_name); +int lmctfy_container_api_create_container( + struct status *s, + struct container **container, + struct container_api *api, + const char *container_name, + const Containers__Lmctfy__ContainerSpec *spec); + #ifdef __cplusplus } #endif // __cplusplus From 03a2372d64fc43061301cdfb709584ce8aba1176 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 21:33:16 -0500 Subject: [PATCH 33/84] Delete container on tear down. --- clmctfy/clmctfy_container_api.cc | 12 ++++++++++++ clmctfy/clmctfy_container_api_ctest.cc | 3 +++ clmctfy/include/clmctfy.h | 4 ++++ 3 files changed, 19 insertions(+) diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index 42af220..b27419a 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -104,6 +104,18 @@ int lmctfy_container_api_create_container(struct status *s, return ret; } +int lmctfy_container_api_destroy_container(struct status *s, + struct container_api *api, + struct container *c) { + int ret = STATUS_OK; + if (c != NULL && c->container_ != NULL) { + Status status = api->container_api_->Destroy(c->container_); + ret = status_copy(s, status); + delete c; + } + return ret; +} + namespace containers { namespace lmctfy { namespace internal { diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index 01379ae..5bb9124 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -43,14 +43,17 @@ class ClmctfyContainerApiTest : public ::testing::Test { public: virtual void SetUp() { container_api_ = NULL; + container_ = NULL; lmctfy_new_container_api(NULL, &container_api_); } virtual void TearDown() { + lmctfy_container_api_destroy_container(NULL, container_api_, container_); lmctfy_delete_container_api(container_api_); } protected: struct container_api *container_api_; + struct container *container_; StrictMockContainerApi *GetMockApi(); }; diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 26310bc..82ee082 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -69,6 +69,10 @@ int lmctfy_container_api_create_container( const char *container_name, const Containers__Lmctfy__ContainerSpec *spec); +int lmctfy_container_api_destroy_container(struct status *s, + struct container_api *api, + struct container *container); + #ifdef __cplusplus } #endif // __cplusplus From 193e0351272a57de5474999679bf5347569de1e2 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 22:05:44 -0500 Subject: [PATCH 34/84] destroy() container in tear down. --- clmctfy/clmctfy_container_api_ctest.cc | 42 ++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index 5bb9124..ef7ef53 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -55,6 +55,7 @@ class ClmctfyContainerApiTest : public ::testing::Test { struct container_api *container_api_; struct container *container_; StrictMockContainerApi *GetMockApi(); + StrictMockContainer *GetMockContainer(); }; StrictMockContainerApi *ClmctfyContainerApiTest::GetMockApi() { @@ -63,16 +64,25 @@ StrictMockContainerApi *ClmctfyContainerApiTest::GetMockApi() { return mock_api; } +StrictMockContainer *ClmctfyContainerApiTest::GetMockContainer() { + Container *ctnr = internal::lmctfy_container_strip(container_); + StrictMockContainer *mock_container = dynamic_cast(ctnr); + return mock_container; +} + TEST_F(ClmctfyContainerApiTest, GetContainer) { StrictMockContainerApi *mock_api = GetMockApi(); const char *container_name = "test"; Container *ctnr = new StrictMockContainer(container_name); StatusOr statusor_container = StatusOr(ctnr); + EXPECT_CALL(*mock_api, Get(_)).WillOnce(Return(statusor_container)); - struct container *c = NULL; - int ret = lmctfy_container_api_get_container(NULL, &c, container_api_, container_name); + EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); + + int ret = lmctfy_container_api_get_container(NULL, &container_, container_api_, container_name); + EXPECT_EQ(ret, 0); - Container *ctnr_2 = internal::lmctfy_container_strip(c); + Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); } @@ -81,15 +91,35 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { const char *container_name = "test"; Container *ctnr = new StrictMockContainer(container_name); StatusOr statusor_container = StatusOr(ctnr); + EXPECT_CALL(*mock_api, Create(_, _)).WillOnce(Return(statusor_container)); - struct container *c = NULL; + EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); + Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; - int ret = lmctfy_container_api_create_container(NULL, &c, container_api_, container_name, &spec); + int ret = lmctfy_container_api_create_container(NULL, &container_, container_api_, container_name, &spec); + EXPECT_EQ(ret, 0); - Container *ctnr_2 = internal::lmctfy_container_strip(c); + Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); } +TEST_F(ClmctfyContainerApiTest, DestroyContainer) { + StrictMockContainerApi *mock_api = GetMockApi(); + const char *container_name = "test"; + Container *ctnr = new StrictMockContainer(container_name); + StatusOr statusor_container = StatusOr(ctnr); + + EXPECT_CALL(*mock_api, Get(_)).WillOnce(Return(statusor_container)); + EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); + + int ret = lmctfy_container_api_get_container(NULL, &container_, container_api_, container_name); + + EXPECT_EQ(ret, 0); + ret = lmctfy_container_api_destroy_container(NULL, container_api_, container_); + container_ = NULL; + EXPECT_EQ(ret, 0); +} + } // namespace lmctfy } // namespace containers From 3610cd61aba425d86476026f403e1d43dfbdd8f9 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 22:18:11 -0500 Subject: [PATCH 35/84] test container name in unit test. --- clmctfy/clmctfy_container_api_ctest.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index ef7ef53..8e07688 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -19,6 +19,7 @@ #include "gmock/gmock.h" #include "util/task/statusor.h" #include "clmctfy_internal.h" +#include "strings/stringpiece.h" using ::testing::NotNull; using ::testing::Return; @@ -76,7 +77,7 @@ TEST_F(ClmctfyContainerApiTest, GetContainer) { Container *ctnr = new StrictMockContainer(container_name); StatusOr statusor_container = StatusOr(ctnr); - EXPECT_CALL(*mock_api, Get(_)).WillOnce(Return(statusor_container)); + EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor_container)); EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); int ret = lmctfy_container_api_get_container(NULL, &container_, container_api_, container_name); @@ -92,7 +93,7 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { Container *ctnr = new StrictMockContainer(container_name); StatusOr statusor_container = StatusOr(ctnr); - EXPECT_CALL(*mock_api, Create(_, _)).WillOnce(Return(statusor_container)); + EXPECT_CALL(*mock_api, Create(StringPiece(container_name), _)).WillOnce(Return(statusor_container)); EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; @@ -109,7 +110,7 @@ TEST_F(ClmctfyContainerApiTest, DestroyContainer) { Container *ctnr = new StrictMockContainer(container_name); StatusOr statusor_container = StatusOr(ctnr); - EXPECT_CALL(*mock_api, Get(_)).WillOnce(Return(statusor_container)); + EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor_container)); EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); int ret = lmctfy_container_api_get_container(NULL, &container_, container_api_, container_name); From 8225bc7ff274cfbd52c4d57f037e2945a4218013 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 22:50:14 -0500 Subject: [PATCH 36/84] detect container: impl & test. --- clmctfy/clmctfy_container_api.cc | 14 +++++++++++++ clmctfy/clmctfy_container_api_ctest.cc | 21 ++++++++++++++++++++ clmctfy/include/clmctfy.h | 27 +++++++++++++++++++++++--- 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index b27419a..4bbdc80 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -116,6 +116,20 @@ int lmctfy_container_api_destroy_container(struct status *s, return ret; } +int lmctfy_container_api_detect_container(struct status *s, + char *container_name, + size_t n, + struct container_api *api, + pid_t pid) { + int ret = STATUS_OK; + StatusOr statusor = api->container_api_->Detect(pid); + ret = status_copy(s, statusor.status()); + if (container_name != NULL && statusor.ok() && n > 0) { + strncpy(container_name, statusor.ValueOrDie().c_str(), n); + } + return ret; +} + namespace containers { namespace lmctfy { namespace internal { diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index 8e07688..d7fbcc0 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -121,6 +121,27 @@ TEST_F(ClmctfyContainerApiTest, DestroyContainer) { EXPECT_EQ(ret, 0); } +#define MAX_CONTAINER_NAME_LEN 512 + +TEST_F(ClmctfyContainerApiTest, DetectContainer) { + StrictMockContainerApi *mock_api = GetMockApi(); + const char *container_name = "test"; + char output_name[MAX_CONTAINER_NAME_LEN]; + pid_t pid = 10; + container_ = NULL; + + memset(output_name, 0, MAX_CONTAINER_NAME_LEN); + + StatusOr statusor = StatusOr(container_name); + + EXPECT_CALL(*mock_api, Detect(pid)).WillOnce(Return(statusor)); + + int ret = lmctfy_container_api_detect_container(NULL, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); + + EXPECT_EQ(ret, 0); + EXPECT_EQ(string(container_name), string(output_name)); +} + } // namespace lmctfy } // namespace containers diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 82ee082..81be161 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -1,5 +1,7 @@ #ifndef LMCTFY_C_BINDING_LMCTFY_C_H_ #define LMCTFY_C_BINDING_LMCTFY_C_H_ + +#include #include "lmctfy.pb-c.h" #ifdef __cplusplus @@ -25,7 +27,7 @@ struct container_api; // // Returns: // Returns the error code. 0 on success. The return code is same as -// status_get_code(s). +// s->error_code when s is not NULL. int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec); // Create a new container_api. @@ -37,7 +39,7 @@ int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *sp // // Returns: // Returns the error code. 0 on success. The return code is same as -// status_get_code(s). +// s->error_code when s is not NULL. int lmctfy_new_container_api(struct status *s, struct container_api **api); // Release the container api. @@ -55,13 +57,26 @@ void lmctfy_delete_container_api(struct container_api *api); // // Returns: // Returns the error code. 0 on success. The return code is same as -// status_get_code(s). +// s->error_code when s is not NULL. int lmctfy_container_api_get_container( struct status *s, struct container **container, const struct container_api *api, const char *container_name); +// Create a container +// +// Arguments: +// +// - s: [output] s will be used as output. It contains the error code/message. +// - container: [output] The address of a pointer to struct container. It will +// - api: A container api. +// - container_name: the container name. +// - spec: container specification. +// +// Returns: +// Returns the error code. 0 on success. The return code is same as +// s->error_code when s is not NULL. int lmctfy_container_api_create_container( struct status *s, struct container **container, @@ -73,6 +88,12 @@ int lmctfy_container_api_destroy_container(struct status *s, struct container_api *api, struct container *container); +int lmctfy_container_api_detect_container(struct status *s, + char *container_name, + size_t n, + struct container_api *api, + pid_t pid); + #ifdef __cplusplus } #endif // __cplusplus From 523c4189b51d968cacc0f30fb0ed2a70c3c46b3f Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 22:59:34 -0500 Subject: [PATCH 37/84] move struct def into internal.h --- clmctfy/clmctfy_container_api.cc | 8 -------- clmctfy/clmctfy_internal.h | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index 4bbdc80..983dd6b 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -15,14 +15,6 @@ using ::util::internal::status_copy; using ::util::Status; using ::util::StatusOr; -struct container { - Container *container_; -}; - -struct container_api { - ContainerApi *container_api_; -}; - int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_size) { InitSpec init_spec; init_spec.ParseFromArray(spec, spec_size); diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index c094b09..1676962 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -7,6 +7,25 @@ #include "util/task/statusor.h" #include "lmctfy.h" +using ::containers::lmctfy::Container; +using ::containers::lmctfy::ContainerApi; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +struct container { + Container *container_; +}; + +struct container_api { + ContainerApi *container_api_; +}; + +#ifdef __cplusplus +} +#endif // __cplusplus + #define RETURN_IF_ERROR_PTR(s, ...) \ do { \ const ::util::Status _status = \ From 16b18e445363ac60b73893ec410cbfd2e0b4ffe9 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 27 Jan 2014 23:52:37 -0500 Subject: [PATCH 38/84] add unit tests on failure. --- clmctfy/clmctfy_container_api.cc | 22 +++-- clmctfy/clmctfy_container_api_ctest.cc | 116 +++++++++++++++++++++++-- clmctfy/clmctfy_internal.h | 1 + clmctfy/include/clmctfy.h | 37 +++++--- 4 files changed, 150 insertions(+), 26 deletions(-) diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index 983dd6b..b603505 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -50,15 +50,22 @@ void lmctfy_delete_container_api(struct container_api *api) { } } +#define COPY_CONTAINER_STRUCTURE(ctnr_ptr, ctnr_struct) do { \ + if ((ctnr_ptr) != NULL) { \ + (*(ctnr_struct)) = new container(); \ + (*(ctnr_struct))->container_ = ctnr_ptr; \ + } \ +} while(0) + int lmctfy_container_api_get_container(struct status *s, struct container **c, const struct container_api *api, const char *container_name) { - *c = new container(); - (*c)->container_ = NULL; + Container *ctnr = NULL; StatusOr statusor = api->container_api_->Get(container_name); - RETURN_IF_ERROR_PTR(s, statusor, &((*c)->container_)); + RETURN_IF_ERROR_PTR(s, statusor, &ctnr); + COPY_CONTAINER_STRUCTURE(ctnr, c); return STATUS_OK; } @@ -69,12 +76,12 @@ int lmctfy_container_api_create_container_raw(struct status *s, const void *spec, const int spec_size) { ContainerSpec container_spec; - *c = new container(); - (*c)->container_ = NULL; + Container *ctnr = NULL; container_spec.ParseFromArray(spec, spec_size); StatusOr statusor = api->container_api_->Create(container_name, container_spec); - RETURN_IF_ERROR_PTR(s, statusor, &((*c)->container_)); + RETURN_IF_ERROR_PTR(s, statusor, &ctnr); + COPY_CONTAINER_STRUCTURE(ctnr, c); return STATUS_OK; } @@ -83,9 +90,6 @@ int lmctfy_container_api_create_container(struct status *s, struct container_api *api, const char *container_name, const Containers__Lmctfy__ContainerSpec *spec) { - *c = new container(); - (*c)->container_ = NULL; - size_t sz = containers__lmctfy__container_spec__get_packed_size(spec); uint8_t *buf = new uint8_t[sz]; diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index d7fbcc0..d177ba2 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -80,13 +80,37 @@ TEST_F(ClmctfyContainerApiTest, GetContainer) { EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor_container)); EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); - int ret = lmctfy_container_api_get_container(NULL, &container_, container_api_, container_name); + struct status s = {0, NULL}; + int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); EXPECT_EQ(ret, 0); + EXPECT_EQ(s.error_code, 0); + EXPECT_EQ(s.message, NULL); Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); } +TEST_F(ClmctfyContainerApiTest, GetContainerFail) { + StrictMockContainerApi *mock_api = GetMockApi(); + const char *container_name = "test"; + string errmsg = "some error message"; + Status status = Status(::util::error::INTERNAL, errmsg); + StatusOr statusor = StatusOr(status); + + EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor)); + + container_ = NULL; + struct status s = {0, NULL}; + int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); + + EXPECT_EQ(ret, ::util::error::INTERNAL); + EXPECT_EQ(s.error_code, ::util::error::INTERNAL); + EXPECT_EQ(container_, NULL); + EXPECT_EQ(errmsg, s.message); + free(s.message); +} + + TEST_F(ClmctfyContainerApiTest, CreateContainer) { StrictMockContainerApi *mock_api = GetMockApi(); const char *container_name = "test"; @@ -97,13 +121,36 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; - int ret = lmctfy_container_api_create_container(NULL, &container_, container_api_, container_name, &spec); + struct status s = {0, NULL}; + int ret = lmctfy_container_api_create_container(&s, &container_, container_api_, container_name, &spec); EXPECT_EQ(ret, 0); + EXPECT_EQ(s.error_code, 0); + EXPECT_EQ(s.message, NULL); Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); } +TEST_F(ClmctfyContainerApiTest, CreateContainerFail) { + StrictMockContainerApi *mock_api = GetMockApi(); + const char *container_name = "test"; + string errmsg = "some error message"; + Status status = Status(::util::error::INTERNAL, errmsg); + StatusOr statusor = StatusOr(status); + + EXPECT_CALL(*mock_api, Create(StringPiece(container_name), _)).WillOnce(Return(statusor)); + + Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; + struct status s = {0, NULL}; + int ret = lmctfy_container_api_create_container(&s, &container_, container_api_, container_name, &spec); + + EXPECT_EQ(ret, ::util::error::INTERNAL); + EXPECT_EQ(s.error_code, ::util::error::INTERNAL); + EXPECT_EQ(container_, NULL); + EXPECT_EQ(errmsg, s.message); + free(s.message); +} + TEST_F(ClmctfyContainerApiTest, DestroyContainer) { StrictMockContainerApi *mock_api = GetMockApi(); const char *container_name = "test"; @@ -113,12 +160,44 @@ TEST_F(ClmctfyContainerApiTest, DestroyContainer) { EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor_container)); EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); - int ret = lmctfy_container_api_get_container(NULL, &container_, container_api_, container_name); + struct status s = {0, NULL}; + int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); EXPECT_EQ(ret, 0); - ret = lmctfy_container_api_destroy_container(NULL, container_api_, container_); + EXPECT_EQ(s.error_code, 0); + EXPECT_EQ(s.message, NULL); + + ret = lmctfy_container_api_destroy_container(&s, container_api_, container_); container_ = NULL; EXPECT_EQ(ret, 0); + EXPECT_EQ(s.error_code, 0); + EXPECT_EQ(s.message, NULL); +} + +TEST_F(ClmctfyContainerApiTest, DestroyContainerFail) { + StrictMockContainerApi *mock_api = GetMockApi(); + const char *container_name = "test"; + Container *ctnr = new StrictMockContainer(container_name); + StatusOr statusor_container = StatusOr(ctnr); + + string errmsg = "some error message"; + Status destroy_status = Status(::util::error::INTERNAL, errmsg); + + EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor_container)); + EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(destroy_status)); + + struct status s = {0, NULL}; + int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); + + EXPECT_EQ(ret, 0); + EXPECT_EQ(s.error_code, 0); + EXPECT_EQ(s.message, NULL); + + ret = lmctfy_container_api_destroy_container(&s, container_api_, container_); + container_ = NULL; + EXPECT_EQ(ret, ::util::error::INTERNAL); + EXPECT_EQ(s.error_code, ::util::error::INTERNAL); + EXPECT_EQ(errmsg, s.message); } #define MAX_CONTAINER_NAME_LEN 512 @@ -136,12 +215,39 @@ TEST_F(ClmctfyContainerApiTest, DetectContainer) { EXPECT_CALL(*mock_api, Detect(pid)).WillOnce(Return(statusor)); - int ret = lmctfy_container_api_detect_container(NULL, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); + struct status s = {0, NULL}; + int ret = lmctfy_container_api_detect_container(&s, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); EXPECT_EQ(ret, 0); + EXPECT_EQ(s.error_code, 0); + EXPECT_EQ(s.message, NULL); EXPECT_EQ(string(container_name), string(output_name)); } +TEST_F(ClmctfyContainerApiTest, DetectContainerFail) { + StrictMockContainerApi *mock_api = GetMockApi(); + const char *container_name = "test"; + char output_name[MAX_CONTAINER_NAME_LEN]; + pid_t pid = 10; + container_ = NULL; + + memset(output_name, 0, MAX_CONTAINER_NAME_LEN); + + string errmsg = "some error message"; + Status status = Status(::util::error::INTERNAL, errmsg); + StatusOr statusor = StatusOr(status); + + EXPECT_CALL(*mock_api, Detect(pid)).WillOnce(Return(statusor)); + + struct status s = {0, NULL}; + int ret = lmctfy_container_api_detect_container(&s, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); + + EXPECT_EQ(ret, status.error_code()); + EXPECT_EQ(s.error_code, status.error_code()); + EXPECT_EQ(errmsg, s.message); + EXPECT_EQ(*output_name, '\0'); +} + } // namespace lmctfy } // namespace containers diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index 1676962..1c076dd 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -11,6 +11,7 @@ using ::containers::lmctfy::Container; using ::containers::lmctfy::ContainerApi; #ifdef __cplusplus +// XXX(monnand): Do we need to extern "C"? extern "C" { #endif // __cplusplus diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 81be161..e009ede 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -8,6 +8,11 @@ extern "C" { #endif // __cplusplus +enum update_policy { + UPDATE_POLICY_DIFF, + UPDATE_POLICY_REPLACE +}; + struct status { int error_code; @@ -22,24 +27,28 @@ struct container_api; // Initializes the machine to start being able to create containers. // // Arguments: -// - s: [output] s will be used as output. It contains the error code/message. +// - s: [output] s will be used as output. s will not be changed on success; +// Otherwise it contains the error code and message. // - spec: The specification. // // Returns: -// Returns the error code. 0 on success. The return code is same as -// s->error_code when s is not NULL. +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec); // Create a new container_api. // // Arguments: -// - s: [output] s will be used as output. It contains the error code/message. +// - s: [output] s will be used as output. s will not be changed on success; +// Otherwise it contains the error code and message. // - api: [output] The address of a pointer to struct container_api. The // pointer of the container api will be stored in this address. // // Returns: -// Returns the error code. 0 on success. The return code is same as -// s->error_code when s is not NULL. +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_new_container_api(struct status *s, struct container_api **api); // Release the container api. @@ -49,15 +58,17 @@ void lmctfy_delete_container_api(struct container_api *api); // // Arguments: // -// - s: [output] s will be used as output. It contains the error code/message. +// - s: [output] s will be used as output. s will not be changed on success; +// Otherwise it contains the error code and message. // - container: [output] The address of a pointer to struct container. It will // be used to store the pointer to the container. // - api: A container api. // - container_name: the container name. // // Returns: -// Returns the error code. 0 on success. The return code is same as -// s->error_code when s is not NULL. +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_api_get_container( struct status *s, struct container **container, @@ -68,15 +79,17 @@ int lmctfy_container_api_get_container( // // Arguments: // -// - s: [output] s will be used as output. It contains the error code/message. +// - s: [output] s will be used as output. s will not be changed on success; +// Otherwise it contains the error code and message. // - container: [output] The address of a pointer to struct container. It will // - api: A container api. // - container_name: the container name. // - spec: container specification. // // Returns: -// Returns the error code. 0 on success. The return code is same as -// s->error_code when s is not NULL. +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_api_create_container( struct status *s, struct container **container, From 20fe25d9edc2ef9cc68c7ec62d7d48d8bb168d9e Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 28 Jan 2014 01:40:55 -0500 Subject: [PATCH 39/84] unit test for container exec(). --- clmctfy/clmctfy_container.cc | 46 +++++++++++ clmctfy/clmctfy_container_api.cc | 2 +- clmctfy/clmctfy_container_api_ctest.cc | 4 +- clmctfy/clmctfy_container_ctest.cc | 109 +++++++++++++++++++++++++ clmctfy/clmctfy_internal.h | 1 + clmctfy/include/clmctfy.h | 39 ++++++++- clmctfy/status-c.cc | 11 +++ 7 files changed, 206 insertions(+), 6 deletions(-) create mode 100644 clmctfy/clmctfy_container.cc create mode 100644 clmctfy/clmctfy_container_ctest.cc diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc new file mode 100644 index 0000000..efec2e0 --- /dev/null +++ b/clmctfy/clmctfy_container.cc @@ -0,0 +1,46 @@ +#include "clmctfy.h" +#include "lmctfy.h" +#include "clmctfy_internal.h" +#include "util/task/statusor.h" +#include + +using namespace ::containers::lmctfy; +using ::util::internal::status_copy; +using ::util::internal::status_new; +using ::util::Status; +using ::util::StatusOr; +using ::util::error::INVALID_ARGUMENT; +using ::std::vector; + +#define STATUS_OK UTIL__ERROR__CODE__OK + +int lmctfy_container_exec(struct status *s, + struct container *container, + const int argc, + const char **argv) { + int ret = STATUS_OK; + if (container == NULL) { + return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "exec: null pointer to container"); + } + if (argc <= 0) { + return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "exec: no enough arugment to run a command"); + } + + vector cmds(argc); + int i = 0; + for (i = 0; i < argc; i++) { + cmds[i] = argv[i]; + } + + Status status = container->container_->Exec(cmds); + return status_copy(s, status); +} + +void lmctfy_delete_container(struct container *container) { + if (container != NULL) { + if (container->container_ != NULL) { + delete container->container_; + } + delete container; + } +} diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index b603505..eb3f67c 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -114,7 +114,7 @@ int lmctfy_container_api_destroy_container(struct status *s, int lmctfy_container_api_detect_container(struct status *s, char *container_name, - size_t n, + const size_t n, struct container_api *api, pid_t pid) { int ret = STATUS_OK; diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index d177ba2..80a1486 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -49,8 +49,8 @@ class ClmctfyContainerApiTest : public ::testing::Test { } virtual void TearDown() { - lmctfy_container_api_destroy_container(NULL, container_api_, container_); lmctfy_delete_container_api(container_api_); + lmctfy_delete_container(container_); } protected: struct container_api *container_api_; @@ -78,7 +78,6 @@ TEST_F(ClmctfyContainerApiTest, GetContainer) { StatusOr statusor_container = StatusOr(ctnr); EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor_container)); - EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); struct status s = {0, NULL}; int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); @@ -118,7 +117,6 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { StatusOr statusor_container = StatusOr(ctnr); EXPECT_CALL(*mock_api, Create(StringPiece(container_name), _)).WillOnce(Return(statusor_container)); - EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; struct status s = {0, NULL}; diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc new file mode 100644 index 0000000..9bf37c7 --- /dev/null +++ b/clmctfy/clmctfy_container_ctest.cc @@ -0,0 +1,109 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "clmctfy.h" + +#include "lmctfy_mock.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "util/task/statusor.h" +#include "clmctfy_internal.h" +#include "strings/stringpiece.h" + +using ::testing::NotNull; +using ::testing::Return; +using ::testing::SetArgPointee; +using ::testing::StrictMock; +using ::testing::_; +using ::util::Status; +using ::util::StatusOr; +using ::std::vector; + +namespace containers { +namespace lmctfy { + +StatusOr ContainerApi::New() { + return new StrictMockContainerApi(); +} + +Status ContainerApi::InitMachine(const InitSpec &spec) { + return Status::OK; +} + +class ClmctfyContainerTest : public ::testing::Test { + public: + virtual void SetUp() { + container_api_ = NULL; + container_ = NULL; + const char *container_name = "test"; + lmctfy_new_container_api(NULL, &container_api_); + StrictMockContainerApi *mock_api = GetMockApi(); + Container *ctnr = new StrictMockContainer(container_name); + StatusOr statusor = StatusOr(ctnr); + EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor)); + + lmctfy_container_api_get_container(NULL, + &container_, + container_api_, + container_name); + } + + virtual void TearDown() { + lmctfy_delete_container_api(container_api_); + lmctfy_delete_container(container_); + } + protected: + struct container_api *container_api_; + struct container *container_; + StrictMockContainerApi *GetMockApi(); + StrictMockContainer *GetMockContainer(); +}; + +StrictMockContainerApi *ClmctfyContainerTest::GetMockApi() { + ContainerApi *capi = internal::lmctfy_container_api_strip(container_api_); + StrictMockContainerApi *mock_api = dynamic_cast(capi); + return mock_api; +} + +StrictMockContainer *ClmctfyContainerTest::GetMockContainer() { + Container *ctnr = internal::lmctfy_container_strip(container_); + StrictMockContainer *mock_container = dynamic_cast(ctnr); + return mock_container; +} + + +TEST_F(ClmctfyContainerTest, ExecSuccess) { + StrictMockContainer *mock_container = GetMockContainer(); + int argc = 2; + const char *argv[] = {"echo", "hello world"}; + vector cmds(argc); + + for (int i = 0; i < argc; i++) { + cmds[i] = argv[i]; + } + + EXPECT_CALL(*mock_container, Exec(cmds)).WillOnce(Return(Status::OK)); + + struct status s = {0, NULL}; + int ret = lmctfy_container_exec(&s, container_, argc, argv); + + EXPECT_EQ(ret, 0); + EXPECT_EQ(s.error_code, 0); + EXPECT_EQ(s.message, NULL); +} + +} // namespace lmctfy +} // namespace containers diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index 1c076dd..bde0f49 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -40,6 +40,7 @@ struct container_api { namespace util { namespace internal { +int status_new(struct status *dst, int code, const char *message); int status_copy(struct status *dst, const Status &src); } // namespace internal diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index e009ede..c489384 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -3,6 +3,7 @@ #include #include "lmctfy.pb-c.h" +#include "util/task/codes.pb-c.h" #ifdef __cplusplus extern "C" { @@ -51,7 +52,12 @@ int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *sp // is same as s->error_code when s is not NULL. int lmctfy_new_container_api(struct status *s, struct container_api **api); -// Release the container api. +// Release the container api. +// +// Arguments: +// +// - api: The container api. This pointer will be invalid after the call to +// this function void lmctfy_delete_container_api(struct container_api *api); // Get a container @@ -82,6 +88,7 @@ int lmctfy_container_api_get_container( // - s: [output] s will be used as output. s will not be changed on success; // Otherwise it contains the error code and message. // - container: [output] The address of a pointer to struct container. It will +// be used to store the newly created container. // - api: A container api. // - container_name: the container name. // - spec: container specification. @@ -97,16 +104,44 @@ int lmctfy_container_api_create_container( const char *container_name, const Containers__Lmctfy__ContainerSpec *spec); +// Destroy a container +// +// Arguments: +// +// - s: [output] s will be used as output. s will not be changed on success; +// Otherwise it contains the error code and message. +// - api: A container api. +// - container: The pointer to struct container. The pointer will become +// invalid after a success destroy(). +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_api_destroy_container(struct status *s, struct container_api *api, struct container *container); int lmctfy_container_api_detect_container(struct status *s, char *container_name, - size_t n, + const size_t n, struct container_api *api, pid_t pid); +// Release the memory used by the container structure. The refered container +// will not be affected. +// +// Arguments: +// +// - container: The container. This pointer will be invalid after the call to +// this function +void lmctfy_delete_container(struct container *container); + +int lmctfy_container_exec(struct status *s, + struct container *container, + const int argc, + const char **argv); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/clmctfy/status-c.cc b/clmctfy/status-c.cc index 1fc3599..464a9f4 100644 --- a/clmctfy/status-c.cc +++ b/clmctfy/status-c.cc @@ -9,6 +9,17 @@ using ::util::Status; namespace util { namespace internal { +int status_new(struct status *dst, int code, const char *message) { + if (dst == NULL) { + return code; + } + dst->error_code = code; + if (message != NULL && code != 0) { + dst->message = strdup(message); + } + return code; +} + int status_copy(struct status *dst, const Status &src) { if (dst == NULL) { return (int)src.error_code(); From 9d3a12cba7fe96cf53ba4cadcf998c312bbec79d Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 28 Jan 2014 16:01:13 -0500 Subject: [PATCH 40/84] Check the parameters. --- clmctfy/clmctfy_container.cc | 8 ++--- clmctfy/clmctfy_container_api.cc | 49 ++++++++++++++++++++------ clmctfy/clmctfy_container_api_ctest.cc | 3 +- clmctfy/clmctfy_internal.h | 18 +++++++++- clmctfy/include/clmctfy-raw.h | 4 +-- clmctfy/status-c.cc | 23 ++++++++++-- 6 files changed, 81 insertions(+), 24 deletions(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index efec2e0..5899a53 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -19,12 +19,8 @@ int lmctfy_container_exec(struct status *s, const int argc, const char **argv) { int ret = STATUS_OK; - if (container == NULL) { - return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "exec: null pointer to container"); - } - if (argc <= 0) { - return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "exec: no enough arugment to run a command"); - } + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_POSITIVE_OR_RETURN(s, argc); vector cmds(argc); int i = 0; diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index eb3f67c..33f0131 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -12,28 +12,39 @@ using namespace ::containers::lmctfy; using ::util::internal::status_copy; +using ::util::internal::status_new; using ::util::Status; using ::util::StatusOr; -int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_size) { +int lmctfy_init_machine_raw(struct status *s, const void *spec, const size_t spec_size) { InitSpec init_spec; - init_spec.ParseFromArray(spec, spec_size); + if (spec != NULL && spec_size > 0) { + // XXX should we consider this as an error? + init_spec.ParseFromArray(spec, spec_size); + } Status v = ContainerApi::InitMachine(init_spec); return status_copy(s, v); } int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec) { - size_t sz = containers__lmctfy__init_spec__get_packed_size(spec); - // TODO(monnand) Can we use alloca(3) here, so that we don't need to use heap? - uint8_t *buf = new uint8_t[sz]; + uint8_t *buf = NULL; + size_t sz = 0; int ret = 0; - containers__lmctfy__init_spec__pack(spec, buf); + + CHECK_NOTNULL_OR_RETURN(s, spec); + sz = containers__lmctfy__init_spec__get_packed_size(spec); + if (sz > 0) { + // TODO(monnand) Can we use alloca(3) here, so that we don't need to use heap? + buf = new uint8_t[sz]; + containers__lmctfy__init_spec__pack(spec, buf); + } ret = lmctfy_init_machine_raw(s, buf, sz); delete []buf; return ret; } int lmctfy_new_container_api(struct status *s, struct container_api **api) { + CHECK_NOTNULL_OR_RETURN(s, api); *api = new container_api(); (*api)->container_api_ = NULL; StatusOr statusor_container_api = ContainerApi::New(); @@ -61,6 +72,8 @@ int lmctfy_container_api_get_container(struct status *s, struct container **c, const struct container_api *api, const char *container_name) { + CHECK_NOTNULL_OR_RETURN(s, api); + CHECK_NOTNULL_OR_RETURN(s, c); Container *ctnr = NULL; StatusOr statusor = api->container_api_->Get(container_name); @@ -74,10 +87,14 @@ int lmctfy_container_api_create_container_raw(struct status *s, struct container_api *api, const char *container_name, const void *spec, - const int spec_size) { + const size_t spec_size) { + CHECK_NOTNULL_OR_RETURN(s, api); + CHECK_NOTNULL_OR_RETURN(s, c); ContainerSpec container_spec; Container *ctnr = NULL; - container_spec.ParseFromArray(spec, spec_size); + if (spec != NULL && spec_size > 0) { + container_spec.ParseFromArray(spec, spec_size); + } StatusOr statusor = api->container_api_->Create(container_name, container_spec); RETURN_IF_ERROR_PTR(s, statusor, &ctnr); @@ -90,10 +107,16 @@ int lmctfy_container_api_create_container(struct status *s, struct container_api *api, const char *container_name, const Containers__Lmctfy__ContainerSpec *spec) { - size_t sz = containers__lmctfy__container_spec__get_packed_size(spec); - uint8_t *buf = new uint8_t[sz]; - + CHECK_NOTNULL_OR_RETURN(s, api); + CHECK_NOTNULL_OR_RETURN(s, c); + CHECK_NOTNULL_OR_RETURN(s, spec); + uint8_t *buf = NULL; + size_t sz = 0; int ret = 0; + sz = containers__lmctfy__container_spec__get_packed_size(spec); + if (sz > 0) { + buf = new uint8_t[sz]; + } containers__lmctfy__container_spec__pack(spec, buf); ret = lmctfy_container_api_create_container_raw(s, c, api, container_name, buf, sz); delete []buf; @@ -103,6 +126,7 @@ int lmctfy_container_api_create_container(struct status *s, int lmctfy_container_api_destroy_container(struct status *s, struct container_api *api, struct container *c) { + CHECK_NOTNULL_OR_RETURN(s, api); int ret = STATUS_OK; if (c != NULL && c->container_ != NULL) { Status status = api->container_api_->Destroy(c->container_); @@ -118,6 +142,9 @@ int lmctfy_container_api_detect_container(struct status *s, struct container_api *api, pid_t pid) { int ret = STATUS_OK; + CHECK_NOTNULL_OR_RETURN(s, api); + CHECK_NOTNULL_OR_RETURN(s, container_name); + CHECK_POSITIVE_OR_RETURN(s, n); StatusOr statusor = api->container_api_->Detect(pid); ret = status_copy(s, statusor.status()); if (container_name != NULL && statusor.ok() && n > 0) { diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index 80a1486..43e6dd6 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -14,6 +14,7 @@ #include "clmctfy.h" +#include "lmctfy.h" #include "lmctfy_mock.h" #include "gtest/gtest.h" #include "gmock/gmock.h" @@ -109,7 +110,6 @@ TEST_F(ClmctfyContainerApiTest, GetContainerFail) { free(s.message); } - TEST_F(ClmctfyContainerApiTest, CreateContainer) { StrictMockContainerApi *mock_api = GetMockApi(); const char *container_name = "test"; @@ -119,6 +119,7 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { EXPECT_CALL(*mock_api, Create(StringPiece(container_name), _)).WillOnce(Return(statusor_container)); Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; + struct status s = {0, NULL}; int ret = lmctfy_container_api_create_container(&s, &container_, container_api_, container_name, &spec); diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index bde0f49..af47b0b 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -37,10 +37,26 @@ struct container_api { } \ } while (0) +#define CHECK_NOTNULL_OR_RETURN(status, ptr) do { \ + if ((ptr) == NULL) { \ + return status_new(status, UTIL__ERROR__CODE__INVALID_ARGUMENT, \ + "In function %s: %s cannot be null", \ + __func__, #ptr); \ + } \ +} while (0) + +#define CHECK_POSITIVE_OR_RETURN(status, value) do { \ + if ((value) <= 0) { \ + return status_new(status, UTIL__ERROR__CODE__INVALID_ARGUMENT, \ + "In function %s: %s=%d, but it should be positive", \ + __func__, #value, value); \ + } \ +} while (0) + namespace util { namespace internal { -int status_new(struct status *dst, int code, const char *message); +int status_new(struct status *dst, int code, const char *fmt, ...); int status_copy(struct status *dst, const Status &src); } // namespace internal diff --git a/clmctfy/include/clmctfy-raw.h b/clmctfy/include/clmctfy-raw.h index 5babbe7..7983e17 100644 --- a/clmctfy/include/clmctfy-raw.h +++ b/clmctfy/include/clmctfy-raw.h @@ -18,7 +18,7 @@ extern "C" { // Returns: // Returns the error code. 0 on success. The return code is same as // status_get_code(s). -int lmctfy_init_machine_raw(struct status *s, const void *spec, const int spec_size); +int lmctfy_init_machine_raw(struct status *s, const void *spec, const size_t spec_size); int lmctfy_container_api_create_container_raw( struct status *s, @@ -26,7 +26,7 @@ int lmctfy_container_api_create_container_raw( struct container_api *api, const char *container_name, const void *spec, - const int spec_size); + const size_t spec_size); #ifdef __cplusplus } diff --git a/clmctfy/status-c.cc b/clmctfy/status-c.cc index 464a9f4..41855a7 100644 --- a/clmctfy/status-c.cc +++ b/clmctfy/status-c.cc @@ -1,4 +1,5 @@ #include // to use strdup +#include #include "clmctfy.h" #include "clmctfy_internal.h" @@ -9,14 +10,30 @@ using ::util::Status; namespace util { namespace internal { -int status_new(struct status *dst, int code, const char *message) { +#define MAXLINE 4096 + +static int status_new_fmt(struct status *dst, int code, const char *fmt, va_list ap) { + char buf[MAXLINE]; if (dst == NULL) { return code; } dst->error_code = code; - if (message != NULL && code != 0) { - dst->message = strdup(message); + + if (fmt == NULL || code == 0) { + return code; } + memset(buf, 0, MAXLINE); + vsnprintf(buf, MAXLINE, fmt, ap); + dst->error_code = code; + dst->message = strdup(buf); + return code; +} + +int status_new(struct status *dst, int code, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + status_new_fmt(dst, code, fmt, ap); + va_end(ap); return code; } From 98dcf248d047b2124b6a865412909364bae44933 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 28 Jan 2014 17:15:27 -0500 Subject: [PATCH 41/84] Invalid argument test for container exec(). --- clmctfy/clmctfy_container.cc | 1 + clmctfy/clmctfy_container_api.cc | 5 ++++ clmctfy/clmctfy_container_ctest.cc | 48 ++++++++++++++++++++++++++++++ clmctfy/include/clmctfy.h | 6 ++-- 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 5899a53..785ec6b 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -20,6 +20,7 @@ int lmctfy_container_exec(struct status *s, const char **argv) { int ret = STATUS_OK; CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); CHECK_POSITIVE_OR_RETURN(s, argc); vector cmds(argc); diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index 33f0131..f68b0f7 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -73,6 +73,7 @@ int lmctfy_container_api_get_container(struct status *s, const struct container_api *api, const char *container_name) { CHECK_NOTNULL_OR_RETURN(s, api); + CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, c); Container *ctnr = NULL; @@ -89,6 +90,7 @@ int lmctfy_container_api_create_container_raw(struct status *s, const void *spec, const size_t spec_size) { CHECK_NOTNULL_OR_RETURN(s, api); + CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, c); ContainerSpec container_spec; Container *ctnr = NULL; @@ -108,6 +110,7 @@ int lmctfy_container_api_create_container(struct status *s, const char *container_name, const Containers__Lmctfy__ContainerSpec *spec) { CHECK_NOTNULL_OR_RETURN(s, api); + CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, c); CHECK_NOTNULL_OR_RETURN(s, spec); uint8_t *buf = NULL; @@ -127,6 +130,7 @@ int lmctfy_container_api_destroy_container(struct status *s, struct container_api *api, struct container *c) { CHECK_NOTNULL_OR_RETURN(s, api); + CHECK_NOTNULL_OR_RETURN(s, api->container_api_); int ret = STATUS_OK; if (c != NULL && c->container_ != NULL) { Status status = api->container_api_->Destroy(c->container_); @@ -143,6 +147,7 @@ int lmctfy_container_api_detect_container(struct status *s, pid_t pid) { int ret = STATUS_OK; CHECK_NOTNULL_OR_RETURN(s, api); + CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, container_name); CHECK_POSITIVE_OR_RETURN(s, n); StatusOr statusor = api->container_api_->Detect(pid); diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 9bf37c7..527272e 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -105,5 +105,53 @@ TEST_F(ClmctfyContainerTest, ExecSuccess) { EXPECT_EQ(s.message, NULL); } +TEST_F(ClmctfyContainerTest, ExecBadArgument) { + StrictMockContainer *mock_container = GetMockContainer(); + + struct status s = {0, NULL}; + int ret = lmctfy_container_exec(&s, container_, 0, NULL); + + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); + + Container *tmp = container_->container_; + container_->container_ = NULL; + s = {0, NULL}; + ret = lmctfy_container_exec(&s, container_, 0, NULL); + container_->container_ = tmp; + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); + + s = {0, NULL}; + ret = lmctfy_container_exec(&s, NULL, 0, NULL); + container_->container_ = tmp; + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); +} + + +TEST_F(ClmctfyContainerTest, ExecFail) { + StrictMockContainer *mock_container = GetMockContainer(); + int argc = 2; + const char *argv[] = {"echo", "hello world"}; + string errmsg = "some error message"; + Status status = Status(::util::error::INTERNAL, errmsg); + vector cmds(argc); + + for (int i = 0; i < argc; i++) { + cmds[i] = argv[i]; + } + + EXPECT_CALL(*mock_container, Exec(cmds)).WillOnce(Return(status)); + + struct status s = {0, NULL}; + int ret = lmctfy_container_exec(&s, container_, argc, argv); + + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, status.error_code()); + EXPECT_EQ(errmsg, s.message); +} + + } // namespace lmctfy } // namespace containers diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index c489384..bbccde7 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -9,9 +9,9 @@ extern "C" { #endif // __cplusplus -enum update_policy { - UPDATE_POLICY_DIFF, - UPDATE_POLICY_REPLACE +enum { + CONTAINER_UPDATE_POLICY_DIFF, + CONTAINER_UPDATE_POLICY_REPLACE }; struct status { From 57659f843d9f089e04d0955358da859eb3612fdf Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 28 Jan 2014 17:15:52 -0500 Subject: [PATCH 42/84] container update() --- clmctfy/clmctfy_container.cc | 48 +++++++++++++++++++++++++++++++++++ clmctfy/include/clmctfy-raw.h | 6 +++++ clmctfy/include/clmctfy.h | 5 ++++ 3 files changed, 59 insertions(+) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 785ec6b..c4ff9f3 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -41,3 +41,51 @@ void lmctfy_delete_container(struct container *container) { delete container; } } + +int lmctfy_container_update_raw(struct status *s, + struct container *container, + int policy, + const void *spec, + const size_t spec_size) { + ContainerSpec container_spec; + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + if (spec != NULL && spec_size > 0) { + container_spec.ParseFromArray(spec, spec_size); + } + Container::UpdatePolicy p; + switch (policy) { + case CONTAINER_UPDATE_POLICY_DIFF: + p = Container::UPDATE_DIFF; + break; + case CONTAINER_UPDATE_POLICY_REPLACE: + p = Container::UPDATE_REPLACE; + break; + default: + return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, + "Unknown update policy: %d", policy); + } + Status status = container->container_->Update(container_spec, p); + return status_copy(s, status); +} + +int lmctfy_container_update(struct status *s, + struct container *container, + int policy, + const Containers__Lmctfy__ContainerSpec *spec) { + + uint8_t *buf = NULL; + size_t sz = 0; + int ret = 0; + + CHECK_NOTNULL_OR_RETURN(s, spec); + CHECK_NOTNULL_OR_RETURN(s, container); + sz = containers__lmctfy__container_spec__get_packed_size(spec); + if (sz > 0) { + buf = new uint8_t[sz]; + containers__lmctfy__container_spec__pack(spec, buf); + } + ret = lmctfy_container_update_raw(s, container, policy, buf, sz); + delete []buf; + return ret; +} diff --git a/clmctfy/include/clmctfy-raw.h b/clmctfy/include/clmctfy-raw.h index 7983e17..9f663ce 100644 --- a/clmctfy/include/clmctfy-raw.h +++ b/clmctfy/include/clmctfy-raw.h @@ -28,6 +28,12 @@ int lmctfy_container_api_create_container_raw( const void *spec, const size_t spec_size); +int lmctfy_container_update_raw(struct status *s, + struct container *container, + int policy, + const void *spec, + const size_t spec_size); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index bbccde7..3381ec4 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -142,6 +142,11 @@ int lmctfy_container_exec(struct status *s, const int argc, const char **argv); +int lmctfy_container_update(struct status *s, + struct container *container, + int policy, + const Containers__Lmctfy__ContainerSpec *spec); + #ifdef __cplusplus } #endif // __cplusplus From 5556a091281c3e235a07ab985feef78e4686526f Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 28 Jan 2014 17:32:55 -0500 Subject: [PATCH 43/84] unit test for update() --- clmctfy/clmctfy_container_ctest.cc | 70 +++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 527272e..803c895 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -84,32 +84,41 @@ StrictMockContainer *ClmctfyContainerTest::GetMockContainer() { return mock_container; } - -TEST_F(ClmctfyContainerTest, ExecSuccess) { +TEST_F(ClmctfyContainerTest, Exec) { StrictMockContainer *mock_container = GetMockContainer(); int argc = 2; const char *argv[] = {"echo", "hello world"}; vector cmds(argc); + string errmsg = "some error message"; + Status status = Status(::util::error::INTERNAL, errmsg); for (int i = 0; i < argc; i++) { cmds[i] = argv[i]; } - EXPECT_CALL(*mock_container, Exec(cmds)).WillOnce(Return(Status::OK)); + EXPECT_CALL(*mock_container, Exec(cmds)) + .WillOnce(Return(Status::OK)) + .WillOnce(Return(status)); + // First call will be success. struct status s = {0, NULL}; int ret = lmctfy_container_exec(&s, container_, argc, argv); EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); EXPECT_EQ(s.message, NULL); -} -TEST_F(ClmctfyContainerTest, ExecBadArgument) { - StrictMockContainer *mock_container = GetMockContainer(); + // second call failed. + s = {0, NULL}; + ret = lmctfy_container_exec(&s, container_, argc, argv); - struct status s = {0, NULL}; - int ret = lmctfy_container_exec(&s, container_, 0, NULL); + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, status.error_code()); + EXPECT_EQ(errmsg, s.message); + + // Invalid arguments. + s = {0, NULL}; + ret = lmctfy_container_exec(&s, container_, 0, NULL); EXPECT_EQ(ret, s.error_code); EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); @@ -127,31 +136,52 @@ TEST_F(ClmctfyContainerTest, ExecBadArgument) { container_->container_ = tmp; EXPECT_EQ(ret, s.error_code); EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); -} +} -TEST_F(ClmctfyContainerTest, ExecFail) { +TEST_F(ClmctfyContainerTest, Update) { StrictMockContainer *mock_container = GetMockContainer(); - int argc = 2; - const char *argv[] = {"echo", "hello world"}; + Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; string errmsg = "some error message"; Status status = Status(::util::error::INTERNAL, errmsg); - vector cmds(argc); - for (int i = 0; i < argc; i++) { - cmds[i] = argv[i]; - } - - EXPECT_CALL(*mock_container, Exec(cmds)).WillOnce(Return(status)); + EXPECT_CALL(*mock_container, Update(_, Container::UPDATE_DIFF)) + .WillOnce(Return(Status::OK)) + .WillOnce(Return(status)); struct status s = {0, NULL}; - int ret = lmctfy_container_exec(&s, container_, argc, argv); + int policy = CONTAINER_UPDATE_POLICY_DIFF; + int ret = lmctfy_container_update(&s, container_, policy, &spec); + EXPECT_EQ(ret, 0); + EXPECT_EQ(s.error_code, 0); + EXPECT_EQ(s.message, NULL); + + s = {0, NULL}; + ret = lmctfy_container_update(&s, container_, policy, &spec); EXPECT_EQ(ret, s.error_code); EXPECT_EQ(s.error_code, status.error_code()); EXPECT_EQ(errmsg, s.message); -} + s = {0, NULL}; + ret = lmctfy_container_update(&s, container_, -1, &spec); + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); + + Container *tmp = container_->container_; + container_->container_ = NULL; + s = {0, NULL}; + ret = lmctfy_container_update(&s, container_, policy, &spec); + container_->container_ = tmp; + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); + + s = {0, NULL}; + ret = lmctfy_container_update(&s, NULL, policy, &spec); + container_->container_ = tmp; + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); +} } // namespace lmctfy } // namespace containers From f1473b5203f18855a9f232146a840494d669a262 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 29 Jan 2014 17:01:03 -0500 Subject: [PATCH 44/84] merge unit tests. --- clmctfy/clmctfy_container_api_ctest.cc | 116 ++++++++++--------------- 1 file changed, 45 insertions(+), 71 deletions(-) diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index 43e6dd6..144d0cd 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -78,7 +78,13 @@ TEST_F(ClmctfyContainerApiTest, GetContainer) { Container *ctnr = new StrictMockContainer(container_name); StatusOr statusor_container = StatusOr(ctnr); - EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor_container)); + string errmsg = "some error message"; + Status status = Status(::util::error::INTERNAL, errmsg); + StatusOr statusor = StatusOr(status); + + EXPECT_CALL(*mock_api, Get(StringPiece(container_name))) + .WillOnce(Return(statusor_container)) + .WillOnce(Return(statusor)); struct status s = {0, NULL}; int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); @@ -88,26 +94,18 @@ TEST_F(ClmctfyContainerApiTest, GetContainer) { EXPECT_EQ(s.message, NULL); Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); -} - -TEST_F(ClmctfyContainerApiTest, GetContainerFail) { - StrictMockContainerApi *mock_api = GetMockApi(); - const char *container_name = "test"; - string errmsg = "some error message"; - Status status = Status(::util::error::INTERNAL, errmsg); - StatusOr statusor = StatusOr(status); - - EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor)); + struct container *tmp = container_; container_ = NULL; - struct status s = {0, NULL}; - int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); + s = {0, NULL}; + ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); EXPECT_EQ(ret, ::util::error::INTERNAL); EXPECT_EQ(s.error_code, ::util::error::INTERNAL); EXPECT_EQ(container_, NULL); EXPECT_EQ(errmsg, s.message); free(s.message); + container_ = tmp; } TEST_F(ClmctfyContainerApiTest, CreateContainer) { @@ -116,7 +114,13 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { Container *ctnr = new StrictMockContainer(container_name); StatusOr statusor_container = StatusOr(ctnr); - EXPECT_CALL(*mock_api, Create(StringPiece(container_name), _)).WillOnce(Return(statusor_container)); + string errmsg = "some error message"; + Status status = Status(::util::error::INTERNAL, errmsg); + StatusOr statusor = StatusOr(status); + + EXPECT_CALL(*mock_api, Create(StringPiece(container_name), _)) + .WillOnce(Return(statusor_container)) + .WillOnce(Return(statusor)); Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; @@ -128,26 +132,18 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { EXPECT_EQ(s.message, NULL); Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); -} -TEST_F(ClmctfyContainerApiTest, CreateContainerFail) { - StrictMockContainerApi *mock_api = GetMockApi(); - const char *container_name = "test"; - string errmsg = "some error message"; - Status status = Status(::util::error::INTERNAL, errmsg); - StatusOr statusor = StatusOr(status); - - EXPECT_CALL(*mock_api, Create(StringPiece(container_name), _)).WillOnce(Return(statusor)); - - Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; - struct status s = {0, NULL}; - int ret = lmctfy_container_api_create_container(&s, &container_, container_api_, container_name, &spec); + struct container *tmp = container_; + container_ = NULL; + s = {0, NULL}; + ret = lmctfy_container_api_create_container(&s, &container_, container_api_, container_name, &spec); EXPECT_EQ(ret, ::util::error::INTERNAL); EXPECT_EQ(s.error_code, ::util::error::INTERNAL); EXPECT_EQ(container_, NULL); EXPECT_EQ(errmsg, s.message); free(s.message); + container_ = tmp; } TEST_F(ClmctfyContainerApiTest, DestroyContainer) { @@ -156,47 +152,38 @@ TEST_F(ClmctfyContainerApiTest, DestroyContainer) { Container *ctnr = new StrictMockContainer(container_name); StatusOr statusor_container = StatusOr(ctnr); - EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor_container)); - EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(Status::OK)); + string errmsg = "some error message"; + Status destroy_status = Status(::util::error::INTERNAL, errmsg); + + EXPECT_CALL(*mock_api, Get(StringPiece(container_name))) + .WillOnce(Return(statusor_container)) + .WillOnce(Return(statusor_container)); + EXPECT_CALL(*mock_api, Destroy(ctnr)) + .WillOnce(Return(Status::OK)) + .WillOnce(Return(destroy_status)); struct status s = {0, NULL}; int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); - EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); EXPECT_EQ(s.message, NULL); - ret = lmctfy_container_api_destroy_container(&s, container_api_, container_); container_ = NULL; EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); EXPECT_EQ(s.message, NULL); -} - -TEST_F(ClmctfyContainerApiTest, DestroyContainerFail) { - StrictMockContainerApi *mock_api = GetMockApi(); - const char *container_name = "test"; - Container *ctnr = new StrictMockContainer(container_name); - StatusOr statusor_container = StatusOr(ctnr); - - string errmsg = "some error message"; - Status destroy_status = Status(::util::error::INTERNAL, errmsg); - - EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor_container)); - EXPECT_CALL(*mock_api, Destroy(ctnr)).WillOnce(Return(destroy_status)); - - struct status s = {0, NULL}; - int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); + s = {0, NULL}; + ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); EXPECT_EQ(s.message, NULL); - ret = lmctfy_container_api_destroy_container(&s, container_api_, container_); container_ = NULL; EXPECT_EQ(ret, ::util::error::INTERNAL); EXPECT_EQ(s.error_code, ::util::error::INTERNAL); EXPECT_EQ(errmsg, s.message); + } #define MAX_CONTAINER_NAME_LEN 512 @@ -207,40 +194,27 @@ TEST_F(ClmctfyContainerApiTest, DetectContainer) { char output_name[MAX_CONTAINER_NAME_LEN]; pid_t pid = 10; container_ = NULL; - memset(output_name, 0, MAX_CONTAINER_NAME_LEN); - StatusOr statusor = StatusOr(container_name); - EXPECT_CALL(*mock_api, Detect(pid)).WillOnce(Return(statusor)); + string errmsg = "some error message"; + Status status = Status(::util::error::INTERNAL, errmsg); + StatusOr statusor_fail = StatusOr(status); + + EXPECT_CALL(*mock_api, Detect(pid)) + .WillOnce(Return(statusor)) + .WillOnce(Return(statusor_fail)); struct status s = {0, NULL}; int ret = lmctfy_container_api_detect_container(&s, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); - EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); EXPECT_EQ(s.message, NULL); EXPECT_EQ(string(container_name), string(output_name)); -} - -TEST_F(ClmctfyContainerApiTest, DetectContainerFail) { - StrictMockContainerApi *mock_api = GetMockApi(); - const char *container_name = "test"; - char output_name[MAX_CONTAINER_NAME_LEN]; - pid_t pid = 10; - container_ = NULL; - - memset(output_name, 0, MAX_CONTAINER_NAME_LEN); - - string errmsg = "some error message"; - Status status = Status(::util::error::INTERNAL, errmsg); - StatusOr statusor = StatusOr(status); - - EXPECT_CALL(*mock_api, Detect(pid)).WillOnce(Return(statusor)); - - struct status s = {0, NULL}; - int ret = lmctfy_container_api_detect_container(&s, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); + *output_name = '\0'; + s = {0, NULL}; + ret = lmctfy_container_api_detect_container(&s, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); EXPECT_EQ(ret, status.error_code()); EXPECT_EQ(s.error_code, status.error_code()); EXPECT_EQ(errmsg, s.message); From 7575a0fb06ad47b84be29c04282f7ebaee6a62cd Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 4 Feb 2014 18:43:20 -0500 Subject: [PATCH 45/84] check status first to propagate error. --- clmctfy/clmctfy_container.cc | 3 +++ clmctfy/clmctfy_container_api.cc | 7 +++++ clmctfy/clmctfy_internal.h | 34 +++++++++++++++--------- clmctfy/include/clmctfy.h | 45 +++++++++++++++++++++----------- 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index c4ff9f3..8faa4c5 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -19,6 +19,7 @@ int lmctfy_container_exec(struct status *s, const int argc, const char **argv) { int ret = STATUS_OK; + CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); CHECK_POSITIVE_OR_RETURN(s, argc); @@ -48,6 +49,7 @@ int lmctfy_container_update_raw(struct status *s, const void *spec, const size_t spec_size) { ContainerSpec container_spec; + CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); if (spec != NULL && spec_size > 0) { @@ -78,6 +80,7 @@ int lmctfy_container_update(struct status *s, size_t sz = 0; int ret = 0; + CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, spec); CHECK_NOTNULL_OR_RETURN(s, container); sz = containers__lmctfy__container_spec__get_packed_size(spec); diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index f68b0f7..4990993 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -18,6 +18,7 @@ using ::util::StatusOr; int lmctfy_init_machine_raw(struct status *s, const void *spec, const size_t spec_size) { InitSpec init_spec; + CHECK_NOTFAIL_OR_RETURN(s); if (spec != NULL && spec_size > 0) { // XXX should we consider this as an error? init_spec.ParseFromArray(spec, spec_size); @@ -31,6 +32,7 @@ int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *sp size_t sz = 0; int ret = 0; + CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, spec); sz = containers__lmctfy__init_spec__get_packed_size(spec); if (sz > 0) { @@ -44,6 +46,7 @@ int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *sp } int lmctfy_new_container_api(struct status *s, struct container_api **api) { + CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, api); *api = new container_api(); (*api)->container_api_ = NULL; @@ -72,6 +75,7 @@ int lmctfy_container_api_get_container(struct status *s, struct container **c, const struct container_api *api, const char *container_name) { + CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, api); CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, c); @@ -109,6 +113,7 @@ int lmctfy_container_api_create_container(struct status *s, struct container_api *api, const char *container_name, const Containers__Lmctfy__ContainerSpec *spec) { + CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, api); CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, c); @@ -129,6 +134,7 @@ int lmctfy_container_api_create_container(struct status *s, int lmctfy_container_api_destroy_container(struct status *s, struct container_api *api, struct container *c) { + CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, api); CHECK_NOTNULL_OR_RETURN(s, api->container_api_); int ret = STATUS_OK; @@ -146,6 +152,7 @@ int lmctfy_container_api_detect_container(struct status *s, struct container_api *api, pid_t pid) { int ret = STATUS_OK; + CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, api); CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, container_name); diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index af47b0b..941b936 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -32,25 +32,33 @@ struct container_api { const ::util::Status _status = \ ::util::errors_internal::PerformSideEffects(__VA_ARGS__); \ if (PREDICT_FALSE(!_status.ok())) { \ - if (s != NULL) status_copy(s, _status); \ - return (int)_status.error_code(); \ + if (s != NULL) status_copy(s, _status); \ + return (int)_status.error_code(); \ } \ } while (0) -#define CHECK_NOTNULL_OR_RETURN(status, ptr) do { \ - if ((ptr) == NULL) { \ - return status_new(status, UTIL__ERROR__CODE__INVALID_ARGUMENT, \ - "In function %s: %s cannot be null", \ - __func__, #ptr); \ +#define CHECK_NOTFAIL_OR_RETURN(status) do { \ + if ((status) != NULL) { \ + if ((status)->error_code != UTIL__ERROR__CODE__OK) { \ + return (status)->error_code; \ } \ + } \ +} while(0) + +#define CHECK_NOTNULL_OR_RETURN(status, ptr) do { \ + if ((ptr) == NULL) { \ + return status_new(status, UTIL__ERROR__CODE__INVALID_ARGUMENT, \ + "In function %s: %s cannot be null", \ + __func__, #ptr); \ + } \ } while (0) -#define CHECK_POSITIVE_OR_RETURN(status, value) do { \ - if ((value) <= 0) { \ - return status_new(status, UTIL__ERROR__CODE__INVALID_ARGUMENT, \ - "In function %s: %s=%d, but it should be positive", \ - __func__, #value, value); \ - } \ +#define CHECK_POSITIVE_OR_RETURN(status, value) do { \ + if ((value) <= 0) { \ + return status_new(status, UTIL__ERROR__CODE__INVALID_ARGUMENT, \ + "In function %s: %s=%d, but it should be positive", \ + __func__, #value, value); \ + } \ } while (0) namespace util { diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 3381ec4..7c44d34 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -28,8 +28,11 @@ struct container_api; // Initializes the machine to start being able to create containers. // // Arguments: -// - s: [output] s will be used as output. s will not be changed on success; -// Otherwise it contains the error code and message. +// - s: [output] s will be used as output. +// If the original value of s->code is not +// UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return +// immediately with value s->code. This will help users to propagete errors. +// Otherwise, it contains the error code and message. // - spec: The specification. // // Returns: @@ -41,10 +44,13 @@ int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *sp // Create a new container_api. // // Arguments: -// - s: [output] s will be used as output. s will not be changed on success; -// Otherwise it contains the error code and message. +// - s: [output] s will be used as output. +// If the original value of s->code is not +// UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return +// immediately with value s->code. This will help users to propagete errors. +// Otherwise, it contains the error code and message. // - api: [output] The address of a pointer to struct container_api. The -// pointer of the container api will be stored in this address. +// pointer of the container api will be stored in this address. // // Returns: // @@ -64,10 +70,13 @@ void lmctfy_delete_container_api(struct container_api *api); // // Arguments: // -// - s: [output] s will be used as output. s will not be changed on success; -// Otherwise it contains the error code and message. +// - s: [output] s will be used as output. +// If the original value of s->code is not +// UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return +// immediately with value s->code. This will help users to propagete errors. +// Otherwise, it contains the error code and message. // - container: [output] The address of a pointer to struct container. It will -// be used to store the pointer to the container. +// be used to store the pointer to the container. // - api: A container api. // - container_name: the container name. // @@ -85,10 +94,13 @@ int lmctfy_container_api_get_container( // // Arguments: // -// - s: [output] s will be used as output. s will not be changed on success; -// Otherwise it contains the error code and message. +// - s: [output] s will be used as output. +// If the original value of s->code is not +// UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return +// immediately with value s->code. This will help users to propagete errors. +// Otherwise, it contains the error code and message. // - container: [output] The address of a pointer to struct container. It will -// be used to store the newly created container. +// be used to store the newly created container. // - api: A container api. // - container_name: the container name. // - spec: container specification. @@ -108,11 +120,14 @@ int lmctfy_container_api_create_container( // // Arguments: // -// - s: [output] s will be used as output. s will not be changed on success; -// Otherwise it contains the error code and message. +// - s: [output] s will be used as output. +// If the original value of s->code is not +// UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return +// immediately with value s->code. This will help users to propagete errors. +// Otherwise, it contains the error code and message. // - api: A container api. // - container: The pointer to struct container. The pointer will become -// invalid after a success destroy(). +// invalid after a success destroy(). // // Returns: // @@ -134,7 +149,7 @@ int lmctfy_container_api_detect_container(struct status *s, // Arguments: // // - container: The container. This pointer will be invalid after the call to -// this function +// this function void lmctfy_delete_container(struct container *container); int lmctfy_container_exec(struct status *s, From 6c2f21eab7517b5f6dd1355563094cc633cf68c8 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 5 Feb 2014 00:23:57 -0500 Subject: [PATCH 46/84] lmctfy_container_enter() --- clmctfy/clmctfy_container.cc | 22 ++++++++++++ clmctfy/clmctfy_container_ctest.cc | 54 ++++++++++++++++++++++++++++++ clmctfy/include/clmctfy.h | 5 +++ 3 files changed, 81 insertions(+) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 8faa4c5..73374b2 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -14,6 +14,28 @@ using ::std::vector; #define STATUS_OK UTIL__ERROR__CODE__OK +int lmctfy_container_enter(struct status *s, + struct container *container, + const pid_t *tids, + const int n) { + int ret = STATUS_OK; + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + + if (tids == NULL || n <= 0) { + return ret; + } + + vector tids_v(n); + int i = 0; + for (i = 0; i < n; i++) { + tids_v[i] = tids[i]; + } + Status status = container->container_->Enter(tids_v); + return status_copy(s, status); +} + int lmctfy_container_exec(struct status *s, struct container *container, const int argc, diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 803c895..994ac7a 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -183,5 +183,59 @@ TEST_F(ClmctfyContainerTest, Update) { EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); } +TEST_F(ClmctfyContainerTest, Enter) { + StrictMockContainer *mock_container = GetMockContainer(); + Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; + string errmsg = "some error message"; + Status status = Status(::util::error::INTERNAL, errmsg); + + EXPECT_CALL(*mock_container, Enter(_)) + .WillOnce(Return(Status::OK)) + .WillOnce(Return(status)); + + struct status s = {0, NULL}; + pid_t tids[] = {1, 2, 3, 4}; + int n = 4; + int ret = lmctfy_container_enter(&s, container_, tids, n); + EXPECT_EQ(ret, 0); + EXPECT_EQ(s.error_code, 0); + EXPECT_EQ(s.message, NULL); + + s = {0, NULL}; + ret = lmctfy_container_enter(&s, container_, tids, n); + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, status.error_code()); + EXPECT_EQ(errmsg, s.message); + + s = {0, NULL}; + ret = lmctfy_container_enter(&s, container_, tids, -1); + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__OK); + + s = {0, NULL}; + ret = lmctfy_container_enter(&s, container_, NULL, 0); + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__OK); + + s = {0, NULL}; + ret = lmctfy_container_enter(&s, container_, tids, 0); + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__OK); + + Container *tmp = container_->container_; + container_->container_ = NULL; + s = {0, NULL}; + ret = lmctfy_container_enter(&s, container_, tids, n); + container_->container_ = tmp; + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); + + s = {0, NULL}; + ret = lmctfy_container_enter(&s, NULL, tids, n); + container_->container_ = tmp; + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); +} + } // namespace lmctfy } // namespace containers diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 7c44d34..9298325 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -152,6 +152,11 @@ int lmctfy_container_api_detect_container(struct status *s, // this function void lmctfy_delete_container(struct container *container); +int lmctfy_container_enter(struct status *s, + struct container *container, + const pid_t *tids, + const int n); + int lmctfy_container_exec(struct status *s, struct container *container, const int argc, From 7d4ab94e568394e1d8c2f7396f2a1d5a75d52e14 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 5 Feb 2014 01:29:13 -0500 Subject: [PATCH 47/84] lcmtfy_container_run() --- clmctfy/clmctfy_container.cc | 56 +++++++++++++++++++++++++- clmctfy/clmctfy_container_api.cc | 8 +++- clmctfy/clmctfy_container_api_ctest.cc | 12 +++--- clmctfy/clmctfy_container_ctest.cc | 46 +++++++++++++++++++-- clmctfy/include/clmctfy-raw.h | 8 ++++ clmctfy/include/clmctfy.h | 16 ++++++++ 6 files changed, 133 insertions(+), 13 deletions(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 73374b2..5930f17 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -14,6 +14,58 @@ using ::std::vector; #define STATUS_OK UTIL__ERROR__CODE__OK +int lmctfy_container_run_raw(struct status *s, + pid_t *tid, + struct container *container, + const int argc, + const char **argv, + const void *spec, + const size_t spec_size) { + RunSpec run_spec; + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + CHECK_NOTNULL_OR_RETURN(s, tid); + CHECK_POSITIVE_OR_RETURN(s, argc); + if (spec != NULL && spec_size > 0) { + run_spec.ParseFromArray(spec, spec_size); + } + vector cmds(argc); + int i = 0; + for (i = 0; i < argc; i++) { + cmds[i] = argv[i]; + } + StatusOr statusor = container->container_->Run(cmds, run_spec); + RETURN_IF_ERROR_PTR(s, statusor, tid); + return STATUS_OK; +} + +int lmctfy_container_run(struct status *s, + pid_t *tid, + struct container *container, + const int argc, + const char **argv, + const Containers__Lmctfy__RunSpec *spec) { + + uint8_t *buf = NULL; + size_t sz = 0; + int ret = 0; + + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, spec); + CHECK_NOTNULL_OR_RETURN(s, container); + sz = containers__lmctfy__run_spec__get_packed_size(spec); + if (sz > 0) { + buf = new uint8_t[sz]; + containers__lmctfy__run_spec__pack(spec, buf); + } + ret = lmctfy_container_run_raw(s, tid, container, argc, argv, buf, sz); + if (buf != NULL) { + delete []buf; + } + return ret; +} + int lmctfy_container_enter(struct status *s, struct container *container, const pid_t *tids, @@ -111,6 +163,8 @@ int lmctfy_container_update(struct status *s, containers__lmctfy__container_spec__pack(spec, buf); } ret = lmctfy_container_update_raw(s, container, policy, buf, sz); - delete []buf; + if (buf != NULL) { + delete []buf; + } return ret; } diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index 4990993..f0e1874 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -41,7 +41,9 @@ int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *sp containers__lmctfy__init_spec__pack(spec, buf); } ret = lmctfy_init_machine_raw(s, buf, sz); - delete []buf; + if (buf != NULL) { + delete []buf; + } return ret; } @@ -127,7 +129,9 @@ int lmctfy_container_api_create_container(struct status *s, } containers__lmctfy__container_spec__pack(spec, buf); ret = lmctfy_container_api_create_container_raw(s, c, api, container_name, buf, sz); - delete []buf; + if (buf != NULL) { + delete []buf; + } return ret; } diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index 144d0cd..852b9fb 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -76,11 +76,11 @@ TEST_F(ClmctfyContainerApiTest, GetContainer) { StrictMockContainerApi *mock_api = GetMockApi(); const char *container_name = "test"; Container *ctnr = new StrictMockContainer(container_name); - StatusOr statusor_container = StatusOr(ctnr); + StatusOr statusor_container(ctnr); string errmsg = "some error message"; Status status = Status(::util::error::INTERNAL, errmsg); - StatusOr statusor = StatusOr(status); + StatusOr statusor(status); EXPECT_CALL(*mock_api, Get(StringPiece(container_name))) .WillOnce(Return(statusor_container)) @@ -112,11 +112,11 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { StrictMockContainerApi *mock_api = GetMockApi(); const char *container_name = "test"; Container *ctnr = new StrictMockContainer(container_name); - StatusOr statusor_container = StatusOr(ctnr); + StatusOr statusor_container(ctnr); string errmsg = "some error message"; Status status = Status(::util::error::INTERNAL, errmsg); - StatusOr statusor = StatusOr(status); + StatusOr statusor(status); EXPECT_CALL(*mock_api, Create(StringPiece(container_name), _)) .WillOnce(Return(statusor_container)) @@ -153,7 +153,7 @@ TEST_F(ClmctfyContainerApiTest, DestroyContainer) { StatusOr statusor_container = StatusOr(ctnr); string errmsg = "some error message"; - Status destroy_status = Status(::util::error::INTERNAL, errmsg); + Status destroy_status(::util::error::INTERNAL, errmsg); EXPECT_CALL(*mock_api, Get(StringPiece(container_name))) .WillOnce(Return(statusor_container)) @@ -195,7 +195,7 @@ TEST_F(ClmctfyContainerApiTest, DetectContainer) { pid_t pid = 10; container_ = NULL; memset(output_name, 0, MAX_CONTAINER_NAME_LEN); - StatusOr statusor = StatusOr(container_name); + StatusOr statusor(container_name); string errmsg = "some error message"; Status status = Status(::util::error::INTERNAL, errmsg); diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 994ac7a..efb523a 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -90,7 +90,7 @@ TEST_F(ClmctfyContainerTest, Exec) { const char *argv[] = {"echo", "hello world"}; vector cmds(argc); string errmsg = "some error message"; - Status status = Status(::util::error::INTERNAL, errmsg); + Status status(::util::error::INTERNAL, errmsg); for (int i = 0; i < argc; i++) { cmds[i] = argv[i]; @@ -115,6 +115,7 @@ TEST_F(ClmctfyContainerTest, Exec) { EXPECT_EQ(ret, s.error_code); EXPECT_EQ(s.error_code, status.error_code()); EXPECT_EQ(errmsg, s.message); + free(s.message); // Invalid arguments. s = {0, NULL}; @@ -143,7 +144,7 @@ TEST_F(ClmctfyContainerTest, Update) { StrictMockContainer *mock_container = GetMockContainer(); Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; string errmsg = "some error message"; - Status status = Status(::util::error::INTERNAL, errmsg); + Status status(::util::error::INTERNAL, errmsg); EXPECT_CALL(*mock_container, Update(_, Container::UPDATE_DIFF)) .WillOnce(Return(Status::OK)) @@ -162,6 +163,7 @@ TEST_F(ClmctfyContainerTest, Update) { EXPECT_EQ(ret, s.error_code); EXPECT_EQ(s.error_code, status.error_code()); EXPECT_EQ(errmsg, s.message); + free(s.message); s = {0, NULL}; ret = lmctfy_container_update(&s, container_, -1, &spec); @@ -183,11 +185,46 @@ TEST_F(ClmctfyContainerTest, Update) { EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); } +TEST_F(ClmctfyContainerTest, Run) { + StrictMockContainer *mock_container = GetMockContainer(); + string errmsg = "some error message"; + Status err_status(::util::error::INTERNAL, errmsg); + StatusOr statusor_success((pid_t)1); + StatusOr statusor_fail(err_status); + Containers__Lmctfy__RunSpec runspec = CONTAINERS__LMCTFY__RUN_SPEC__INIT; + struct status s = {0, NULL}; + int ret = 0; + pid_t tid; + const char *argv[] = {"/bin/echo", "hello world"}; + int argc = 2; + vector cmds(argc); + for (int i = 0; i < argc; i++) { + cmds[i] = argv[i]; + } + + EXPECT_CALL(*mock_container, Run(cmds, _)) + .WillOnce(Return(statusor_success)) + .WillOnce(Return(statusor_fail)); + + s = {0, NULL}; + ret = lmctfy_container_run(&s, &tid, container_, argc, argv, &runspec); + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, 0); + EXPECT_EQ(s.message, NULL); + EXPECT_EQ(tid, 1); + + s = {0, NULL}; + ret = lmctfy_container_run(&s, &tid, container_, argc, argv, &runspec); + EXPECT_EQ(ret, s.error_code); + EXPECT_EQ(s.error_code, err_status.error_code()); + EXPECT_EQ(errmsg, s.message); + free(s.message); +} + TEST_F(ClmctfyContainerTest, Enter) { StrictMockContainer *mock_container = GetMockContainer(); - Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; string errmsg = "some error message"; - Status status = Status(::util::error::INTERNAL, errmsg); + Status status(::util::error::INTERNAL, errmsg); EXPECT_CALL(*mock_container, Enter(_)) .WillOnce(Return(Status::OK)) @@ -206,6 +243,7 @@ TEST_F(ClmctfyContainerTest, Enter) { EXPECT_EQ(ret, s.error_code); EXPECT_EQ(s.error_code, status.error_code()); EXPECT_EQ(errmsg, s.message); + free(s.message); s = {0, NULL}; ret = lmctfy_container_enter(&s, container_, tids, -1); diff --git a/clmctfy/include/clmctfy-raw.h b/clmctfy/include/clmctfy-raw.h index 9f663ce..4aa38dd 100644 --- a/clmctfy/include/clmctfy-raw.h +++ b/clmctfy/include/clmctfy-raw.h @@ -28,6 +28,14 @@ int lmctfy_container_api_create_container_raw( const void *spec, const size_t spec_size); +int lmctfy_container_run_raw(struct status *s, + pid_t *tid, + struct container *container, + const int argc, + const char **argv, + const void *spec, + const size_t spec_size); + int lmctfy_container_update_raw(struct status *s, struct container *container, int policy, diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 9298325..cb690d4 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -157,6 +157,22 @@ int lmctfy_container_enter(struct status *s, const pid_t *tids, const int n); +// +// Arguments: +// +// - s: [output] +// - tid: [output] On success, tid stores the PID of the command. +// - container +// - argc: number of arguments (including the binary file path). +// - argv: All arguments. The first element is the binary that will be executed +// and must be an absolute path. +int lmctfy_container_run(struct status *s, + pid_t *tid, + struct container *container, + const int argc, + const char **argv, + const Containers__Lmctfy__RunSpec *spec); + int lmctfy_container_exec(struct status *s, struct container *container, const int argc, From 7fccb694a8e2468784a2c84e3b9ab79b5d296962 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 5 Feb 2014 16:30:06 -0500 Subject: [PATCH 48/84] For .ctest.cc, open -fpermissive. --- Makefile | 11 +++++++++-- clmctfy/clmctfy_container_api_ctest.cc | 16 ++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 0f18291..b76614c 100755 --- a/Makefile +++ b/Makefile @@ -109,6 +109,9 @@ CXXFLAGS += `pkg-config --cflags --libs protobuf` # Add proto-c flags. CXXFLAGS += -lprotobuf-c +# FLAGS for C binding +CFLAGS = -fpermissive + CLI = lmctfy NSCON = lmctfy-nscon NSINIT = lmctfy-nsinit @@ -241,7 +244,7 @@ $(CREAPER): lmctfy-creaper.go %_ctest: gtest_main.a $(SYSTEM_API_TEST_OBJS) clmctfy_only_api.a $(create_bin) $(CXX) -o $(OUT_DIR)/$@ $*.cc $*_ctest.cc $(addprefix $(OUT_DIR)/,$^) \ - $(CXXFLAGS) + $(CXXFLAGS) $(CFLAGS) %_proto: %.proto $(PROTOC) $^ --cpp_out=. @@ -253,10 +256,14 @@ $(CREAPER): lmctfy-creaper.go %.pb-c.o: %_proto $(create_bin) - $(CXX) -c $*.pb-c.c -o $(OUT_DIR)/$@ $(CXXFLAGS) + $(CXX) -c $*.pb-c.c -o $(OUT_DIR)/$@ $(CXXFLAGS) $(CFLAGS) gen_protos: $(addsuffix _proto,$(INCLUDE_PROTOS) $(UTIL_PROTOS)) +%_ctest.o: gen_protos %_ctest.cc + $(create_bin) + $(CXX) -c $*.cc -o $(OUT_DIR)/$@ $(CXXFLAGS) $(CFLAGS) + %.o: gen_protos %.cc $(create_bin) $(CXX) -c $*.cc -o $(OUT_DIR)/$@ $(CXXFLAGS) diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index 852b9fb..62d2631 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -91,7 +91,7 @@ TEST_F(ClmctfyContainerApiTest, GetContainer) { EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, NULL); + EXPECT_EQ(s.message, (const char *)NULL); Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); @@ -102,7 +102,7 @@ TEST_F(ClmctfyContainerApiTest, GetContainer) { EXPECT_EQ(ret, ::util::error::INTERNAL); EXPECT_EQ(s.error_code, ::util::error::INTERNAL); - EXPECT_EQ(container_, NULL); + EXPECT_EQ(container_, (struct container *)NULL); EXPECT_EQ(errmsg, s.message); free(s.message); container_ = tmp; @@ -129,7 +129,7 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, NULL); + EXPECT_EQ(s.message, (const char *)NULL); Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); @@ -140,7 +140,7 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { EXPECT_EQ(ret, ::util::error::INTERNAL); EXPECT_EQ(s.error_code, ::util::error::INTERNAL); - EXPECT_EQ(container_, NULL); + EXPECT_EQ(container_, (struct container *)NULL); EXPECT_EQ(errmsg, s.message); free(s.message); container_ = tmp; @@ -166,18 +166,18 @@ TEST_F(ClmctfyContainerApiTest, DestroyContainer) { int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, NULL); + EXPECT_EQ(s.message, (const char *)NULL); ret = lmctfy_container_api_destroy_container(&s, container_api_, container_); container_ = NULL; EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, NULL); + EXPECT_EQ(s.message, (const char *)NULL); s = {0, NULL}; ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, NULL); + EXPECT_EQ(s.message, (const char *)NULL); ret = lmctfy_container_api_destroy_container(&s, container_api_, container_); container_ = NULL; EXPECT_EQ(ret, ::util::error::INTERNAL); @@ -209,7 +209,7 @@ TEST_F(ClmctfyContainerApiTest, DetectContainer) { int ret = lmctfy_container_api_detect_container(&s, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, NULL); + EXPECT_EQ(s.message, (const char *)NULL); EXPECT_EQ(string(container_name), string(output_name)); *output_name = '\0'; From c56a45b9031decb0edfb7ec3c5f2868f7c349905 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Thu, 6 Feb 2014 00:02:59 -0500 Subject: [PATCH 49/84] use macros to write unit test. --- clmctfy/clmctfy_container_ctest.cc | 109 ++++++----------------------- clmctfy/clmctfy_macros_ctest.h | 52 ++++++++++++++ 2 files changed, 75 insertions(+), 86 deletions(-) create mode 100644 clmctfy/clmctfy_macros_ctest.h diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index efb523a..6d1ba43 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -15,6 +15,7 @@ #include #include "clmctfy.h" +#include "clmctfy_macros_ctest.h" #include "lmctfy_mock.h" #include "gtest/gtest.h" @@ -100,44 +101,10 @@ TEST_F(ClmctfyContainerTest, Exec) { .WillOnce(Return(Status::OK)) .WillOnce(Return(status)); - // First call will be success. - struct status s = {0, NULL}; - int ret = lmctfy_container_exec(&s, container_, argc, argv); - - EXPECT_EQ(ret, 0); - EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, NULL); - - // second call failed. - s = {0, NULL}; - ret = lmctfy_container_exec(&s, container_, argc, argv); - - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, status.error_code()); - EXPECT_EQ(errmsg, s.message); - free(s.message); - - // Invalid arguments. - s = {0, NULL}; - ret = lmctfy_container_exec(&s, container_, 0, NULL); - - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); - - Container *tmp = container_->container_; - container_->container_ = NULL; - s = {0, NULL}; - ret = lmctfy_container_exec(&s, container_, 0, NULL); - container_->container_ = tmp; - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); - - s = {0, NULL}; - ret = lmctfy_container_exec(&s, NULL, 0, NULL); - container_->container_ = tmp; - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); - + SHOULD_SUCCESS_ON(lmctfy_container_exec, &s, container_, argc, argv); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_exec, &s, container_, argc, argv); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_exec, &s, container_, 0, NULL); + WITH_NULL_CONTAINER_RUN(lmctfy_container_exec, &s, container_, argc, argv); } TEST_F(ClmctfyContainerTest, Update) { @@ -150,39 +117,11 @@ TEST_F(ClmctfyContainerTest, Update) { .WillOnce(Return(Status::OK)) .WillOnce(Return(status)); - struct status s = {0, NULL}; int policy = CONTAINER_UPDATE_POLICY_DIFF; - int ret = lmctfy_container_update(&s, container_, policy, &spec); - - EXPECT_EQ(ret, 0); - EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, NULL); - - s = {0, NULL}; - ret = lmctfy_container_update(&s, container_, policy, &spec); - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, status.error_code()); - EXPECT_EQ(errmsg, s.message); - free(s.message); - - s = {0, NULL}; - ret = lmctfy_container_update(&s, container_, -1, &spec); - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); - - Container *tmp = container_->container_; - container_->container_ = NULL; - s = {0, NULL}; - ret = lmctfy_container_update(&s, container_, policy, &spec); - container_->container_ = tmp; - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); - - s = {0, NULL}; - ret = lmctfy_container_update(&s, NULL, policy, &spec); - container_->container_ = tmp; - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); + SHOULD_SUCCESS_ON(lmctfy_container_update, &s, container_, policy, &spec); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_update, &s, container_, policy, &spec); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_update, &s, container_, -1, &spec); + WITH_NULL_CONTAINER_RUN(lmctfy_container_update, &s, container_, -1, &spec); } TEST_F(ClmctfyContainerTest, Run) { @@ -192,8 +131,6 @@ TEST_F(ClmctfyContainerTest, Run) { StatusOr statusor_success((pid_t)1); StatusOr statusor_fail(err_status); Containers__Lmctfy__RunSpec runspec = CONTAINERS__LMCTFY__RUN_SPEC__INIT; - struct status s = {0, NULL}; - int ret = 0; pid_t tid; const char *argv[] = {"/bin/echo", "hello world"}; int argc = 2; @@ -206,19 +143,10 @@ TEST_F(ClmctfyContainerTest, Run) { .WillOnce(Return(statusor_success)) .WillOnce(Return(statusor_fail)); - s = {0, NULL}; - ret = lmctfy_container_run(&s, &tid, container_, argc, argv, &runspec); - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, NULL); - EXPECT_EQ(tid, 1); - - s = {0, NULL}; - ret = lmctfy_container_run(&s, &tid, container_, argc, argv, &runspec); - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, err_status.error_code()); - EXPECT_EQ(errmsg, s.message); - free(s.message); + SHOULD_SUCCESS_ON(lmctfy_container_run, &s, &tid, container_, argc, argv, &runspec); + SHOULD_FAIL_WITH_ERROR(err_status, lmctfy_container_run, &s, &tid, container_, argc, argv, &runspec); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_run, &s, &tid, container_, 0, NULL, &runspec); + WITH_NULL_CONTAINER_RUN(lmctfy_container_run, &s, &tid, container_, argc, argv, &runspec); } TEST_F(ClmctfyContainerTest, Enter) { @@ -230,14 +158,22 @@ TEST_F(ClmctfyContainerTest, Enter) { .WillOnce(Return(Status::OK)) .WillOnce(Return(status)); - struct status s = {0, NULL}; pid_t tids[] = {1, 2, 3, 4}; int n = 4; + SHOULD_SUCCESS_ON(lmctfy_container_enter, &s, container_, tids, n); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_enter, &s, container_, tids, n); + // With 0 tid, it should success. + SHOULD_SUCCESS_ON(lmctfy_container_enter, &s, container_, NULL, 0); + WITH_NULL_CONTAINER_RUN(lmctfy_container_enter, &s, container_, NULL, 0); + + /* + struct status s = {0, NULL}; int ret = lmctfy_container_enter(&s, container_, tids, n); EXPECT_EQ(ret, 0); EXPECT_EQ(s.error_code, 0); EXPECT_EQ(s.message, NULL); + s = {0, NULL}; ret = lmctfy_container_enter(&s, container_, tids, n); EXPECT_EQ(ret, s.error_code); @@ -273,6 +209,7 @@ TEST_F(ClmctfyContainerTest, Enter) { container_->container_ = tmp; EXPECT_EQ(ret, s.error_code); EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); + */ } } // namespace lmctfy diff --git a/clmctfy/clmctfy_macros_ctest.h b/clmctfy/clmctfy_macros_ctest.h new file mode 100644 index 0000000..0226215 --- /dev/null +++ b/clmctfy/clmctfy_macros_ctest.h @@ -0,0 +1,52 @@ +#ifndef LMCTFY__CLMCTFY_MACROS_CTEST_H_ +#define LMCTFY__CLMCTFY_MACROS_CTEST_H_ + +// Some useful macros for writing test cases. + +#define WITH_NULL_CONTAINER_RUN(func, ...) do { \ + Container *tmp = container_->container_; \ + container_->container_ = NULL; \ + struct status s = {0, NULL}; \ + int ret = func(__VA_ARGS__); \ + EXPECT_EQ(ret, s.error_code); \ + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ + container_->container_ = tmp; \ + \ + struct container *tmp_container = container_; \ + container_ = NULL; \ + s = {0, NULL}; \ + ret = func(__VA_ARGS__); \ + EXPECT_EQ(ret, s.error_code); \ + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ + container_ = tmp_container; \ +} while (0) + +#define SHOULD_SUCCESS_ON(func, ...) do { \ + struct status s = {0, NULL}; \ + int ret = func(__VA_ARGS__); \ + EXPECT_EQ(ret, 0); \ + EXPECT_EQ(s.error_code, 0); \ + EXPECT_EQ(s.message, NULL); \ +} while (0) + +#define SHOULD_FAIL_WITH_ERROR(st, func, ...) do { \ + struct status s = {0, NULL}; \ + int ret = func(__VA_ARGS__); \ + EXPECT_EQ(ret, s.error_code); \ + EXPECT_EQ(s.error_code, (st).error_code()); \ + EXPECT_EQ((st).error_message(), s.message); \ + free(s.message); \ +} while (0) + +#define SHOULD_BE_INVALID_ARGUMENT(func, ...) do { \ + struct status s = {0, NULL}; \ + int ret = func(__VA_ARGS__); \ + EXPECT_EQ(ret, s.error_code); \ + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ + if (s.message != NULL) { \ + free(s.message); \ + } \ +} while (0) + +#endif // LMCTFY__CLMCTFY_MACROS_CTEST_H_ + From 0ce03bd786fb27f72440baf6131100e11bcbdd7b Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Thu, 6 Feb 2014 00:03:36 -0500 Subject: [PATCH 50/84] remove comments. --- clmctfy/clmctfy_container_ctest.cc | 45 ------------------------------ 1 file changed, 45 deletions(-) diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 6d1ba43..6feee7e 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -165,51 +165,6 @@ TEST_F(ClmctfyContainerTest, Enter) { // With 0 tid, it should success. SHOULD_SUCCESS_ON(lmctfy_container_enter, &s, container_, NULL, 0); WITH_NULL_CONTAINER_RUN(lmctfy_container_enter, &s, container_, NULL, 0); - - /* - struct status s = {0, NULL}; - int ret = lmctfy_container_enter(&s, container_, tids, n); - EXPECT_EQ(ret, 0); - EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, NULL); - - - s = {0, NULL}; - ret = lmctfy_container_enter(&s, container_, tids, n); - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, status.error_code()); - EXPECT_EQ(errmsg, s.message); - free(s.message); - - s = {0, NULL}; - ret = lmctfy_container_enter(&s, container_, tids, -1); - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__OK); - - s = {0, NULL}; - ret = lmctfy_container_enter(&s, container_, NULL, 0); - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__OK); - - s = {0, NULL}; - ret = lmctfy_container_enter(&s, container_, tids, 0); - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__OK); - - Container *tmp = container_->container_; - container_->container_ = NULL; - s = {0, NULL}; - ret = lmctfy_container_enter(&s, container_, tids, n); - container_->container_ = tmp; - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); - - s = {0, NULL}; - ret = lmctfy_container_enter(&s, NULL, tids, n); - container_->container_ = tmp; - EXPECT_EQ(ret, s.error_code); - EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); - */ } } // namespace lmctfy From b863563428559b7d90e004f072c519ad58f336ce Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Thu, 6 Feb 2014 00:53:57 -0500 Subject: [PATCH 51/84] use macros in unit test. --- clmctfy/clmctfy_container_api.cc | 6 ++ clmctfy/clmctfy_container_api_ctest.cc | 84 ++++++++------------------ clmctfy/clmctfy_container_ctest.cc | 32 +++++----- clmctfy/clmctfy_macros_ctest.h | 30 +++++++-- 4 files changed, 70 insertions(+), 82 deletions(-) diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index f0e1874..b1d9356 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -81,6 +81,8 @@ int lmctfy_container_api_get_container(struct status *s, CHECK_NOTNULL_OR_RETURN(s, api); CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, c); + CHECK_NOTNULL_OR_RETURN(s, container_name); + CHECK_POSITIVE_OR_RETURN(s, strlen(container_name)); Container *ctnr = NULL; StatusOr statusor = api->container_api_->Get(container_name); @@ -98,6 +100,8 @@ int lmctfy_container_api_create_container_raw(struct status *s, CHECK_NOTNULL_OR_RETURN(s, api); CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, c); + CHECK_NOTNULL_OR_RETURN(s, container_name); + CHECK_POSITIVE_OR_RETURN(s, strlen(container_name)); ContainerSpec container_spec; Container *ctnr = NULL; if (spec != NULL && spec_size > 0) { @@ -120,6 +124,8 @@ int lmctfy_container_api_create_container(struct status *s, CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, c); CHECK_NOTNULL_OR_RETURN(s, spec); + CHECK_NOTNULL_OR_RETURN(s, container_name); + CHECK_POSITIVE_OR_RETURN(s, strlen(container_name)); uint8_t *buf = NULL; size_t sz = 0; int ret = 0; diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index 62d2631..e1bf896 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -14,6 +14,7 @@ #include "clmctfy.h" +#include "clmctfy_macros_ctest.h" #include "lmctfy.h" #include "lmctfy_mock.h" #include "gtest/gtest.h" @@ -86,25 +87,16 @@ TEST_F(ClmctfyContainerApiTest, GetContainer) { .WillOnce(Return(statusor_container)) .WillOnce(Return(statusor)); - struct status s = {0, NULL}; - int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); - - EXPECT_EQ(ret, 0); - EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, (const char *)NULL); + SHOULD_SUCCEED(lmctfy_container_api_get_container, &container_, container_api_, container_name); Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); - struct container *tmp = container_; container_ = NULL; - s = {0, NULL}; - ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); - - EXPECT_EQ(ret, ::util::error::INTERNAL); - EXPECT_EQ(s.error_code, ::util::error::INTERNAL); - EXPECT_EQ(container_, (struct container *)NULL); - EXPECT_EQ(errmsg, s.message); - free(s.message); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_get_container, &container_, container_api_, container_name); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_get_container, NULL, container_api_, container_name); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_get_container, &container_, container_api_, NULL); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_get_container, &container_, container_api_, ""); + WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_get_container, &container_, container_api_, container_name); container_ = tmp; } @@ -124,25 +116,18 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; - struct status s = {0, NULL}; - int ret = lmctfy_container_api_create_container(&s, &container_, container_api_, container_name, &spec); - - EXPECT_EQ(ret, 0); - EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, (const char *)NULL); + SHOULD_SUCCEED(lmctfy_container_api_create_container, &container_, container_api_, container_name, &spec); Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); - struct container *tmp = container_; container_ = NULL; - s = {0, NULL}; - ret = lmctfy_container_api_create_container(&s, &container_, container_api_, container_name, &spec); - - EXPECT_EQ(ret, ::util::error::INTERNAL); - EXPECT_EQ(s.error_code, ::util::error::INTERNAL); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_create_container, &container_, container_api_, container_name, &spec); EXPECT_EQ(container_, (struct container *)NULL); - EXPECT_EQ(errmsg, s.message); - free(s.message); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, NULL, container_api_, container_name, &spec); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, &container_, container_api_, container_name, NULL); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, &container_, container_api_, NULL, &spec); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, &container_, container_api_, "", &spec); + WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_get_container, &container_, container_api_, container_name); container_ = tmp; } @@ -162,28 +147,15 @@ TEST_F(ClmctfyContainerApiTest, DestroyContainer) { .WillOnce(Return(Status::OK)) .WillOnce(Return(destroy_status)); - struct status s = {0, NULL}; - int ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); - EXPECT_EQ(ret, 0); - EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, (const char *)NULL); - ret = lmctfy_container_api_destroy_container(&s, container_api_, container_); - container_ = NULL; - EXPECT_EQ(ret, 0); - EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, (const char *)NULL); - - s = {0, NULL}; - ret = lmctfy_container_api_get_container(&s, &container_, container_api_, container_name); - EXPECT_EQ(ret, 0); - EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, (const char *)NULL); - ret = lmctfy_container_api_destroy_container(&s, container_api_, container_); - container_ = NULL; - EXPECT_EQ(ret, ::util::error::INTERNAL); - EXPECT_EQ(s.error_code, ::util::error::INTERNAL); - EXPECT_EQ(errmsg, s.message); + SHOULD_SUCCEED(lmctfy_container_api_get_container, &container_, container_api_, container_name); + SHOULD_SUCCEED(lmctfy_container_api_destroy_container, container_api_, container_); + + SHOULD_SUCCEED(lmctfy_container_api_get_container, &container_, container_api_, container_name); + SHOULD_FAIL_WITH_ERROR(destroy_status, lmctfy_container_api_destroy_container, container_api_, container_); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_destroy_container, NULL, container_); + // XXX(monnand): Should succeed or not? + SHOULD_SUCCEED(lmctfy_container_api_destroy_container, container_api_, NULL); } #define MAX_CONTAINER_NAME_LEN 512 @@ -205,19 +177,11 @@ TEST_F(ClmctfyContainerApiTest, DetectContainer) { .WillOnce(Return(statusor)) .WillOnce(Return(statusor_fail)); - struct status s = {0, NULL}; - int ret = lmctfy_container_api_detect_container(&s, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); - EXPECT_EQ(ret, 0); - EXPECT_EQ(s.error_code, 0); - EXPECT_EQ(s.message, (const char *)NULL); + SHOULD_SUCCEED(lmctfy_container_api_detect_container, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); EXPECT_EQ(string(container_name), string(output_name)); *output_name = '\0'; - s = {0, NULL}; - ret = lmctfy_container_api_detect_container(&s, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); - EXPECT_EQ(ret, status.error_code()); - EXPECT_EQ(s.error_code, status.error_code()); - EXPECT_EQ(errmsg, s.message); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_detect_container, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); EXPECT_EQ(*output_name, '\0'); } diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 6feee7e..85e8106 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -101,10 +101,10 @@ TEST_F(ClmctfyContainerTest, Exec) { .WillOnce(Return(Status::OK)) .WillOnce(Return(status)); - SHOULD_SUCCESS_ON(lmctfy_container_exec, &s, container_, argc, argv); - SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_exec, &s, container_, argc, argv); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_exec, &s, container_, 0, NULL); - WITH_NULL_CONTAINER_RUN(lmctfy_container_exec, &s, container_, argc, argv); + SHOULD_SUCCEED(lmctfy_container_exec, container_, argc, argv); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_exec, container_, argc, argv); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_exec, container_, 0, NULL); + WITH_NULL_CONTAINER_RUN(lmctfy_container_exec, container_, argc, argv); } TEST_F(ClmctfyContainerTest, Update) { @@ -118,10 +118,10 @@ TEST_F(ClmctfyContainerTest, Update) { .WillOnce(Return(status)); int policy = CONTAINER_UPDATE_POLICY_DIFF; - SHOULD_SUCCESS_ON(lmctfy_container_update, &s, container_, policy, &spec); - SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_update, &s, container_, policy, &spec); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_update, &s, container_, -1, &spec); - WITH_NULL_CONTAINER_RUN(lmctfy_container_update, &s, container_, -1, &spec); + SHOULD_SUCCEED(lmctfy_container_update, container_, policy, &spec); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_update, container_, policy, &spec); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_update, container_, -1, &spec); + WITH_NULL_CONTAINER_RUN(lmctfy_container_update, container_, -1, &spec); } TEST_F(ClmctfyContainerTest, Run) { @@ -143,10 +143,10 @@ TEST_F(ClmctfyContainerTest, Run) { .WillOnce(Return(statusor_success)) .WillOnce(Return(statusor_fail)); - SHOULD_SUCCESS_ON(lmctfy_container_run, &s, &tid, container_, argc, argv, &runspec); - SHOULD_FAIL_WITH_ERROR(err_status, lmctfy_container_run, &s, &tid, container_, argc, argv, &runspec); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_run, &s, &tid, container_, 0, NULL, &runspec); - WITH_NULL_CONTAINER_RUN(lmctfy_container_run, &s, &tid, container_, argc, argv, &runspec); + SHOULD_SUCCEED(lmctfy_container_run, &tid, container_, argc, argv, &runspec); + SHOULD_FAIL_WITH_ERROR(err_status, lmctfy_container_run, &tid, container_, argc, argv, &runspec); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_run, &tid, container_, 0, NULL, &runspec); + WITH_NULL_CONTAINER_RUN(lmctfy_container_run, &tid, container_, argc, argv, &runspec); } TEST_F(ClmctfyContainerTest, Enter) { @@ -160,11 +160,11 @@ TEST_F(ClmctfyContainerTest, Enter) { pid_t tids[] = {1, 2, 3, 4}; int n = 4; - SHOULD_SUCCESS_ON(lmctfy_container_enter, &s, container_, tids, n); - SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_enter, &s, container_, tids, n); + SHOULD_SUCCEED(lmctfy_container_enter, container_, tids, n); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_enter, container_, tids, n); // With 0 tid, it should success. - SHOULD_SUCCESS_ON(lmctfy_container_enter, &s, container_, NULL, 0); - WITH_NULL_CONTAINER_RUN(lmctfy_container_enter, &s, container_, NULL, 0); + SHOULD_SUCCEED(lmctfy_container_enter, container_, NULL, 0); + WITH_NULL_CONTAINER_RUN(lmctfy_container_enter, container_, NULL, 0); } } // namespace lmctfy diff --git a/clmctfy/clmctfy_macros_ctest.h b/clmctfy/clmctfy_macros_ctest.h index 0226215..33b7f0d 100644 --- a/clmctfy/clmctfy_macros_ctest.h +++ b/clmctfy/clmctfy_macros_ctest.h @@ -3,11 +3,29 @@ // Some useful macros for writing test cases. +#define WITH_NULL_CONTAINER_API_RUN(func, ...) do { \ + ContainerApi *tmp = container_api_->container_api_; \ + container_api_->container_api_ = NULL; \ + struct status s = {0, NULL}; \ + int ret = func(&s, __VA_ARGS__); \ + EXPECT_EQ(ret, s.error_code); \ + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ + container_api_->container_api_ = tmp; \ + \ + struct container_api *tmp_api = container_api_; \ + container_api_ = NULL; \ + s = {0, NULL}; \ + ret = func(&s, __VA_ARGS__); \ + EXPECT_EQ(ret, s.error_code); \ + EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ + container_api_ = tmp_api; \ +} while(0) + #define WITH_NULL_CONTAINER_RUN(func, ...) do { \ Container *tmp = container_->container_; \ container_->container_ = NULL; \ struct status s = {0, NULL}; \ - int ret = func(__VA_ARGS__); \ + int ret = func(&s, __VA_ARGS__); \ EXPECT_EQ(ret, s.error_code); \ EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ container_->container_ = tmp; \ @@ -15,15 +33,15 @@ struct container *tmp_container = container_; \ container_ = NULL; \ s = {0, NULL}; \ - ret = func(__VA_ARGS__); \ + ret = func(&s, __VA_ARGS__); \ EXPECT_EQ(ret, s.error_code); \ EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ container_ = tmp_container; \ } while (0) -#define SHOULD_SUCCESS_ON(func, ...) do { \ +#define SHOULD_SUCCEED(func, ...) do { \ struct status s = {0, NULL}; \ - int ret = func(__VA_ARGS__); \ + int ret = func(&s, __VA_ARGS__); \ EXPECT_EQ(ret, 0); \ EXPECT_EQ(s.error_code, 0); \ EXPECT_EQ(s.message, NULL); \ @@ -31,7 +49,7 @@ #define SHOULD_FAIL_WITH_ERROR(st, func, ...) do { \ struct status s = {0, NULL}; \ - int ret = func(__VA_ARGS__); \ + int ret = func(&s, __VA_ARGS__); \ EXPECT_EQ(ret, s.error_code); \ EXPECT_EQ(s.error_code, (st).error_code()); \ EXPECT_EQ((st).error_message(), s.message); \ @@ -40,7 +58,7 @@ #define SHOULD_BE_INVALID_ARGUMENT(func, ...) do { \ struct status s = {0, NULL}; \ - int ret = func(__VA_ARGS__); \ + int ret = func(&s, __VA_ARGS__); \ EXPECT_EQ(ret, s.error_code); \ EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ if (s.message != NULL) { \ From b3b60e45ba1169dba4eee039733d2fb2f5ff289b Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Thu, 6 Feb 2014 01:13:50 -0500 Subject: [PATCH 52/84] more complete test cases. --- clmctfy/clmctfy_container_api_ctest.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index e1bf896..801e97f 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -153,7 +153,7 @@ TEST_F(ClmctfyContainerApiTest, DestroyContainer) { SHOULD_SUCCEED(lmctfy_container_api_get_container, &container_, container_api_, container_name); SHOULD_FAIL_WITH_ERROR(destroy_status, lmctfy_container_api_destroy_container, container_api_, container_); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_destroy_container, NULL, container_); + WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_destroy_container, container_api_, container_); // XXX(monnand): Should succeed or not? SHOULD_SUCCEED(lmctfy_container_api_destroy_container, container_api_, NULL); } @@ -183,6 +183,7 @@ TEST_F(ClmctfyContainerApiTest, DetectContainer) { *output_name = '\0'; SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_detect_container, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); EXPECT_EQ(*output_name, '\0'); + WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_detect_container, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); } } // namespace lmctfy From 7386f4fcf9daeec5b3d440cda74ab35cb1ac973c Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Thu, 6 Feb 2014 02:36:52 -0500 Subject: [PATCH 53/84] lmctfy_container_spec() --- clmctfy/clmctfy_container.cc | 31 +++++++++++++++++++++++++++++- clmctfy/clmctfy_container_ctest.cc | 19 ++++++++++++++++++ clmctfy/include/clmctfy.h | 4 ++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 5930f17..56b29d9 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -54,6 +54,7 @@ int lmctfy_container_run(struct status *s, CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, spec); CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); sz = containers__lmctfy__run_spec__get_packed_size(spec); if (sz > 0) { buf = new uint8_t[sz]; @@ -152,11 +153,12 @@ int lmctfy_container_update(struct status *s, uint8_t *buf = NULL; size_t sz = 0; - int ret = 0; + int ret = STATUS_OK; CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, spec); CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); sz = containers__lmctfy__container_spec__get_packed_size(spec); if (sz > 0) { buf = new uint8_t[sz]; @@ -168,3 +170,30 @@ int lmctfy_container_update(struct status *s, } return ret; } + +int lmctfy_container_spec(struct status *s, + struct container *container, + Containers__Lmctfy__ContainerSpec **spec) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + CHECK_NOTNULL_OR_RETURN(s, spec); + + int ret = STATUS_OK; + uint8_t *buf = NULL; + StatusOr statusor_container_spec = container->container_->Spec(); + if (!statusor_container_spec.ok()) { + return status_copy(s, statusor_container_spec.status()); + } + + const ContainerSpec container_spec = statusor_container_spec.ValueOrDie(); + int sz = container_spec.ByteSize(); + *spec = NULL; + if (sz > 0) { + buf = new uint8_t[sz]; + container_spec.SerializeToArray(buf, sz); + *spec = containers__lmctfy__container_spec__unpack(NULL, sz, buf); + delete []buf; + } + return ret; +} diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 85e8106..c509096 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -167,5 +167,24 @@ TEST_F(ClmctfyContainerTest, Enter) { WITH_NULL_CONTAINER_RUN(lmctfy_container_enter, container_, NULL, 0); } +TEST_F(ClmctfyContainerTest, Spec) { + StrictMockContainer *mock_container = GetMockContainer(); + Status status(::util::error::INTERNAL, "some error message"); + + ContainerSpec spec; + StatusOr statusor_spec(spec); + StatusOr statusor_fail(status); + + EXPECT_CALL(*mock_container, Spec()) + .WillOnce(Return(statusor_spec)) + .WillOnce(Return(statusor_fail)); + + Containers__Lmctfy__ContainerSpec *container_spec; + SHOULD_SUCCEED(lmctfy_container_spec, container_, &container_spec); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_spec, container_, &container_spec); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_spec, container_, NULL); + WITH_NULL_CONTAINER_RUN(lmctfy_container_spec, container_, &container_spec); +} + } // namespace lmctfy } // namespace containers diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index cb690d4..164816f 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -183,6 +183,10 @@ int lmctfy_container_update(struct status *s, int policy, const Containers__Lmctfy__ContainerSpec *spec); +int lmctfy_container_spec(struct status *s, + struct container *container, + Containers__Lmctfy__ContainerSpec **spec); + #ifdef __cplusplus } #endif // __cplusplus From 882266ee915e89af42108a41d35c334defb9b019 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 7 Feb 2014 22:41:30 -0500 Subject: [PATCH 54/84] lmctfy_container_list_subcontainers() --- clmctfy/clmctfy_container.cc | 55 ++++++++++++++++++++++++++++++ clmctfy/clmctfy_container_ctest.cc | 42 ++++++++++++++++++++++- clmctfy/include/clmctfy.h | 42 +++++++++++++++++++++++ 3 files changed, 138 insertions(+), 1 deletion(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 56b29d9..eb360a0 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -197,3 +197,58 @@ int lmctfy_container_spec(struct status *s, } return ret; } + +int lmctfy_container_list_subcontainers(struct status *s, + struct container **subcontainers[], + int *nr_subcontainers, + struct container *c, + int list_policy) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, c); + CHECK_NOTNULL_OR_RETURN(s, c->container_); + CHECK_NOTNULL_OR_RETURN(s, subcontainers); + CHECK_NOTNULL_OR_RETURN(s, nr_subcontainers); + + *nr_subcontainers = 0; + *subcontainers = NULL; + Container::ListPolicy policy; + + switch (list_policy) { + case CONTAINER_LIST_POLICY_SELF: + policy = Container::LIST_SELF; + break; + case CONTAINER_LIST_POLICY_RECURSIVE: + policy = Container::LIST_RECURSIVE; + break; + default: + return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "Unknown list policy: %d", list_policy); + } + + StatusOr< vector > statusor_subcontainers = + c->container_->ListSubcontainers(policy); + + if (!statusor_subcontainers.ok()) { + return status_copy(s, statusor_subcontainers.status()); + } + + const vector &subcontainers_vector = statusor_subcontainers.ValueOrDie(); + if (subcontainers_vector.size() == 0) { + return STATUS_OK; + } + struct container **subctnrs = (struct container **)malloc(sizeof(struct container *) * subcontainers_vector.size()); + if (subctnrs == NULL) { + return status_new(s, UTIL__ERROR__CODE__RESOURCE_EXHAUSTED, "out of memory"); + } + *subcontainers = subctnrs; + *nr_subcontainers = subcontainers_vector.size(); + + vector::const_iterator container_iter = subcontainers_vector.begin(); + for (container_iter = subcontainers_vector.begin(); container_iter != subcontainers_vector.end(); container_iter++) { + struct container *ctnr = new container(); + ctnr->container_ = *container_iter; + *subctnrs = ctnr; + subctnrs++; + } + return STATUS_OK; +} + diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index c509096..6211c6e 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -49,7 +49,8 @@ class ClmctfyContainerTest : public ::testing::Test { virtual void SetUp() { container_api_ = NULL; container_ = NULL; - const char *container_name = "test"; + const char *container_name = "/test"; + container_name_ = container_name; lmctfy_new_container_api(NULL, &container_api_); StrictMockContainerApi *mock_api = GetMockApi(); Container *ctnr = new StrictMockContainer(container_name); @@ -71,6 +72,7 @@ class ClmctfyContainerTest : public ::testing::Test { struct container *container_; StrictMockContainerApi *GetMockApi(); StrictMockContainer *GetMockContainer(); + string container_name_; }; StrictMockContainerApi *ClmctfyContainerTest::GetMockApi() { @@ -186,5 +188,43 @@ TEST_F(ClmctfyContainerTest, Spec) { WITH_NULL_CONTAINER_RUN(lmctfy_container_spec, container_, &container_spec); } +TEST_F(ClmctfyContainerTest, ListSubContainers) { + StrictMockContainer *mock_container = GetMockContainer(); + Status status(::util::error::INTERNAL, "some error message"); + + StrictMockContainer *ctnr1 = new StrictMockContainer("container1"); + StrictMockContainer *ctnr2 = new StrictMockContainer("container2"); + + vector subcontainers_vector(2); + subcontainers_vector[0] = ctnr1; + subcontainers_vector[1] = ctnr2; + StatusOr> statusor_subcontainers(subcontainers_vector); + Container::ListPolicy policy = Container::LIST_SELF; + + StatusOr> statusor_fail(status); + + EXPECT_CALL(*mock_container, ListSubcontainers(policy)) + .WillOnce(Return(statusor_subcontainers)) + .WillOnce(Return(statusor_fail)); + + struct container **subcontainers; + int nr_containers; + SHOULD_SUCCEED(lmctfy_container_list_subcontainers, &subcontainers, &nr_containers, container_, CONTAINER_LIST_POLICY_SELF); + EXPECT_EQ(nr_containers, subcontainers_vector.size()); + vector::iterator iter; + int i = 0; + for (i = 0, iter = subcontainers_vector.begin(); iter != subcontainers_vector.end(); iter++, i++) { + Container *ctnr = internal::lmctfy_container_strip(subcontainers[i]); + EXPECT_EQ(*iter, ctnr); + lmctfy_delete_container(subcontainers[i]); + } + free(subcontainers); + + subcontainers = NULL; + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_list_subcontainers, &subcontainers, &nr_containers, container_, CONTAINER_LIST_POLICY_SELF); + EXPECT_EQ(nr_containers, 0); + EXPECT_EQ(subcontainers, (struct container **)NULL); +} + } // namespace lmctfy } // namespace containers diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 164816f..08aa5bc 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -14,6 +14,16 @@ enum { CONTAINER_UPDATE_POLICY_REPLACE }; +enum { + CONTAINER_LIST_POLICY_SELF, + CONTAINER_LIST_POLICY_RECURSIVE +}; + +enum { + CONTAINER_STATS_TYPE_SUMMARY, + CONTAINER_STATS_TYPE_FULL +}; + struct status { int error_code; @@ -22,9 +32,22 @@ struct status { char *message; }; + struct container; struct container_api; +// Callback used on an event notification. +// +// The container and status structure pointers are only valid within the +// callback. +// +// - container: The container that received the notification. It is an error +// to delete it. +// - status: The status of the notification. If OK, then the event registered +// occured. Otherwise, an error is reported in the status. Errors may +// be caused by container deletion or unexpected registration errors. +typedef void lmctfy_event_callback_f(struct container *, const struct status *); + // Initializes the machine to start being able to create containers. // // Arguments: @@ -187,6 +210,25 @@ int lmctfy_container_spec(struct status *s, struct container *container, Containers__Lmctfy__ContainerSpec **spec); +// List all subcontainers. +// +// Arguments: +// +// - s: [output] +// - subcontainers: [output] The address of a pointer points to an array of +// struct container pointers. The caller takes the onwership. On success, the +// pointer will be assigned an address to an array of containers. The pointed +// array should be released with free(). The containers inside the array +// should be deleted/destroyed individually. +// - nr_subcontainers: [output] The address of an integer used to store number +// of subcontainers in the array. +// - container: The container +// - list_policy: CONTAINER_LIST_POLICY_SELF or CONTAINER_LIST_POLICY_RECURSIVE +int lmctfy_container_list_subcontainers(struct status *s, + struct container **subcontainers[], + int *nr_subcontainers, + struct container *container, + int list_policy); #ifdef __cplusplus } #endif // __cplusplus From 53b19fa0aa71709a91308c198e6d6fde6b11ede8 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Sat, 8 Feb 2014 00:38:54 -0500 Subject: [PATCH 55/84] lmctfy_list_processes/threads() --- clmctfy/clmctfy_container.cc | 88 ++++++++++++++++++++++++++++++ clmctfy/clmctfy_container_ctest.cc | 83 ++++++++++++++++++++++++++++ clmctfy/include/clmctfy.h | 12 ++++ 3 files changed, 183 insertions(+) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index eb360a0..ad71994 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -252,3 +252,91 @@ int lmctfy_container_list_subcontainers(struct status *s, return STATUS_OK; } +int lmctfy_container_list_threads(struct status *s, + pid_t *threads[], + int *nr_threads, + struct container *c, + int list_policy) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, c); + CHECK_NOTNULL_OR_RETURN(s, c->container_); + CHECK_NOTNULL_OR_RETURN(s, threads); + CHECK_NOTNULL_OR_RETURN(s, nr_threads); + + *threads = NULL; + *nr_threads = 0; + Container::ListPolicy policy; + switch (list_policy) { + case CONTAINER_LIST_POLICY_SELF: + policy = Container::LIST_SELF; + break; + case CONTAINER_LIST_POLICY_RECURSIVE: + policy = Container::LIST_RECURSIVE; + break; + default: + return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "Unknown list policy: %d", list_policy); + } + + StatusOr> statusor_pids = c->container_->ListThreads(policy); + if (!statusor_pids.ok()) { + return status_copy(s, statusor_pids.status()); + } + const vector &pids = statusor_pids.ValueOrDie(); + *nr_threads = pids.size(); + if (*nr_threads == 0) { + return STATUS_OK; + } + + pid_t *ptr = (pid_t *)malloc(sizeof(pid_t) * pids.size()); + *threads = ptr; + vector::const_iterator iter; + for (iter = pids.begin(); iter != pids.end(); iter++, ptr++) { + *ptr = *iter; + } + return STATUS_OK; +} + +int lmctfy_container_list_processes(struct status *s, + pid_t *processes[], + int *nr_processes, + struct container *c, + int list_policy) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, c); + CHECK_NOTNULL_OR_RETURN(s, c->container_); + CHECK_NOTNULL_OR_RETURN(s, processes); + CHECK_NOTNULL_OR_RETURN(s, nr_processes); + + *processes = NULL; + *nr_processes = 0; + Container::ListPolicy policy; + switch (list_policy) { + case CONTAINER_LIST_POLICY_SELF: + policy = Container::LIST_SELF; + break; + case CONTAINER_LIST_POLICY_RECURSIVE: + policy = Container::LIST_RECURSIVE; + break; + default: + return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "Unknown list policy: %d", list_policy); + } + + StatusOr> statusor_pids = c->container_->ListProcesses(policy); + if (!statusor_pids.ok()) { + return status_copy(s, statusor_pids.status()); + } + const vector &pids = statusor_pids.ValueOrDie(); + *nr_processes = pids.size(); + if (*nr_processes == 0) { + return STATUS_OK; + } + + pid_t *ptr = (pid_t *)malloc(sizeof(pid_t) * pids.size()); + *processes = ptr; + vector::const_iterator iter; + for (iter = pids.begin(); iter != pids.end(); iter++, ptr++) { + *ptr = *iter; + } + return STATUS_OK; +} + diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 6211c6e..ca558ce 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -224,6 +224,89 @@ TEST_F(ClmctfyContainerTest, ListSubContainers) { SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_list_subcontainers, &subcontainers, &nr_containers, container_, CONTAINER_LIST_POLICY_SELF); EXPECT_EQ(nr_containers, 0); EXPECT_EQ(subcontainers, (struct container **)NULL); + + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_subcontainers, NULL, &nr_containers, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_subcontainers, &subcontainers, NULL, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_subcontainers, &subcontainers, &nr_containers, container_, -1); + WITH_NULL_CONTAINER_RUN(lmctfy_container_list_subcontainers, &subcontainers, &nr_containers, container_, CONTAINER_LIST_POLICY_SELF); +} + +TEST_F(ClmctfyContainerTest, ListThreads) { + StrictMockContainer *mock_container = GetMockContainer(); + Status status(::util::error::INTERNAL, "some error message"); + + int N = 10; + vector pids_vector(N); + for (int i = 0; i < N; i++) { + pids_vector[i] = i + 1; + } + + StatusOr> statusor_pids(pids_vector); + StatusOr> statusor_fail(status); + Container::ListPolicy policy = Container::LIST_SELF; + + EXPECT_CALL(*mock_container, ListThreads(policy)) + .WillOnce(Return(statusor_pids)) + .WillOnce(Return(statusor_fail)); + + pid_t *pids; + int nr_threads; + SHOULD_SUCCEED(lmctfy_container_list_threads, &pids, &nr_threads, container_, CONTAINER_LIST_POLICY_SELF); + EXPECT_EQ(nr_threads, pids_vector.size()); + vector::const_iterator iter; + int i = 0; + for (i = 0, iter = pids_vector.begin(); iter != pids_vector.end(); iter++, i++) { + EXPECT_EQ(pids[i], *iter); + } + free(pids); + + pids = NULL; + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_list_threads, &pids, &nr_threads, container_, CONTAINER_LIST_POLICY_SELF); + EXPECT_EQ(nr_threads, 0); + EXPECT_EQ(pids, (pid_t *)NULL); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_threads, NULL, &nr_threads, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_threads, &pids, NULL, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_threads, &pids, &nr_threads, container_, -1); + WITH_NULL_CONTAINER_RUN(lmctfy_container_list_threads, &pids, &nr_threads, container_, CONTAINER_LIST_POLICY_SELF); +} + +TEST_F(ClmctfyContainerTest, ListProcesses) { + StrictMockContainer *mock_container = GetMockContainer(); + Status status(::util::error::INTERNAL, "some error message"); + + int N = 10; + vector pids_vector(N); + for (int i = 0; i < N; i++) { + pids_vector[i] = i + 1; + } + + StatusOr> statusor_pids(pids_vector); + StatusOr> statusor_fail(status); + Container::ListPolicy policy = Container::LIST_SELF; + + EXPECT_CALL(*mock_container, ListProcesses(policy)) + .WillOnce(Return(statusor_pids)) + .WillOnce(Return(statusor_fail)); + + pid_t *pids; + int nr_processes; + SHOULD_SUCCEED(lmctfy_container_list_processes, &pids, &nr_processes, container_, CONTAINER_LIST_POLICY_SELF); + EXPECT_EQ(nr_processes, pids_vector.size()); + vector::const_iterator iter; + int i = 0; + for (i = 0, iter = pids_vector.begin(); iter != pids_vector.end(); iter++, i++) { + EXPECT_EQ(pids[i], *iter); + } + free(pids); + + pids = NULL; + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_list_processes, &pids, &nr_processes, container_, CONTAINER_LIST_POLICY_SELF); + EXPECT_EQ(nr_processes, 0); + EXPECT_EQ(pids, (pid_t *)NULL); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_processes, NULL, &nr_processes, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_processes, &pids, NULL, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_processes, &pids, &nr_processes, container_, -1); + WITH_NULL_CONTAINER_RUN(lmctfy_container_list_processes, &pids, &nr_processes, container_, CONTAINER_LIST_POLICY_SELF); } } // namespace lmctfy diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 08aa5bc..0bb8be2 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -229,6 +229,18 @@ int lmctfy_container_list_subcontainers(struct status *s, int *nr_subcontainers, struct container *container, int list_policy); + +int lmctfy_container_list_threads(struct status *s, + pid_t *threads[], + int *nr_threads, + struct container *container, + int list_policy); + +int lmctfy_container_list_processes(struct status *s, + pid_t *processes[], + int *nr_processes, + struct container *container, + int list_policy); #ifdef __cplusplus } #endif // __cplusplus From 1418aa1b8e5037a3b90783f0c1e03b16b50bd2c8 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Sat, 8 Feb 2014 02:23:13 -0500 Subject: [PATCH 56/84] register_nitification() --- clmctfy/clmctfy_container.cc | 152 ++++++++++++++++++++++++++++++++++- clmctfy/clmctfy_internal.h | 22 +++-- clmctfy/include/clmctfy.h | 23 +++++- 3 files changed, 187 insertions(+), 10 deletions(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index ad71994..5c60eab 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -2,7 +2,10 @@ #include "lmctfy.h" #include "clmctfy_internal.h" #include "util/task/statusor.h" +#include "base/callback.h" +#include "base/macros.h" #include +#include using namespace ::containers::lmctfy; using ::util::internal::status_copy; @@ -11,6 +14,7 @@ using ::util::Status; using ::util::StatusOr; using ::util::error::INVALID_ARGUMENT; using ::std::vector; +using ::std::unordered_map; #define STATUS_OK UTIL__ERROR__CODE__OK @@ -186,7 +190,7 @@ int lmctfy_container_spec(struct status *s, return status_copy(s, statusor_container_spec.status()); } - const ContainerSpec container_spec = statusor_container_spec.ValueOrDie(); + const ContainerSpec &container_spec = statusor_container_spec.ValueOrDie(); int sz = container_spec.ByteSize(); *spec = NULL; if (sz > 0) { @@ -340,3 +344,149 @@ int lmctfy_container_list_processes(struct status *s, return STATUS_OK; } +int lmctfy_container_pause(struct status *s, + struct container *container) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + + Status status = container->container_->Pause(); + return status_copy(s, status); +} + +int lmctfy_container_resume(struct status *s, + struct container *container) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + + Status status = container->container_->Resume(); + return status_copy(s, status); +} + +int lmctfy_container_killall(struct status *s, + struct container *container) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + + Status status = container->container_->KillAll(); + return status_copy(s, status); +} + +int lmctfy_container_stats(struct status *s, + struct container *container, + int stats_type, + Containers__Lmctfy__ContainerStats **stats) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + CHECK_NOTNULL_OR_RETURN(s, stats); + + int ret = STATUS_OK; + uint8_t *buf = NULL; + Container::StatsType type; + switch (stats_type) { + case CONTAINER_STATS_TYPE_SUMMARY: + type = Container::STATS_SUMMARY; + break; + case CONTAINER_STATS_TYPE_FULL: + type = Container::STATS_FULL; + break; + default: + return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "Unknown stats type: %d", stats_type); + } + StatusOr statusor_container_stats = container->container_->Stats(type); + if (!statusor_container_stats.ok()) { + return status_copy(s, statusor_container_stats.status()); + } + + const ContainerStats &container_stats = statusor_container_stats.ValueOrDie(); + int sz = container_stats.ByteSize(); + *stats = NULL; + if (sz > 0) { + buf = new uint8_t[sz]; + container_stats.SerializeToArray(buf, sz); + *stats = containers__lmctfy__container_stats__unpack(NULL, sz, buf); + delete []buf; + } + return ret; +} + +const char *lmctfy_container_name(struct container *container) { + if (container == NULL) { + return NULL; + } + if (container->container_ == NULL) { + return NULL; + } + return container->container_->name().c_str(); +} + +inline void EventCallbackWrapper::Run(Container *c, Status s) { + if (callback_ == NULL) { + return; + } + struct container ctnr; + struct status sts; + ctnr.container_ = c; + status_copy(&sts, s); + + if (c == NULL) { + callback_(NULL, &sts); + } else { + callback_(&ctnr, &sts); + } + if (sts.message != NULL) { + free(sts.message); + } +} + +int lmctfy_container_register_notification_raw(struct status *s, + notification_id_t *notif_id, + struct container *container, + lmctfy_event_callback_f callback, + const void *spec, + const size_t spec_size) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + EventSpec event_spec; + if (spec != NULL && spec_size > 0) { + event_spec.ParseFromArray(spec, spec_size); + } + EventCallbackWrapper *cb = new EventCallbackWrapper(callback); + + // Container object does not take the ownership of the callback. + StatusOr statusor_id = container->container_->RegisterNotification(event_spec, cb); + + if (!statusor_id.ok()) { + delete cb; + return status_copy(s, statusor_id.status()); + } + notification_id_t nid = statusor_id.ValueOrDie(); + container->notif_map_[nid] = cb; + *notif_id = nid; + return STATUS_OK; +} + + +int lmctfy_container_unregister_notification_raw(struct status *s, + struct container *container, + const notification_id_t notif_id) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + unordered_map::iterator iter = + container->notif_map_.find(notif_id); + if (iter == container->notif_map_.end()) { + return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "unknown notification id"); + } + Status status = container->container_->UnregisterNotification(notif_id); + if (!status.ok()) { + return status_copy(s, status); + } + container->notif_map_.erase(iter); + delete iter->second; + return STATUS_OK; +} diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index 941b936..cdd6eef 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -7,26 +7,32 @@ #include "util/task/statusor.h" #include "lmctfy.h" +#include + using ::containers::lmctfy::Container; using ::containers::lmctfy::ContainerApi; -#ifdef __cplusplus -// XXX(monnand): Do we need to extern "C"? -extern "C" { -#endif // __cplusplus +class EventCallbackWrapper : public Callback2 { + public: + EventCallbackWrapper(lmctfy_event_callback_f cb) : callback_(cb) { } + EventCallbackWrapper(EventCallbackWrapper &other) : callback_(other.callback_) { } + void operator=(const EventCallbackWrapper &rhs) { callback_ = rhs.callback_; } + virtual ~EventCallbackWrapper() {} + virtual bool IsRepeatable() const { return true; } + virtual void Run(Container *c, ::util::Status s); + private: + lmctfy_event_callback_f callback_; +}; struct container { Container *container_; + ::std::unordered_map notif_map_; }; struct container_api { ContainerApi *container_api_; }; -#ifdef __cplusplus -} -#endif // __cplusplus - #define RETURN_IF_ERROR_PTR(s, ...) \ do { \ const ::util::Status _status = \ diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 0bb8be2..ae736c8 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -2,6 +2,7 @@ #define LMCTFY_C_BINDING_LMCTFY_C_H_ #include +#include #include "lmctfy.pb-c.h" #include "util/task/codes.pb-c.h" @@ -46,7 +47,10 @@ struct container_api; // - status: The status of the notification. If OK, then the event registered // occured. Otherwise, an error is reported in the status. Errors may // be caused by container deletion or unexpected registration errors. -typedef void lmctfy_event_callback_f(struct container *, const struct status *); +// it will be an error if the user call free(s->message); +typedef void (*lmctfy_event_callback_f)(struct container *, const struct status *); + +typedef uint64_t notification_id_t; // Initializes the machine to start being able to create containers. // @@ -241,6 +245,23 @@ int lmctfy_container_list_processes(struct status *s, int *nr_processes, struct container *container, int list_policy); + +int lmctfy_container_pause(struct status *s, + struct container *container); + +int lmctfy_container_resume(struct status *s, + struct container *container); + +int lmctfy_container_killall(struct status *s, + struct container *container); + +int lmctfy_container_stats(struct status *s, + struct container *container, + int stats_type, + Containers__Lmctfy__ContainerStats **stats); + +const char *lmctfy_container_name(struct container *container); + #ifdef __cplusplus } #endif // __cplusplus From ec915bdf9f7e15075cf44d018ef0cc1ab52f5380 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Sat, 8 Feb 2014 02:28:49 -0500 Subject: [PATCH 57/84] register_notification() --- clmctfy/clmctfy_container.cc | 35 ++++++++++++++++++++++++++++++++--- clmctfy/clmctfy_internal.h | 5 ++--- clmctfy/include/clmctfy-raw.h | 7 +++++++ clmctfy/include/clmctfy.h | 10 ++++++++++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 5c60eab..fb4f9df 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -451,6 +451,8 @@ int lmctfy_container_register_notification_raw(struct status *s, CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); + CHECK_NOTNULL_OR_RETURN(s, notif_id); + CHECK_NOTNULL_OR_RETURN(s, callback); EventSpec event_spec; if (spec != NULL && spec_size > 0) { event_spec.ParseFromArray(spec, spec_size); @@ -470,10 +472,37 @@ int lmctfy_container_register_notification_raw(struct status *s, return STATUS_OK; } +int lmctfy_container_register_notification(struct status *s, + notification_id_t *notif_id, + struct container *container, + lmctfy_event_callback_f callback, + Containers__Lmctfy__EventSpec *spec) { -int lmctfy_container_unregister_notification_raw(struct status *s, - struct container *container, - const notification_id_t notif_id) { + uint8_t *buf = NULL; + size_t sz = 0; + int ret = 0; + + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, spec); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + CHECK_NOTNULL_OR_RETURN(s, notif_id); + CHECK_NOTNULL_OR_RETURN(s, callback); + sz = containers__lmctfy__event_spec__get_packed_size(spec); + if (sz > 0) { + buf = new uint8_t[sz]; + containers__lmctfy__event_spec__pack(spec, buf); + } + ret = lmctfy_container_register_notification_raw(s, notif_id, container, callback, buf, sz); + if (buf != NULL) { + delete []buf; + } + return ret; +} + +int lmctfy_container_unregister_notification(struct status *s, + struct container *container, + const notification_id_t notif_id) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index cdd6eef..13673b5 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -15,18 +15,17 @@ using ::containers::lmctfy::ContainerApi; class EventCallbackWrapper : public Callback2 { public: EventCallbackWrapper(lmctfy_event_callback_f cb) : callback_(cb) { } - EventCallbackWrapper(EventCallbackWrapper &other) : callback_(other.callback_) { } - void operator=(const EventCallbackWrapper &rhs) { callback_ = rhs.callback_; } virtual ~EventCallbackWrapper() {} virtual bool IsRepeatable() const { return true; } virtual void Run(Container *c, ::util::Status s); private: lmctfy_event_callback_f callback_; + DISALLOW_COPY_AND_ASSIGN(EventCallbackWrapper); }; struct container { Container *container_; - ::std::unordered_map notif_map_; + ::std::unordered_map notif_map_; }; struct container_api { diff --git a/clmctfy/include/clmctfy-raw.h b/clmctfy/include/clmctfy-raw.h index 4aa38dd..5c011a0 100644 --- a/clmctfy/include/clmctfy-raw.h +++ b/clmctfy/include/clmctfy-raw.h @@ -42,6 +42,13 @@ int lmctfy_container_update_raw(struct status *s, const void *spec, const size_t spec_size); +int lmctfy_container_register_notification_raw(struct status *s, + notification_id_t *notif_id, + struct container *container, + lmctfy_event_callback_f callback, + const void *spec, + const size_t spec_size); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index ae736c8..bf7fb8e 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -262,6 +262,16 @@ int lmctfy_container_stats(struct status *s, const char *lmctfy_container_name(struct container *container); +int lmctfy_container_register_notification(struct status *s, + notification_id_t *notif_id, + struct container *container, + lmctfy_event_callback_f callback, + Containers__Lmctfy__EventSpec *spec); + +int lmctfy_container_unregister_notification(struct status *s, + struct container *container, + const notification_id_t notif_id); + #ifdef __cplusplus } #endif // __cplusplus From f623ad27919c18f2f0236f06425160683dd7411b Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Sat, 8 Feb 2014 03:04:39 -0500 Subject: [PATCH 58/84] user_data for callback. --- clmctfy/clmctfy_container.cc | 32 ++++++++++++++++++++++---------- clmctfy/clmctfy_internal.h | 9 ++++++++- clmctfy/include/clmctfy-raw.h | 1 + clmctfy/include/clmctfy.h | 6 +++++- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index fb4f9df..6982733 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -427,18 +427,28 @@ inline void EventCallbackWrapper::Run(Container *c, Status s) { if (callback_ == NULL) { return; } - struct container ctnr; struct status sts; - ctnr.container_ = c; status_copy(&sts, s); - + if (c != container_->container_) { + struct container ctnr; + ctnr.container_ = c; + // This should never happen. + status_new(&sts, UTIL__ERROR__CODE__UNKNOWN, "Unknown container passed to the callback"); + callback_(NULL, &sts, user_data_); + if (c == NULL) { + callback_(NULL, &sts, user_data_); + } else { + callback_(&ctnr, &sts, user_data_); + } + if (sts.message != NULL) { + free(sts.message); + } + return; + } if (c == NULL) { - callback_(NULL, &sts); + callback_(NULL, &sts, user_data_); } else { - callback_(&ctnr, &sts); - } - if (sts.message != NULL) { - free(sts.message); + callback_(container_, &sts, user_data_); } } @@ -446,6 +456,7 @@ int lmctfy_container_register_notification_raw(struct status *s, notification_id_t *notif_id, struct container *container, lmctfy_event_callback_f callback, + void *user_data, const void *spec, const size_t spec_size) { CHECK_NOTFAIL_OR_RETURN(s); @@ -457,7 +468,7 @@ int lmctfy_container_register_notification_raw(struct status *s, if (spec != NULL && spec_size > 0) { event_spec.ParseFromArray(spec, spec_size); } - EventCallbackWrapper *cb = new EventCallbackWrapper(callback); + EventCallbackWrapper *cb = new EventCallbackWrapper(container, callback, user_data); // Container object does not take the ownership of the callback. StatusOr statusor_id = container->container_->RegisterNotification(event_spec, cb); @@ -476,6 +487,7 @@ int lmctfy_container_register_notification(struct status *s, notification_id_t *notif_id, struct container *container, lmctfy_event_callback_f callback, + void *user_data, Containers__Lmctfy__EventSpec *spec) { uint8_t *buf = NULL; @@ -493,7 +505,7 @@ int lmctfy_container_register_notification(struct status *s, buf = new uint8_t[sz]; containers__lmctfy__event_spec__pack(spec, buf); } - ret = lmctfy_container_register_notification_raw(s, notif_id, container, callback, buf, sz); + ret = lmctfy_container_register_notification_raw(s, notif_id, container, callback, user_data, buf, sz); if (buf != NULL) { delete []buf; } diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index 13673b5..ba326bc 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -14,12 +14,19 @@ using ::containers::lmctfy::ContainerApi; class EventCallbackWrapper : public Callback2 { public: - EventCallbackWrapper(lmctfy_event_callback_f cb) : callback_(cb) { } + EventCallbackWrapper(struct container *c, + lmctfy_event_callback_f cb, + void *user_data) + : container_(c), + callback_(cb), + user_data_(user_data) { } virtual ~EventCallbackWrapper() {} virtual bool IsRepeatable() const { return true; } virtual void Run(Container *c, ::util::Status s); private: lmctfy_event_callback_f callback_; + void *user_data_; + struct container *container_; DISALLOW_COPY_AND_ASSIGN(EventCallbackWrapper); }; diff --git a/clmctfy/include/clmctfy-raw.h b/clmctfy/include/clmctfy-raw.h index 5c011a0..f77046b 100644 --- a/clmctfy/include/clmctfy-raw.h +++ b/clmctfy/include/clmctfy-raw.h @@ -46,6 +46,7 @@ int lmctfy_container_register_notification_raw(struct status *s, notification_id_t *notif_id, struct container *container, lmctfy_event_callback_f callback, + void *user_data, const void *spec, const size_t spec_size); diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index bf7fb8e..6d0b79f 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -48,7 +48,10 @@ struct container_api; // occured. Otherwise, an error is reported in the status. Errors may // be caused by container deletion or unexpected registration errors. // it will be an error if the user call free(s->message); -typedef void (*lmctfy_event_callback_f)(struct container *, const struct status *); +// - user_data: +typedef void (*lmctfy_event_callback_f)(struct container *container, + const struct status *status, + void *user_data); typedef uint64_t notification_id_t; @@ -266,6 +269,7 @@ int lmctfy_container_register_notification(struct status *s, notification_id_t *notif_id, struct container *container, lmctfy_event_callback_f callback, + void *user_data, Containers__Lmctfy__EventSpec *spec); int lmctfy_container_unregister_notification(struct status *s, From d8709f3357d49c2a5fd04467833d8489009538ad Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Sat, 8 Feb 2014 03:07:15 -0500 Subject: [PATCH 59/84] Done. Need to test. --- clmctfy/clmctfy_internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index ba326bc..abdb618 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -32,6 +32,7 @@ class EventCallbackWrapper : public Callback2 { struct container { Container *container_; + // TODO(monnand): Make it thread-safe? ::std::unordered_map notif_map_; }; From cd42f04380f11071627ef961e011e2296c03a135 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Sat, 8 Feb 2014 19:45:44 -0500 Subject: [PATCH 60/84] EventCallbackWrapper --- clmctfy/clmctfy_container.cc | 48 +++++++++++++++++++++++++----------- clmctfy/clmctfy_internal.h | 1 + 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 6982733..c273124 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -429,26 +429,35 @@ inline void EventCallbackWrapper::Run(Container *c, Status s) { } struct status sts; status_copy(&sts, s); + if (c == NULL) { + callback_(NULL, &sts, user_data_); + if (sts.message != NULL) { + free(sts.message); + } + return; + } if (c != container_->container_) { + char *oldmsg = sts.message; + int olderrcode = sts.error_code; struct container ctnr; ctnr.container_ = c; // This should never happen. - status_new(&sts, UTIL__ERROR__CODE__UNKNOWN, "Unknown container passed to the callback"); - callback_(NULL, &sts, user_data_); - if (c == NULL) { - callback_(NULL, &sts, user_data_); - } else { - callback_(&ctnr, &sts, user_data_); - } + status_new(&sts, UTIL__ERROR__CODE__UNKNOWN, + "Unknown container passed to the callback. " + "(ErrorCode=%d, Message=\"%s\")", olderrcode, + (oldmsg == NULL ? "" : oldmsg)); + callback_(&ctnr, &sts, user_data_); if (sts.message != NULL) { free(sts.message); } + if (oldmsg != NULL) { + free(oldmsg); + } return; } - if (c == NULL) { - callback_(NULL, &sts, user_data_); - } else { - callback_(container_, &sts, user_data_); + callback_(container_, &sts, user_data_); + if (sts.message != NULL) { + free(sts.message); } } @@ -468,10 +477,12 @@ int lmctfy_container_register_notification_raw(struct status *s, if (spec != NULL && spec_size > 0) { event_spec.ParseFromArray(spec, spec_size); } - EventCallbackWrapper *cb = new EventCallbackWrapper(container, callback, user_data); + EventCallbackWrapper *cb = + new EventCallbackWrapper(container, callback, user_data); // Container object does not take the ownership of the callback. - StatusOr statusor_id = container->container_->RegisterNotification(event_spec, cb); + StatusOr statusor_id = + container->container_->RegisterNotification(event_spec, cb); if (!statusor_id.ok()) { delete cb; @@ -505,7 +516,13 @@ int lmctfy_container_register_notification(struct status *s, buf = new uint8_t[sz]; containers__lmctfy__event_spec__pack(spec, buf); } - ret = lmctfy_container_register_notification_raw(s, notif_id, container, callback, user_data, buf, sz); + ret = lmctfy_container_register_notification_raw(s, + notif_id, + container, + callback, + user_data, + buf, + sz); if (buf != NULL) { delete []buf; } @@ -523,7 +540,8 @@ int lmctfy_container_unregister_notification(struct status *s, if (iter == container->notif_map_.end()) { return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "unknown notification id"); } - Status status = container->container_->UnregisterNotification(notif_id); + Status status = + container->container_->UnregisterNotification(notif_id); if (!status.ok()) { return status_copy(s, status); } diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index abdb618..5550258 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -27,6 +27,7 @@ class EventCallbackWrapper : public Callback2 { lmctfy_event_callback_f callback_; void *user_data_; struct container *container_; + Container::NotificationId notif_id_; DISALLOW_COPY_AND_ASSIGN(EventCallbackWrapper); }; From da83fd8ef92eb430fbce2e25f8e3aa988ada894c Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Sun, 9 Feb 2014 23:47:08 -0500 Subject: [PATCH 61/84] simple test cases. --- clmctfy/clmctfy_container_ctest.cc | 53 ++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index ca558ce..752695e 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -309,5 +309,58 @@ TEST_F(ClmctfyContainerTest, ListProcesses) { WITH_NULL_CONTAINER_RUN(lmctfy_container_list_processes, &pids, &nr_processes, container_, CONTAINER_LIST_POLICY_SELF); } +TEST_F(ClmctfyContainerTest, Pause) { + StrictMockContainer *mock_container = GetMockContainer(); + Status status(::util::error::INTERNAL, "some error message"); + + EXPECT_CALL(*mock_container, Pause()) + .WillOnce(Return(Status::OK)) + .WillOnce(Return(status)); + + SHOULD_SUCCEED(lmctfy_container_pause, container_); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_pause, container_); + WITH_NULL_CONTAINER_RUN(lmctfy_container_pause, container_); +} + +TEST_F(ClmctfyContainerTest, Resume) { + StrictMockContainer *mock_container = GetMockContainer(); + Status status(::util::error::INTERNAL, "some error message"); + + EXPECT_CALL(*mock_container, Resume()) + .WillOnce(Return(Status::OK)) + .WillOnce(Return(status)); + + SHOULD_SUCCEED(lmctfy_container_resume, container_); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_resume, container_); + WITH_NULL_CONTAINER_RUN(lmctfy_container_resume, container_); +} + +TEST_F(ClmctfyContainerTest, KillAll) { + StrictMockContainer *mock_container = GetMockContainer(); + Status status(::util::error::INTERNAL, "some error message"); + + EXPECT_CALL(*mock_container, KillAll()) + .WillOnce(Return(Status::OK)) + .WillOnce(Return(status)); + + SHOULD_SUCCEED(lmctfy_container_killall, container_); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_killall, container_); + WITH_NULL_CONTAINER_RUN(lmctfy_container_killall, container_); +} + +TEST_F(ClmctfyContainerTest, Name) { + StrictMockContainer *mock_container = GetMockContainer(); + string container_name = mock_container->name(); + const char *name = lmctfy_container_name(container_); + EXPECT_EQ(container_name, name); + name = lmctfy_container_name(NULL); + EXPECT_EQ(name, NULL); + Container *tmp = container_->container_; + container_->container_ = NULL; + name = lmctfy_container_name(container_); + EXPECT_EQ(name, NULL); + container_->container_ = tmp; +} + } // namespace lmctfy } // namespace containers From 2d3e7bfc11a3ef043d9fe94e9aca64f5707829b1 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 10 Feb 2014 12:49:15 -0500 Subject: [PATCH 62/84] Tested all functions. Need an example. --- clmctfy/clmctfy_container.cc | 9 +++++++++ clmctfy/clmctfy_container_api.cc | 1 - clmctfy/clmctfy_container_ctest.cc | 30 ++++++++++++++++++++++++++++++ clmctfy/include/clmctfy.h | 4 +++- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index c273124..0fe64cd 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -116,6 +116,15 @@ int lmctfy_container_exec(struct status *s, void lmctfy_delete_container(struct container *container) { if (container != NULL) { if (container->container_ != NULL) { + unordered_map::iterator iter; + for (iter = container->notif_map_.begin(); + iter != container->notif_map_.end(); + iter++) { + container->container_->UnregisterNotification(iter->first); + delete iter->second; + iter->second = NULL; + } + container->notif_map_.clear(); delete container->container_; } delete container; diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index b1d9356..3d88c26 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -151,7 +151,6 @@ int lmctfy_container_api_destroy_container(struct status *s, if (c != NULL && c->container_ != NULL) { Status status = api->container_api_->Destroy(c->container_); ret = status_copy(s, status); - delete c; } return ret; } diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 752695e..d301981 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -362,5 +362,35 @@ TEST_F(ClmctfyContainerTest, Name) { container_->container_ = tmp; } +static void event_callback_counter(struct container *container, + const struct status *s, + void *data) { + if (data != NULL) { + (*((int *)data))++; + } +} + +TEST_F(ClmctfyContainerTest, RegisterThenUnRegister) { + StrictMockContainer *mock_container = GetMockContainer(); + Containers__Lmctfy__EventSpec spec = CONTAINERS__LMCTFY__EVENT_SPEC__INIT; + notification_id_t notif_id = 0; + StatusOr statusor_success((Container::NotificationId)1); + int evt_counter = 0; + + EXPECT_CALL(*mock_container, RegisterNotification(_, _)) + .WillOnce(Return(statusor_success)); + + EXPECT_CALL(*mock_container, UnregisterNotification(1)) + .WillOnce(Return(Status::OK)); + + SHOULD_SUCCEED(lmctfy_container_register_notification, + ¬if_id, + container_, + event_callback_counter, + &evt_counter, + &spec); + EXPECT_EQ(notif_id, 1); +} + } // namespace lmctfy } // namespace containers diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 6d0b79f..791486d 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -146,7 +146,9 @@ int lmctfy_container_api_create_container( const char *container_name, const Containers__Lmctfy__ContainerSpec *spec); -// Destroy a container +// Destroy a container. The caller has to call lmctfy_delete_container after +// detroying a container. Otherwise, the memory of occupied by the container +// structure will not be released. // // Arguments: // From 18682aba350b735069f1f293818b8e2dfa6d802e Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Thu, 13 Feb 2014 23:21:53 -0500 Subject: [PATCH 63/84] do not include _ctest.cc in the library. --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b76614c..63a2185 100755 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ OPT ?= -O2 -DNDEBUG # (A) Production use (optimized mode) # Use default if no configuration specified. CXX ?= g++ AR ?= ar +CC ?= gcc # Version number of lmctfy. VERSION = "\"0.4.5\"" @@ -22,7 +23,7 @@ PROTOC = protoc PROTOC_C = protoc-c # Function for getting a set of source files. -get_srcs = $(shell find $(1) -name \*.cc -a ! -name \*_test.cc | tr "\n" " ") +get_srcs = $(shell find $(1) -name \*.cc -a ! -name \*_test.cc -a ! -name \*_ctest.cc | tr "\n" " ") INCLUDE_PROTOS = include/virtual_host include/lmctfy include/namespaces UTIL_PROTOS = util/task/codes From 074ffb6271ba3ed726915434b95587ad968de794 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Thu, 13 Feb 2014 23:37:37 -0500 Subject: [PATCH 64/84] detect self --- clmctfy/include/clmctfy.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index 791486d..a6d59c3 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -169,12 +169,26 @@ int lmctfy_container_api_destroy_container(struct status *s, struct container_api *api, struct container *container); +// Detect what container the specified thread is in. +// +// Arguments: +// - s: [output] Will be used to store the status. The function will first +// check the error code stored in s->error_code and will only proceed if the +// error code is not zero. +// - container_name: [output] Will be used to store the container name +// - n: The size of the buffer pointed by container_name +// - api: The container api. +// - pid: The thread ID to check. 0 refers to self. int lmctfy_container_api_detect_container(struct status *s, char *container_name, const size_t n, struct container_api *api, pid_t pid); +// XXX(monnand): Do we really need this macro? +#define lmctfy_container_api_detect_self(s, container_name, n, api) \ + lmctfy_container_api_detect_container((s), (container_name), (n), (api), 0) + // Release the memory used by the container structure. The refered container // will not be affected. // From 7d59e758d546ea451d80099a5dbf661efd27b376 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 14 Feb 2014 00:15:45 -0500 Subject: [PATCH 65/84] example using the C APIs. --- examples/clmctfy_simple_existing.c | 58 ++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 examples/clmctfy_simple_existing.c diff --git a/examples/clmctfy_simple_existing.c b/examples/clmctfy_simple_existing.c new file mode 100644 index 0000000..3428720 --- /dev/null +++ b/examples/clmctfy_simple_existing.c @@ -0,0 +1,58 @@ +// Simple example of the struct container_api usage for accessing +// information about an existing container. + +#include +#include +#include +#include + +#include "clmctfy.h" +#include "lmctfy.pb-c.h" + +#define CONTAINER_NAME_MAX_LENGTH 2014 + +int main() { + struct container_api *lmctfy = NULL; + struct container *container = NULL; + struct status s = {0, NULL}; + int err = 0; + char container_name[CONTAINER_NAME_MAX_LENGTH]; + Containers__Lmctfy__ContainerStats *stats = NULL; + + memset(container_name, 0, CONTAINER_NAME_MAX_LENGTH); + + err = lmctfy_new_container_api(&s, &lmctfy); + if (err != 0) { + printf("Failed to instantiate container_api: %s\n", s.message); + free(s.message); + return -1; + } + + err = lmctfy_container_api_detect_self(&s, container_name, CONTAINER_NAME_MAX_LENGTH, lmctfy); + if (err != 0) { + printf("Failed to detect the current container: %s\n", s.message); + free(s.message); + return -1; + } + printf("Current container: %s\n", container_name); + + err = lmctfy_container_api_get_container(&s, &container, lmctfy, "."); + if (err != 0) { + printf("Failed to get container: %s\n", s.message); + free(s.message); + return -1; + } + + err = lmctfy_container_stats(&s, container, CONTAINER_STATS_TYPE_SUMMARY, &stats); + if (err != 0) { + printf("Failed to get container stats: %s\n", s.message); + free(s.message); + return -1; + } + + printf("Memory usage: %ld\nWorking set: %ld\n", + stats->memory->usage, + stats->memory->working_set); + + return 0; +} From 8dd19412f7aaaecb8627bcb8a0688c75c89f8c46 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 14 Feb 2014 01:02:54 -0500 Subject: [PATCH 66/84] Build example for c binding in Makefile. --- Makefile | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 63a2185..01fbd77 100755 --- a/Makefile +++ b/Makefile @@ -110,8 +110,16 @@ CXXFLAGS += `pkg-config --cflags --libs protobuf` # Add proto-c flags. CXXFLAGS += -lprotobuf-c -# FLAGS for C binding -CFLAGS = -fpermissive +# flags for linker +LDFLAGS = -lprotobuf-c +LDFLAGS += `pkg-config --cflags --libs protobuf` +LDFLAGS += -lpthread +LDFLAGS += -pthread +LDFLAGS += -lrt -lre2 -lgflags -lm + +# linker's flag for C bindings +CLDFLAGS = -lstdc++ + CLI = lmctfy NSCON = lmctfy-nscon @@ -178,6 +186,9 @@ examples/simple_existing: examples/simple_existing.o $(LIBRARY) # All common base sources (non-lmctfy and non-nscon). COMMON_SOURCES = $(INCLUDE_SOURCES) $(BASE_SOURCES) $(STRINGS_SOURCES) \ $(FILE_SOURCES) $(THREAD_SOURCES) $(UTIL_SOURCES) +examples/clmctfy_simple_existing: examples/clmctfy_simple_existing.o $(CLIBRARY) + $(create_bin) + $(CC) -o $(OUT_DIR)/$@ $(addprefix $(OUT_DIR)/,$^) $(LDFLAGS) $(CLDFLAGS) # All sources needed by the library (minus the system API). LIBRARY_SOURCES = $(COMMON_SOURCES) $(LIBLMCTFY_SOURCES) $(NSCON_SOURCES) @@ -245,7 +256,7 @@ $(CREAPER): lmctfy-creaper.go %_ctest: gtest_main.a $(SYSTEM_API_TEST_OBJS) clmctfy_only_api.a $(create_bin) $(CXX) -o $(OUT_DIR)/$@ $*.cc $*_ctest.cc $(addprefix $(OUT_DIR)/,$^) \ - $(CXXFLAGS) $(CFLAGS) + $(CXXFLAGS) -fpermissive %_proto: %.proto $(PROTOC) $^ --cpp_out=. @@ -257,13 +268,17 @@ $(CREAPER): lmctfy-creaper.go %.pb-c.o: %_proto $(create_bin) - $(CXX) -c $*.pb-c.c -o $(OUT_DIR)/$@ $(CXXFLAGS) $(CFLAGS) + $(CXX) -c $*.pb-c.c -o $(OUT_DIR)/$@ $(CXXFLAGS) -fpermissive gen_protos: $(addsuffix _proto,$(INCLUDE_PROTOS) $(UTIL_PROTOS)) %_ctest.o: gen_protos %_ctest.cc $(create_bin) - $(CXX) -c $*.cc -o $(OUT_DIR)/$@ $(CXXFLAGS) $(CFLAGS) + $(CXX) -c $*.cc -o $(OUT_DIR)/$@ $(CXXFLAGS) -fpermissive + +%.o: gen_protos %.c + $(create_bin) + $(CC) -c $*.c -o $(OUT_DIR)/$@ $(CXXFLAGS) %.o: gen_protos %.cc $(create_bin) From 376e9b0d13b7feeb09348ac78d2a64b91b79e249 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Mon, 24 Feb 2014 23:28:51 -0500 Subject: [PATCH 67/84] change the signatore of lmctfy_container_api_detect() --- clmctfy/clmctfy_container_api.cc | 9 ++++----- clmctfy/clmctfy_container_api_ctest.cc | 16 +++++++--------- clmctfy/include/clmctfy.h | 11 +++++------ examples/clmctfy_simple_existing.c | 8 ++------ 4 files changed, 18 insertions(+), 26 deletions(-) diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index 3d88c26..eb05dc4 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -1,4 +1,5 @@ #include +#include #include "clmctfy.h" #include "clmctfy-raw.h" @@ -156,8 +157,7 @@ int lmctfy_container_api_destroy_container(struct status *s, } int lmctfy_container_api_detect_container(struct status *s, - char *container_name, - const size_t n, + char **container_name, struct container_api *api, pid_t pid) { int ret = STATUS_OK; @@ -165,11 +165,10 @@ int lmctfy_container_api_detect_container(struct status *s, CHECK_NOTNULL_OR_RETURN(s, api); CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, container_name); - CHECK_POSITIVE_OR_RETURN(s, n); StatusOr statusor = api->container_api_->Detect(pid); ret = status_copy(s, statusor.status()); - if (container_name != NULL && statusor.ok() && n > 0) { - strncpy(container_name, statusor.ValueOrDie().c_str(), n); + if (container_name != NULL && statusor.ok()) { + *container_name = strdup(statusor.ValueOrDie().c_str()); } return ret; } diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index 801e97f..e45be7a 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -158,15 +158,12 @@ TEST_F(ClmctfyContainerApiTest, DestroyContainer) { SHOULD_SUCCEED(lmctfy_container_api_destroy_container, container_api_, NULL); } -#define MAX_CONTAINER_NAME_LEN 512 - TEST_F(ClmctfyContainerApiTest, DetectContainer) { StrictMockContainerApi *mock_api = GetMockApi(); const char *container_name = "test"; - char output_name[MAX_CONTAINER_NAME_LEN]; + char *output_name = NULL; pid_t pid = 10; container_ = NULL; - memset(output_name, 0, MAX_CONTAINER_NAME_LEN); StatusOr statusor(container_name); string errmsg = "some error message"; @@ -177,13 +174,14 @@ TEST_F(ClmctfyContainerApiTest, DetectContainer) { .WillOnce(Return(statusor)) .WillOnce(Return(statusor_fail)); - SHOULD_SUCCEED(lmctfy_container_api_detect_container, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); + SHOULD_SUCCEED(lmctfy_container_api_detect_container, &output_name, container_api_, pid); EXPECT_EQ(string(container_name), string(output_name)); + free(output_name); - *output_name = '\0'; - SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_detect_container, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); - EXPECT_EQ(*output_name, '\0'); - WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_detect_container, output_name, MAX_CONTAINER_NAME_LEN, container_api_, pid); + output_name = NULL; + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_detect_container, &output_name, container_api_, pid); + EXPECT_EQ(output_name, NULL); + WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_detect_container, &output_name, container_api_, pid); } } // namespace lmctfy diff --git a/clmctfy/include/clmctfy.h b/clmctfy/include/clmctfy.h index a6d59c3..e643d93 100644 --- a/clmctfy/include/clmctfy.h +++ b/clmctfy/include/clmctfy.h @@ -175,19 +175,18 @@ int lmctfy_container_api_destroy_container(struct status *s, // - s: [output] Will be used to store the status. The function will first // check the error code stored in s->error_code and will only proceed if the // error code is not zero. -// - container_name: [output] Will be used to store the container name -// - n: The size of the buffer pointed by container_name +// - container_name: [output] Will be used to store the container name. +// It's the caller's responsibility to free() *container_name. // - api: The container api. // - pid: The thread ID to check. 0 refers to self. int lmctfy_container_api_detect_container(struct status *s, - char *container_name, - const size_t n, + char **container_name, struct container_api *api, pid_t pid); // XXX(monnand): Do we really need this macro? -#define lmctfy_container_api_detect_self(s, container_name, n, api) \ - lmctfy_container_api_detect_container((s), (container_name), (n), (api), 0) +#define lmctfy_container_api_detect_self(s, container_name, api) \ + lmctfy_container_api_detect_container((s), (container_name), (api), 0) // Release the memory used by the container structure. The refered container // will not be affected. diff --git a/examples/clmctfy_simple_existing.c b/examples/clmctfy_simple_existing.c index 3428720..78a9ded 100644 --- a/examples/clmctfy_simple_existing.c +++ b/examples/clmctfy_simple_existing.c @@ -9,18 +9,14 @@ #include "clmctfy.h" #include "lmctfy.pb-c.h" -#define CONTAINER_NAME_MAX_LENGTH 2014 - int main() { struct container_api *lmctfy = NULL; struct container *container = NULL; struct status s = {0, NULL}; int err = 0; - char container_name[CONTAINER_NAME_MAX_LENGTH]; + char *container_name = NULL; Containers__Lmctfy__ContainerStats *stats = NULL; - memset(container_name, 0, CONTAINER_NAME_MAX_LENGTH); - err = lmctfy_new_container_api(&s, &lmctfy); if (err != 0) { printf("Failed to instantiate container_api: %s\n", s.message); @@ -28,7 +24,7 @@ int main() { return -1; } - err = lmctfy_container_api_detect_self(&s, container_name, CONTAINER_NAME_MAX_LENGTH, lmctfy); + err = lmctfy_container_api_detect_self(&s, &container_name, lmctfy); if (err != 0) { printf("Failed to detect the current container: %s\n", s.message); free(s.message); From 4d813131677fde2ae83759bf834dd873957cdead Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 25 Feb 2014 20:03:32 -0500 Subject: [PATCH 68/84] include "clmctfy-raw.h" in clmctfy_container.cc --- clmctfy/clmctfy_container.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 0fe64cd..5a324ec 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -1,4 +1,5 @@ #include "clmctfy.h" +#include "clmctfy-raw.h" #include "lmctfy.h" #include "clmctfy_internal.h" #include "util/task/statusor.h" From 70ff857545f86d558e9aef4d191d0ba3a1ab93c5 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 11 Mar 2014 19:02:18 -0400 Subject: [PATCH 69/84] Follow the Google coding style. --- Makefile | 2 +- clmctfy/clmctfy_container.cc | 19 ++++++++++++++----- clmctfy/clmctfy_container_api.cc | 15 ++++++++++----- clmctfy/clmctfy_container_api_ctest.cc | 9 +++++---- clmctfy/clmctfy_container_ctest.cc | 11 ++++++----- clmctfy/clmctfy_internal.h | 6 ++++-- clmctfy/status-c.cc | 3 ++- {clmctfy/include => include}/clmctfy-raw.h | 2 +- {clmctfy/include => include}/clmctfy.h | 9 +++++---- 9 files changed, 48 insertions(+), 28 deletions(-) rename {clmctfy/include => include}/clmctfy-raw.h (100%) rename {clmctfy/include => include}/clmctfy.h (98%) diff --git a/Makefile b/Makefile index 01fbd77..3ef263b 100755 --- a/Makefile +++ b/Makefile @@ -102,7 +102,7 @@ CXXFLAGS += -I. -I./include -I./base -I./lmctfy -I$(GTEST_DIR)/include \ -I$(GMOCK_DIR)/include -I/usr/local/include -L/usr/local/lib \ -I/usr/include -L/usr/lib # Add include for c binding -CXXFLAGS += -I./clmctfy/include -I./clmctfy +CXXFLAGS += -I./clmctfy # Add proto flags. CXXFLAGS += `pkg-config --cflags --libs protobuf` diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 5a324ec..6d4fb80 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -1,14 +1,23 @@ #include "clmctfy.h" #include "clmctfy-raw.h" -#include "lmctfy.h" -#include "clmctfy_internal.h" + +#include +#include + #include "util/task/statusor.h" #include "base/callback.h" #include "base/macros.h" -#include -#include +#include "lmctfy.h" + +#include "clmctfy_internal.h" -using namespace ::containers::lmctfy; +using ::containers::lmctfy::Container; +using ::containers::lmctfy::ContainerApi; +using ::containers::lmctfy::InitSpec; +using ::containers::lmctfy::ContainerSpec; +using ::containers::lmctfy::RunSpec; +using ::containers::lmctfy::EventSpec; +using ::containers::lmctfy::ContainerStats; using ::util::internal::status_copy; using ::util::internal::status_new; using ::util::Status; diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index eb05dc4..a3834bd 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -1,17 +1,22 @@ +#include "clmctfy.h" +#include "clmctfy-raw.h" + #include #include -#include "clmctfy.h" -#include "clmctfy-raw.h" -#include "lmctfy.h" #include "util/task/statusor.h" -#include "clmctfy_internal.h" #include "lmctfy.pb.h" #include "util/task/codes.pb-c.h" +#include "lmctfy.h" + +#include "clmctfy_internal.h" #define STATUS_OK UTIL__ERROR__CODE__OK -using namespace ::containers::lmctfy; +using ::containers::lmctfy::Container; +using ::containers::lmctfy::ContainerApi; +using ::containers::lmctfy::InitSpec; +using ::containers::lmctfy::ContainerSpec; using ::util::internal::status_copy; using ::util::internal::status_new; using ::util::Status; diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index e45be7a..08a3f49 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -14,15 +14,16 @@ #include "clmctfy.h" -#include "clmctfy_macros_ctest.h" -#include "lmctfy.h" -#include "lmctfy_mock.h" #include "gtest/gtest.h" #include "gmock/gmock.h" #include "util/task/statusor.h" -#include "clmctfy_internal.h" #include "strings/stringpiece.h" +#include "lmctfy_mock.h" +#include "lmctfy.h" +#include "clmctfy_macros_ctest.h" +#include "clmctfy_internal.h" + using ::testing::NotNull; using ::testing::Return; using ::testing::SetArgPointee; diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index d301981..bfc672b 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -12,18 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include - #include "clmctfy.h" -#include "clmctfy_macros_ctest.h" -#include "lmctfy_mock.h" +#include + #include "gtest/gtest.h" #include "gmock/gmock.h" #include "util/task/statusor.h" -#include "clmctfy_internal.h" #include "strings/stringpiece.h" +#include "lmctfy_mock.h" +#include "clmctfy_macros_ctest.h" +#include "clmctfy_internal.h" + using ::testing::NotNull; using ::testing::Return; using ::testing::SetArgPointee; diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index 5550258..c338050 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -1,13 +1,15 @@ #ifndef LMCTFY_C_BINDING_STATUS_INTERNAL_H_ #define LMCTFY_C_BINDING_STATUS_INTERNAL_H_ +#include + #include "util/errors.h" -#include "clmctfy.h" #include "util/task/status.h" #include "util/task/statusor.h" + #include "lmctfy.h" +#include "clmctfy.h" -#include using ::containers::lmctfy::Container; using ::containers::lmctfy::ContainerApi; diff --git a/clmctfy/status-c.cc b/clmctfy/status-c.cc index 41855a7..8ef4b54 100644 --- a/clmctfy/status-c.cc +++ b/clmctfy/status-c.cc @@ -1,9 +1,10 @@ #include // to use strdup #include +#include "util/task/status.h" + #include "clmctfy.h" #include "clmctfy_internal.h" -#include "util/task/status.h" using ::util::Status; diff --git a/clmctfy/include/clmctfy-raw.h b/include/clmctfy-raw.h similarity index 100% rename from clmctfy/include/clmctfy-raw.h rename to include/clmctfy-raw.h index f77046b..63db589 100644 --- a/clmctfy/include/clmctfy-raw.h +++ b/include/clmctfy-raw.h @@ -1,8 +1,8 @@ #ifndef LMCTFY_C_BINDING_CLMCTFY_RAW_H_ #define LMCTFY_C_BINDING_CLMCTFY_RAW_H_ -#include "clmctfy.h" #include "lmctfy.pb-c.h" +#include "clmctfy.h" #ifdef __cplusplus extern "C" { diff --git a/clmctfy/include/clmctfy.h b/include/clmctfy.h similarity index 98% rename from clmctfy/include/clmctfy.h rename to include/clmctfy.h index e643d93..6c4a31a 100644 --- a/clmctfy/include/clmctfy.h +++ b/include/clmctfy.h @@ -1,10 +1,11 @@ -#ifndef LMCTFY_C_BINDING_LMCTFY_C_H_ -#define LMCTFY_C_BINDING_LMCTFY_C_H_ +#ifndef LMCTFY_INCLUDE_CLMCTFY_H_ +#define LMCTFY_INCLUDE_CLMCTFY_H_ #include #include -#include "lmctfy.pb-c.h" + #include "util/task/codes.pb-c.h" +#include "lmctfy.pb-c.h" #ifdef __cplusplus extern "C" { @@ -294,4 +295,4 @@ int lmctfy_container_unregister_notification(struct status *s, #ifdef __cplusplus } #endif // __cplusplus -#endif // LMCTFY_C_BINDING_LMCTFY_C_H_ +#endif // LMCTFY_INCLUDE_CLMCTFY_H_ From 3f067af0476e776a6b1011884482fcb98b901a70 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 11 Mar 2014 19:04:35 -0400 Subject: [PATCH 70/84] s/propagete/propagate/g --- include/clmctfy.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/clmctfy.h b/include/clmctfy.h index 6c4a31a..27e0366 100644 --- a/include/clmctfy.h +++ b/include/clmctfy.h @@ -62,7 +62,7 @@ typedef uint64_t notification_id_t; // - s: [output] s will be used as output. // If the original value of s->code is not // UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return -// immediately with value s->code. This will help users to propagete errors. +// immediately with value s->code. This will help users to propagate errors. // Otherwise, it contains the error code and message. // - spec: The specification. // @@ -78,7 +78,7 @@ int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *sp // - s: [output] s will be used as output. // If the original value of s->code is not // UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return -// immediately with value s->code. This will help users to propagete errors. +// immediately with value s->code. This will help users to propagate errors. // Otherwise, it contains the error code and message. // - api: [output] The address of a pointer to struct container_api. The // pointer of the container api will be stored in this address. @@ -104,7 +104,7 @@ void lmctfy_delete_container_api(struct container_api *api); // - s: [output] s will be used as output. // If the original value of s->code is not // UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return -// immediately with value s->code. This will help users to propagete errors. +// immediately with value s->code. This will help users to propagate errors. // Otherwise, it contains the error code and message. // - container: [output] The address of a pointer to struct container. It will // be used to store the pointer to the container. @@ -128,7 +128,7 @@ int lmctfy_container_api_get_container( // - s: [output] s will be used as output. // If the original value of s->code is not // UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return -// immediately with value s->code. This will help users to propagete errors. +// immediately with value s->code. This will help users to propagate errors. // Otherwise, it contains the error code and message. // - container: [output] The address of a pointer to struct container. It will // be used to store the newly created container. @@ -156,7 +156,7 @@ int lmctfy_container_api_create_container( // - s: [output] s will be used as output. // If the original value of s->code is not // UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return -// immediately with value s->code. This will help users to propagete errors. +// immediately with value s->code. This will help users to propagate errors. // Otherwise, it contains the error code and message. // - api: A container api. // - container: The pointer to struct container. The pointer will become From efe3d486f310750530de36f2b066179c155d7258 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 11 Mar 2014 19:56:06 -0400 Subject: [PATCH 71/84] comments --- include/clmctfy-raw.h | 3 +- include/clmctfy.h | 227 +++++++++++++++++++++++++++++++++--------- 2 files changed, 183 insertions(+), 47 deletions(-) diff --git a/include/clmctfy-raw.h b/include/clmctfy-raw.h index 63db589..b1f6816 100644 --- a/include/clmctfy-raw.h +++ b/include/clmctfy-raw.h @@ -1,8 +1,9 @@ #ifndef LMCTFY_C_BINDING_CLMCTFY_RAW_H_ #define LMCTFY_C_BINDING_CLMCTFY_RAW_H_ -#include "lmctfy.pb-c.h" #include "clmctfy.h" +#include "lmctfy.pb-c.h" +#include "lmctfy.h" #ifdef __cplusplus extern "C" { diff --git a/include/clmctfy.h b/include/clmctfy.h index 27e0366..4c91637 100644 --- a/include/clmctfy.h +++ b/include/clmctfy.h @@ -12,17 +12,27 @@ extern "C" { #endif // __cplusplus enum { + // Update only the specified fields. CONTAINER_UPDATE_POLICY_DIFF, + + // Replace the existing container with the new specification. CONTAINER_UPDATE_POLICY_REPLACE }; enum { + // Only output the information of this container. CONTAINER_LIST_POLICY_SELF, + + // Output the information of this container and all of its subcontainers and + // their subcontainers. CONTAINER_LIST_POLICY_RECURSIVE }; enum { + // A summary of the statistics (see each resource's definition of summary). CONTAINER_STATS_TYPE_SUMMARY, + + // All available statistics. CONTAINER_STATS_TYPE_FULL }; @@ -59,12 +69,9 @@ typedef uint64_t notification_id_t; // Initializes the machine to start being able to create containers. // // Arguments: -// - s: [output] s will be used as output. -// If the original value of s->code is not -// UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return -// immediately with value s->code. This will help users to propagate errors. -// Otherwise, it contains the error code and message. -// - spec: The specification. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - spec: The specification. Caller owns the pointer. // // Returns: // @@ -75,11 +82,8 @@ int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *sp // Create a new container_api. // // Arguments: -// - s: [output] s will be used as output. -// If the original value of s->code is not -// UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return -// immediately with value s->code. This will help users to propagate errors. -// Otherwise, it contains the error code and message. +// - s: [output] The status of the operations and an error message if the +// status is not OK. // - api: [output] The address of a pointer to struct container_api. The // pointer of the container api will be stored in this address. // @@ -93,19 +97,15 @@ int lmctfy_new_container_api(struct status *s, struct container_api **api); // // Arguments: // -// - api: The container api. This pointer will be invalid after the call to -// this function +// - api: The container api. The function takes the ownershp. void lmctfy_delete_container_api(struct container_api *api); // Get a container // // Arguments: // -// - s: [output] s will be used as output. -// If the original value of s->code is not -// UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return -// immediately with value s->code. This will help users to propagate errors. -// Otherwise, it contains the error code and message. +// - s: [output] The status of the operations and an error message if the +// status is not OK. // - container: [output] The address of a pointer to struct container. It will // be used to store the pointer to the container. // - api: A container api. @@ -125,16 +125,13 @@ int lmctfy_container_api_get_container( // // Arguments: // -// - s: [output] s will be used as output. -// If the original value of s->code is not -// UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return -// immediately with value s->code. This will help users to propagate errors. -// Otherwise, it contains the error code and message. +// - s: [output] The status of the operations and an error message if the +// status is not OK. // - container: [output] The address of a pointer to struct container. It will // be used to store the newly created container. // - api: A container api. // - container_name: the container name. -// - spec: container specification. +// - spec: container specification. Caller owns the pointer. // // Returns: // @@ -148,19 +145,16 @@ int lmctfy_container_api_create_container( const Containers__Lmctfy__ContainerSpec *spec); // Destroy a container. The caller has to call lmctfy_delete_container after -// detroying a container. Otherwise, the memory of occupied by the container +// detroying a container. Otherwise, the memory occupied by the container // structure will not be released. // // Arguments: // -// - s: [output] s will be used as output. -// If the original value of s->code is not -// UTIL__ERROR__CODE__INVALID_ARGUMENT, then the function will return -// immediately with value s->code. This will help users to propagate errors. -// Otherwise, it contains the error code and message. +// - s: [output] The status of the operations and an error message if the +// status is not OK. // - api: A container api. // - container: The pointer to struct container. The pointer will become -// invalid after a success destroy(). +// invalid after a successful destroy(). // // Returns: // @@ -173,9 +167,8 @@ int lmctfy_container_api_destroy_container(struct status *s, // Detect what container the specified thread is in. // // Arguments: -// - s: [output] Will be used to store the status. The function will first -// check the error code stored in s->error_code and will only proceed if the -// error code is not zero. +// - s: [output] The status of the operations and an error message if the +// status is not OK. // - container_name: [output] Will be used to store the container name. // It's the caller's responsibility to free() *container_name. // - api: The container api. @@ -185,10 +178,6 @@ int lmctfy_container_api_detect_container(struct status *s, struct container_api *api, pid_t pid); -// XXX(monnand): Do we really need this macro? -#define lmctfy_container_api_detect_self(s, container_name, api) \ - lmctfy_container_api_detect_container((s), (container_name), (api), 0) - // Release the memory used by the container structure. The refered container // will not be affected. // @@ -198,15 +187,29 @@ int lmctfy_container_api_detect_container(struct status *s, // this function void lmctfy_delete_container(struct container *container); +// Moves the specified threads into this container. Enter is atomic. +// +// Arguments: +// +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - container +// - tids: Array of thread IDs to move into the container. Caller takes the +// ownership. +// - tids_size: Number of thread IDs stored in tids. Caller takes the +// ownership. int lmctfy_container_enter(struct status *s, struct container *container, const pid_t *tids, - const int n); + const int tids_size); -// +// Run the specified command inside the container. Multiple instances of run +// can be active simultaneously. Processes MUST be reaped by the caller. +// // Arguments: // -// - s: [output] +// - s: [output] The status of the operations and an error message if the +// status is not OK. // - tid: [output] On success, tid stores the PID of the command. // - container // - argc: number of arguments (including the binary file path). @@ -219,16 +222,54 @@ int lmctfy_container_run(struct status *s, const char **argv, const Containers__Lmctfy__RunSpec *spec); +// Execute the specified command inside the container. This replaces the +// current process image with the specified command. The PATH environment +// variable is used, and the existing environment is passed to the new +// process image unchanged. +// +// Arguments: +// +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - container +// - argc: number of arguments (including the binary file path). +// - argv: All arguments. The first element is the binary that will be executed +// and must be an absolute path. int lmctfy_container_exec(struct status *s, struct container *container, const int argc, const char **argv); +// Updates the container according to the specification. The set of resource +// types being isolated cannot change during an Update. This means that a +// CONTAINER_UPDATE_POLICY_REPLACE must specify all the resources being isolated +// and a CONTAINER_UPDATE_POLICY_DIFF cannot specify any resource that is not +// already being isolated. +// +// Arguments: +// +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - container +// - policy: Update policy. Can be either CONTAINER_UPDATE_POLICY_DIFF, or +// CONTAINER_UPDATE_POLICY_REPLACE. +// - spec: The specification of the desired updates. int lmctfy_container_update(struct status *s, struct container *container, int policy, const Containers__Lmctfy__ContainerSpec *spec); +// Returns the resource isolation specification (ContainerSpec) of this +// container. +// +// Arguments: +// +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - container: The container +// - spec: [output] An address of a ContainerSpec pointer. *spec will points to +// the ContainerSpec of the container. Caller takes the ownership. *spec can +// be released by calling free(). int lmctfy_container_spec(struct status *s, struct container *container, Containers__Lmctfy__ContainerSpec **spec); @@ -237,50 +278,136 @@ int lmctfy_container_spec(struct status *s, // // Arguments: // -// - s: [output] +// - s: [output] The status of the operations and an error message if the +// status is not OK. // - subcontainers: [output] The address of a pointer points to an array of // struct container pointers. The caller takes the onwership. On success, the // pointer will be assigned an address to an array of containers. The pointed // array should be released with free(). The containers inside the array // should be deleted/destroyed individually. -// - nr_subcontainers: [output] The address of an integer used to store number +// - subcontainers_size: [output] The address of an integer used to store number // of subcontainers in the array. // - container: The container // - list_policy: CONTAINER_LIST_POLICY_SELF or CONTAINER_LIST_POLICY_RECURSIVE int lmctfy_container_list_subcontainers(struct status *s, struct container **subcontainers[], - int *nr_subcontainers, + int *subcontainers_size, struct container *container, int list_policy); +// List all TIDs in the container. +// +// Arguments: +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - threads: [output] The address of a pointer points to an array of pid_t. +// The caller takes the ownership. The array can be released with free(). +// - threads_size: [output] *threads_size is the number of TIDs stored in *threads. +// - list_policy: List policy. int lmctfy_container_list_threads(struct status *s, pid_t *threads[], - int *nr_threads, + int *threads_size, struct container *container, int list_policy); +// Get all PIDs in this container. +// +// Arguments: +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - processes: [output] The address of a pointer points to an array of pid_t. +// The caller takes the ownership. The array can be released with free(). +// - processes_size: [output] *processes_size is the number of PIDs stored in +// *processes. +// - list_policy: List policy. int lmctfy_container_list_processes(struct status *s, pid_t *processes[], - int *nr_processes, + int *processes_size, struct container *container, int list_policy); +// Atomically stops the execution of all threads inside the container and all +// subcontainers (recursively). All threads moved to a paused container will +// be paused as well (regardless of whether the PID is in the container). This +// guarantees to get all threads. +// +// Arguments: +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - container: The container. int lmctfy_container_pause(struct status *s, struct container *container); +// Atomically resumes the execution of all threads inside the container and +// all subcontainers (recursively). All paused threads moved to a non-paused +// container will be resumed. +// +// Arguments: +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - container: The container. int lmctfy_container_resume(struct status *s, struct container *container); +// Kills all processes running in the container. This operation is atomic and +// is synchronized with any mutable operations on this container. +// +// The operation sends a SIGKILL to all processes in the containers. Tourist +// threads are killed via SIGKILL after all processes have exited. +// +// Note that this operation can potentially take a long time (O(seconds)) if +// the processes in the container do not finish quickly. This operation also +// blocks all mutable container operations while it is in progress. +// +// Arguments: +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - container: The container. int lmctfy_container_killall(struct status *s, struct container *container); +// Gets usage and state information for the container. Note that the snapshot +// is not atomic. +// +// Arguments: +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - container: The container. +// - stats_type: The type of statistics to output. +// - stats: [output] Used to store a pointer points to the container's +// statistics. The call takes the ownership of *stats, which should be +// free()'ed. int lmctfy_container_stats(struct status *s, struct container *container, int stats_type, Containers__Lmctfy__ContainerStats **stats); +// Get the name of the container. +// +// Arguments: +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Return: +// The container name. The caller does not take the ownership. const char *lmctfy_container_name(struct container *container); +// Register a notification for a specified container event. All notifications +// are unregistered when the container is destroyed. +// +// Arguments: +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - notif_id: [output] The ID for the notification. The ID is unique within +// the current container_api instance. It will be used to unregister the +// notification +// - container: The container. +// - callback: The callback to run when the event is triggered. The caller +// takes ownership of the callback which MUST be a repeatable callback. +// - user_data: The pointer which will be passed to the callback function as +// its last parameter. The caller takes the ownership. +// - spec: The specification for the event for which to register notifications. +// The caller takes the ownership. int lmctfy_container_register_notification(struct status *s, notification_id_t *notif_id, struct container *container, @@ -288,6 +415,14 @@ int lmctfy_container_register_notification(struct status *s, void *user_data, Containers__Lmctfy__EventSpec *spec); +// Unregister (stop) the specified notification from being received. +// +// Arguments: +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - container: The container. +// - notif_id: The unique notification ID for the container +// notification. int lmctfy_container_unregister_notification(struct status *s, struct container *container, const notification_id_t notif_id); From b4f9606901558e260af9772e43b2249741807712 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 11 Mar 2014 20:12:01 -0400 Subject: [PATCH 72/84] better example. --- examples/clmctfy_simple_existing.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/clmctfy_simple_existing.c b/examples/clmctfy_simple_existing.c index 78a9ded..3147d7f 100644 --- a/examples/clmctfy_simple_existing.c +++ b/examples/clmctfy_simple_existing.c @@ -21,13 +21,16 @@ int main() { if (err != 0) { printf("Failed to instantiate container_api: %s\n", s.message); free(s.message); + lmctfy_delete_container_api(lmctfy); return -1; } - err = lmctfy_container_api_detect_self(&s, &container_name, lmctfy); + // Get what container the current thread is in. + err = lmctfy_container_api_detect_container(&s, &container_name, lmctfy, 0); if (err != 0) { printf("Failed to detect the current container: %s\n", s.message); free(s.message); + lmctfy_delete_container_api(lmctfy); return -1; } printf("Current container: %s\n", container_name); @@ -36,6 +39,8 @@ int main() { if (err != 0) { printf("Failed to get container: %s\n", s.message); free(s.message); + free(container_name); + lmctfy_delete_container_api(lmctfy); return -1; } @@ -43,12 +48,19 @@ int main() { if (err != 0) { printf("Failed to get container stats: %s\n", s.message); free(s.message); + free(container_name); + lmctfy_delete_container(container); + lmctfy_delete_container_api(lmctfy); return -1; } printf("Memory usage: %ld\nWorking set: %ld\n", stats->memory->usage, stats->memory->working_set); + free(container_name); + free(stats); + lmctfy_delete_container(container); + lmctfy_delete_container_api(lmctfy); return 0; } From a1e266ff9dfc4153b496b2c39d99e4f4782575bf Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Tue, 11 Mar 2014 21:54:54 -0400 Subject: [PATCH 73/84] changed the order of headers. --- clmctfy/status-c.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clmctfy/status-c.cc b/clmctfy/status-c.cc index 8ef4b54..b6bfff9 100644 --- a/clmctfy/status-c.cc +++ b/clmctfy/status-c.cc @@ -1,10 +1,11 @@ +#include "clmctfy_internal.h" + #include // to use strdup #include #include "util/task/status.h" #include "clmctfy.h" -#include "clmctfy_internal.h" using ::util::Status; From 0fa1b94d3e50f8b398b3b574dd5ae27a3f1a6453 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 12 Mar 2014 00:07:21 -0400 Subject: [PATCH 74/84] changed the order of parameters. --- clmctfy/clmctfy_container.cc | 160 +++++++++--------- clmctfy/clmctfy_container_api.cc | 44 ++--- clmctfy/clmctfy_container_api_ctest.cc | 38 ++--- clmctfy/clmctfy_container_ctest.cc | 55 +++--- clmctfy/clmctfy_macros_ctest.h | 14 +- include/clmctfy-raw.h | 81 +++++++-- include/clmctfy.h | 222 +++++++++++++------------ 7 files changed, 329 insertions(+), 285 deletions(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 6d4fb80..2f200b7 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -28,13 +28,13 @@ using ::std::unordered_map; #define STATUS_OK UTIL__ERROR__CODE__OK -int lmctfy_container_run_raw(struct status *s, - pid_t *tid, - struct container *container, +int lmctfy_container_run_raw(struct container *container, const int argc, const char **argv, const void *spec, - const size_t spec_size) { + const size_t spec_size, + pid_t *tid, + struct status *s) { RunSpec run_spec; CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); @@ -54,13 +54,12 @@ int lmctfy_container_run_raw(struct status *s, return STATUS_OK; } -int lmctfy_container_run(struct status *s, - pid_t *tid, - struct container *container, +int lmctfy_container_run(struct container *container, const int argc, const char **argv, - const Containers__Lmctfy__RunSpec *spec) { - + const Containers__Lmctfy__RunSpec *spec, + pid_t *tid, + struct status *s) { uint8_t *buf = NULL; size_t sz = 0; int ret = 0; @@ -74,39 +73,39 @@ int lmctfy_container_run(struct status *s, buf = new uint8_t[sz]; containers__lmctfy__run_spec__pack(spec, buf); } - ret = lmctfy_container_run_raw(s, tid, container, argc, argv, buf, sz); + ret = lmctfy_container_run_raw(container, argc, argv, buf, sz, tid, s); if (buf != NULL) { delete []buf; } return ret; } -int lmctfy_container_enter(struct status *s, - struct container *container, +int lmctfy_container_enter(struct container *container, const pid_t *tids, - const int n) { + const int tids_size, + struct status *s) { int ret = STATUS_OK; CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); - if (tids == NULL || n <= 0) { + if (tids == NULL || tids_size <= 0) { return ret; } - vector tids_v(n); + vector tids_v(tids_size); int i = 0; - for (i = 0; i < n; i++) { + for (i = 0; i < tids_size; i++) { tids_v[i] = tids[i]; } Status status = container->container_->Enter(tids_v); return status_copy(s, status); } -int lmctfy_container_exec(struct status *s, - struct container *container, +int lmctfy_container_exec(struct container *container, const int argc, - const char **argv) { + const char **argv, + struct status *s) { int ret = STATUS_OK; CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); @@ -141,11 +140,11 @@ void lmctfy_delete_container(struct container *container) { } } -int lmctfy_container_update_raw(struct status *s, - struct container *container, - int policy, - const void *spec, - const size_t spec_size) { +int lmctfy_container_update_raw(struct container *container, + int policy, + const void *spec, + const size_t spec_size, + struct status *s) { ContainerSpec container_spec; CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); @@ -169,11 +168,10 @@ int lmctfy_container_update_raw(struct status *s, return status_copy(s, status); } -int lmctfy_container_update(struct status *s, - struct container *container, +int lmctfy_container_update(struct container *container, int policy, - const Containers__Lmctfy__ContainerSpec *spec) { - + const Containers__Lmctfy__ContainerSpec *spec, + struct status *s) { uint8_t *buf = NULL; size_t sz = 0; int ret = STATUS_OK; @@ -187,16 +185,16 @@ int lmctfy_container_update(struct status *s, buf = new uint8_t[sz]; containers__lmctfy__container_spec__pack(spec, buf); } - ret = lmctfy_container_update_raw(s, container, policy, buf, sz); + ret = lmctfy_container_update_raw(container, policy, buf, sz, s); if (buf != NULL) { delete []buf; } return ret; } -int lmctfy_container_spec(struct status *s, - struct container *container, - Containers__Lmctfy__ContainerSpec **spec) { +int lmctfy_container_spec(struct container *container, + Containers__Lmctfy__ContainerSpec **spec, + struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); @@ -221,18 +219,18 @@ int lmctfy_container_spec(struct status *s, return ret; } -int lmctfy_container_list_subcontainers(struct status *s, +int lmctfy_container_list_subcontainers(struct container *c, + int list_policy, struct container **subcontainers[], - int *nr_subcontainers, - struct container *c, - int list_policy) { + int *subcontainers_size, + struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, c); CHECK_NOTNULL_OR_RETURN(s, c->container_); CHECK_NOTNULL_OR_RETURN(s, subcontainers); - CHECK_NOTNULL_OR_RETURN(s, nr_subcontainers); + CHECK_NOTNULL_OR_RETURN(s, subcontainers_size); - *nr_subcontainers = 0; + *subcontainers_size = 0; *subcontainers = NULL; Container::ListPolicy policy; @@ -263,7 +261,7 @@ int lmctfy_container_list_subcontainers(struct status *s, return status_new(s, UTIL__ERROR__CODE__RESOURCE_EXHAUSTED, "out of memory"); } *subcontainers = subctnrs; - *nr_subcontainers = subcontainers_vector.size(); + *subcontainers_size = subcontainers_vector.size(); vector::const_iterator container_iter = subcontainers_vector.begin(); for (container_iter = subcontainers_vector.begin(); container_iter != subcontainers_vector.end(); container_iter++) { @@ -275,19 +273,19 @@ int lmctfy_container_list_subcontainers(struct status *s, return STATUS_OK; } -int lmctfy_container_list_threads(struct status *s, +int lmctfy_container_list_threads(struct container *container, + int list_policy, pid_t *threads[], - int *nr_threads, - struct container *c, - int list_policy) { + int *threads_size, + struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); - CHECK_NOTNULL_OR_RETURN(s, c); - CHECK_NOTNULL_OR_RETURN(s, c->container_); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); CHECK_NOTNULL_OR_RETURN(s, threads); - CHECK_NOTNULL_OR_RETURN(s, nr_threads); + CHECK_POSITIVE_OR_RETURN(s, threads_size); *threads = NULL; - *nr_threads = 0; + *threads_size = 0; Container::ListPolicy policy; switch (list_policy) { case CONTAINER_LIST_POLICY_SELF: @@ -300,13 +298,13 @@ int lmctfy_container_list_threads(struct status *s, return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "Unknown list policy: %d", list_policy); } - StatusOr> statusor_pids = c->container_->ListThreads(policy); + StatusOr> statusor_pids = container->container_->ListThreads(policy); if (!statusor_pids.ok()) { return status_copy(s, statusor_pids.status()); } const vector &pids = statusor_pids.ValueOrDie(); - *nr_threads = pids.size(); - if (*nr_threads == 0) { + *threads_size = pids.size(); + if (*threads_size == 0) { return STATUS_OK; } @@ -319,19 +317,19 @@ int lmctfy_container_list_threads(struct status *s, return STATUS_OK; } -int lmctfy_container_list_processes(struct status *s, +int lmctfy_container_list_processes(struct container *c, + int list_policy, pid_t *processes[], - int *nr_processes, - struct container *c, - int list_policy) { + int *processes_size, + struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, c); CHECK_NOTNULL_OR_RETURN(s, c->container_); CHECK_NOTNULL_OR_RETURN(s, processes); - CHECK_NOTNULL_OR_RETURN(s, nr_processes); + CHECK_NOTNULL_OR_RETURN(s, processes_size); *processes = NULL; - *nr_processes = 0; + *processes_size = 0; Container::ListPolicy policy; switch (list_policy) { case CONTAINER_LIST_POLICY_SELF: @@ -349,8 +347,8 @@ int lmctfy_container_list_processes(struct status *s, return status_copy(s, statusor_pids.status()); } const vector &pids = statusor_pids.ValueOrDie(); - *nr_processes = pids.size(); - if (*nr_processes == 0) { + *processes_size = pids.size(); + if (*processes_size == 0) { return STATUS_OK; } @@ -363,8 +361,7 @@ int lmctfy_container_list_processes(struct status *s, return STATUS_OK; } -int lmctfy_container_pause(struct status *s, - struct container *container) { +int lmctfy_container_pause(struct container *container, struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); @@ -373,8 +370,7 @@ int lmctfy_container_pause(struct status *s, return status_copy(s, status); } -int lmctfy_container_resume(struct status *s, - struct container *container) { +int lmctfy_container_resume(struct container *container, struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); @@ -383,8 +379,7 @@ int lmctfy_container_resume(struct status *s, return status_copy(s, status); } -int lmctfy_container_killall(struct status *s, - struct container *container) { +int lmctfy_container_killall(struct container *container, struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); @@ -393,10 +388,10 @@ int lmctfy_container_killall(struct status *s, return status_copy(s, status); } -int lmctfy_container_stats(struct status *s, - struct container *container, +int lmctfy_container_stats(struct container *container, int stats_type, - Containers__Lmctfy__ContainerStats **stats) { + Containers__Lmctfy__ContainerStats **stats, + struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); @@ -480,13 +475,13 @@ inline void EventCallbackWrapper::Run(Container *c, Status s) { } } -int lmctfy_container_register_notification_raw(struct status *s, - notification_id_t *notif_id, - struct container *container, +int lmctfy_container_register_notification_raw(struct container *container, lmctfy_event_callback_f callback, void *user_data, const void *spec, - const size_t spec_size) { + const size_t spec_size, + notification_id_t *notif_id, + struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); @@ -513,13 +508,12 @@ int lmctfy_container_register_notification_raw(struct status *s, return STATUS_OK; } -int lmctfy_container_register_notification(struct status *s, - notification_id_t *notif_id, - struct container *container, +int lmctfy_container_register_notification(struct container *container, lmctfy_event_callback_f callback, void *user_data, - Containers__Lmctfy__EventSpec *spec) { - + Containers__Lmctfy__EventSpec *spec, + notification_id_t *notif_id, + struct status *s) { uint8_t *buf = NULL; size_t sz = 0; int ret = 0; @@ -535,22 +529,22 @@ int lmctfy_container_register_notification(struct status *s, buf = new uint8_t[sz]; containers__lmctfy__event_spec__pack(spec, buf); } - ret = lmctfy_container_register_notification_raw(s, - notif_id, - container, + ret = lmctfy_container_register_notification_raw(container, callback, user_data, buf, - sz); + sz, + notif_id, + s); if (buf != NULL) { delete []buf; } return ret; } -int lmctfy_container_unregister_notification(struct status *s, - struct container *container, - const notification_id_t notif_id) { +int lmctfy_container_unregister_notification(struct container *container, + const notification_id_t notif_id, + struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, container); CHECK_NOTNULL_OR_RETURN(s, container->container_); diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index a3834bd..f60b1cb 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -22,7 +22,7 @@ using ::util::internal::status_new; using ::util::Status; using ::util::StatusOr; -int lmctfy_init_machine_raw(struct status *s, const void *spec, const size_t spec_size) { +int lmctfy_init_machine_raw(const void *spec, const size_t spec_size, struct status *s) { InitSpec init_spec; CHECK_NOTFAIL_OR_RETURN(s); if (spec != NULL && spec_size > 0) { @@ -33,7 +33,7 @@ int lmctfy_init_machine_raw(struct status *s, const void *spec, const size_t spe return status_copy(s, v); } -int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec) { +int lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec, struct status *s) { uint8_t *buf = NULL; size_t sz = 0; int ret = 0; @@ -46,14 +46,14 @@ int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *sp buf = new uint8_t[sz]; containers__lmctfy__init_spec__pack(spec, buf); } - ret = lmctfy_init_machine_raw(s, buf, sz); + ret = lmctfy_init_machine_raw(buf, sz, s); if (buf != NULL) { delete []buf; } return ret; } -int lmctfy_new_container_api(struct status *s, struct container_api **api) { +int lmctfy_new_container_api(struct container_api **api, struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, api); *api = new container_api(); @@ -79,10 +79,10 @@ void lmctfy_delete_container_api(struct container_api *api) { } \ } while(0) -int lmctfy_container_api_get_container(struct status *s, +int lmctfy_container_api_get_container(const struct container_api *api, + const char *container_name, struct container **c, - const struct container_api *api, - const char *container_name) { + struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, api); CHECK_NOTNULL_OR_RETURN(s, api->container_api_); @@ -97,12 +97,12 @@ int lmctfy_container_api_get_container(struct status *s, return STATUS_OK; } -int lmctfy_container_api_create_container_raw(struct status *s, - struct container **c, - struct container_api *api, +int lmctfy_container_api_create_container_raw(struct container_api *api, const char *container_name, const void *spec, - const size_t spec_size) { + const size_t spec_size, + struct container **c, + struct status *s) { CHECK_NOTNULL_OR_RETURN(s, api); CHECK_NOTNULL_OR_RETURN(s, api->container_api_); CHECK_NOTNULL_OR_RETURN(s, c); @@ -120,11 +120,11 @@ int lmctfy_container_api_create_container_raw(struct status *s, return STATUS_OK; } -int lmctfy_container_api_create_container(struct status *s, - struct container **c, - struct container_api *api, +int lmctfy_container_api_create_container(struct container_api *api, const char *container_name, - const Containers__Lmctfy__ContainerSpec *spec) { + const Containers__Lmctfy__ContainerSpec *spec, + struct container **c, + struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, api); CHECK_NOTNULL_OR_RETURN(s, api->container_api_); @@ -140,16 +140,16 @@ int lmctfy_container_api_create_container(struct status *s, buf = new uint8_t[sz]; } containers__lmctfy__container_spec__pack(spec, buf); - ret = lmctfy_container_api_create_container_raw(s, c, api, container_name, buf, sz); + ret = lmctfy_container_api_create_container_raw(api, container_name, buf, sz, c, s); if (buf != NULL) { delete []buf; } return ret; } -int lmctfy_container_api_destroy_container(struct status *s, - struct container_api *api, - struct container *c) { +int lmctfy_container_api_destroy_container(struct container_api *api, + struct container *c, + struct status *s) { CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, api); CHECK_NOTNULL_OR_RETURN(s, api->container_api_); @@ -161,10 +161,10 @@ int lmctfy_container_api_destroy_container(struct status *s, return ret; } -int lmctfy_container_api_detect_container(struct status *s, +int lmctfy_container_api_detect_container(struct container_api *api, + pid_t pid, char **container_name, - struct container_api *api, - pid_t pid) { + struct status *s) { int ret = STATUS_OK; CHECK_NOTFAIL_OR_RETURN(s); CHECK_NOTNULL_OR_RETURN(s, api); diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index 08a3f49..ebe44f6 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -48,7 +48,7 @@ class ClmctfyContainerApiTest : public ::testing::Test { virtual void SetUp() { container_api_ = NULL; container_ = NULL; - lmctfy_new_container_api(NULL, &container_api_); + lmctfy_new_container_api(&container_api_, NULL); } virtual void TearDown() { @@ -88,16 +88,16 @@ TEST_F(ClmctfyContainerApiTest, GetContainer) { .WillOnce(Return(statusor_container)) .WillOnce(Return(statusor)); - SHOULD_SUCCEED(lmctfy_container_api_get_container, &container_, container_api_, container_name); + SHOULD_SUCCEED(lmctfy_container_api_get_container, container_api_, container_name, &container_); Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); struct container *tmp = container_; container_ = NULL; - SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_get_container, &container_, container_api_, container_name); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_get_container, NULL, container_api_, container_name); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_get_container, &container_, container_api_, NULL); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_get_container, &container_, container_api_, ""); - WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_get_container, &container_, container_api_, container_name); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_get_container, container_api_, container_name, &container_); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_get_container, container_api_, container_name, NULL); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_get_container, container_api_, NULL, &container_); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_get_container, container_api_, "", &container_); + WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_get_container, container_api_, container_name, &container_); container_ = tmp; } @@ -117,18 +117,18 @@ TEST_F(ClmctfyContainerApiTest, CreateContainer) { Containers__Lmctfy__ContainerSpec spec = CONTAINERS__LMCTFY__CONTAINER_SPEC__INIT; - SHOULD_SUCCEED(lmctfy_container_api_create_container, &container_, container_api_, container_name, &spec); + SHOULD_SUCCEED(lmctfy_container_api_create_container, container_api_, container_name, &spec, &container_); Container *ctnr_2 = GetMockContainer(); EXPECT_EQ(ctnr_2, ctnr); struct container *tmp = container_; container_ = NULL; - SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_create_container, &container_, container_api_, container_name, &spec); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_create_container, container_api_, container_name, &spec, &container_); EXPECT_EQ(container_, (struct container *)NULL); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, NULL, container_api_, container_name, &spec); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, &container_, container_api_, container_name, NULL); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, &container_, container_api_, NULL, &spec); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, &container_, container_api_, "", &spec); - WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_get_container, &container_, container_api_, container_name); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, container_api_, container_name, &spec, NULL); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, container_api_, container_name, NULL, &container_); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, container_api_, NULL, &spec, &container_); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_api_create_container, container_api_, "", &spec, &container_); + WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_get_container, container_api_, container_name, &container_); container_ = tmp; } @@ -148,10 +148,10 @@ TEST_F(ClmctfyContainerApiTest, DestroyContainer) { .WillOnce(Return(Status::OK)) .WillOnce(Return(destroy_status)); - SHOULD_SUCCEED(lmctfy_container_api_get_container, &container_, container_api_, container_name); + SHOULD_SUCCEED(lmctfy_container_api_get_container, container_api_, container_name, &container_); SHOULD_SUCCEED(lmctfy_container_api_destroy_container, container_api_, container_); - SHOULD_SUCCEED(lmctfy_container_api_get_container, &container_, container_api_, container_name); + SHOULD_SUCCEED(lmctfy_container_api_get_container, container_api_, container_name, &container_); SHOULD_FAIL_WITH_ERROR(destroy_status, lmctfy_container_api_destroy_container, container_api_, container_); WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_destroy_container, container_api_, container_); @@ -175,14 +175,14 @@ TEST_F(ClmctfyContainerApiTest, DetectContainer) { .WillOnce(Return(statusor)) .WillOnce(Return(statusor_fail)); - SHOULD_SUCCEED(lmctfy_container_api_detect_container, &output_name, container_api_, pid); + SHOULD_SUCCEED(lmctfy_container_api_detect_container, container_api_, pid, &output_name); EXPECT_EQ(string(container_name), string(output_name)); free(output_name); output_name = NULL; - SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_detect_container, &output_name, container_api_, pid); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_api_detect_container, container_api_, pid, &output_name); EXPECT_EQ(output_name, NULL); - WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_detect_container, &output_name, container_api_, pid); + WITH_NULL_CONTAINER_API_RUN(lmctfy_container_api_detect_container, container_api_, pid, &output_name); } } // namespace lmctfy diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index bfc672b..2f49e27 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -52,16 +52,13 @@ class ClmctfyContainerTest : public ::testing::Test { container_ = NULL; const char *container_name = "/test"; container_name_ = container_name; - lmctfy_new_container_api(NULL, &container_api_); + lmctfy_new_container_api(&container_api_, NULL); StrictMockContainerApi *mock_api = GetMockApi(); Container *ctnr = new StrictMockContainer(container_name); StatusOr statusor = StatusOr(ctnr); EXPECT_CALL(*mock_api, Get(StringPiece(container_name))).WillOnce(Return(statusor)); - lmctfy_container_api_get_container(NULL, - &container_, - container_api_, - container_name); + lmctfy_container_api_get_container(container_api_, container_name, &container_, NULL); } virtual void TearDown() { @@ -146,10 +143,10 @@ TEST_F(ClmctfyContainerTest, Run) { .WillOnce(Return(statusor_success)) .WillOnce(Return(statusor_fail)); - SHOULD_SUCCEED(lmctfy_container_run, &tid, container_, argc, argv, &runspec); - SHOULD_FAIL_WITH_ERROR(err_status, lmctfy_container_run, &tid, container_, argc, argv, &runspec); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_run, &tid, container_, 0, NULL, &runspec); - WITH_NULL_CONTAINER_RUN(lmctfy_container_run, &tid, container_, argc, argv, &runspec); + SHOULD_SUCCEED(lmctfy_container_run, container_, argc, argv, &runspec, &tid); + SHOULD_FAIL_WITH_ERROR(err_status, lmctfy_container_run, container_, argc, argv, &runspec, &tid); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_run, container_, 0, NULL, &runspec, &tid); + WITH_NULL_CONTAINER_RUN(lmctfy_container_run, container_, argc, argv, &runspec, &tid); } TEST_F(ClmctfyContainerTest, Enter) { @@ -210,7 +207,7 @@ TEST_F(ClmctfyContainerTest, ListSubContainers) { struct container **subcontainers; int nr_containers; - SHOULD_SUCCEED(lmctfy_container_list_subcontainers, &subcontainers, &nr_containers, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_SUCCEED(lmctfy_container_list_subcontainers, container_, CONTAINER_LIST_POLICY_SELF, &subcontainers, &nr_containers); EXPECT_EQ(nr_containers, subcontainers_vector.size()); vector::iterator iter; int i = 0; @@ -222,14 +219,14 @@ TEST_F(ClmctfyContainerTest, ListSubContainers) { free(subcontainers); subcontainers = NULL; - SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_list_subcontainers, &subcontainers, &nr_containers, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_list_subcontainers, container_, CONTAINER_LIST_POLICY_SELF, &subcontainers, &nr_containers); EXPECT_EQ(nr_containers, 0); EXPECT_EQ(subcontainers, (struct container **)NULL); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_subcontainers, NULL, &nr_containers, container_, CONTAINER_LIST_POLICY_SELF); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_subcontainers, &subcontainers, NULL, container_, CONTAINER_LIST_POLICY_SELF); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_subcontainers, &subcontainers, &nr_containers, container_, -1); - WITH_NULL_CONTAINER_RUN(lmctfy_container_list_subcontainers, &subcontainers, &nr_containers, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_subcontainers, container_, CONTAINER_LIST_POLICY_SELF, NULL, &nr_containers); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_subcontainers, container_, CONTAINER_LIST_POLICY_SELF, &subcontainers, NULL); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_subcontainers, container_, -1, &subcontainers, &nr_containers); + WITH_NULL_CONTAINER_RUN(lmctfy_container_list_subcontainers, container_, CONTAINER_LIST_POLICY_SELF, &subcontainers, &nr_containers); } TEST_F(ClmctfyContainerTest, ListThreads) { @@ -252,7 +249,7 @@ TEST_F(ClmctfyContainerTest, ListThreads) { pid_t *pids; int nr_threads; - SHOULD_SUCCEED(lmctfy_container_list_threads, &pids, &nr_threads, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_SUCCEED(lmctfy_container_list_threads, container_, CONTAINER_LIST_POLICY_SELF, &pids, &nr_threads); EXPECT_EQ(nr_threads, pids_vector.size()); vector::const_iterator iter; int i = 0; @@ -262,13 +259,13 @@ TEST_F(ClmctfyContainerTest, ListThreads) { free(pids); pids = NULL; - SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_list_threads, &pids, &nr_threads, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_list_threads, container_, CONTAINER_LIST_POLICY_SELF, &pids, &nr_threads); EXPECT_EQ(nr_threads, 0); EXPECT_EQ(pids, (pid_t *)NULL); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_threads, NULL, &nr_threads, container_, CONTAINER_LIST_POLICY_SELF); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_threads, &pids, NULL, container_, CONTAINER_LIST_POLICY_SELF); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_threads, &pids, &nr_threads, container_, -1); - WITH_NULL_CONTAINER_RUN(lmctfy_container_list_threads, &pids, &nr_threads, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_threads, container_, CONTAINER_LIST_POLICY_SELF, NULL, &nr_threads); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_threads, container_, CONTAINER_LIST_POLICY_SELF, &pids, NULL); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_threads, container_, -1, &pids, &nr_threads); + WITH_NULL_CONTAINER_RUN(lmctfy_container_list_threads, container_, CONTAINER_LIST_POLICY_SELF, &pids, &nr_threads); } TEST_F(ClmctfyContainerTest, ListProcesses) { @@ -291,7 +288,7 @@ TEST_F(ClmctfyContainerTest, ListProcesses) { pid_t *pids; int nr_processes; - SHOULD_SUCCEED(lmctfy_container_list_processes, &pids, &nr_processes, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_SUCCEED(lmctfy_container_list_processes, container_, CONTAINER_LIST_POLICY_SELF, &pids, &nr_processes); EXPECT_EQ(nr_processes, pids_vector.size()); vector::const_iterator iter; int i = 0; @@ -301,13 +298,13 @@ TEST_F(ClmctfyContainerTest, ListProcesses) { free(pids); pids = NULL; - SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_list_processes, &pids, &nr_processes, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_FAIL_WITH_ERROR(status, lmctfy_container_list_processes, container_, CONTAINER_LIST_POLICY_SELF, &pids, &nr_processes); EXPECT_EQ(nr_processes, 0); EXPECT_EQ(pids, (pid_t *)NULL); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_processes, NULL, &nr_processes, container_, CONTAINER_LIST_POLICY_SELF); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_processes, &pids, NULL, container_, CONTAINER_LIST_POLICY_SELF); - SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_processes, &pids, &nr_processes, container_, -1); - WITH_NULL_CONTAINER_RUN(lmctfy_container_list_processes, &pids, &nr_processes, container_, CONTAINER_LIST_POLICY_SELF); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_processes, container_, CONTAINER_LIST_POLICY_SELF, NULL, &nr_processes); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_processes, container_, CONTAINER_LIST_POLICY_SELF, &pids, NULL); + SHOULD_BE_INVALID_ARGUMENT(lmctfy_container_list_processes, container_, -1, &pids, &nr_processes); + WITH_NULL_CONTAINER_RUN(lmctfy_container_list_processes, container_, CONTAINER_LIST_POLICY_SELF, &pids, &nr_processes); } TEST_F(ClmctfyContainerTest, Pause) { @@ -385,11 +382,11 @@ TEST_F(ClmctfyContainerTest, RegisterThenUnRegister) { .WillOnce(Return(Status::OK)); SHOULD_SUCCEED(lmctfy_container_register_notification, - ¬if_id, container_, event_callback_counter, &evt_counter, - &spec); + &spec, + ¬if_id); EXPECT_EQ(notif_id, 1); } diff --git a/clmctfy/clmctfy_macros_ctest.h b/clmctfy/clmctfy_macros_ctest.h index 33b7f0d..012faa7 100644 --- a/clmctfy/clmctfy_macros_ctest.h +++ b/clmctfy/clmctfy_macros_ctest.h @@ -7,7 +7,7 @@ ContainerApi *tmp = container_api_->container_api_; \ container_api_->container_api_ = NULL; \ struct status s = {0, NULL}; \ - int ret = func(&s, __VA_ARGS__); \ + int ret = func(__VA_ARGS__, &s); \ EXPECT_EQ(ret, s.error_code); \ EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ container_api_->container_api_ = tmp; \ @@ -15,7 +15,7 @@ struct container_api *tmp_api = container_api_; \ container_api_ = NULL; \ s = {0, NULL}; \ - ret = func(&s, __VA_ARGS__); \ + ret = func(__VA_ARGS__, &s); \ EXPECT_EQ(ret, s.error_code); \ EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ container_api_ = tmp_api; \ @@ -25,7 +25,7 @@ Container *tmp = container_->container_; \ container_->container_ = NULL; \ struct status s = {0, NULL}; \ - int ret = func(&s, __VA_ARGS__); \ + int ret = func(__VA_ARGS__, &s); \ EXPECT_EQ(ret, s.error_code); \ EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ container_->container_ = tmp; \ @@ -33,7 +33,7 @@ struct container *tmp_container = container_; \ container_ = NULL; \ s = {0, NULL}; \ - ret = func(&s, __VA_ARGS__); \ + ret = func(__VA_ARGS__, &s); \ EXPECT_EQ(ret, s.error_code); \ EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ container_ = tmp_container; \ @@ -41,7 +41,7 @@ #define SHOULD_SUCCEED(func, ...) do { \ struct status s = {0, NULL}; \ - int ret = func(&s, __VA_ARGS__); \ + int ret = func(__VA_ARGS__, &s); \ EXPECT_EQ(ret, 0); \ EXPECT_EQ(s.error_code, 0); \ EXPECT_EQ(s.message, NULL); \ @@ -49,7 +49,7 @@ #define SHOULD_FAIL_WITH_ERROR(st, func, ...) do { \ struct status s = {0, NULL}; \ - int ret = func(&s, __VA_ARGS__); \ + int ret = func(__VA_ARGS__, &s); \ EXPECT_EQ(ret, s.error_code); \ EXPECT_EQ(s.error_code, (st).error_code()); \ EXPECT_EQ((st).error_message(), s.message); \ @@ -58,7 +58,7 @@ #define SHOULD_BE_INVALID_ARGUMENT(func, ...) do { \ struct status s = {0, NULL}; \ - int ret = func(&s, __VA_ARGS__); \ + int ret = func(__VA_ARGS__, &s); \ EXPECT_EQ(ret, s.error_code); \ EXPECT_EQ(s.error_code, UTIL__ERROR__CODE__INVALID_ARGUMENT); \ if (s.message != NULL) { \ diff --git a/include/clmctfy-raw.h b/include/clmctfy-raw.h index b1f6816..ecec8db 100644 --- a/include/clmctfy-raw.h +++ b/include/clmctfy-raw.h @@ -12,44 +12,93 @@ extern "C" { // Initializes the machine to start being able to create containers. // // Arguments: -// - s: [output] s will be used as output. It contains the error code/message. // - spec: Serialized data (protobuf format) containing the specification. +// Caller takes the ownership. // - spec_size: Size of the serialized data. +// - s: [output] s will be used as output. It contains the error code/message. // // Returns: // Returns the error code. 0 on success. The return code is same as // status_get_code(s). -int lmctfy_init_machine_raw(struct status *s, const void *spec, const size_t spec_size); +int lmctfy_init_machine_raw(const void *spec, const size_t spec_size, struct status *s); int lmctfy_container_api_create_container_raw( - struct status *s, - struct container **container, struct container_api *api, const char *container_name, const void *spec, - const size_t spec_size); + const size_t spec_size, + struct container **container, + struct status *s); -int lmctfy_container_run_raw(struct status *s, - pid_t *tid, - struct container *container, +// Run the specified command inside the container. Multiple instances of run +// can be active simultaneously. Processes MUST be reaped by the caller. +// +// Arguments: +// +// - container: The container. +// - argc: number of arguments (including the binary file path). +// - argv: All arguments. The first element is the binary that will be executed +// and must be an absolute path. +// - spec: Serialized data (protobuf format) containing the specification. +// Caller takes the ownership. +// - spec_size: Size of the serialized data. +// - tid: [output] On success, tid stores the PID of the command. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_run_raw(struct container *container, const int argc, const char **argv, const void *spec, - const size_t spec_size); + const size_t spec_size, + pid_t *tid, + struct status *s); -int lmctfy_container_update_raw(struct status *s, - struct container *container, +// Updates the container according to the specification. The set of resource +// types being isolated cannot change during an Update. This means that a +// CONTAINER_UPDATE_POLICY_REPLACE must specify all the resources being isolated +// and a CONTAINER_UPDATE_POLICY_DIFF cannot specify any resource that is not +// already being isolated. +// +// Arguments: +// +// - container +// - policy: Update policy. Can be either CONTAINER_UPDATE_POLICY_DIFF, or +// CONTAINER_UPDATE_POLICY_REPLACE. +// - spec: Serialized data (protobuf format) containing the specification. +// Caller takes the ownership. +// - spec_size: Size of the serialized data. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_update_raw(struct container *container, int policy, const void *spec, - const size_t spec_size); + const size_t spec_size, + struct status *s); -int lmctfy_container_register_notification_raw(struct status *s, - notification_id_t *notif_id, - struct container *container, +// Register a notification for a specified container event. All notifications +// are unregistered when the container is destroyed. +// +// Arguments: +// - container: The container. +// - callback: The callback to run when the event is triggered. The caller +// takes ownership of the callback which MUST be a repeatable callback. +// - user_data: The pointer which will be passed to the callback function as +// its last parameter. The caller takes the ownership. +// - spec: Serialized data (protobuf format) containing the specification. +// Caller takes the ownership. +// - spec_size: Size of the serialized data. +// - notif_id: [output] The ID for the notification. The ID is unique within +// the current container_api instance. It will be used to unregister the +// notification +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_register_notification_raw(struct container *container, lmctfy_event_callback_f callback, void *user_data, const void *spec, - const size_t spec_size); + const size_t spec_size, + notification_id_t *notif_id, + struct status *s); #ifdef __cplusplus } diff --git a/include/clmctfy.h b/include/clmctfy.h index 4c91637..fef9714 100644 --- a/include/clmctfy.h +++ b/include/clmctfy.h @@ -69,29 +69,29 @@ typedef uint64_t notification_id_t; // Initializes the machine to start being able to create containers. // // Arguments: +// - spec: The specification. Caller owns the pointer. // - s: [output] The status of the operations and an error message if the // status is not OK. -// - spec: The specification. Caller owns the pointer. // // Returns: // // Returns the error code. 0 on success. When there's an error, the return code // is same as s->error_code when s is not NULL. -int lmctfy_init_machine(struct status *s, const Containers__Lmctfy__InitSpec *spec); +int lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec, struct status *s); // Create a new container_api. // // Arguments: -// - s: [output] The status of the operations and an error message if the -// status is not OK. // - api: [output] The address of a pointer to struct container_api. The // pointer of the container api will be stored in this address. +// - s: [output] The status of the operations and an error message if the +// status is not OK. // // Returns: // // Returns the error code. 0 on success. When there's an error, the return code // is same as s->error_code when s is not NULL. -int lmctfy_new_container_api(struct status *s, struct container_api **api); +int lmctfy_new_container_api(struct container_api **api, struct status *s); // Release the container api. // @@ -104,45 +104,46 @@ void lmctfy_delete_container_api(struct container_api *api); // // Arguments: // +// - api: A container api. +// - container_name: the container name. // - s: [output] The status of the operations and an error message if the // status is not OK. // - container: [output] The address of a pointer to struct container. It will -// be used to store the pointer to the container. -// - api: A container api. -// - container_name: the container name. +// be used to store the pointer to the container. The caller takes the +// ownership. // // Returns: // // Returns the error code. 0 on success. When there's an error, the return code // is same as s->error_code when s is not NULL. int lmctfy_container_api_get_container( - struct status *s, - struct container **container, const struct container_api *api, - const char *container_name); + const char *container_name, + struct container **container, + struct status *s); // Create a container // // Arguments: // -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// - container: [output] The address of a pointer to struct container. It will -// be used to store the newly created container. // - api: A container api. // - container_name: the container name. // - spec: container specification. Caller owns the pointer. +// - container: [output] The address of a pointer to struct container. It will +// be used to store the newly created container. +// - s: [output] The status of the operations and an error message if the +// status is not OK. // // Returns: // // Returns the error code. 0 on success. When there's an error, the return code // is same as s->error_code when s is not NULL. int lmctfy_container_api_create_container( - struct status *s, - struct container **container, struct container_api *api, const char *container_name, - const Containers__Lmctfy__ContainerSpec *spec); + const Containers__Lmctfy__ContainerSpec *spec, + struct container **container, + struct status *s); // Destroy a container. The caller has to call lmctfy_delete_container after // detroying a container. Otherwise, the memory occupied by the container @@ -150,40 +151,39 @@ int lmctfy_container_api_create_container( // // Arguments: // -// - s: [output] The status of the operations and an error message if the -// status is not OK. // - api: A container api. // - container: The pointer to struct container. The pointer will become // invalid after a successful destroy(). +// - s: [output] The status of the operations and an error message if the +// status is not OK. // // Returns: // // Returns the error code. 0 on success. When there's an error, the return code // is same as s->error_code when s is not NULL. -int lmctfy_container_api_destroy_container(struct status *s, - struct container_api *api, - struct container *container); - +int lmctfy_container_api_destroy_container(struct container_api *api, + struct container *container, + struct status *s); // Detect what container the specified thread is in. // // Arguments: -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// - container_name: [output] Will be used to store the container name. -// It's the caller's responsibility to free() *container_name. // - api: The container api. // - pid: The thread ID to check. 0 refers to self. -int lmctfy_container_api_detect_container(struct status *s, +// - container_name: [output] Will be used to store the container name. +// It's the caller's responsibility to free() *container_name. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_api_detect_container(struct container_api *api, + pid_t pid, char **container_name, - struct container_api *api, - pid_t pid); + struct status *s); // Release the memory used by the container structure. The refered container // will not be affected. // // Arguments: // -// - container: The container. This pointer will be invalid after the call to +// - container: The container. This pointer will be invalid after the call to // this function void lmctfy_delete_container(struct container *container); @@ -191,36 +191,38 @@ void lmctfy_delete_container(struct container *container); // // Arguments: // -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// - container +// - container: The container. // - tids: Array of thread IDs to move into the container. Caller takes the // ownership. // - tids_size: Number of thread IDs stored in tids. Caller takes the // ownership. -int lmctfy_container_enter(struct status *s, - struct container *container, +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_enter(struct container *container, const pid_t *tids, - const int tids_size); + const int tids_size, + struct status *s); // Run the specified command inside the container. Multiple instances of run // can be active simultaneously. Processes MUST be reaped by the caller. // // Arguments: // -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// - tid: [output] On success, tid stores the PID of the command. -// - container +// - container: The container. // - argc: number of arguments (including the binary file path). // - argv: All arguments. The first element is the binary that will be executed // and must be an absolute path. -int lmctfy_container_run(struct status *s, - pid_t *tid, - struct container *container, +// - spec: The specification of the runtime environment to use for the +// execution of the command. +// - tid: [output] On success, tid stores the PID of the command. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_run(struct container *container, const int argc, const char **argv, - const Containers__Lmctfy__RunSpec *spec); + const Containers__Lmctfy__RunSpec *spec, + pid_t *tid, + struct status *s); // Execute the specified command inside the container. This replaces the // current process image with the specified command. The PATH environment @@ -229,16 +231,16 @@ int lmctfy_container_run(struct status *s, // // Arguments: // -// - s: [output] The status of the operations and an error message if the -// status is not OK. // - container // - argc: number of arguments (including the binary file path). // - argv: All arguments. The first element is the binary that will be executed // and must be an absolute path. -int lmctfy_container_exec(struct status *s, - struct container *container, +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_exec(struct container *container, const int argc, - const char **argv); + const char **argv, + struct status *s); // Updates the container according to the specification. The set of resource // types being isolated cannot change during an Update. This means that a @@ -248,38 +250,38 @@ int lmctfy_container_exec(struct status *s, // // Arguments: // -// - s: [output] The status of the operations and an error message if the -// status is not OK. // - container // - policy: Update policy. Can be either CONTAINER_UPDATE_POLICY_DIFF, or // CONTAINER_UPDATE_POLICY_REPLACE. // - spec: The specification of the desired updates. -int lmctfy_container_update(struct status *s, - struct container *container, +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_update(struct container *container, int policy, - const Containers__Lmctfy__ContainerSpec *spec); + const Containers__Lmctfy__ContainerSpec *spec, + struct status *s); // Returns the resource isolation specification (ContainerSpec) of this // container. // // Arguments: // -// - s: [output] The status of the operations and an error message if the -// status is not OK. // - container: The container // - spec: [output] An address of a ContainerSpec pointer. *spec will points to // the ContainerSpec of the container. Caller takes the ownership. *spec can // be released by calling free(). -int lmctfy_container_spec(struct status *s, - struct container *container, - Containers__Lmctfy__ContainerSpec **spec); +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_spec(struct container *container, + Containers__Lmctfy__ContainerSpec **spec, + struct status *s); // List all subcontainers. // // Arguments: // -// - s: [output] The status of the operations and an error message if the -// status is not OK. +// - container: The container +// - list_policy: CONTAINER_LIST_POLICY_SELF or CONTAINER_LIST_POLICY_RECURSIVE // - subcontainers: [output] The address of a pointer points to an array of // struct container pointers. The caller takes the onwership. On success, the // pointer will be assigned an address to an array of containers. The pointed @@ -287,44 +289,46 @@ int lmctfy_container_spec(struct status *s, // should be deleted/destroyed individually. // - subcontainers_size: [output] The address of an integer used to store number // of subcontainers in the array. -// - container: The container -// - list_policy: CONTAINER_LIST_POLICY_SELF or CONTAINER_LIST_POLICY_RECURSIVE -int lmctfy_container_list_subcontainers(struct status *s, +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_list_subcontainers(struct container *container, + int list_policy, struct container **subcontainers[], - int *subcontainers_size, - struct container *container, - int list_policy); + int *subcontainers_size, + struct status *s); // List all TIDs in the container. // // Arguments: -// - s: [output] The status of the operations and an error message if the -// status is not OK. +// - container +// - list_policy: List policy. // - threads: [output] The address of a pointer points to an array of pid_t. // The caller takes the ownership. The array can be released with free(). // - threads_size: [output] *threads_size is the number of TIDs stored in *threads. -// - list_policy: List policy. -int lmctfy_container_list_threads(struct status *s, +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_list_threads(struct container *container, + int list_policy, pid_t *threads[], int *threads_size, - struct container *container, - int list_policy); + struct status *s); // Get all PIDs in this container. // // Arguments: -// - s: [output] The status of the operations and an error message if the -// status is not OK. +// - container +// - list_policy: List policy. // - processes: [output] The address of a pointer points to an array of pid_t. // The caller takes the ownership. The array can be released with free(). // - processes_size: [output] *processes_size is the number of PIDs stored in // *processes. -// - list_policy: List policy. -int lmctfy_container_list_processes(struct status *s, +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_list_processes(struct container *container, + int list_policy, pid_t *processes[], int *processes_size, - struct container *container, - int list_policy); + struct status *s); // Atomically stops the execution of all threads inside the container and all // subcontainers (recursively). All threads moved to a paused container will @@ -332,22 +336,22 @@ int lmctfy_container_list_processes(struct status *s, // guarantees to get all threads. // // Arguments: +// - container: The container. // - s: [output] The status of the operations and an error message if the // status is not OK. -// - container: The container. -int lmctfy_container_pause(struct status *s, - struct container *container); +int lmctfy_container_pause(struct container *container, + struct status *s); // Atomically resumes the execution of all threads inside the container and // all subcontainers (recursively). All paused threads moved to a non-paused // container will be resumed. // // Arguments: +// - container: The container. // - s: [output] The status of the operations and an error message if the // status is not OK. -// - container: The container. -int lmctfy_container_resume(struct status *s, - struct container *container); +int lmctfy_container_resume(struct container *container, + struct status *s); // Kills all processes running in the container. This operation is atomic and // is synchronized with any mutable operations on this container. @@ -360,27 +364,27 @@ int lmctfy_container_resume(struct status *s, // blocks all mutable container operations while it is in progress. // // Arguments: +// - container: The container. // - s: [output] The status of the operations and an error message if the // status is not OK. -// - container: The container. -int lmctfy_container_killall(struct status *s, - struct container *container); +int lmctfy_container_killall(struct container *container, + struct status *s); // Gets usage and state information for the container. Note that the snapshot // is not atomic. // // Arguments: -// - s: [output] The status of the operations and an error message if the -// status is not OK. // - container: The container. // - stats_type: The type of statistics to output. // - stats: [output] Used to store a pointer points to the container's // statistics. The call takes the ownership of *stats, which should be // free()'ed. -int lmctfy_container_stats(struct status *s, - struct container *container, +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_stats(struct container *container, int stats_type, - Containers__Lmctfy__ContainerStats **stats); + Containers__Lmctfy__ContainerStats **stats, + struct status *s); // Get the name of the container. // @@ -396,11 +400,6 @@ const char *lmctfy_container_name(struct container *container); // are unregistered when the container is destroyed. // // Arguments: -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// - notif_id: [output] The ID for the notification. The ID is unique within -// the current container_api instance. It will be used to unregister the -// notification // - container: The container. // - callback: The callback to run when the event is triggered. The caller // takes ownership of the callback which MUST be a repeatable callback. @@ -408,24 +407,29 @@ const char *lmctfy_container_name(struct container *container); // its last parameter. The caller takes the ownership. // - spec: The specification for the event for which to register notifications. // The caller takes the ownership. -int lmctfy_container_register_notification(struct status *s, - notification_id_t *notif_id, - struct container *container, +// - notif_id: [output] The ID for the notification. The ID is unique within +// the current container_api instance. It will be used to unregister the +// notification +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_register_notification(struct container *container, lmctfy_event_callback_f callback, void *user_data, - Containers__Lmctfy__EventSpec *spec); + Containers__Lmctfy__EventSpec *spec, + notification_id_t *notif_id, + struct status *s); // Unregister (stop) the specified notification from being received. // // Arguments: -// - s: [output] The status of the operations and an error message if the -// status is not OK. // - container: The container. // - notif_id: The unique notification ID for the container // notification. -int lmctfy_container_unregister_notification(struct status *s, - struct container *container, - const notification_id_t notif_id); +// - s: [output] The status of the operations and an error message if the +// status is not OK. +int lmctfy_container_unregister_notification(struct container *container, + const notification_id_t notif_id, + struct status *s); #ifdef __cplusplus } From f219fffc6e3fc0c08bfc8d3551796b5f97d9e136 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 12 Mar 2014 00:11:31 -0400 Subject: [PATCH 75/84] comment on create_container_raw() --- include/clmctfy-raw.h | 33 ++++++++++++++++++ include/clmctfy.h | 80 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/include/clmctfy-raw.h b/include/clmctfy-raw.h index ecec8db..bf19569 100644 --- a/include/clmctfy-raw.h +++ b/include/clmctfy-raw.h @@ -22,6 +22,24 @@ extern "C" { // status_get_code(s). int lmctfy_init_machine_raw(const void *spec, const size_t spec_size, struct status *s); +// Create a container +// +// Arguments: +// +// - api: A container api. +// - container_name: the container name. +// - spec: Serialized data (protobuf format) containing the specification. +// Caller takes the ownership. +// - spec_size: Size of the serialized data. +// - container: [output] The address of a pointer to struct container. It will +// be used to store the newly created container. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_api_create_container_raw( struct container_api *api, const char *container_name, @@ -45,6 +63,11 @@ int lmctfy_container_api_create_container_raw( // - tid: [output] On success, tid stores the PID of the command. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_run_raw(struct container *container, const int argc, const char **argv, @@ -69,6 +92,11 @@ int lmctfy_container_run_raw(struct container *container, // - spec_size: Size of the serialized data. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_update_raw(struct container *container, int policy, const void *spec, @@ -92,6 +120,11 @@ int lmctfy_container_update_raw(struct container *container, // notification // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_register_notification_raw(struct container *container, lmctfy_event_callback_f callback, void *user_data, diff --git a/include/clmctfy.h b/include/clmctfy.h index fef9714..d2df69a 100644 --- a/include/clmctfy.h +++ b/include/clmctfy.h @@ -173,6 +173,11 @@ int lmctfy_container_api_destroy_container(struct container_api *api, // It's the caller's responsibility to free() *container_name. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_api_detect_container(struct container_api *api, pid_t pid, char **container_name, @@ -185,6 +190,11 @@ int lmctfy_container_api_detect_container(struct container_api *api, // // - container: The container. This pointer will be invalid after the call to // this function +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. void lmctfy_delete_container(struct container *container); // Moves the specified threads into this container. Enter is atomic. @@ -198,6 +208,11 @@ void lmctfy_delete_container(struct container *container); // ownership. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_enter(struct container *container, const pid_t *tids, const int tids_size, @@ -217,6 +232,11 @@ int lmctfy_container_enter(struct container *container, // - tid: [output] On success, tid stores the PID of the command. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_run(struct container *container, const int argc, const char **argv, @@ -237,6 +257,11 @@ int lmctfy_container_run(struct container *container, // and must be an absolute path. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_exec(struct container *container, const int argc, const char **argv, @@ -256,6 +281,11 @@ int lmctfy_container_exec(struct container *container, // - spec: The specification of the desired updates. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_update(struct container *container, int policy, const Containers__Lmctfy__ContainerSpec *spec, @@ -272,6 +302,11 @@ int lmctfy_container_update(struct container *container, // be released by calling free(). // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_spec(struct container *container, Containers__Lmctfy__ContainerSpec **spec, struct status *s); @@ -291,6 +326,11 @@ int lmctfy_container_spec(struct container *container, // of subcontainers in the array. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_list_subcontainers(struct container *container, int list_policy, struct container **subcontainers[], @@ -307,6 +347,11 @@ int lmctfy_container_list_subcontainers(struct container *container, // - threads_size: [output] *threads_size is the number of TIDs stored in *threads. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_list_threads(struct container *container, int list_policy, pid_t *threads[], @@ -324,6 +369,11 @@ int lmctfy_container_list_threads(struct container *container, // *processes. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_list_processes(struct container *container, int list_policy, pid_t *processes[], @@ -339,6 +389,11 @@ int lmctfy_container_list_processes(struct container *container, // - container: The container. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_pause(struct container *container, struct status *s); @@ -350,6 +405,11 @@ int lmctfy_container_pause(struct container *container, // - container: The container. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_resume(struct container *container, struct status *s); @@ -367,6 +427,11 @@ int lmctfy_container_resume(struct container *container, // - container: The container. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_killall(struct container *container, struct status *s); @@ -381,6 +446,11 @@ int lmctfy_container_killall(struct container *container, // free()'ed. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_stats(struct container *container, int stats_type, Containers__Lmctfy__ContainerStats **stats, @@ -412,6 +482,11 @@ const char *lmctfy_container_name(struct container *container); // notification // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_register_notification(struct container *container, lmctfy_event_callback_f callback, void *user_data, @@ -427,6 +502,11 @@ int lmctfy_container_register_notification(struct container *container, // notification. // - s: [output] The status of the operations and an error message if the // status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. int lmctfy_container_unregister_notification(struct container *container, const notification_id_t notif_id, struct status *s); From 9ed0da0a91b99bc7b79d449a387ff8aaf6867538 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 12 Mar 2014 16:15:16 -0400 Subject: [PATCH 76/84] remove unnecessary functions. --- clmctfy/clmctfy_container_api.cc | 16 ---------------- clmctfy/clmctfy_container_api_ctest.cc | 4 ++-- clmctfy/clmctfy_container_ctest.cc | 6 +++--- clmctfy/clmctfy_internal.h | 17 +++-------------- clmctfy/clmctfy_macros_ctest.h | 6 +++--- 5 files changed, 11 insertions(+), 38 deletions(-) diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index f60b1cb..4a42228 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -177,19 +177,3 @@ int lmctfy_container_api_detect_container(struct container_api *api, } return ret; } - -namespace containers { -namespace lmctfy { -namespace internal { - -ContainerApi *lmctfy_container_api_strip(struct container_api *api) { - return api->container_api_; -} - -Container *lmctfy_container_strip(struct container *c) { - return c->container_; -} - -} // internal -} // lmctfy -} // containers diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index ebe44f6..cb6ca73 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -63,13 +63,13 @@ class ClmctfyContainerApiTest : public ::testing::Test { }; StrictMockContainerApi *ClmctfyContainerApiTest::GetMockApi() { - ContainerApi *capi = internal::lmctfy_container_api_strip(container_api_); + ContainerApi *capi = container_api_->container_api_; StrictMockContainerApi *mock_api = dynamic_cast(capi); return mock_api; } StrictMockContainer *ClmctfyContainerApiTest::GetMockContainer() { - Container *ctnr = internal::lmctfy_container_strip(container_); + Container *ctnr = container_->container_; StrictMockContainer *mock_container = dynamic_cast(ctnr); return mock_container; } diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 2f49e27..41b7245 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -74,13 +74,13 @@ class ClmctfyContainerTest : public ::testing::Test { }; StrictMockContainerApi *ClmctfyContainerTest::GetMockApi() { - ContainerApi *capi = internal::lmctfy_container_api_strip(container_api_); + ContainerApi *capi = container_api_->container_api_; StrictMockContainerApi *mock_api = dynamic_cast(capi); return mock_api; } StrictMockContainer *ClmctfyContainerTest::GetMockContainer() { - Container *ctnr = internal::lmctfy_container_strip(container_); + Container *ctnr = container_->container_; StrictMockContainer *mock_container = dynamic_cast(ctnr); return mock_container; } @@ -212,7 +212,7 @@ TEST_F(ClmctfyContainerTest, ListSubContainers) { vector::iterator iter; int i = 0; for (i = 0, iter = subcontainers_vector.begin(); iter != subcontainers_vector.end(); iter++, i++) { - Container *ctnr = internal::lmctfy_container_strip(subcontainers[i]); + Container *ctnr = subcontainers[i]->container_; EXPECT_EQ(*iter, ctnr); lmctfy_delete_container(subcontainers[i]); } diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_internal.h index c338050..51d29ae 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_internal.h @@ -1,5 +1,5 @@ -#ifndef LMCTFY_C_BINDING_STATUS_INTERNAL_H_ -#define LMCTFY_C_BINDING_STATUS_INTERNAL_H_ +#ifndef LMCTFY_CLMCTFY_CLMCTFY_INTERNAL_H_ +#define LMCTFY_CLMCTFY_CLMCTFY_INTERNAL_H_ #include @@ -86,15 +86,4 @@ int status_copy(struct status *dst, const Status &src); } // namespace internal } // namespace util -namespace containers { -namespace lmctfy { -namespace internal { - -ContainerApi *lmctfy_container_api_strip(struct container_api *api); -Container *lmctfy_container_strip(struct container *container); - -} // internal -} // lmctfy -} // containers - -#endif // LMCTFY_C_BINDING_STATUS_INTERNAL_H_ +#endif // LMCTFY_CLMCTFY_CLMCTFY_INTERNAL_H_ diff --git a/clmctfy/clmctfy_macros_ctest.h b/clmctfy/clmctfy_macros_ctest.h index 012faa7..2033df9 100644 --- a/clmctfy/clmctfy_macros_ctest.h +++ b/clmctfy/clmctfy_macros_ctest.h @@ -1,5 +1,5 @@ -#ifndef LMCTFY__CLMCTFY_MACROS_CTEST_H_ -#define LMCTFY__CLMCTFY_MACROS_CTEST_H_ +#ifndef LMCTFY_CLMCTFY_CLMCTFY_MACROS_CTEST_H_ +#define LMCTFY_CLMCTFY_CLMCTFY_MACROS_CTEST_H_ // Some useful macros for writing test cases. @@ -66,5 +66,5 @@ } \ } while (0) -#endif // LMCTFY__CLMCTFY_MACROS_CTEST_H_ +#endif // LMCTFY_CLMCTFY_CLMCTFY_MACROS_CTEST_H_ From 5d36c6b4a8911441797f018d0500921c5b72c2d6 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 12 Mar 2014 22:07:09 -0400 Subject: [PATCH 77/84] rearrange file layouts. --- clmctfy/clmctfy_container.cc | 137 +----- clmctfy/clmctfy_container_api.cc | 7 +- clmctfy/clmctfy_container_api_ctest.cc | 7 +- clmctfy/clmctfy_container_api_raw.cc | 3 + clmctfy/clmctfy_container_api_struct.h | 10 + clmctfy/clmctfy_container_ctest.cc | 6 +- clmctfy/clmctfy_container_raw.cc | 115 +++++ clmctfy/clmctfy_container_struct.h | 17 + clmctfy/clmctfy_event_callback_wrapper.cc | 50 +++ clmctfy/clmctfy_event_callback_wrapper.h | 26 ++ .../{clmctfy_internal.h => clmctfy_macros.h} | 61 +-- clmctfy/clmctfy_macros_ctest.h | 12 + ...status-c.cc => clmctfy_status_internal.cc} | 4 +- clmctfy/clmctfy_status_internal.h | 16 + include/clmctfy-raw.h | 7 + include/clmctfy.h | 8 + include/clmctfy_container.h | 394 ++++++++++++++++++ include/clmctfy_container_api.h | 138 ++++++ include/clmctfy_container_api_raw.h | 58 +++ include/clmctfy_container_raw.h | 105 +++++ include/clmctfy_status.h | 20 + 21 files changed, 1009 insertions(+), 192 deletions(-) create mode 100644 clmctfy/clmctfy_container_api_raw.cc create mode 100644 clmctfy/clmctfy_container_api_struct.h create mode 100644 clmctfy/clmctfy_container_raw.cc create mode 100644 clmctfy/clmctfy_container_struct.h create mode 100644 clmctfy/clmctfy_event_callback_wrapper.cc create mode 100644 clmctfy/clmctfy_event_callback_wrapper.h rename clmctfy/{clmctfy_internal.h => clmctfy_macros.h} (50%) rename clmctfy/{status-c.cc => clmctfy_status_internal.cc} (95%) create mode 100644 clmctfy/clmctfy_status_internal.h create mode 100644 include/clmctfy_container.h create mode 100644 include/clmctfy_container_api.h create mode 100644 include/clmctfy_container_api_raw.h create mode 100644 include/clmctfy_container_raw.h create mode 100644 include/clmctfy_status.h diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 2f200b7..79882fb 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -1,5 +1,4 @@ -#include "clmctfy.h" -#include "clmctfy-raw.h" +#include "clmctfy_container.h" #include #include @@ -7,13 +6,15 @@ #include "util/task/statusor.h" #include "base/callback.h" #include "base/macros.h" -#include "lmctfy.h" -#include "clmctfy_internal.h" +#include "lmctfy.h" +#include "clmctfy_macros.h" +#include "clmctfy_container_struct.h" +#include "clmctfy_container_raw.h" +#include "clmctfy_event_callback_wrapper.h" using ::containers::lmctfy::Container; using ::containers::lmctfy::ContainerApi; -using ::containers::lmctfy::InitSpec; using ::containers::lmctfy::ContainerSpec; using ::containers::lmctfy::RunSpec; using ::containers::lmctfy::EventSpec; @@ -28,32 +29,6 @@ using ::std::unordered_map; #define STATUS_OK UTIL__ERROR__CODE__OK -int lmctfy_container_run_raw(struct container *container, - const int argc, - const char **argv, - const void *spec, - const size_t spec_size, - pid_t *tid, - struct status *s) { - RunSpec run_spec; - CHECK_NOTFAIL_OR_RETURN(s); - CHECK_NOTNULL_OR_RETURN(s, container); - CHECK_NOTNULL_OR_RETURN(s, container->container_); - CHECK_NOTNULL_OR_RETURN(s, tid); - CHECK_POSITIVE_OR_RETURN(s, argc); - if (spec != NULL && spec_size > 0) { - run_spec.ParseFromArray(spec, spec_size); - } - vector cmds(argc); - int i = 0; - for (i = 0; i < argc; i++) { - cmds[i] = argv[i]; - } - StatusOr statusor = container->container_->Run(cmds, run_spec); - RETURN_IF_ERROR_PTR(s, statusor, tid); - return STATUS_OK; -} - int lmctfy_container_run(struct container *container, const int argc, const char **argv, @@ -140,34 +115,6 @@ void lmctfy_delete_container(struct container *container) { } } -int lmctfy_container_update_raw(struct container *container, - int policy, - const void *spec, - const size_t spec_size, - struct status *s) { - ContainerSpec container_spec; - CHECK_NOTFAIL_OR_RETURN(s); - CHECK_NOTNULL_OR_RETURN(s, container); - CHECK_NOTNULL_OR_RETURN(s, container->container_); - if (spec != NULL && spec_size > 0) { - container_spec.ParseFromArray(spec, spec_size); - } - Container::UpdatePolicy p; - switch (policy) { - case CONTAINER_UPDATE_POLICY_DIFF: - p = Container::UPDATE_DIFF; - break; - case CONTAINER_UPDATE_POLICY_REPLACE: - p = Container::UPDATE_REPLACE; - break; - default: - return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, - "Unknown update policy: %d", policy); - } - Status status = container->container_->Update(container_spec, p); - return status_copy(s, status); -} - int lmctfy_container_update(struct container *container, int policy, const Containers__Lmctfy__ContainerSpec *spec, @@ -437,77 +384,6 @@ const char *lmctfy_container_name(struct container *container) { return container->container_->name().c_str(); } -inline void EventCallbackWrapper::Run(Container *c, Status s) { - if (callback_ == NULL) { - return; - } - struct status sts; - status_copy(&sts, s); - if (c == NULL) { - callback_(NULL, &sts, user_data_); - if (sts.message != NULL) { - free(sts.message); - } - return; - } - if (c != container_->container_) { - char *oldmsg = sts.message; - int olderrcode = sts.error_code; - struct container ctnr; - ctnr.container_ = c; - // This should never happen. - status_new(&sts, UTIL__ERROR__CODE__UNKNOWN, - "Unknown container passed to the callback. " - "(ErrorCode=%d, Message=\"%s\")", olderrcode, - (oldmsg == NULL ? "" : oldmsg)); - callback_(&ctnr, &sts, user_data_); - if (sts.message != NULL) { - free(sts.message); - } - if (oldmsg != NULL) { - free(oldmsg); - } - return; - } - callback_(container_, &sts, user_data_); - if (sts.message != NULL) { - free(sts.message); - } -} - -int lmctfy_container_register_notification_raw(struct container *container, - lmctfy_event_callback_f callback, - void *user_data, - const void *spec, - const size_t spec_size, - notification_id_t *notif_id, - struct status *s) { - CHECK_NOTFAIL_OR_RETURN(s); - CHECK_NOTNULL_OR_RETURN(s, container); - CHECK_NOTNULL_OR_RETURN(s, container->container_); - CHECK_NOTNULL_OR_RETURN(s, notif_id); - CHECK_NOTNULL_OR_RETURN(s, callback); - EventSpec event_spec; - if (spec != NULL && spec_size > 0) { - event_spec.ParseFromArray(spec, spec_size); - } - EventCallbackWrapper *cb = - new EventCallbackWrapper(container, callback, user_data); - - // Container object does not take the ownership of the callback. - StatusOr statusor_id = - container->container_->RegisterNotification(event_spec, cb); - - if (!statusor_id.ok()) { - delete cb; - return status_copy(s, statusor_id.status()); - } - notification_id_t nid = statusor_id.ValueOrDie(); - container->notif_map_[nid] = cb; - *notif_id = nid; - return STATUS_OK; -} - int lmctfy_container_register_notification(struct container *container, lmctfy_event_callback_f callback, void *user_data, @@ -562,3 +438,4 @@ int lmctfy_container_unregister_notification(struct container *container, delete iter->second; return STATUS_OK; } + diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index 4a42228..1e5f945 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -1,5 +1,4 @@ -#include "clmctfy.h" -#include "clmctfy-raw.h" +#include "clmctfy_container_api.h" #include #include @@ -9,7 +8,9 @@ #include "util/task/codes.pb-c.h" #include "lmctfy.h" -#include "clmctfy_internal.h" +#include "clmctfy_macros.h" +#include "clmctfy_container_struct.h" +#include "clmctfy_container_api_struct.h" #define STATUS_OK UTIL__ERROR__CODE__OK diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index cb6ca73..7a37b3c 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -12,17 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "clmctfy.h" +#include "clmctfy_container_api.h" #include "gtest/gtest.h" #include "gmock/gmock.h" +#include "util/task/status.h" #include "util/task/statusor.h" +#include "util/task/codes.pb-c.h" #include "strings/stringpiece.h" #include "lmctfy_mock.h" #include "lmctfy.h" #include "clmctfy_macros_ctest.h" -#include "clmctfy_internal.h" +#include "clmctfy_container_struct.h" +#include "clmctfy_container_api_struct.h" using ::testing::NotNull; using ::testing::Return; diff --git a/clmctfy/clmctfy_container_api_raw.cc b/clmctfy/clmctfy_container_api_raw.cc new file mode 100644 index 0000000..c93971c --- /dev/null +++ b/clmctfy/clmctfy_container_api_raw.cc @@ -0,0 +1,3 @@ +#include "clmctfy_container_api_raw.h" + +#define STATUS_OK UTIL__ERROR__CODE__OK diff --git a/clmctfy/clmctfy_container_api_struct.h b/clmctfy/clmctfy_container_api_struct.h new file mode 100644 index 0000000..ba8c073 --- /dev/null +++ b/clmctfy/clmctfy_container_api_struct.h @@ -0,0 +1,10 @@ +#ifndef LMCTFY_CLMCTFY_CLMCTFY_CONTAINER_API_STRUCT_H_ +#define LMCTFY_CLMCTFY_CLMCTFY_CONTAINER_API_STRUCT_H_ + +#include "lmctfy.h" + +struct container_api { + ::containers::lmctfy::ContainerApi *container_api_; +}; + +#endif // LMCTFY_CLMCTFY_CLMCTFY_CONTAINER_API_STRUCT_H_ diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 41b7245..8dc448e 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "clmctfy.h" +#include "clmctfy_container.h" #include @@ -22,8 +22,10 @@ #include "strings/stringpiece.h" #include "lmctfy_mock.h" +#include "lmctfy.pb.h" #include "clmctfy_macros_ctest.h" -#include "clmctfy_internal.h" +#include "clmctfy_container_struct.h" +#include "clmctfy_container_api_struct.h" using ::testing::NotNull; using ::testing::Return; diff --git a/clmctfy/clmctfy_container_raw.cc b/clmctfy/clmctfy_container_raw.cc new file mode 100644 index 0000000..0e0256b --- /dev/null +++ b/clmctfy/clmctfy_container_raw.cc @@ -0,0 +1,115 @@ +#include +#include +using ::std::vector; + +#include "clmctfy_container_raw.h" + +#include "util/task/codes.pb.h" + +#include "lmctfy.h" +#include "clmctfy_macros.h" +#include "clmctfy_container_struct.h" +#include "clmctfy_event_callback_wrapper.h" + +using ::containers::lmctfy::Container; +using ::containers::lmctfy::ContainerApi; +using ::containers::lmctfy::InitSpec; +using ::containers::lmctfy::ContainerSpec; +using ::containers::lmctfy::RunSpec; +using ::containers::lmctfy::EventSpec; +using ::containers::lmctfy::ContainerStats; +using ::util::Status; +using ::util::StatusOr; +using ::util::internal::status_copy; +using ::util::internal::status_new; + +#define STATUS_OK UTIL__ERROR__CODE__OK + +int lmctfy_container_run_raw(struct container *container, + const int argc, + const char **argv, + const void *spec, + const size_t spec_size, + pid_t *tid, + struct status *s) { + RunSpec run_spec; + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + CHECK_NOTNULL_OR_RETURN(s, tid); + CHECK_POSITIVE_OR_RETURN(s, argc); + if (spec != NULL && spec_size > 0) { + run_spec.ParseFromArray(spec, spec_size); + } + vector cmds(argc); + int i = 0; + for (i = 0; i < argc; i++) { + cmds[i] = argv[i]; + } + StatusOr statusor = container->container_->Run(cmds, run_spec); + RETURN_IF_ERROR_PTR(s, statusor, tid); + return STATUS_OK; +} + +int lmctfy_container_update_raw(struct container *container, + int policy, + const void *spec, + const size_t spec_size, + struct status *s) { + ContainerSpec container_spec; + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + if (spec != NULL && spec_size > 0) { + container_spec.ParseFromArray(spec, spec_size); + } + Container::UpdatePolicy p; + switch (policy) { + case CONTAINER_UPDATE_POLICY_DIFF: + p = Container::UPDATE_DIFF; + break; + case CONTAINER_UPDATE_POLICY_REPLACE: + p = Container::UPDATE_REPLACE; + break; + default: + return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, + "Unknown update policy: %d", policy); + } + Status status = container->container_->Update(container_spec, p); + return status_copy(s, status); +} + +int lmctfy_container_register_notification_raw(struct container *container, + lmctfy_event_callback_f callback, + void *user_data, + const void *spec, + const size_t spec_size, + notification_id_t *notif_id, + struct status *s) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + CHECK_NOTNULL_OR_RETURN(s, notif_id); + CHECK_NOTNULL_OR_RETURN(s, callback); + EventSpec event_spec; + if (spec != NULL && spec_size > 0) { + event_spec.ParseFromArray(spec, spec_size); + } + EventCallbackWrapper *cb = + new EventCallbackWrapper(container, callback, user_data); + + // Container object does not take the ownership of the callback. + StatusOr statusor_id = + container->container_->RegisterNotification(event_spec, cb); + + if (!statusor_id.ok()) { + delete cb; + return status_copy(s, statusor_id.status()); + } + notification_id_t nid = statusor_id.ValueOrDie(); + container->notif_map_[nid] = cb; + *notif_id = nid; + return STATUS_OK; +} + + diff --git a/clmctfy/clmctfy_container_struct.h b/clmctfy/clmctfy_container_struct.h new file mode 100644 index 0000000..ba580ba --- /dev/null +++ b/clmctfy/clmctfy_container_struct.h @@ -0,0 +1,17 @@ +#ifndef LMCTFY_CLMCTFY_CLMCTFY_CONTAINER_STRUCT_H_ +#define LMCTFY_CLMCTFY_CLMCTFY_CONTAINER_STRUCT_H_ + +#include +#include "lmctfy.h" +#include "clmctfy_container.h" + +class EventCallbackWrapper; + +struct container { + ::containers::lmctfy::Container *container_; + // TODO(monnand): Make it thread-safe? + ::std::unordered_map notif_map_; +}; + + +#endif // LMCTFY_CLMCTFY_CLMCTFY_CONTAINER_STRUCT_H_ diff --git a/clmctfy/clmctfy_event_callback_wrapper.cc b/clmctfy/clmctfy_event_callback_wrapper.cc new file mode 100644 index 0000000..48a8560 --- /dev/null +++ b/clmctfy/clmctfy_event_callback_wrapper.cc @@ -0,0 +1,50 @@ +#include "clmctfy_event_callback_wrapper.h" + +#include "util/task/status.h" +#include "lmctfy.h" +#include "clmctfy_status_internal.h" +#include "clmctfy_container_struct.h" + +using ::containers::lmctfy::Container; +using ::util::Status; +using ::util::internal::status_copy; +using ::util::internal::status_new; + +void EventCallbackWrapper::Run(Container *c, Status s) { + if (callback_ == NULL) { + return; + } + struct status sts; + status_copy(&sts, s); + if (c == NULL) { + callback_(NULL, &sts, user_data_); + if (sts.message != NULL) { + free(sts.message); + } + return; + } + if (c != container_->container_) { + char *oldmsg = sts.message; + int olderrcode = sts.error_code; + struct container ctnr; + ctnr.container_ = c; + // This should never happen. + status_new(&sts, UTIL__ERROR__CODE__UNKNOWN, + "Unknown container passed to the callback. " + "(ErrorCode=%d, Message=\"%s\")", olderrcode, + (oldmsg == NULL ? "" : oldmsg)); + callback_(&ctnr, &sts, user_data_); + if (sts.message != NULL) { + free(sts.message); + } + if (oldmsg != NULL) { + free(oldmsg); + } + return; + } + callback_(container_, &sts, user_data_); + if (sts.message != NULL) { + free(sts.message); + } +} + diff --git a/clmctfy/clmctfy_event_callback_wrapper.h b/clmctfy/clmctfy_event_callback_wrapper.h new file mode 100644 index 0000000..cd953fc --- /dev/null +++ b/clmctfy/clmctfy_event_callback_wrapper.h @@ -0,0 +1,26 @@ +#ifndef LMCTFY_CLMCTFY_CLMCTFY_EVENT_CALLBACK_WRAPPER_H_ +#define LMCTFY_CLMCTFY_CLMCTFY_EVENT_CALLBACK_WRAPPER_H_ + +#include "lmctfy.h" +#include "clmctfy_container.h" + +class EventCallbackWrapper : public Callback2<::containers::lmctfy::Container *, ::util::Status> { + public: + EventCallbackWrapper(struct container *c, + lmctfy_event_callback_f cb, + void *user_data) + : container_(c), + callback_(cb), + user_data_(user_data) { } + virtual ~EventCallbackWrapper() {} + virtual bool IsRepeatable() const { return true; } + virtual void Run(::containers::lmctfy::Container *c, ::util::Status s); + private: + lmctfy_event_callback_f callback_; + void *user_data_; + struct container *container_; + ::containers::lmctfy::Container ::NotificationId notif_id_; + DISALLOW_COPY_AND_ASSIGN(EventCallbackWrapper); +}; + +#endif // LMCTFY_CLMCTFY_CLMCTFY_EVENT_CALLBACK_WRAPPER_H_ diff --git a/clmctfy/clmctfy_internal.h b/clmctfy/clmctfy_macros.h similarity index 50% rename from clmctfy/clmctfy_internal.h rename to clmctfy/clmctfy_macros.h index 51d29ae..72d874f 100644 --- a/clmctfy/clmctfy_internal.h +++ b/clmctfy/clmctfy_macros.h @@ -1,54 +1,20 @@ -#ifndef LMCTFY_CLMCTFY_CLMCTFY_INTERNAL_H_ -#define LMCTFY_CLMCTFY_CLMCTFY_INTERNAL_H_ - -#include +#ifndef LMCTFY_CLMCTFY_CLMCTFY_MACROS_H_H +#define LMCTFY_CLMCTFY_CLMCTFY_MACROS_H_H #include "util/errors.h" #include "util/task/status.h" #include "util/task/statusor.h" +#include "util/task/codes.pb-c.h" -#include "lmctfy.h" -#include "clmctfy.h" - - -using ::containers::lmctfy::Container; -using ::containers::lmctfy::ContainerApi; - -class EventCallbackWrapper : public Callback2 { - public: - EventCallbackWrapper(struct container *c, - lmctfy_event_callback_f cb, - void *user_data) - : container_(c), - callback_(cb), - user_data_(user_data) { } - virtual ~EventCallbackWrapper() {} - virtual bool IsRepeatable() const { return true; } - virtual void Run(Container *c, ::util::Status s); - private: - lmctfy_event_callback_f callback_; - void *user_data_; - struct container *container_; - Container::NotificationId notif_id_; - DISALLOW_COPY_AND_ASSIGN(EventCallbackWrapper); -}; - -struct container { - Container *container_; - // TODO(monnand): Make it thread-safe? - ::std::unordered_map notif_map_; -}; - -struct container_api { - ContainerApi *container_api_; -}; +#include "clmctfy_status.h" +#include "clmctfy_status_internal.h" #define RETURN_IF_ERROR_PTR(s, ...) \ do { \ const ::util::Status _status = \ ::util::errors_internal::PerformSideEffects(__VA_ARGS__); \ if (PREDICT_FALSE(!_status.ok())) { \ - if (s != NULL) status_copy(s, _status); \ + if (s != NULL) ::util::internal::status_copy(s, _status); \ return (int)_status.error_code(); \ } \ } while (0) @@ -63,7 +29,7 @@ struct container_api { #define CHECK_NOTNULL_OR_RETURN(status, ptr) do { \ if ((ptr) == NULL) { \ - return status_new(status, UTIL__ERROR__CODE__INVALID_ARGUMENT, \ + return ::util::internal::status_new(status, UTIL__ERROR__CODE__INVALID_ARGUMENT, \ "In function %s: %s cannot be null", \ __func__, #ptr); \ } \ @@ -71,19 +37,10 @@ struct container_api { #define CHECK_POSITIVE_OR_RETURN(status, value) do { \ if ((value) <= 0) { \ - return status_new(status, UTIL__ERROR__CODE__INVALID_ARGUMENT, \ + return ::util::internal::status_new(status, UTIL__ERROR__CODE__INVALID_ARGUMENT, \ "In function %s: %s=%d, but it should be positive", \ __func__, #value, value); \ } \ } while (0) -namespace util { -namespace internal { - -int status_new(struct status *dst, int code, const char *fmt, ...); -int status_copy(struct status *dst, const Status &src); - -} // namespace internal -} // namespace util - -#endif // LMCTFY_CLMCTFY_CLMCTFY_INTERNAL_H_ +#endif // LMCTFY_CLMCTFY_CLMCTFY_MACROS_H_H diff --git a/clmctfy/clmctfy_macros_ctest.h b/clmctfy/clmctfy_macros_ctest.h index 2033df9..b44beb9 100644 --- a/clmctfy/clmctfy_macros_ctest.h +++ b/clmctfy/clmctfy_macros_ctest.h @@ -1,6 +1,18 @@ #ifndef LMCTFY_CLMCTFY_CLMCTFY_MACROS_CTEST_H_ #define LMCTFY_CLMCTFY_CLMCTFY_MACROS_CTEST_H_ +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "util/task/status.h" +#include "util/task/statusor.h" +#include "util/task/codes.pb-c.h" + +#include "clmctfy_status.h" +#include "clmctfy_container_api.h" +#include "clmctfy_container.h" +#include "clmctfy_container_struct.h" +#include "clmctfy_container_api_struct.h" + // Some useful macros for writing test cases. #define WITH_NULL_CONTAINER_API_RUN(func, ...) do { \ diff --git a/clmctfy/status-c.cc b/clmctfy/clmctfy_status_internal.cc similarity index 95% rename from clmctfy/status-c.cc rename to clmctfy/clmctfy_status_internal.cc index b6bfff9..0b21316 100644 --- a/clmctfy/status-c.cc +++ b/clmctfy/clmctfy_status_internal.cc @@ -1,12 +1,10 @@ -#include "clmctfy_internal.h" +#include "clmctfy_status_internal.h" #include // to use strdup #include #include "util/task/status.h" -#include "clmctfy.h" - using ::util::Status; namespace util { diff --git a/clmctfy/clmctfy_status_internal.h b/clmctfy/clmctfy_status_internal.h new file mode 100644 index 0000000..2997243 --- /dev/null +++ b/clmctfy/clmctfy_status_internal.h @@ -0,0 +1,16 @@ +#ifndef LMCTFY_CLMCTFY_CLMCTFY_STATUS_INTERNAL_H_ +#define LMCTFY_CLMCTFY_CLMCTFY_STATUS_INTERNAL_H_ + +#include "clmctfy_status.h" +#include "util/task/status.h" + +namespace util { +namespace internal { + +int status_new(struct status *dst, int code, const char *fmt, ...); +int status_copy(struct status *dst, const Status &src); + +} // namespace internal +} // namespace util + +#endif // LMCTFY_CLMCTFY_CLMCTFY_STATUS_INTERNAL_H_ diff --git a/include/clmctfy-raw.h b/include/clmctfy-raw.h index bf19569..724d4bf 100644 --- a/include/clmctfy-raw.h +++ b/include/clmctfy-raw.h @@ -1,6 +1,11 @@ #ifndef LMCTFY_C_BINDING_CLMCTFY_RAW_H_ #define LMCTFY_C_BINDING_CLMCTFY_RAW_H_ +#include "clmctfy_status.h" +#include "clmctfy_container_api_raw.h" +#include "clmctfy_container_raw.h" + +#if 0 #include "clmctfy.h" #include "lmctfy.pb-c.h" #include "lmctfy.h" @@ -136,4 +141,6 @@ int lmctfy_container_register_notification_raw(struct container *container, #ifdef __cplusplus } #endif // __cplusplus + +#endif #endif // LMCTFY_C_BINDING_CLMCTFY_RAW_H_ diff --git a/include/clmctfy.h b/include/clmctfy.h index d2df69a..cd5f50d 100644 --- a/include/clmctfy.h +++ b/include/clmctfy.h @@ -1,6 +1,11 @@ #ifndef LMCTFY_INCLUDE_CLMCTFY_H_ #define LMCTFY_INCLUDE_CLMCTFY_H_ +#include "clmctfy_status.h" +#include "clmctfy_container_api.h" +#include "clmctfy_container.h" + +#if 0 #include #include @@ -514,4 +519,7 @@ int lmctfy_container_unregister_notification(struct container *container, #ifdef __cplusplus } #endif // __cplusplus + +#endif + #endif // LMCTFY_INCLUDE_CLMCTFY_H_ diff --git a/include/clmctfy_container.h b/include/clmctfy_container.h new file mode 100644 index 0000000..a164351 --- /dev/null +++ b/include/clmctfy_container.h @@ -0,0 +1,394 @@ +#ifndef CLMCTFY_INCLUDE_CLMCTFY_CONTAINER_H_ +#define CLMCTFY_INCLUDE_CLMCTFY_CONTAINER_H_ + +#include +#include + +#include "util/task/codes.pb-c.h" +#include "lmctfy.pb-c.h" +#include "clmctfy_status.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +struct container; +struct container_api; + +enum { + // Update only the specified fields. + CONTAINER_UPDATE_POLICY_DIFF, + + // Replace the existing container with the new specification. + CONTAINER_UPDATE_POLICY_REPLACE +}; + +enum { + // Only output the information of this container. + CONTAINER_LIST_POLICY_SELF, + + // Output the information of this container and all of its subcontainers and + // their subcontainers. + CONTAINER_LIST_POLICY_RECURSIVE +}; + +enum { + // A summary of the statistics (see each resource's definition of summary). + CONTAINER_STATS_TYPE_SUMMARY, + + // All available statistics. + CONTAINER_STATS_TYPE_FULL +}; + +// Callback used on an event notification. +// +// The container and status structure pointers are only valid within the +// callback. +// +// - container: The container that received the notification. It is an error +// to delete it. +// - status: The status of the notification. If OK, then the event registered +// occured. Otherwise, an error is reported in the status. Errors may +// be caused by container deletion or unexpected registration errors. +// it will be an error if the user call free(s->message); +// - user_data: +typedef void (*lmctfy_event_callback_f)(struct container *container, + const struct status *status, + void *user_data); + +typedef uint64_t notification_id_t; + +// Release the memory used by the container structure. The refered container +// will not be affected. +// +// Arguments: +// +// - container: The container. This pointer will be invalid after the call to +// this function +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +void lmctfy_delete_container(struct container *container); + +// Moves the specified threads into this container. Enter is atomic. +// +// Arguments: +// +// - container: The container. +// - tids: Array of thread IDs to move into the container. Caller takes the +// ownership. +// - tids_size: Number of thread IDs stored in tids. Caller takes the +// ownership. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_enter(struct container *container, + const pid_t *tids, + const int tids_size, + struct status *s); + +// Run the specified command inside the container. Multiple instances of run +// can be active simultaneously. Processes MUST be reaped by the caller. +// +// Arguments: +// +// - container: The container. +// - argc: number of arguments (including the binary file path). +// - argv: All arguments. The first element is the binary that will be executed +// and must be an absolute path. +// - spec: The specification of the runtime environment to use for the +// execution of the command. +// - tid: [output] On success, tid stores the PID of the command. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_run(struct container *container, + const int argc, + const char **argv, + const Containers__Lmctfy__RunSpec *spec, + pid_t *tid, + struct status *s); + +// Execute the specified command inside the container. This replaces the +// current process image with the specified command. The PATH environment +// variable is used, and the existing environment is passed to the new +// process image unchanged. +// +// Arguments: +// +// - container +// - argc: number of arguments (including the binary file path). +// - argv: All arguments. The first element is the binary that will be executed +// and must be an absolute path. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_exec(struct container *container, + const int argc, + const char **argv, + struct status *s); + +// Updates the container according to the specification. The set of resource +// types being isolated cannot change during an Update. This means that a +// CONTAINER_UPDATE_POLICY_REPLACE must specify all the resources being isolated +// and a CONTAINER_UPDATE_POLICY_DIFF cannot specify any resource that is not +// already being isolated. +// +// Arguments: +// +// - container +// - policy: Update policy. Can be either CONTAINER_UPDATE_POLICY_DIFF, or +// CONTAINER_UPDATE_POLICY_REPLACE. +// - spec: The specification of the desired updates. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_update(struct container *container, + int policy, + const Containers__Lmctfy__ContainerSpec *spec, + struct status *s); + +// Returns the resource isolation specification (ContainerSpec) of this +// container. +// +// Arguments: +// +// - container: The container +// - spec: [output] An address of a ContainerSpec pointer. *spec will points to +// the ContainerSpec of the container. Caller takes the ownership. *spec can +// be released by calling free(). +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_spec(struct container *container, + Containers__Lmctfy__ContainerSpec **spec, + struct status *s); + +// List all subcontainers. +// +// Arguments: +// +// - container: The container +// - list_policy: CONTAINER_LIST_POLICY_SELF or CONTAINER_LIST_POLICY_RECURSIVE +// - subcontainers: [output] The address of a pointer points to an array of +// struct container pointers. The caller takes the onwership. On success, the +// pointer will be assigned an address to an array of containers. The pointed +// array should be released with free(). The containers inside the array +// should be deleted/destroyed individually. +// - subcontainers_size: [output] The address of an integer used to store number +// of subcontainers in the array. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_list_subcontainers(struct container *container, + int list_policy, + struct container **subcontainers[], + int *subcontainers_size, + struct status *s); + +// List all TIDs in the container. +// +// Arguments: +// - container +// - list_policy: List policy. +// - threads: [output] The address of a pointer points to an array of pid_t. +// The caller takes the ownership. The array can be released with free(). +// - threads_size: [output] *threads_size is the number of TIDs stored in *threads. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_list_threads(struct container *container, + int list_policy, + pid_t *threads[], + int *threads_size, + struct status *s); + +// Get all PIDs in this container. +// +// Arguments: +// - container +// - list_policy: List policy. +// - processes: [output] The address of a pointer points to an array of pid_t. +// The caller takes the ownership. The array can be released with free(). +// - processes_size: [output] *processes_size is the number of PIDs stored in +// *processes. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_list_processes(struct container *container, + int list_policy, + pid_t *processes[], + int *processes_size, + struct status *s); + +// Atomically stops the execution of all threads inside the container and all +// subcontainers (recursively). All threads moved to a paused container will +// be paused as well (regardless of whether the PID is in the container). This +// guarantees to get all threads. +// +// Arguments: +// - container: The container. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_pause(struct container *container, + struct status *s); + +// Atomically resumes the execution of all threads inside the container and +// all subcontainers (recursively). All paused threads moved to a non-paused +// container will be resumed. +// +// Arguments: +// - container: The container. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_resume(struct container *container, + struct status *s); + +// Kills all processes running in the container. This operation is atomic and +// is synchronized with any mutable operations on this container. +// +// The operation sends a SIGKILL to all processes in the containers. Tourist +// threads are killed via SIGKILL after all processes have exited. +// +// Note that this operation can potentially take a long time (O(seconds)) if +// the processes in the container do not finish quickly. This operation also +// blocks all mutable container operations while it is in progress. +// +// Arguments: +// - container: The container. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_killall(struct container *container, + struct status *s); + +// Gets usage and state information for the container. Note that the snapshot +// is not atomic. +// +// Arguments: +// - container: The container. +// - stats_type: The type of statistics to output. +// - stats: [output] Used to store a pointer points to the container's +// statistics. The call takes the ownership of *stats, which should be +// free()'ed. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_stats(struct container *container, + int stats_type, + Containers__Lmctfy__ContainerStats **stats, + struct status *s); + +// Get the name of the container. +// +// Arguments: +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Return: +// The container name. The caller does not take the ownership. +const char *lmctfy_container_name(struct container *container); + +// Register a notification for a specified container event. All notifications +// are unregistered when the container is destroyed. +// +// Arguments: +// - container: The container. +// - callback: The callback to run when the event is triggered. The caller +// takes ownership of the callback which MUST be a repeatable callback. +// - user_data: The pointer which will be passed to the callback function as +// its last parameter. The caller takes the ownership. +// - spec: The specification for the event for which to register notifications. +// The caller takes the ownership. +// - notif_id: [output] The ID for the notification. The ID is unique within +// the current container_api instance. It will be used to unregister the +// notification +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_register_notification(struct container *container, + lmctfy_event_callback_f callback, + void *user_data, + Containers__Lmctfy__EventSpec *spec, + notification_id_t *notif_id, + struct status *s); + +// Unregister (stop) the specified notification from being received. +// +// Arguments: +// - container: The container. +// - notif_id: The unique notification ID for the container +// notification. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_unregister_notification(struct container *container, + const notification_id_t notif_id, + struct status *s); + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // CLMCTFY_INCLUDE_CLMCTFY_CONTAINER_H_ diff --git a/include/clmctfy_container_api.h b/include/clmctfy_container_api.h new file mode 100644 index 0000000..6371166 --- /dev/null +++ b/include/clmctfy_container_api.h @@ -0,0 +1,138 @@ +#ifndef LMCTFY_INCLUDE_CLMCTFY_CONTAINER_API_H_ +#define LMCTFY_INCLUDE_CLMCTFY_CONTAINER_API_H_ + +#include + +#include "lmctfy.pb-c.h" +#include "clmctfy_status.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +struct container; +struct container_api; + +// Initializes the machine to start being able to create containers. +// +// Arguments: +// - spec: The specification. Caller owns the pointer. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec, struct status *s); + +// Create a new container_api. +// +// Arguments: +// - api: [output] The address of a pointer to struct container_api. The +// pointer of the container api will be stored in this address. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_new_container_api(struct container_api **api, struct status *s); + +// Release the container api. +// +// Arguments: +// +// - api: The container api. The function takes the ownershp. +void lmctfy_delete_container_api(struct container_api *api); + +// Get a container +// +// Arguments: +// +// - api: A container api. +// - container_name: the container name. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// - container: [output] The address of a pointer to struct container. It will +// be used to store the pointer to the container. The caller takes the +// ownership. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_api_get_container( + const struct container_api *api, + const char *container_name, + struct container **container, + struct status *s); + +// Create a container +// +// Arguments: +// +// - api: A container api. +// - container_name: the container name. +// - spec: container specification. Caller owns the pointer. +// - container: [output] The address of a pointer to struct container. It will +// be used to store the newly created container. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_api_create_container( + struct container_api *api, + const char *container_name, + const Containers__Lmctfy__ContainerSpec *spec, + struct container **container, + struct status *s); + +// Destroy a container. The caller has to call lmctfy_delete_container after +// detroying a container. Otherwise, the memory occupied by the container +// structure will not be released. +// +// Arguments: +// +// - api: A container api. +// - container: The pointer to struct container. The pointer will become +// invalid after a successful destroy(). +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_api_destroy_container(struct container_api *api, + struct container *container, + struct status *s); + +// Detect what container the specified thread is in. +// +// Arguments: +// - api: The container api. +// - pid: The thread ID to check. 0 refers to self. +// - container_name: [output] Will be used to store the container name. +// It's the caller's responsibility to free() *container_name. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_api_detect_container(struct container_api *api, + pid_t pid, + char **container_name, + struct status *s); + + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // LMCTFY_INCLUDE_CLMCTFY_CONTAINER_API_H_ diff --git a/include/clmctfy_container_api_raw.h b/include/clmctfy_container_api_raw.h new file mode 100644 index 0000000..393f2c2 --- /dev/null +++ b/include/clmctfy_container_api_raw.h @@ -0,0 +1,58 @@ +#ifndef LMCTFY_INCLUDE_CLMCTFY_CONTAINER_API_RAW_H_ +#define LMCTFY_INCLUDE_CLMCTFY_CONTAINER_API_RAW_H_ + +#include +#include "clmctfy_status.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +struct container; +struct container_api; + +// Initializes the machine to start being able to create containers. +// +// Arguments: +// - spec: Serialized data (protobuf format) containing the specification. +// Caller takes the ownership. +// - spec_size: Size of the serialized data. +// - s: [output] s will be used as output. It contains the error code/message. +// +// Returns: +// Returns the error code. 0 on success. The return code is same as +// status_get_code(s). +int lmctfy_init_machine_raw(const void *spec, const size_t spec_size, struct status *s); + +// Create a container +// +// Arguments: +// +// - api: A container api. +// - container_name: the container name. +// - spec: Serialized data (protobuf format) containing the specification. +// Caller takes the ownership. +// - spec_size: Size of the serialized data. +// - container: [output] The address of a pointer to struct container. It will +// be used to store the newly created container. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_api_create_container_raw( + struct container_api *api, + const char *container_name, + const void *spec, + const size_t spec_size, + struct container **container, + struct status *s); + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // LMCTFY_INCLUDE_CLMCTFY_CONTAINER_API_RAW_H_ diff --git a/include/clmctfy_container_raw.h b/include/clmctfy_container_raw.h new file mode 100644 index 0000000..09b7cd6 --- /dev/null +++ b/include/clmctfy_container_raw.h @@ -0,0 +1,105 @@ +#ifndef LMCTFY_INCLUDE_CLMCTFY_CONTAINER_RAW_H_ +#define LMCTFY_INCLUDE_CLMCTFY_CONTAINER_RAW_H_ + +#include +#include "clmctfy_status.h" +#include "clmctfy_container.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +struct container_api; +struct container; + +// Run the specified command inside the container. Multiple instances of run +// can be active simultaneously. Processes MUST be reaped by the caller. +// +// Arguments: +// +// - container: The container. +// - argc: number of arguments (including the binary file path). +// - argv: All arguments. The first element is the binary that will be executed +// and must be an absolute path. +// - spec: Serialized data (protobuf format) containing the specification. +// Caller takes the ownership. +// - spec_size: Size of the serialized data. +// - tid: [output] On success, tid stores the PID of the command. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_run_raw(struct container *container, + const int argc, + const char **argv, + const void *spec, + const size_t spec_size, + pid_t *tid, + struct status *s); + +// Updates the container according to the specification. The set of resource +// types being isolated cannot change during an Update. This means that a +// CONTAINER_UPDATE_POLICY_REPLACE must specify all the resources being isolated +// and a CONTAINER_UPDATE_POLICY_DIFF cannot specify any resource that is not +// already being isolated. +// +// Arguments: +// +// - container +// - policy: Update policy. Can be either CONTAINER_UPDATE_POLICY_DIFF, or +// CONTAINER_UPDATE_POLICY_REPLACE. +// - spec: Serialized data (protobuf format) containing the specification. +// Caller takes the ownership. +// - spec_size: Size of the serialized data. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_update_raw(struct container *container, + int policy, + const void *spec, + const size_t spec_size, + struct status *s); + +// Register a notification for a specified container event. All notifications +// are unregistered when the container is destroyed. +// +// Arguments: +// - container: The container. +// - callback: The callback to run when the event is triggered. The caller +// takes ownership of the callback which MUST be a repeatable callback. +// - user_data: The pointer which will be passed to the callback function as +// its last parameter. The caller takes the ownership. +// - spec: Serialized data (protobuf format) containing the specification. +// Caller takes the ownership. +// - spec_size: Size of the serialized data. +// - notif_id: [output] The ID for the notification. The ID is unique within +// the current container_api instance. It will be used to unregister the +// notification +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_register_notification_raw(struct container *container, + lmctfy_event_callback_f callback, + void *user_data, + const void *spec, + const size_t spec_size, + notification_id_t *notif_id, + struct status *s); + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // LMCTFY_INCLUDE_CLMCTFY_CONTAINER_RAW_H_ diff --git a/include/clmctfy_status.h b/include/clmctfy_status.h new file mode 100644 index 0000000..91c8717 --- /dev/null +++ b/include/clmctfy_status.h @@ -0,0 +1,20 @@ +#ifndef LMCTFY_INCLUDE_CLMCTFY_STATUS_H_ +#define LMCTFY_INCLUDE_CLMCTFY_STATUS_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#ifdef __cplusplus +} +#endif // __cplusplus + +struct status { + int error_code; + + // Null-terminated string allocated on heap. + // Needs to be free()'ed. + char *message; +}; + +#endif // LMCTFY_INCLUDE_CLMCTFY_STATUS_H_ From 308adee1db66321c5885d04aa4a445816bb5ccb7 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 12 Mar 2014 22:09:44 -0400 Subject: [PATCH 78/84] remove unnecessary code. --- include/clmctfy-raw.h | 138 ----------- include/clmctfy.h | 517 ------------------------------------------ 2 files changed, 655 deletions(-) diff --git a/include/clmctfy-raw.h b/include/clmctfy-raw.h index 724d4bf..b765241 100644 --- a/include/clmctfy-raw.h +++ b/include/clmctfy-raw.h @@ -5,142 +5,4 @@ #include "clmctfy_container_api_raw.h" #include "clmctfy_container_raw.h" -#if 0 -#include "clmctfy.h" -#include "lmctfy.pb-c.h" -#include "lmctfy.h" - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -// Initializes the machine to start being able to create containers. -// -// Arguments: -// - spec: Serialized data (protobuf format) containing the specification. -// Caller takes the ownership. -// - spec_size: Size of the serialized data. -// - s: [output] s will be used as output. It contains the error code/message. -// -// Returns: -// Returns the error code. 0 on success. The return code is same as -// status_get_code(s). -int lmctfy_init_machine_raw(const void *spec, const size_t spec_size, struct status *s); - -// Create a container -// -// Arguments: -// -// - api: A container api. -// - container_name: the container name. -// - spec: Serialized data (protobuf format) containing the specification. -// Caller takes the ownership. -// - spec_size: Size of the serialized data. -// - container: [output] The address of a pointer to struct container. It will -// be used to store the newly created container. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_api_create_container_raw( - struct container_api *api, - const char *container_name, - const void *spec, - const size_t spec_size, - struct container **container, - struct status *s); - -// Run the specified command inside the container. Multiple instances of run -// can be active simultaneously. Processes MUST be reaped by the caller. -// -// Arguments: -// -// - container: The container. -// - argc: number of arguments (including the binary file path). -// - argv: All arguments. The first element is the binary that will be executed -// and must be an absolute path. -// - spec: Serialized data (protobuf format) containing the specification. -// Caller takes the ownership. -// - spec_size: Size of the serialized data. -// - tid: [output] On success, tid stores the PID of the command. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_run_raw(struct container *container, - const int argc, - const char **argv, - const void *spec, - const size_t spec_size, - pid_t *tid, - struct status *s); - -// Updates the container according to the specification. The set of resource -// types being isolated cannot change during an Update. This means that a -// CONTAINER_UPDATE_POLICY_REPLACE must specify all the resources being isolated -// and a CONTAINER_UPDATE_POLICY_DIFF cannot specify any resource that is not -// already being isolated. -// -// Arguments: -// -// - container -// - policy: Update policy. Can be either CONTAINER_UPDATE_POLICY_DIFF, or -// CONTAINER_UPDATE_POLICY_REPLACE. -// - spec: Serialized data (protobuf format) containing the specification. -// Caller takes the ownership. -// - spec_size: Size of the serialized data. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_update_raw(struct container *container, - int policy, - const void *spec, - const size_t spec_size, - struct status *s); - -// Register a notification for a specified container event. All notifications -// are unregistered when the container is destroyed. -// -// Arguments: -// - container: The container. -// - callback: The callback to run when the event is triggered. The caller -// takes ownership of the callback which MUST be a repeatable callback. -// - user_data: The pointer which will be passed to the callback function as -// its last parameter. The caller takes the ownership. -// - spec: Serialized data (protobuf format) containing the specification. -// Caller takes the ownership. -// - spec_size: Size of the serialized data. -// - notif_id: [output] The ID for the notification. The ID is unique within -// the current container_api instance. It will be used to unregister the -// notification -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_register_notification_raw(struct container *container, - lmctfy_event_callback_f callback, - void *user_data, - const void *spec, - const size_t spec_size, - notification_id_t *notif_id, - struct status *s); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif #endif // LMCTFY_C_BINDING_CLMCTFY_RAW_H_ diff --git a/include/clmctfy.h b/include/clmctfy.h index cd5f50d..96f3ee0 100644 --- a/include/clmctfy.h +++ b/include/clmctfy.h @@ -5,521 +5,4 @@ #include "clmctfy_container_api.h" #include "clmctfy_container.h" -#if 0 -#include -#include - -#include "util/task/codes.pb-c.h" -#include "lmctfy.pb-c.h" - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -enum { - // Update only the specified fields. - CONTAINER_UPDATE_POLICY_DIFF, - - // Replace the existing container with the new specification. - CONTAINER_UPDATE_POLICY_REPLACE -}; - -enum { - // Only output the information of this container. - CONTAINER_LIST_POLICY_SELF, - - // Output the information of this container and all of its subcontainers and - // their subcontainers. - CONTAINER_LIST_POLICY_RECURSIVE -}; - -enum { - // A summary of the statistics (see each resource's definition of summary). - CONTAINER_STATS_TYPE_SUMMARY, - - // All available statistics. - CONTAINER_STATS_TYPE_FULL -}; - -struct status { - int error_code; - - // Null-terminated string allocated on heap. - // Needs to be free()'ed. - char *message; -}; - - -struct container; -struct container_api; - -// Callback used on an event notification. -// -// The container and status structure pointers are only valid within the -// callback. -// -// - container: The container that received the notification. It is an error -// to delete it. -// - status: The status of the notification. If OK, then the event registered -// occured. Otherwise, an error is reported in the status. Errors may -// be caused by container deletion or unexpected registration errors. -// it will be an error if the user call free(s->message); -// - user_data: -typedef void (*lmctfy_event_callback_f)(struct container *container, - const struct status *status, - void *user_data); - -typedef uint64_t notification_id_t; - -// Initializes the machine to start being able to create containers. -// -// Arguments: -// - spec: The specification. Caller owns the pointer. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec, struct status *s); - -// Create a new container_api. -// -// Arguments: -// - api: [output] The address of a pointer to struct container_api. The -// pointer of the container api will be stored in this address. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_new_container_api(struct container_api **api, struct status *s); - -// Release the container api. -// -// Arguments: -// -// - api: The container api. The function takes the ownershp. -void lmctfy_delete_container_api(struct container_api *api); - -// Get a container -// -// Arguments: -// -// - api: A container api. -// - container_name: the container name. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// - container: [output] The address of a pointer to struct container. It will -// be used to store the pointer to the container. The caller takes the -// ownership. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_api_get_container( - const struct container_api *api, - const char *container_name, - struct container **container, - struct status *s); - -// Create a container -// -// Arguments: -// -// - api: A container api. -// - container_name: the container name. -// - spec: container specification. Caller owns the pointer. -// - container: [output] The address of a pointer to struct container. It will -// be used to store the newly created container. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_api_create_container( - struct container_api *api, - const char *container_name, - const Containers__Lmctfy__ContainerSpec *spec, - struct container **container, - struct status *s); - -// Destroy a container. The caller has to call lmctfy_delete_container after -// detroying a container. Otherwise, the memory occupied by the container -// structure will not be released. -// -// Arguments: -// -// - api: A container api. -// - container: The pointer to struct container. The pointer will become -// invalid after a successful destroy(). -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_api_destroy_container(struct container_api *api, - struct container *container, - struct status *s); -// Detect what container the specified thread is in. -// -// Arguments: -// - api: The container api. -// - pid: The thread ID to check. 0 refers to self. -// - container_name: [output] Will be used to store the container name. -// It's the caller's responsibility to free() *container_name. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_api_detect_container(struct container_api *api, - pid_t pid, - char **container_name, - struct status *s); - -// Release the memory used by the container structure. The refered container -// will not be affected. -// -// Arguments: -// -// - container: The container. This pointer will be invalid after the call to -// this function -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -void lmctfy_delete_container(struct container *container); - -// Moves the specified threads into this container. Enter is atomic. -// -// Arguments: -// -// - container: The container. -// - tids: Array of thread IDs to move into the container. Caller takes the -// ownership. -// - tids_size: Number of thread IDs stored in tids. Caller takes the -// ownership. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_enter(struct container *container, - const pid_t *tids, - const int tids_size, - struct status *s); - -// Run the specified command inside the container. Multiple instances of run -// can be active simultaneously. Processes MUST be reaped by the caller. -// -// Arguments: -// -// - container: The container. -// - argc: number of arguments (including the binary file path). -// - argv: All arguments. The first element is the binary that will be executed -// and must be an absolute path. -// - spec: The specification of the runtime environment to use for the -// execution of the command. -// - tid: [output] On success, tid stores the PID of the command. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_run(struct container *container, - const int argc, - const char **argv, - const Containers__Lmctfy__RunSpec *spec, - pid_t *tid, - struct status *s); - -// Execute the specified command inside the container. This replaces the -// current process image with the specified command. The PATH environment -// variable is used, and the existing environment is passed to the new -// process image unchanged. -// -// Arguments: -// -// - container -// - argc: number of arguments (including the binary file path). -// - argv: All arguments. The first element is the binary that will be executed -// and must be an absolute path. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_exec(struct container *container, - const int argc, - const char **argv, - struct status *s); - -// Updates the container according to the specification. The set of resource -// types being isolated cannot change during an Update. This means that a -// CONTAINER_UPDATE_POLICY_REPLACE must specify all the resources being isolated -// and a CONTAINER_UPDATE_POLICY_DIFF cannot specify any resource that is not -// already being isolated. -// -// Arguments: -// -// - container -// - policy: Update policy. Can be either CONTAINER_UPDATE_POLICY_DIFF, or -// CONTAINER_UPDATE_POLICY_REPLACE. -// - spec: The specification of the desired updates. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_update(struct container *container, - int policy, - const Containers__Lmctfy__ContainerSpec *spec, - struct status *s); - -// Returns the resource isolation specification (ContainerSpec) of this -// container. -// -// Arguments: -// -// - container: The container -// - spec: [output] An address of a ContainerSpec pointer. *spec will points to -// the ContainerSpec of the container. Caller takes the ownership. *spec can -// be released by calling free(). -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_spec(struct container *container, - Containers__Lmctfy__ContainerSpec **spec, - struct status *s); - -// List all subcontainers. -// -// Arguments: -// -// - container: The container -// - list_policy: CONTAINER_LIST_POLICY_SELF or CONTAINER_LIST_POLICY_RECURSIVE -// - subcontainers: [output] The address of a pointer points to an array of -// struct container pointers. The caller takes the onwership. On success, the -// pointer will be assigned an address to an array of containers. The pointed -// array should be released with free(). The containers inside the array -// should be deleted/destroyed individually. -// - subcontainers_size: [output] The address of an integer used to store number -// of subcontainers in the array. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_list_subcontainers(struct container *container, - int list_policy, - struct container **subcontainers[], - int *subcontainers_size, - struct status *s); - -// List all TIDs in the container. -// -// Arguments: -// - container -// - list_policy: List policy. -// - threads: [output] The address of a pointer points to an array of pid_t. -// The caller takes the ownership. The array can be released with free(). -// - threads_size: [output] *threads_size is the number of TIDs stored in *threads. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_list_threads(struct container *container, - int list_policy, - pid_t *threads[], - int *threads_size, - struct status *s); - -// Get all PIDs in this container. -// -// Arguments: -// - container -// - list_policy: List policy. -// - processes: [output] The address of a pointer points to an array of pid_t. -// The caller takes the ownership. The array can be released with free(). -// - processes_size: [output] *processes_size is the number of PIDs stored in -// *processes. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_list_processes(struct container *container, - int list_policy, - pid_t *processes[], - int *processes_size, - struct status *s); - -// Atomically stops the execution of all threads inside the container and all -// subcontainers (recursively). All threads moved to a paused container will -// be paused as well (regardless of whether the PID is in the container). This -// guarantees to get all threads. -// -// Arguments: -// - container: The container. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_pause(struct container *container, - struct status *s); - -// Atomically resumes the execution of all threads inside the container and -// all subcontainers (recursively). All paused threads moved to a non-paused -// container will be resumed. -// -// Arguments: -// - container: The container. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_resume(struct container *container, - struct status *s); - -// Kills all processes running in the container. This operation is atomic and -// is synchronized with any mutable operations on this container. -// -// The operation sends a SIGKILL to all processes in the containers. Tourist -// threads are killed via SIGKILL after all processes have exited. -// -// Note that this operation can potentially take a long time (O(seconds)) if -// the processes in the container do not finish quickly. This operation also -// blocks all mutable container operations while it is in progress. -// -// Arguments: -// - container: The container. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_killall(struct container *container, - struct status *s); - -// Gets usage and state information for the container. Note that the snapshot -// is not atomic. -// -// Arguments: -// - container: The container. -// - stats_type: The type of statistics to output. -// - stats: [output] Used to store a pointer points to the container's -// statistics. The call takes the ownership of *stats, which should be -// free()'ed. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_stats(struct container *container, - int stats_type, - Containers__Lmctfy__ContainerStats **stats, - struct status *s); - -// Get the name of the container. -// -// Arguments: -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Return: -// The container name. The caller does not take the ownership. -const char *lmctfy_container_name(struct container *container); - -// Register a notification for a specified container event. All notifications -// are unregistered when the container is destroyed. -// -// Arguments: -// - container: The container. -// - callback: The callback to run when the event is triggered. The caller -// takes ownership of the callback which MUST be a repeatable callback. -// - user_data: The pointer which will be passed to the callback function as -// its last parameter. The caller takes the ownership. -// - spec: The specification for the event for which to register notifications. -// The caller takes the ownership. -// - notif_id: [output] The ID for the notification. The ID is unique within -// the current container_api instance. It will be used to unregister the -// notification -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_register_notification(struct container *container, - lmctfy_event_callback_f callback, - void *user_data, - Containers__Lmctfy__EventSpec *spec, - notification_id_t *notif_id, - struct status *s); - -// Unregister (stop) the specified notification from being received. -// -// Arguments: -// - container: The container. -// - notif_id: The unique notification ID for the container -// notification. -// - s: [output] The status of the operations and an error message if the -// status is not OK. -// -// Returns: -// -// Returns the error code. 0 on success. When there's an error, the return code -// is same as s->error_code when s is not NULL. -int lmctfy_container_unregister_notification(struct container *container, - const notification_id_t notif_id, - struct status *s); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif - #endif // LMCTFY_INCLUDE_CLMCTFY_H_ From db61f9a4bbb8c3035352c7b0f3bb2f9ff5783d7d Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 12 Mar 2014 22:18:42 -0400 Subject: [PATCH 79/84] rename a header file. --- clmctfy/clmctfy_container_api_ctest.cc | 2 +- clmctfy/clmctfy_container_ctest.cc | 2 +- clmctfy/{clmctfy_macros_ctest.h => clmctfy_test_macros.h} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename clmctfy/{clmctfy_macros_ctest.h => clmctfy_test_macros.h} (100%) diff --git a/clmctfy/clmctfy_container_api_ctest.cc b/clmctfy/clmctfy_container_api_ctest.cc index 7a37b3c..a1bfc6c 100644 --- a/clmctfy/clmctfy_container_api_ctest.cc +++ b/clmctfy/clmctfy_container_api_ctest.cc @@ -23,7 +23,7 @@ #include "lmctfy_mock.h" #include "lmctfy.h" -#include "clmctfy_macros_ctest.h" +#include "clmctfy_test_macros.h" #include "clmctfy_container_struct.h" #include "clmctfy_container_api_struct.h" diff --git a/clmctfy/clmctfy_container_ctest.cc b/clmctfy/clmctfy_container_ctest.cc index 8dc448e..c6b9ede 100644 --- a/clmctfy/clmctfy_container_ctest.cc +++ b/clmctfy/clmctfy_container_ctest.cc @@ -23,7 +23,7 @@ #include "lmctfy_mock.h" #include "lmctfy.pb.h" -#include "clmctfy_macros_ctest.h" +#include "clmctfy_test_macros.h" #include "clmctfy_container_struct.h" #include "clmctfy_container_api_struct.h" diff --git a/clmctfy/clmctfy_macros_ctest.h b/clmctfy/clmctfy_test_macros.h similarity index 100% rename from clmctfy/clmctfy_macros_ctest.h rename to clmctfy/clmctfy_test_macros.h From 60864c7732a8e451f6dea9b70b0e5770364e4b86 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Wed, 12 Mar 2014 22:31:07 -0400 Subject: [PATCH 80/84] change the example for clmctfy. --- examples/clmctfy_simple_existing.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/clmctfy_simple_existing.c b/examples/clmctfy_simple_existing.c index 3147d7f..6c8994f 100644 --- a/examples/clmctfy_simple_existing.c +++ b/examples/clmctfy_simple_existing.c @@ -17,7 +17,7 @@ int main() { char *container_name = NULL; Containers__Lmctfy__ContainerStats *stats = NULL; - err = lmctfy_new_container_api(&s, &lmctfy); + err = lmctfy_new_container_api(&lmctfy, &s); if (err != 0) { printf("Failed to instantiate container_api: %s\n", s.message); free(s.message); @@ -26,7 +26,7 @@ int main() { } // Get what container the current thread is in. - err = lmctfy_container_api_detect_container(&s, &container_name, lmctfy, 0); + err = lmctfy_container_api_detect_container(lmctfy, 0, &container_name, &s); if (err != 0) { printf("Failed to detect the current container: %s\n", s.message); free(s.message); @@ -35,7 +35,7 @@ int main() { } printf("Current container: %s\n", container_name); - err = lmctfy_container_api_get_container(&s, &container, lmctfy, "."); + err = lmctfy_container_api_get_container(lmctfy, ".", &container, &s); if (err != 0) { printf("Failed to get container: %s\n", s.message); free(s.message); @@ -44,7 +44,7 @@ int main() { return -1; } - err = lmctfy_container_stats(&s, container, CONTAINER_STATS_TYPE_SUMMARY, &stats); + err = lmctfy_container_stats(container, CONTAINER_STATS_TYPE_SUMMARY, &stats, &s); if (err != 0) { printf("Failed to get container stats: %s\n", s.message); free(s.message); From 11c13afb2e2ececdfb5caa1ea507a1a7c3b45109 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 21 Mar 2014 13:25:59 -0400 Subject: [PATCH 81/84] container_api_raw functions --- clmctfy/clmctfy_container_api.cc | 35 +--------------- clmctfy/clmctfy_container_api_raw.cc | 60 ++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/clmctfy/clmctfy_container_api.cc b/clmctfy/clmctfy_container_api.cc index 1e5f945..d85a3b1 100644 --- a/clmctfy/clmctfy_container_api.cc +++ b/clmctfy/clmctfy_container_api.cc @@ -11,6 +11,7 @@ #include "clmctfy_macros.h" #include "clmctfy_container_struct.h" #include "clmctfy_container_api_struct.h" +#include "clmctfy_container_api_raw.h" #define STATUS_OK UTIL__ERROR__CODE__OK @@ -23,17 +24,6 @@ using ::util::internal::status_new; using ::util::Status; using ::util::StatusOr; -int lmctfy_init_machine_raw(const void *spec, const size_t spec_size, struct status *s) { - InitSpec init_spec; - CHECK_NOTFAIL_OR_RETURN(s); - if (spec != NULL && spec_size > 0) { - // XXX should we consider this as an error? - init_spec.ParseFromArray(spec, spec_size); - } - Status v = ContainerApi::InitMachine(init_spec); - return status_copy(s, v); -} - int lmctfy_init_machine(const Containers__Lmctfy__InitSpec *spec, struct status *s) { uint8_t *buf = NULL; size_t sz = 0; @@ -98,29 +88,6 @@ int lmctfy_container_api_get_container(const struct container_api *api, return STATUS_OK; } -int lmctfy_container_api_create_container_raw(struct container_api *api, - const char *container_name, - const void *spec, - const size_t spec_size, - struct container **c, - struct status *s) { - CHECK_NOTNULL_OR_RETURN(s, api); - CHECK_NOTNULL_OR_RETURN(s, api->container_api_); - CHECK_NOTNULL_OR_RETURN(s, c); - CHECK_NOTNULL_OR_RETURN(s, container_name); - CHECK_POSITIVE_OR_RETURN(s, strlen(container_name)); - ContainerSpec container_spec; - Container *ctnr = NULL; - if (spec != NULL && spec_size > 0) { - container_spec.ParseFromArray(spec, spec_size); - } - - StatusOr statusor = api->container_api_->Create(container_name, container_spec); - RETURN_IF_ERROR_PTR(s, statusor, &ctnr); - COPY_CONTAINER_STRUCTURE(ctnr, c); - return STATUS_OK; -} - int lmctfy_container_api_create_container(struct container_api *api, const char *container_name, const Containers__Lmctfy__ContainerSpec *spec, diff --git a/clmctfy/clmctfy_container_api_raw.cc b/clmctfy/clmctfy_container_api_raw.cc index c93971c..0785f71 100644 --- a/clmctfy/clmctfy_container_api_raw.cc +++ b/clmctfy/clmctfy_container_api_raw.cc @@ -1,3 +1,63 @@ #include "clmctfy_container_api_raw.h" +#include "util/task/statusor.h" +#include "lmctfy.pb.h" +#include "util/task/codes.pb-c.h" +#include "lmctfy.h" + +#include "clmctfy_macros.h" +#include "clmctfy_container_struct.h" +#include "clmctfy_container_api_struct.h" + #define STATUS_OK UTIL__ERROR__CODE__OK + +using ::containers::lmctfy::Container; +using ::containers::lmctfy::ContainerApi; +using ::containers::lmctfy::InitSpec; +using ::containers::lmctfy::ContainerSpec; +using ::util::internal::status_copy; +using ::util::internal::status_new; +using ::util::Status; +using ::util::StatusOr; + +int lmctfy_init_machine_raw(const void *spec, const size_t spec_size, struct status *s) { + InitSpec init_spec; + CHECK_NOTFAIL_OR_RETURN(s); + if (spec != NULL && spec_size > 0) { + // XXX should we consider this as an error? + init_spec.ParseFromArray(spec, spec_size); + } + Status v = ContainerApi::InitMachine(init_spec); + return status_copy(s, v); +} + +#define COPY_CONTAINER_STRUCTURE(ctnr_ptr, ctnr_struct) do { \ + if ((ctnr_ptr) != NULL) { \ + (*(ctnr_struct)) = new container(); \ + (*(ctnr_struct))->container_ = ctnr_ptr; \ + } \ +} while(0) + +int lmctfy_container_api_create_container_raw(struct container_api *api, + const char *container_name, + const void *spec, + const size_t spec_size, + struct container **c, + struct status *s) { + CHECK_NOTNULL_OR_RETURN(s, api); + CHECK_NOTNULL_OR_RETURN(s, api->container_api_); + CHECK_NOTNULL_OR_RETURN(s, c); + CHECK_NOTNULL_OR_RETURN(s, container_name); + CHECK_POSITIVE_OR_RETURN(s, strlen(container_name)); + ContainerSpec container_spec; + Container *ctnr = NULL; + if (spec != NULL && spec_size > 0) { + container_spec.ParseFromArray(spec, spec_size); + } + + StatusOr statusor = api->container_api_->Create(container_name, container_spec); + RETURN_IF_ERROR_PTR(s, statusor, &ctnr); + COPY_CONTAINER_STRUCTURE(ctnr, c); + return STATUS_OK; +} + From beeecad3485d6015eedbd978c22d1cb1df63205d Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 21 Mar 2014 13:56:30 -0400 Subject: [PATCH 82/84] order of #include --- clmctfy/clmctfy_container_raw.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clmctfy/clmctfy_container_raw.cc b/clmctfy/clmctfy_container_raw.cc index 0e0256b..c5a5e94 100644 --- a/clmctfy/clmctfy_container_raw.cc +++ b/clmctfy/clmctfy_container_raw.cc @@ -1,9 +1,9 @@ +#include "clmctfy_container_raw.h" + #include #include using ::std::vector; -#include "clmctfy_container_raw.h" - #include "util/task/codes.pb.h" #include "lmctfy.h" From a7fd50f20272e710b5b9a4a05e7d9a70474ecee5 Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Sat, 22 Mar 2014 00:36:24 -0400 Subject: [PATCH 83/84] lmctfy_container_stats_raw() --- clmctfy/clmctfy_container.cc | 10 +++++++++ clmctfy/clmctfy_container_raw.cc | 36 ++++++++++++++++++++++++++++++++ include/clmctfy_container_raw.h | 23 +++++++++++++++++++- 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/clmctfy/clmctfy_container.cc b/clmctfy/clmctfy_container.cc index 79882fb..fa5ca56 100644 --- a/clmctfy/clmctfy_container.cc +++ b/clmctfy/clmctfy_container.cc @@ -346,6 +346,15 @@ int lmctfy_container_stats(struct container *container, int ret = STATUS_OK; uint8_t *buf = NULL; + size_t sz; + ret = lmctfy_container_stats_raw(container, stats_type, (void **)&buf, &sz, s); + if (ret != STATUS_OK) { + return ret; + } + *stats = containers__lmctfy__container_stats__unpack(NULL, sz, buf); + free(buf); + return ret; + /* Container::StatsType type; switch (stats_type) { case CONTAINER_STATS_TYPE_SUMMARY: @@ -372,6 +381,7 @@ int lmctfy_container_stats(struct container *container, delete []buf; } return ret; + */ } const char *lmctfy_container_name(struct container *container) { diff --git a/clmctfy/clmctfy_container_raw.cc b/clmctfy/clmctfy_container_raw.cc index c5a5e94..b71b995 100644 --- a/clmctfy/clmctfy_container_raw.cc +++ b/clmctfy/clmctfy_container_raw.cc @@ -113,3 +113,39 @@ int lmctfy_container_register_notification_raw(struct container *container, } +int lmctfy_container_stats_raw(struct container *container, + int stats_type, + void **stats, + size_t *sz, + struct status *s) { + CHECK_NOTFAIL_OR_RETURN(s); + CHECK_NOTNULL_OR_RETURN(s, container); + CHECK_NOTNULL_OR_RETURN(s, container->container_); + CHECK_NOTNULL_OR_RETURN(s, stats); + + int ret = STATUS_OK; + Container::StatsType type; + switch (stats_type) { + case CONTAINER_STATS_TYPE_SUMMARY: + type = Container::STATS_SUMMARY; + break; + case CONTAINER_STATS_TYPE_FULL: + type = Container::STATS_FULL; + break; + default: + return status_new(s, UTIL__ERROR__CODE__INVALID_ARGUMENT, "Unknown stats type: %d", stats_type); + } + StatusOr statusor_container_stats = container->container_->Stats(type); + if (!statusor_container_stats.ok()) { + return status_copy(s, statusor_container_stats.status()); + } + + const ContainerStats &container_stats = statusor_container_stats.ValueOrDie(); + *sz = container_stats.ByteSize(); + *stats = NULL; + if (sz > 0) { + *stats = malloc(*sz); + container_stats.SerializeToArray(*stats, *sz); + } + return ret; +} diff --git a/include/clmctfy_container_raw.h b/include/clmctfy_container_raw.h index 09b7cd6..588b2aa 100644 --- a/include/clmctfy_container_raw.h +++ b/include/clmctfy_container_raw.h @@ -97,7 +97,28 @@ int lmctfy_container_register_notification_raw(struct container *container, notification_id_t *notif_id, struct status *s); - +// Gets usage and state information for the container. Note that the snapshot +// is not atomic. +// +// Arguments: +// - container: The container. +// - stats_type: The type of statistics to output. +// - spec: [output] Used to store a pointer points to the container's +// statistics, which is serialized. The call takes the ownership of +// *spec, which should be free()'ed. +// - stats_size: [output] The size of the serialized data. +// - s: [output] The status of the operations and an error message if the +// status is not OK. +// +// Returns: +// +// Returns the error code. 0 on success. When there's an error, the return code +// is same as s->error_code when s is not NULL. +int lmctfy_container_stats_raw(struct container *container, + int stats_type, + void **stats, + size_t *stats_size, + struct status *s); #ifdef __cplusplus } #endif // __cplusplus From 4ff0ff2ae825bb31f7dedebbfe224975ffbeefaa Mon Sep 17 00:00:00 2001 From: Nan Monnand Deng Date: Fri, 18 Apr 2014 21:08:41 -0400 Subject: [PATCH 84/84] rebase onto 0.4.5 --- Makefile | 2 +- clmctfy/clmctfy_macros.h | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 3ef263b..7788b31 100755 --- a/Makefile +++ b/Makefile @@ -260,7 +260,7 @@ $(CREAPER): lmctfy-creaper.go %_proto: %.proto $(PROTOC) $^ --cpp_out=. - $(PROTOC_C) $^ --c_out=$(dir $^) --proto_path=$(dir $^) + $(PROTOC_C) $^ --c_out=$(dir $^) --proto_path=$(dir $^):. %.pb.o: %_proto $(create_bin) diff --git a/clmctfy/clmctfy_macros.h b/clmctfy/clmctfy_macros.h index 72d874f..a730ef0 100644 --- a/clmctfy/clmctfy_macros.h +++ b/clmctfy/clmctfy_macros.h @@ -9,14 +9,15 @@ #include "clmctfy_status.h" #include "clmctfy_status_internal.h" -#define RETURN_IF_ERROR_PTR(s, ...) \ - do { \ - const ::util::Status _status = \ - ::util::errors_internal::PerformSideEffects(__VA_ARGS__); \ - if (PREDICT_FALSE(!_status.ok())) { \ - if (s != NULL) ::util::internal::status_copy(s, _status); \ - return (int)_status.error_code(); \ - } \ +#define RETURN_IF_ERROR_PTR(s, expr, out) \ + do { \ + auto _expr_result = (expr); \ + if (PREDICT_FALSE(!_expr_result.ok())) { \ + const ::util::Status _status = _expr_result.status(); \ + if (s != NULL) ::util::internal::status_copy(s, _status); \ + return (int)_status.error_code(); \ + } \ + (*(out)) = _expr_result.ValueOrDie(); \ } while (0) #define CHECK_NOTFAIL_OR_RETURN(status) do { \