use nix build & meson & zlog

This commit is contained in:
Rongsong Shen 2025-11-03 18:19:59 +08:00
parent 0123623742
commit 346768a144
60 changed files with 13739 additions and 0 deletions

37
src/default.nix Normal file
View file

@ -0,0 +1,37 @@
{
pkgs,
myCommitId,
...
}:
let
xce = pkgs.callPackage ./xce.nix {
inherit pkgs myCommitId;
withDebug = false;
withAsan = false;
withoutDb = false;
};
xce_withoutdb = pkgs.callPackage ./xce.nix {
inherit pkgs myCommitId;
withDebug = false;
withAsan = false;
withoutDb = true;
};
xce_withoutdb_debug = pkgs.callPackage ./xce.nix {
inherit pkgs myCommitId;
withDebug = true;
withAsan = true;
withoutDb = true;
};
xce_debug = pkgs.callPackage ./xce.nix {
inherit pkgs myCommitId;
withDebug = true;
withAsan = true;
withoutDb = false;
};
in
{
xce = xce;
xce_debug = xce_debug;
xce_withoutdb = xce_withoutdb;
xce_withoutdb_debug = xce_withoutdb_debug;
}

97
src/flake.lock generated Normal file
View file

@ -0,0 +1,97 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1761907660,
"narHash": "sha256-kJ8lIZsiPOmbkJypG+B5sReDXSD1KGu2VEPNqhRa/ew=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "2fb006b87f04c4d3bdf08cfdbc7fab9c13d94a15",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1755615617,
"narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "20075955deac2583bb12f07151c2df830ef346b4",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"xbuild": "xbuild"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"xbuild": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1762160937,
"narHash": "sha256-L0wBnhZxneDKm9ym7XroRexjuio62sVV0xi5sgAMiaA=",
"owner": "shen390s",
"repo": "my-nix-channel",
"rev": "3eb8b50d886f197ec5b842aadb022b026c9b2bfd",
"type": "github"
},
"original": {
"owner": "shen390s",
"ref": "master",
"repo": "my-nix-channel",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

38
src/flake.nix Normal file
View file

@ -0,0 +1,38 @@
{
description = "Flake for NEXA xce";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
xbuild.url = "github:shen390s/my-nix-channel?ref=master";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, xbuild, flake-utils }:
let
supportedSystems = [ "x86_64-linux" ];
myCommitId =
if builtins.hasAttr "shortRev" self
then self.shortRev
else self.dirtyShortRev;
in
flake-utils.lib.eachSystem supportedSystems (
system: let
mypkgs = xbuild.packages.${system};
overlays = [
(final: prev: prev // mypkgs)
];
pkgs = import nixpkgs { inherit overlays system;};
xpkgs = import ./default.nix {
inherit pkgs myCommitId;
};
in rec {
packages = pkgs // xpkgs;
defaultPackage = xpkgs.xce_withoutdb_debug;
devShells.default = pkgs.mkShell {
nativeBuildInputs = xpkgs.xce.nativeBuildInputs;
};
devShell = self.devShells.${system}.default;
}
);
}

81
src/include/client.h Normal file
View file

@ -0,0 +1,81 @@
#if !defined(_CLIENT_H_)
#define _CLIENT_H_
#include <stdint.h>
#include "netio.h"
#include "request.h"
#include "xce/types.h"
#include "xceapi.h"
typedef int (*xce_request_handler_t)(xce_request_t*);
typedef void* xcecli_ctx_t;
#define N_MAX_MASTERS (3)
typedef struct {
int nmasters;
char* masters[N_MAX_MASTERS];
int master_ports[N_MAX_MASTERS];
char* from;
char* key;
} xce_client_config_t;
#define xcecli_jobfinish(ctx, finish) \
xcecli_notify_jobfinish(ctx, finish)
extern int xcecli_ctx_init(xcecli_ctx_t*, xce_client_config_t*);
extern void xcecli_ctx_fini(xcecli_ctx_t);
extern int xcecli_set_handler(xcecli_ctx_t, xce_request_handler_t);
extern int xcecli_start(xcecli_ctx_t);
extern int xcecli_stop(xcecli_ctx_t);
extern int xcecli_wakeup(xcecli_ctx_t, int);
extern int xcecli_hello(xcecli_ctx_t, char*);
extern int xcecli_shutdown(xcecli_ctx_t);
extern int xcecli_reslist(xcecli_ctx_t, xce_resource_t***);
extern int xcecli_join(xcecli_ctx_t, int, hostattrs_t*);
extern int xcecli_workerlist(xcecli_ctx_t, xce_worker_t***);
extern int xcecli_jobdispatch(xcecli_ctx_t, xce_job_dispatch_t*);
extern int xcecli_joblist(xcecli_ctx_t, xce_job_t***);
extern int xcecli_clusterconf(xcecli_ctx_t, xce_clusterconf_t**);
extern int xcecli_notify_jobfinish(xcecli_ctx_t, xce_jobfinish_t*);
extern int xcecli_notify_jobstart(xcecli_ctx_t, job_pidinfo_t*);
extern int xcecli_notify_jobfail(xcecli_ctx_t c, job_failinfo_t*);
extern int xcecli_notify_jobstop(xcecli_ctx_t, uint64_t);
extern int xcecli_notify_jobresume(xcecli_ctx_t, uint64_t);
extern int xcecli_notify_jobpostdone(xcecli_ctx_t, uint64_t);
extern int xcecli_jobsubmit(xcecli_ctx_t, xce_job_submit_t*,
uint64_t*);
extern int xcecli_update_resvals(xcecli_ctx_t, int, xce_resval_t**);
extern int xcecli_resval(xcecli_ctx_t, char*,
char*, xce_resval_t***);
extern int xcecli_update_jusage(xcecli_ctx_t, uint64_t, int, int*,
int, int*, int, xce_rusage_t**);
extern int xcecli_notify(xcecli_ctx_t, xce_notify_data_t*);
extern int xcecli_jobctrl(xcecli_ctx_t, xce_jobctrl_t*);
extern int xcecli_notify_jobchkpt(xcecli_ctx_t, uint64_t, char*);
extern int xcecli_queuectrl(xcecli_ctx_t, xce_queuectrl_t*);
extern int xcecli_runtask(xcecli_ctx_t, xce_taskrun_t*);
extern int xcecli_notify_taskstart(xcecli_ctx_t, xce_task_pidinfo_t*);
extern int xcecli_notify_taskfail(xcecli_ctx_t, xce_task_failinfo_t*);
extern int xcecli_notify_taskfinish(xcecli_ctx_t, xce_task_finish_t*);
extern endpoint_t* xcecli_get_my_endpoint(xcecli_ctx_t);
extern xce_peerinfo_t* xcecli_get_myinfo(xcecli_ctx_t);
extern void xcecli_block_tasks(xcecli_ctx_t);
extern void xcecli_unblock_tasks(xcecli_ctx_t);
#define xcecli_free_ress(nres, ress) \
xce_free_ress(nres, ress)
#define xcecli_free_workers(nworkers, workers) \
xce_free_workers(nworkers, workers)
#define xcecli_free_jobs(njobs, jobs) \
xce_free_jobs(njobs, jobs)
#define xcecli_free_queues(nqueues, queues) \
xce_free_queues(nqueues, queues)
#define xcecli_free_groups(ngroups, groups) \
xce_free_groups(ngroups, groups)
#define xcecli_free_clusterconf(conf) \
xce_free_clusterconf(conf)
#endif

View file

@ -0,0 +1,58 @@
#if !defined(_CLUSTERCONFIG_H_)
#define _CLUSTERCONFIG_H_ 1
#include "xce/types.h"
typedef struct {
int nhash_slots;
int delta;
} hash_zarray_config_t;
typedef hash_zarray_config_t jobmgr_config_t;
typedef hash_zarray_config_t workermgr_config_t;
typedef hash_zarray_config_t qmgr_config_t;
typedef struct {
int nhash_slots;
int delta;
int inst_delta;
} resmgr_config_t;
typedef hash_zarray_config_t xstrings_config_t;
typedef struct {
char* name;
char* host;
int port;
} master_candidate_t;
typedef struct {
char* clustername;
int port;
int ncandidates;
master_candidate_t** candidates;
int heartbeat_interval;
int inactive_heartbeat_count;
int fetch_job_interval;
int netio_timeout;
int vcpus;
int nres;
xce_resource_t** resources;
int nqueues;
xce_queue_t** queues;
int nugroups;
xce_group_t** ugroups;
int nhgroups;
xce_group_t** hgroups;
int nhconfigs;
xce_hostconfig_t** hconfigs;
jobmgr_config_t* jobmgr;
workermgr_config_t* workermgr;
qmgr_config_t* qmgr;
resmgr_config_t* resmgr;
xstrings_config_t* xstrings;
} cluster_config_t;
#endif

20
src/include/config.h Normal file
View file

@ -0,0 +1,20 @@
#if !defined(_CONFIG_H_)
#define _CONFIG_H_
#define BUG_EMAIL "rshen@shenrs.eu"
#define XCE_MAXNAME_LEN (64)
#define XCE_MAXHOSTNAME_LEN (256) /* hostname suggest to 256 */
#define XCE_MAXDESC_LEN (4096) /* enlarge to 4096 */
#define XCE_MAXKEY_LEN (256)
#define XCE_MAXMODEL_LEN (32)
#define XCE_MAXTYPE_LEN (32)
#define XCE_WORKER_HTAB_SIZE (673)
#define XCE_JOB_HTAB_SIZE (5009)
#define XCE_MAXPATH_LEN (4096) /* enlarge to 4096 */
#define XCE_MAXCMD_LEN (4096)
#define XCE_MAX_ERRMSG_LEN (4096)
#endif

28
src/include/dataq.h Normal file
View file

@ -0,0 +1,28 @@
#if !defined(_DATAQ_H_)
#define _DATAQ_H_ 1
#include "mylock.h"
typedef struct _data_item {
struct _data_item* next;
} data_item_t;
typedef int (*data_item_match_fn_t)(data_item_t*);
typedef void (*data_item_killer_t)(data_item_t*);
typedef struct {
data_item_t* head;
data_item_t* tail;
data_item_killer_t killer;
mylock_t lock;
} dataq_t;
#define DATAQ_EMPTY(q) ((q)->head == NULL)
extern int dataq_init(dataq_t*, data_item_killer_t);
extern data_item_t* dataq_deq(dataq_t*, data_item_match_fn_t);
extern int dataq_enq(dataq_t*, data_item_t*);
extern void dataq_fini(dataq_t*);
#endif

30
src/include/hook.h Normal file
View file

@ -0,0 +1,30 @@
#if !defined(__HOOK_H__)
#define __HOOK_H__ 1
#include <stdarg.h>
#include <stddef.h>
#include "xlist.h"
#define HOOK_BEFORE_EVENT (0)
#define HOOK_AFTER_EVENT (1)
typedef int (*hook_fn_t)(int, int, int, void*, va_list);
typedef struct {
hook_fn_t fn;
void* data;
} hook_item_t;
typedef struct {
int maxtypes;
xlist_t* hooks;
} hooksys_t;
extern int xce_hook_init(hooksys_t*, int);
extern int xce_add_hook(hooksys_t*, int,
hook_fn_t, void*);
extern int xce_run_hooks(hooksys_t*, int, int, int, ...);
extern void xce_hook_fini(hooksys_t*);
#endif

44
src/include/htab.h Normal file
View file

@ -0,0 +1,44 @@
#if !defined(_HTAB_H_)
#define _HTAB_H_ 1
#include <stdint.h>
#include "mylock.h"
typedef unsigned int (*hash_key_hash_fn_t)(void*);
typedef int (*hash_key_cmp_fn_t)(void*, void*);
typedef void* (*hash_key_copy_fn_t)(void*);
typedef void (*hash_key_free_fn_t)(void*);
typedef struct {
hash_key_hash_fn_t hash;
hash_key_cmp_fn_t cmp;
hash_key_copy_fn_t copy;
hash_key_free_fn_t free;
} hash_key_fn_t;
typedef struct _hent {
struct _hent* next;
void* key;
int64_t data;
} hent_t;
typedef struct {
mylock_t lock;
int nslots;
hash_key_fn_t fn;
hent_t** slots;
} htab_t;
extern hash_key_fn_t string_hash_key;
extern hash_key_fn_t int_hash_key;
extern int ht_init(htab_t*, int,
hash_key_fn_t);
extern void ht_fini(htab_t*);
extern hent_t* ht_get(htab_t*, void*);
extern hent_t* ht_add(htab_t*, void*);
extern int ht_del(htab_t*, void*);
#endif

26
src/include/kvmgr.h Normal file
View file

@ -0,0 +1,26 @@
#if !defined(__KVMGR_H__)
#define __KVMGR_H__ 1
#include "htab.h"
#include "mylock.h"
#include "xlist.h"
#include "zarray.h"
typedef struct {
mylock_t lock;
htab_t htab;
zarray_t data;
} kvmgr_t;
extern int kvmgr_init(kvmgr_t*, hash_key_fn_t,
int, int,
zarray_item_killer_t);
extern void kvmgr_fini(kvmgr_t*);
extern void* kvmgr_lock(kvmgr_t*, void*, int);
extern int32_t kvmgr_add(kvmgr_t*, void*, void*);
extern void kvmgr_del(kvmgr_t*, void*);
extern int kvmgr_publish(kvmgr_t*, xlist_action_fn_t, void*);
extern int kvmgr_iter(kvmgr_t*, xlist_t*, void*);
#endif

38
src/include/mylock.h Normal file
View file

@ -0,0 +1,38 @@
#if !defined(_MYLOCK_H_)
#define _MYLOCK_H_ 1
#include <pthread.h>
typedef pthread_mutex_t mylock_t;
typedef pthread_rwlock_t my_rwlock_t;
typedef struct {
int ncap;
int head;
int len;
int isize;
void* data;
pthread_mutex_t mutex;
pthread_cond_t condget;
pthread_cond_t condput;
} cbuf_t;
extern int mylock_init(mylock_t*);
extern void mylock_fini(mylock_t*);
extern int mylock_try(mylock_t*);
extern int mylock_lock(mylock_t*);
extern int mylock_unlock(mylock_t*);
extern int my_rwlock_init(my_rwlock_t*);
extern void my_rwlock_fini(my_rwlock_t*);
extern int my_rwlock_rlock(my_rwlock_t*);
extern int my_rwlock_wlock(my_rwlock_t*);
extern int my_rwlock_unlock(my_rwlock_t*);
extern int cbuf_init(cbuf_t*, int, int);
extern void cbuf_fini(cbuf_t*);
extern int cbuf_put(cbuf_t*, void*);
extern int cbuf_tryput(cbuf_t*, void*);
extern int cbuf_get(cbuf_t*, void*);
#endif

73
src/include/netio.h Normal file
View file

@ -0,0 +1,73 @@
#if !defined(_NETIO_H_)
#define _NETIO_H_ 1
#include <stdint.h>
#include <stdio.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include "dataq.h"
#include "mylock.h"
typedef int (*msghandler_t)(struct epoll_event*);
#define IO_MON_INPUT (0x01)
#define IO_MON_OUTPUT (0x02)
typedef struct {
uint16_t sz;
char* data;
} io_packet_t;
typedef struct {
mylock_t lock;
int epoll_fd;
struct epoll_event ev;
pthread_t worker;
} iomgr_t;
typedef struct {
mylock_t lock;
iomgr_t* iomgr;
int fd;
int idx;
int flags;
unsigned int busy : 1;
unsigned int needfree : 1;
uint32_t refcount;
dataq_t outq;
uint64_t seq;
msghandler_t handler;
void* owner;
void* data;
} endpoint_t;
extern int netio_write(int, char*, int);
extern int netio_read(int, char*, int);
extern int write_packet(int, io_packet_t*);
extern int alloc_packet(io_packet_t*);
extern int read_packet(int, io_packet_t*);
extern void free_packet(io_packet_t*);
extern endpoint_t* endpoint_get(void);
extern int endpoint_init(endpoint_t*, int, int, int, int);
extern int endpoint_connect(endpoint_t*, char*, int);
extern int endpoint_accept(endpoint_t*, endpoint_t*);
extern int endpoint_set_handler(endpoint_t*, msghandler_t, void*);
extern int endpoint_enq(endpoint_t*, data_item_t*);
extern data_item_t* endpoint_deq(endpoint_t*);
extern endpoint_t* endpoint_ref(endpoint_t*);
extern void endpoint_deref(endpoint_t*);
extern uint64_t endpoint_getseq(endpoint_t*);
extern void endpoint_block_tasks(endpoint_t*);
extern void endpoint_unblock_tasks(endpoint_t*);
extern int endpoint_is_task_blocked(endpoint_t*);
extern int iomgr_init(iomgr_t*);
extern int iomgr_monitor(iomgr_t*, endpoint_t*);
extern int iomgr_unmonitor(iomgr_t*, endpoint_t*);
extern int iomgr_start(iomgr_t*);
extern int iomgr_fini(iomgr_t*);
extern int iomgr_stop(iomgr_t*);
#endif

78
src/include/objmgr.h Normal file
View file

@ -0,0 +1,78 @@
#if !defined(__OBJMGR_H__)
#define __OBJMGR_H__
#include "config.h"
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include "htab.h"
#include "mylock.h"
#include "zarray.h"
#define OBJ_MAGIC (0x4a424f58)
#define OBJREF_NOP (0) /* ref obj without lock, \
* just keep object alive */
#define OBJREF_READ (1) /* ref obj with read lock */
#define OBJREF_UPDATE (2) /* ref obj with write lock */
typedef void* (*obj_create_fn_t)(void*, void*,
va_list);
typedef void (*obj_fini_fn_t)(void*);
typedef void (*objtype_fini_fn_t)(void*);
typedef struct {
char* type; /* name of type */
mylock_t lock;
obj_create_fn_t fn_create; /* function to initialize object */
obj_fini_fn_t fn_fini; /* function to finalize obj */
objtype_fini_fn_t fn_type_fini; /* function to finalize typeinfo */
void* typedata; /* extra information for type */
} objtype_t;
typedef struct {
uint32_t magic;
uint32_t nref;
my_rwlock_t rwlock;
mylock_t lock;
objtype_t* type;
int32_t exdata;
uint32_t nread : 28;
uint32_t nwrite : 4;
} myobj_t;
typedef struct {
mylock_t lock;
htab_t names;
zarray_t types;
} objmgr_t;
#define MYOBJ_TO_OBJ(type, myobj) \
((type)(((char*)myobj) + sizeof(myobj_t)))
#define TO_MYOBJ(obj) \
((myobj_t*)(((char*)obj) - sizeof(myobj_t)))
#define DEREF_OBJ(obj) \
if ((obj) != NULL) { \
obj_deref(obj); \
(obj) = NULL; \
}
extern int objmgr_init(objmgr_t*);
extern void objmgr_fini(objmgr_t*);
extern int objmgr_register(objmgr_t*, objtype_t*);
extern int obj_init(objmgr_t*, objtype_t*, int32_t, myobj_t*);
extern void* create_obj_by_typeid(objmgr_t*, int, ...);
extern void* create_obj_by_typename(objmgr_t*, char*, ...);
extern void* obj_ref(void*, int);
extern void obj_deref(void*);
extern int typeid_of_name(objmgr_t*, char*);
extern objmgr_t* objmgr_get_default();
extern int objmgr_set_default(objmgr_t*);
extern myobj_t* obj_alloc(size_t);
#endif

9
src/include/objs.h Normal file
View file

@ -0,0 +1,9 @@
#if !defined(_OBJS_H_)
#define _OBJS_H_ 1
#include "xce/types.h"
job_pidinfo_t *new_job_pidinfo(job_pidinfo_t *);
#endif

82
src/include/request.h Normal file
View file

@ -0,0 +1,82 @@
#if !defined(_REQUEST_H_)
#define _REQUEST_H_ 1
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "netio.h"
#include "typemap.h"
#include "utils.h"
#include "xce/types.h"
typedef struct {
int wait;
} reqbar_t;
typedef struct {
data_item_t link;
endpoint_t* ep;
xce_peerinfo_t* from;
io_packet_t pkt;
struct capn c;
struct Request rq;
uint32_t nrefs;
} ioctx_t;
#define ITPTR_TO_IOCTX(p) \
((ioctx_t*)(((char*)p) - offsetof(ioctx_t, link)))
typedef int (*xce_check_fn_t)(void*);
extern ioctx_t* ioctx_alloc(endpoint_t*, xce_peerinfo_t*);
extern int ioctx_ref(ioctx_t*);
extern void ioctx_deref(ioctx_t*, int);
extern int ioctx_flush(ioctx_t*, int);
extern int ioctx_encode(ioctx_t*, xce_request_t*);
extern int ioctx_decode(ioctx_t*, xce_request_t*);
extern int xce_reply(endpoint_t*, xce_peerinfo_t*, xce_reply_t*);
extern int xce_hello_req(ioctx_t*, char*);
extern int xce_nop_req(ioctx_t*);
extern int xce_shutdown_req(ioctx_t*);
extern void init_reply_by_req(xce_reply_t*, xce_request_t*);
extern int xce_join_req(ioctx_t*, int, hostattrs_t*);
extern int xce_pushconfig_req(endpoint_t*,
xce_peerinfo_t*,
xce_configdata_t*);
extern int xce_push_data_req(endpoint_t*, xce_peerinfo_t*,
xce_data_t*, xce_check_fn_t,
void*, int);
extern int xce_workerlist_req(ioctx_t*, xce_peerinfo_t*);
extern int xce_reply_workerlist(endpoint_t*, uint64_t, int,
xce_peerinfo_t*, xce_workerlist_t*);
extern int xce_jobdispatch_req(ioctx_t*, xce_job_dispatch_t*);
extern int xce_jobsubmit_req(ioctx_t*, xce_job_submit_t*);
extern int xce_reply_jobdispatch(endpoint_t*, uint64_t, int32_t,
xce_peerinfo_t*);
extern int xce_reply_jobid(endpoint_t*, int,
uint64_t, uint64_t,
xce_peerinfo_t*);
extern int xce_joblist_req(ioctx_t*, xce_peerinfo_t*);
extern int xce_reply_joblist(endpoint_t*, uint64_t, int,
xce_peerinfo_t*, xce_job_list_t*);
extern int xce_startjob_req(ioctx_t*, xce_job_exec_t*);
extern int xce_clusterconf_req(ioctx_t*);
extern int xce_reply_clusterconf(endpoint_t*, uint64_t, int,
xce_peerinfo_t*,
xce_clusterconf_t*);
extern int xce_get_req(ioctx_t*, xce_get_t*);
extern int xce_reply_get(endpoint_t*, xce_peerinfo_t*,
xce_reply_t*, xce_check_fn_t,
void*, int);
extern int xce_notify_req(ioctx_t*, xce_notify_data_t*);
extern int extract_data(dataset_t*, xce_data_t*);
extern int xce_update_req(ioctx_t*, xce_update_data_t*);
extern int xce_jobctrl_req(ioctx_t*, xce_jobctrl_t*);
extern int xce_queuectrl_req(ioctx_t*, xce_queuectrl_t*);
extern int xce_runtask_req(ioctx_t* , xce_taskrun_t *) ;
#endif

192
src/include/typemap.h Normal file
View file

@ -0,0 +1,192 @@
#if !defined(_TYPEMAP_H_)
#define _TYPEMAP_H_ 1
#include <stdint.h>
#include "xce/types.h"
typedef struct {
char* resname;
char* hostname;
} xce_reskey_t;
typedef struct {
int type;
union {
uint64_t jobid;
char* wname;
xce_reskey_t* reskey;
} condition;
} xce_match_t;
typedef struct {
int table;
int nrows;
void* rows;
} dataset_t;
typedef struct {
int role;
int data_which;
union {
hostattrs_t* attrs;
} data;
} xce_joindata_t;
typedef struct {
char* clustername;
int n_confvars;
xce_config_t** confvars;
int n_resources;
xce_resource_t** resources;
int n_queues;
xce_queue_t** queues;
int n_ugroups;
xce_group_t** ugroups;
int n_hgroups;
xce_group_t** hgroups;
int nresvals;
xce_val_with_idx_t** resvals;
} xce_conf4sched_t;
typedef struct {
char* clustername;
int n_confvars;
xce_config_t** confvars;
} xce_conf4worker_t;
typedef struct {
int data_which;
union {
xce_conf4sched_t* conf4sched;
xce_conf4worker_t* conf4worker;
} data;
} xce_configdata_t;
typedef struct {
int n_total;
int pos;
int count;
xce_job_t** jobs;
} xce_jobs_data_t;
typedef struct {
int n_total;
int pos;
int count;
xce_worker_t** workers;
} xce_workers_data_t;
typedef struct {
int n_total;
int pos;
int count;
xce_resource_t** resources;
} xce_resource_data_t;
typedef struct {
int n_total;
int pos;
int count;
xce_resval_t** vals;
} xce_resval_data_t;
typedef struct {
int count;
xce_resval_t** vals;
} xce_resval_list_t;
typedef struct {
uint64_t jobid;
int npids;
int* pids;
int npgids;
int* pgids;
int count;
xce_rusage_t** usages;
} xce_job_rusages_t;
typedef struct {
int table;
union {
xce_jobs_data_t* jobs;
xce_workers_data_t* workers;
xce_resource_data_t* resources;
xce_resval_data_t* resvals;
} data;
} xce_data_t;
typedef struct {
int table;
xce_match_t* condition;
} xce_get_t;
typedef struct {
int event;
union {
job_pidinfo_t* pidinfo;
job_failinfo_t* failinfo;
job_failinfo_t* dispatchfail;
xce_jobfinish_t* finishinfo;
uint64_t sched_start_job;
uint64_t sched_exit_job;
uint64_t sched_fail_job;
xce_job_t* sched_update_job;
xce_resval_list_t* sched_update_resvals;
uint64_t stopped_job;
uint64_t resumed_job;
xce_ckptinfo_t* ckptinfo;
xce_queue_t* sched_update_queue;
xce_task_pidinfo_t* taskinfo;
xce_task_failinfo_t* taskfailinfo;
xce_task_finish_t* taskfinish;
uint64_t pdone_job;
} data;
} xce_notify_data_t;
typedef struct {
int table;
union {
xce_resval_list_t* resvals;
xce_job_rusages_t* jobrusages;
} data;
} xce_update_data_t;
typedef struct {
uint64_t seq;
uint32_t opcode;
int32_t status;
int data_which;
union {
char* debugmsg;
uint64_t jobid;
xce_data_t* getdata;
xce_clusterconf_t* clusterconf;
} data;
} xce_reply_t;
typedef struct {
uint32_t opcode;
uint64_t seq;
xce_peerinfo_t* from;
int body_which;
union {
xce_reply_t* replymsg;
char* hellomsg;
xce_joindata_t* joinmsg;
xce_configdata_t* configpushmsg;
xce_data_t* pushmsg;
xce_get_t* getmsg;
dataset_t* datamsg;
xce_job_dispatch_t* dispatchmsg;
xce_job_exec_t* jobstartmsg;
xce_notify_data_t* notifymsg;
xce_job_submit_t* jobsubmsg;
xce_update_data_t* updatemsg;
xce_jobctrl_t* jobctrlmsg;
xce_queuectrl_t* queuectrlmsg;
xce_taskrun_t* runtaskmsg;
} body;
} xce_request_t;
#endif

94
src/include/utils.h Normal file
View file

@ -0,0 +1,94 @@
#if !defined(_UTILS_H_)
#define _UTILS_H_
#include "config.h"
#include <capnp_c.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "controller.capnp.h"
#include "xce/errnox.h"
#include "xce/types.h"
#define xce_use(x) (void)(x)
#define float_near_zero (0.000001)
#define float_equal(a, b) (fabs((a) - (b)) < float_near_zero)
#define STR(x) _STR(x)
#define _STR(x) #x
#define MK_VERSION(ver, commit) ver commit
#ifndef FREEUP
#define FREEUP(p) \
if ((p) != NULL) { \
free(p); \
(p) = NULL; \
}
#endif
#define N_EL_ARRAY(arr) (sizeof(arr) / sizeof(arr[0]))
#define PTR_STEP(p, delta) \
((void*)(((char*)p) + (delta)))
#define N_EL_ARRAY(arr) (sizeof(arr) / sizeof(arr[0]))
#define PTR_STEP(p, delta) \
((void*)(((char*)p) + (delta)))
/* move the owner ship of pointer from src to dst */
#define MOVE_PTR(dst, src) \
do { \
(dst) = (src); \
(src) = NULL; \
} while (0)
#define NULLSTR(p) (((p) == NULL) || (strlen(p) == 0))
#define SET_ERROR(code) \
do { \
set_error((char*)__FILE__, \
(char*)__func__, \
__LINE__, \
(code)); \
} while (0)
#define PERROR(s) xce_perror(s)
typedef struct {
char* file;
char* func;
int line;
int code;
} ectx_t;
#define TRACE(...)
#define WARN(...)
extern capn_text chars_to_text(const char*);
extern int parse_argv(char*, char***);
extern void free_argv(char**, int);
extern void freeup_kvs(int, xce_kv_t*);
extern int mylog_init(char*, char*, char*, int, int);
extern void mylog_fini(void);
extern int mylog_setlevel(char*);
extern void set_error(char*, char*, int, int);
extern ectx_t* get_ectx(void);
extern int xce_vprintf(const char*, va_list);
extern int xce_strerror_r(int, char*, size_t);
extern void xce_perror(const char*);
extern char* frame_symbol(int);
extern int copy_int_list(int**, int*, int);
extern int copy_strlist(xce_strlist_t*, xce_strlist_t);
extern void free_timewindow_config(xce_timewindow_config_t*);
extern xce_timewindow_config_t* dup_timewindow_config(xce_timewindow_config_t*);
extern void free_resource_thresholds(xce_res_threshold_t**, int);
extern xce_res_threshold_t** dup_resource_thresholds(xce_res_threshold_t**, int);
extern void free_resval_with_idx_list(xce_val_with_idx_t***, int);
extern void free_strlist(xce_strlist_t*);
#endif

61
src/include/vtaskmgr.h Normal file
View file

@ -0,0 +1,61 @@
#if !defined(_VTASKMGR_H_)
#define _VTASKMGR_H_ 1
#include <pthread.h>
#include <stddef.h>
#include "dataq.h"
#include "mylock.h"
#include "netio.h"
#include "request.h"
typedef int (*vtask_func_t)(void*);
typedef struct {
void* owner;
ioctx_t ctx;
int vcpu;
vtask_func_t entry;
} vtask_t;
#define ITPTR_TO_VTASK(p) \
((vtask_t*)(((char*)p) - offsetof(ioctx_t, link) - offsetof(vtask_t, ctx)))
typedef enum {
VCPU_IDLE = 0,
VCPU_BUSY,
VCPU_ERR
} vcpu_state_t;
typedef struct {
int cpuid;
vcpu_state_t state;
void* owner;
cbuf_t wbuf;
vtask_t* task;
pthread_t vcpu;
} vcpu_t;
typedef struct {
int n_vcpus;
pthread_t dispatcher;
vcpu_t* vcpus;
cbuf_t wbuf;
cbuf_t wtbuf; /* used to wake up vtaskmgr to check tasks */
dataq_t taskq;
} vtaskmgr_t;
extern vtask_t* vtask_alloc();
extern int vtask_init(vtask_t*, vtask_func_t, endpoint_t*);
extern void vtask_fini(vtask_t*);
extern int vtask_enq(vtaskmgr_t*, vtask_t*);
extern int vtaskmgr_init(vtaskmgr_t*, int);
extern int vtaskmgr_start(vtaskmgr_t*);
extern void vtaskmgr_fini(vtaskmgr_t*);
extern void vtaskmgr_wait(vtaskmgr_t *);
extern void vtaskmgr_wakeup(vtaskmgr_t *);
#endif

View file

@ -0,0 +1,168 @@
#ifndef XCE_CLUSTER_DEF_H
#define XCE_CLUSTER_DEF_H
#include "config.h"
#include <pthread.h>
#include <stdint.h>
#include "hook.h"
#include "htab.h"
#include "kvmgr.h"
#include "myconf.h"
#include "mylock.h"
#include "netio.h"
#include "objmgr.h"
#include "vtaskmgr.h"
#include "xce/types.h"
#include "xlist.h"
#include "zarray.h"
#define N_CONTROLLER_MAX (16)
enum {
XCE_CONTROLLER_HOOK_JOB = 0,
XCE_CONTROLLER_HOOK_WORKER,
XCE_CONTROLLER_HOOK_SCHEDULER,
XCE_CONTROLLER_HOOK_CLUSTER,
XCE_CONTROLLER_HOOK_RESOURCE,
XCE_CONTROLLER_HOOK_CTRL_REQ,
XCE_CONTROLLER_HOOK_QUEUE,
XCE_CONTROLLER_HOOK_USERGROUP,
XCE_CONTROLLER_HOOK_HOSTGROUP,
XCE_CONTROLLER_HOOK_MAX /* keep this as the max */
};
enum {
HOOK_DETAIL_JOB_NEW = 0,
HOOK_DETAIL_JOB_START,
HOOK_DETAIL_JOB_EXIT,
HOOK_DETAIL_JOB_FAIL,
HOOK_DETAIL_JOB_UPDATE,
HOOK_DETAIL_JOB_CKPT,
HOOK_DETAIL_WORKER_JOIN,
HOOK_DETAIL_WORKER_DEAD,
HOOK_DETAIL_WORKER_UPDATE,
HOOK_DETAIL_SCHEDULER_JOIN,
HOOK_DETAIL_SCHEDULER_DEAD,
HOOK_DETAIL_CLUSTER_INIT,
HOOK_DETAIL_DB_INIT,
HOOK_DETAIL_CLUSTER_SHUTDOWN,
HOOK_DETAIL_DB_SHUTDOWN,
HOOK_DETAIL_RESOURCE_UPDATE,
HOOK_DETAIL_RESOURCE_LOC_UPDATE,
HOOK_DETAIL_CTRL_REQ_FINISH,
HOOK_DETAIL_QUEUE_UPDATE,
HOOK_DETAIL_USERGROUP_UPDATE,
HOOK_DETAIL_HOSTGROUP_UPDATE
};
#define XCE_NS_CONFIG (0)
#define XCE_NS_UGROUP (1)
#define XCE_NS_HGROUP (2)
#define XCE_NS_MAX (2)
typedef struct {
int role;
union {
int idx;
} u;
} ep_private_t;
typedef struct {
endpoint_t* ep;
} controller_t;
typedef struct {
} metrics_t;
typedef struct {
xce_queue_t queue;
} queue_t;
typedef struct {
xce_job_t job;
} job_t;
typedef struct {
mylock_t lock;
htab_t htab;
zarray_t jobs;
} jobmgr_t;
typedef struct {
mylock_t lock;
htab_t htab;
int nshared;
int nunshared;
zarray_t defs;
zarray_t sharedinst;
} resmgr_t;
typedef struct {
mylock_t lock;
htab_t htab;
zarray_t workers;
} workermgr_t;
typedef struct {
mylock_t lock;
htab_t htab;
zarray_t queues;
} qmgr_t;
typedef struct {
mylock_t lock;
endpoint_t* ep;
} scheduler_t;
typedef struct {
DBPool* db_pool;
DBHandle* db_handle;
pthread_t fetch_thread;
int64_t fetch_job_pos;
int fetch_job_interval;
int running;
mylock_t db_lock;
} db_ctx_t;
typedef struct {
pthread_t thread;
int runing;
int interval;
} ctrlreq_ctx_t;
typedef struct {
mylock_t lock;
ctrlreq_ctx_t ctrlreq_ctx;
} ctrl_req_mgr_t;
typedef struct {
myconf_t* myconf;
xce_peerinfo_t* myhost;
hooksys_t hooksys;
iomgr_t iomgr;
objmgr_t objmgr;
zarray_t endpoints;
endpoint_t ep;
zarray_t configs;
controller_t controllers[N_CONTROLLER_MAX];
int myidx;
int master;
int ncontrollers;
scheduler_t sched;
jobmgr_t jobmgr;
resmgr_t resmgr;
workermgr_t workermgr;
qmgr_t qmgr;
kvmgr_t configmgr;
kvmgr_t ugmgr;
kvmgr_t hgmgr;
vtaskmgr_t vtaskmgr;
cbuf_t wbuf;
int running;
db_ctx_t dbctx;
ctrl_req_mgr_t ctrl_req_mgr;
} cluster_t;
#endif /* XCE_CLUSTER_DEF_H */

26
src/include/xce/errnox.h Normal file
View file

@ -0,0 +1,26 @@
#if !defined(__XCE_ERRNOX_H__)
#define __XCE_ERRNOX_H__ 1
#include <errno.h>
#include <string.h>
#include <stddef.h>
#define XCE_ERRNO_BASE (10001)
enum {
E_XCE_BAD_JOB = XCE_ERRNO_BASE,
E_XCE_BAD_WORKER,
E_XCE_DUP_JOB,
E_XCE_DUP_WORKER,
E_XCE_BAD_OPCODE,
E_XCE_BAD_ROLE,
E_XCE_BAD_RES,
E_XCE_BAD_QUEUE,
E_XCE_BAD_GROUP,
E_XCE_INTERNAL,
E_XCE_MAX
};
#endif

619
src/include/xce/types.h Normal file
View file

@ -0,0 +1,619 @@
#if !defined(_XCE_TYPES_H_)
#define _XCE_TYPES_H_
#include "config.h"
#include <stdint.h>
#include <time.h>
#include "xlist.h"
#include "zarray.h"
#define XCE_VAL_STRING (0)
#define XCE_VAL_NUMERIC (1)
#define XCE_VAL_BOOLEAN (2)
typedef enum {
XCE_ORD_INCR = 0,
XCE_ORD_DECR,
XCE_ORD_NA
} xce_order_t;
typedef struct {
int which;
union {
int32_t ivalue32;
uint32_t uvalue32;
int64_t ivalue64;
uint64_t uvalue64;
char* svalue;
double fvalue;
int bvalue;
} u;
} xce_val_t;
typedef struct {
int idx;
xce_val_t* val;
} xce_val_with_idx_t;
typedef struct {
char* name;
char* host;
xce_val_t* val;
} xce_resval_t;
typedef struct {
int field;
xce_val_t value;
} xce_kv_t;
typedef struct {
int count;
xce_kv_t* vals;
} xce_kv_list_t;
typedef struct {
int day; /* 1 - 7 (Mon to Sun, 0 unspecified) */
int hour; /* 0 - 23 */
int min; /* 0 - 59 */
} xce_timewindow_time_t;
typedef struct {
char* tz;
xce_timewindow_time_t* open;
xce_timewindow_time_t* close;
} xce_timewindow_seg_config_t;
typedef struct {
int nsegs;
xce_timewindow_seg_config_t** segs;
} xce_timewindow_config_t;
#define XCE_RESF_BUILTIN (0x01)
#define XCE_RESF_DYNAMIC (0x02)
#define XCE_RESF_GLOBAL (0x04)
#define XCE_RESF_SHARED (0x08)
#define XCE_RESF_EXTERNAL (0x10)
#define XCE_RESF_RELEASE (0x20)
#define XCE_RESF_DEFAULT_HOST (0x40)
#define XCE_RESF_CONSUMABLE (0x80)
typedef struct {
int count;
void* data;
} xce_list_t;
typedef struct {
int count;
int* data;
} xce_intlist_t;
typedef struct {
int count;
char** data;
} xce_strlist_t;
typedef struct {
char* name;
char* key;
} xce_peerinfo_t;
typedef struct {
char* name;
char* value;
} xce_config_t;
typedef struct {
int count;
xce_config_t** configs;
} xce_configlist_t;
typedef struct {
char* name;
xce_strlist_t members;
xce_strlist_t ex_members;
} xce_group_t;
typedef struct {
int count;
xce_group_t** groups;
} xce_grouplist_t;
typedef struct {
xce_val_t* value;
int nhosts;
char** hosts;
} res_distribution_t;
typedef struct {
char* name;
char* desc;
int idx;
int valtype;
xce_order_t ordtype;
int flags;
int interval;
time_t last_report;
int ndistributions;
res_distribution_t** distributions;
xce_val_t* hbased_defined;
} xce_resource_t;
typedef struct {
int count;
xce_resource_t** res;
} xce_reslist_t;
typedef struct {
char* name;
double sched;
double stop;
} xce_res_threshold_t;
typedef struct {
char* name;
char* hostmodel;
char* hosttype;
int mxj;
int nresources;
xce_config_t** resources;
int nthresholds;
xce_res_threshold_t** thresholds;
xce_timewindow_config_t* dispatchwindow;
} xce_hostconfig_t;
#define XCE_WORKER_UNAVAIL (0x00010000)
#define XCE_WORKER_LOCKEDU (0x00020000)
#define XCE_WORKER_LOCKEDW (0x00040000)
#define XCE_WORKER_BUSY (0x00080000)
#define XCE_WORKER_CLOSED (0x00100000)
#define IS_WORKER_UNAVAIL(status) \
(((status) & XCE_WORKER_UNAVAIL) != 0)
#define IS_WORKER_LOCKEDU(status) \
(((status) & XCE_WORKER_LOCKEDU) != 0)
#define IS_WORKER_LOCKEDW(status) \
(((status) & XCE_WORKER_LOCKEDW) != 0)
#define IS_WORKER_LOCKED(status) \
(IS_WORKER_LOCKEDU(status) || IS_WORKER_LOCKEDW(status))
#define IS_WORKER_BUSY(status) \
(((status) & XCE_WORKER_BUSY) != 0)
typedef struct {
char* hosttype;
char* hostmodel;
double cpufactor;
int maxcpus;
double maxmem;
double maxswap;
double maxtmp;
int ndisks;
} hostattrs_t;
typedef struct {
uint64_t start;
uint64_t end;
} xce_timerange_t;
typedef struct {
int nsegs;
xce_timerange_t* ranges;
} xce_timewindow_t;
typedef struct {
char* name;
hostattrs_t* attrs;
uint32_t status;
zarray_t resvals;
time_t dead_since;
int64_t pending_ctrl;
xce_timewindow_config_t* dispatch_window_config;
int nthresholds;
xce_res_threshold_t** thresholds;
/* following two vars used to push resource values to sched */
int nresvals_to_sched;
xce_val_with_idx_t** resvals_to_sched;
} xce_worker_t;
typedef struct {
int count;
xce_worker_t** workers;
} xce_workerlist_t;
typedef struct {
char* host;
int nranks;
} xce_host_launch_t;
typedef struct {
int nhosts;
xce_host_launch_t** hosts;
} xce_launch_t;
typedef struct {
char* exechome;
char* execcwd;
char* execuser;
char* cmdline;
char* exdata;
char* launch_type;
char* q_pre_exec;
char* q_post_exec;
char* job_pre_exec;
char* job_post_exec;
} job_startinfo_t;
typedef struct {
uint64_t jobid;
int npids;
unsigned int* pids;
int npgids;
unsigned int* pgids;
char* exdata;
} job_pidinfo_t;
typedef struct {
uint64_t jobid;
uint32_t stage;
int code;
char* detail;
} job_failinfo_t;
typedef struct {
char* resname;
char* reserve;
uint32_t instid;
double value;
uint64_t from;
int64_t duration;
} xce_alloc_t;
typedef struct {
char* host;
int nallocs;
xce_alloc_t** allocs;
} xce_host_alloc_t;
typedef struct {
uint64_t jobid;
int nhosts;
xce_host_alloc_t** allocs;
} xce_job_alloc_t;
typedef struct {
int njobs;
xce_job_alloc_t** allocs;
} xce_job_dispatch_t;
typedef struct {
char* queue;
char* user;
char* cmdline;
char* resreq;
char* exdata;
char* pre_exec;
char* post_exec;
uint32_t mintasks;
uint32_t maxtasks;
} xce_job_submit_t;
typedef struct {
int exitcode;
} job_exitinfo_t;
#define JOB_STAT_NULL 0x00 /**< NULL. */
#define JOB_STAT_PEND 0x01 /**< Job is submitted. */
#define JOB_STAT_RUN 0x02 /**< Job is running. */
#define JOB_STAT_EXIT 0x04 /**< Job is exit. */
#define JOB_STAT_DONE 0x08 /**< Job is done. */
#define JOB_STAT_PSUSP 0x10 /**< Job is pending and suspend*/
#define JOB_STAT_USUSP 0x20 /**< Job is user suspend*/
#define JOB_STAT_SSUSP 0x40 /**< Job is system suspend*/
#define JOB_STAT_PDONE (0x80) /**< Post job process done successfully */
#define JOB_STAT_PERR (0x100) /**< Post job process has error */
#define JOB_STAT_WAIT (0x200) /**< Chunk job waiting its turn to exec */
#define JOB_STAT_RUNKWN 0x8000 /* Flag : Job status is UNKWN caused by losting contact with remote cluster */
#define JOB_STAT_UNKWN 0x10000 /**< The worker on the host on which the \
* job is processed has lost contact with controller */
#define JOB_STAT_PROV (0x20000) /**< this state shows that the job is dispatched to a standby \
* power saved host, and this host is \
* being waken up or started up */
#define JOB_STAT_ERR (0x40000) /**ERROR */
#define JOB_EXEC_STAGE_Q_PRE_EXEC (0)
#define JOB_EXEC_STAGE_PRE_EXEC (1)
#define JOB_EXEC_STAGE_MAIN (2)
#define JOB_EXEC_STAGE_POST_EXEC (3)
#define JOB_EXEC_STAGE_Q_POST_EXEC (4)
#define QUEUE_STAT_OPEN 0x00 /**< OPEN. */
#define QUEUE_STAT_CLOSED 0x01 /**< The queue is closed */
#define QUEUE_STAT_INACT_WINDOW 0x02 /**< The queue inactivated due to dispatch or run windows closed */
#define QUEUE_STAT_INACT_ADMIN 0x04 /**< The queue inactivated by admin */
#define QUEUE_STAT_NOPERM 0x08 /**< Remote queue rejecting jobs. */
#define QUEUE_STAT_DISC 0x10 /**< Remote queue status is disconnected. */
#define QUEUE_STAT_FAIRSHARE_DEFAULT 0x20 /**< Fairshare queue with null user share defined*/
typedef enum {
NORMAL = 0,
TTY,
XJOB,
DISPLAY
} xce_job_type;
typedef struct {
char* host_name;
int num_slots;
} xce_job_host_slots_t;
typedef struct {
int num_hosts;
xce_job_host_slots_t* host_slots;
} xce_job_slots_alloc_t;
typedef struct {
char* host_name;
int cpu_time;
double mem_usage;
} xce_host_runusage_t;
typedef struct {
double max_mem;
double avg_mem;
double used_mem;
int cpu_time;
int peak_cpu_time;
int peak_cpu_duration;
float mem_efficiency;
float avg_cpu_efficiency;
float peak_cpu_efficiency;
int num_hosts;
xce_host_runusage_t** host_runusage;
} xce_job_runusage_t;
typedef struct {
uint64_t jobid;
char* ckptinfo;
} xce_ckptinfo_t;
typedef struct {
uint64_t jobid;
uint64_t array_base_id;
int array_idx;
char* queue;
char* user;
int64_t idx;
time_t sub_time;
time_t queue_time;
time_t start_time;
time_t finish_time;
uint32_t mintasks;
uint32_t maxtasks;
job_pidinfo_t* pidinfo;
job_startinfo_t* start_info;
unsigned int state;
char* job_name;
char* project_name;
char* user_group;
char* job_description;
char* resreq;
xce_job_alloc_t* allocs;
int run_time;
xce_job_runusage_t* run_usage;
job_exitinfo_t* exit_info;
char* ckptinfo;
int64_t pending_ctrl;
} xce_job_t;
typedef struct {
int count;
xce_job_t** data;
} xce_job_list_t;
typedef struct {
uint64_t jobid;
job_startinfo_t* start_info;
xce_launch_t* launchinfo;
} xce_job_exec_t;
typedef struct {
uint64_t jobid;
job_pidinfo_t pidinfo;
} xce_job_runinfo_t;
typedef struct {
uint64_t jobid;
int exit_code;
} xce_jobfinish_t;
typedef struct {
char* queue;
uint32_t attrs;
uint32_t status;
int32_t priority;
int32_t accept_interval;
int32_t sched_delay;
char* resreq;
xce_group_t* users;
xce_group_t* hosts;
int32_t nthresholds;
xce_res_threshold_t** thresholds;
xce_timewindow_t* runwindow;
xce_timewindow_t* dispatchwindow;
xce_timewindow_config_t* runwindow_config;
xce_timewindow_config_t* dispatchwindow_config;
int64_t pending_ctrl;
char* pre_exec;
char* post_exec;
} xce_queue_t;
typedef struct {
int count;
xce_queue_t** queues;
} xce_queuelist_t;
typedef struct {
char* name;
xce_reslist_t reslist;
xce_queuelist_t qlist;
xce_workerlist_t wlist;
xce_grouplist_t uglist;
xce_grouplist_t hglist;
xce_configlist_t cfglist;
} xce_clusterconf_t;
typedef enum {
CONTROL_NONE = 0,
CONTROL_JOB,
CONTROL_HOST,
CONTROL_QUEUE,
CONTROL_CLUSTER,
CONTROL_DEBUG
} ctrl_target_type_t;
typedef enum {
JOB_DO_NONE = 0,
JOB_STOP,
JOB_RESUME,
JOB_KILL,
JOB_MIG,
JOB_REQUEUE,
JOB_MODIFY,
JOB_SWITCH,
JOB_CHKPNT,
JOB_POST,
JOB_READ,
JOB_TOP,
JOB_BOT
} job_ctrl_type_t;
typedef enum {
HOST_DO_NONE = 0,
HOST_OPEN,
HOST_CLOSE,
HOST_TAG,
HOST_UNTAG
} host_ctrl_type_t;
typedef enum {
QUEUE_DO_NONE = 0,
QUEUE_OPEN,
QUEUE_CLOSE,
QUEUE_INACTIVE,
QUEUE_ACTIVE
} queue_ctrl_type_t;
typedef struct {
uint64_t jobid;
int signal;
int forcekill;
char* method;
char* comment;
} job_ctrl_content_t;
typedef struct {
char* hostname;
char* comment;
} host_ctrl_content_t;
typedef struct {
char* queuename;
char* comment;
} queue_ctrl_content_t;
typedef struct {
int64_t id;
int target_type;
int action_type;
time_t request_time;
char* user;
void* content;
} xce_ctrl_req_t;
typedef struct {
int signo;
int force;
} xce_signal_t;
typedef struct {
int kill;
char* method;
} xce_ckpt_options_t;
typedef struct {
int action;
uint64_t jobid;
union {
xce_signal_t* siginfo;
xce_ckpt_options_t* ckptoption;
} u;
} xce_jobctrl_t;
typedef struct {
int action;
char* queue;
} xce_queuectrl_t;
typedef struct {
int action;
char* hostname;
} xce_hostctrl_t;
typedef struct {
char* host;
char* launch_type; /* MPI ranks or something others */
int ntasks;
char* exechome;
char* execcwd;
char* execuser;
char* cmdline;
char* exdata;
} xce_taskhost_t;
typedef struct {
uint64_t jobid;
int nhosts;
int clientidx;
xce_taskhost_t** taskhosts;
} xce_taskrun_t;
typedef struct {
uint64_t jobid;
char* host;
int clientidx;
int taskidx;
int npids;
unsigned int* pids;
int npgids;
unsigned int* pgids;
char* exdata;
} xce_task_pidinfo_t;
typedef struct {
uint64_t jobid;
char* host;
int clientidx;
int taskidx; /* taskidx == -1 for fail of all tasks
* in the same host of xcecli_runtask()
*/
int code;
char* detail;
} xce_task_failinfo_t;
typedef struct {
uint64_t jobid;
char* host;
int taskidx;
int clientidx;
int exit_code;
} xce_task_finish_t;
typedef struct {
char* resname;
float value;
} xce_rusage_t;
#endif

34
src/include/xceapi.h Normal file
View file

@ -0,0 +1,34 @@
#if !defined(_XCEAPI_H_)
#define _XCEAPI_H_ 1
#include "config.h"
#include "xce/types.h"
#include "xcectx.h"
extern int xce_hello(xce_ctx_t*, char*);
extern int xce_shutdown(xce_ctx_t*);
extern int xce_reslist(xce_ctx_t*, xce_resource_t***);
extern int xce_join(xce_ctx_t*, int, hostattrs_t*);
extern int xce_workerlist(xce_ctx_t*, xce_worker_t***);
extern int xce_jobdispatch(xce_ctx_t*, xce_job_dispatch_t*);
extern int xce_jobsubmit(xce_ctx_t*, xce_job_submit_t*,
uint64_t*);
extern int xce_joblist(xce_ctx_t*, xce_job_t***);
extern int xce_clusterconf(xce_ctx_t*, xce_clusterconf_t**);
extern int xce_push(xce_ctx_t*, xce_check_fn_t,
void*, int, int, int, void**);
extern int xce_update_rows(xce_ctx_t*, int, int, xlist_t*);
extern int xce_resval(xce_ctx_t*, char*,
char*, xce_resval_t***);
extern int xce_notify(xce_ctx_t*, xce_notify_data_t*);
extern int xce_update_resvals(xce_ctx_t*, int, xce_resval_t**);
extern int xce_jobctrl(xce_ctx_t*, xce_jobctrl_t*);
extern int xce_queuectrl(xce_ctx_t*, xce_queuectrl_t*);
extern int xce_runtask(xce_ctx_t*, xce_taskrun_t*);
extern int xce_update_jusage(xce_ctx_t*, uint64_t, int,
int*, int, int*, int, xce_rusage_t**);
#endif

52
src/include/xcectx.h Normal file
View file

@ -0,0 +1,52 @@
#if !defined(_XCECTX_H_)
#define _XCECTX_H_ 1
#include "netio.h"
#include "request.h"
#include "vtaskmgr.h"
#include "xce/types.h"
typedef enum {
XCE_CTX_INIT = 0,
XCE_CTX_RUN,
XCE_CTX_DOWN,
XCE_CTX_BUSY,
XCE_CTX_ERR
} xce_ctx_state_t;
typedef int (*xce_request_handler_t)(xce_request_t*);
typedef struct {
xce_ctx_state_t state;
xce_peerinfo_t myinfo;
iomgr_t iomgr;
vtaskmgr_t vtaskmgr;
endpoint_t* ep;
xce_request_handler_t handler;
cbuf_t wbuf;
dataset_t* dataset;
struct {
union {
char* debugmsg;
dataset_t* get;
uint64_t jobid;
xce_clusterconf_t* clusterconf;
} u;
} reply;
} xce_ctx_t;
extern int xce_ctx_init(xce_ctx_t*, char*, char*);
extern void xce_ctx_fini(xce_ctx_t*);
extern int xce_ctx_set_handler(xce_ctx_t*,
xce_request_handler_t);
extern int xce_ctx_start(xce_ctx_t*);
extern int xce_ctx_stop(xce_ctx_t*);
extern int xce_wakeup(xce_ctx_t*, int);
extern int xce_try_wakeup(xce_ctx_t*, int);
extern int xce_ctx_set_endpoint(xce_ctx_t*, endpoint_t*);
extern void xce_block_tasks(xce_ctx_t*);
extern void xce_unblock_tasks(xce_ctx_t*);
#endif

21
src/include/xlist.h Normal file
View file

@ -0,0 +1,21 @@
#if !defined(__XLIST_H__)
#define __XLIST_H__ 1
typedef int (*xlist_iter_fn_t)(void*, void*);
typedef struct {
int count;
int caps;
int delta;
void** data;
} xlist_t;
typedef int (*xlist_action_fn_t)(xlist_t*, void*);
extern int xlist_init(xlist_t*, int);
extern int xlist_store(xlist_t*, void*);
extern void xlist_clear(xlist_t*);
extern int xlist_iter(xlist_t*, xlist_iter_fn_t, void*);
extern void xlist_fini(xlist_t*);
#endif

25
src/include/xstring.h Normal file
View file

@ -0,0 +1,25 @@
#if !defined(__XSTRING_H__)
#define __XSTRING_H__ 1
#include "objmgr.h"
typedef struct {
htab_t tab;
zarray_t strings;
} xstring_typedata_t;
#define XSTRING_OBJ_TYPE_HTAB(obj) \
(((xstring_typedata_t *)obj->type->typedata)->tab)
#define XSTRING_OBJ_TYPE_STRINGS(obj) \
(((xstring_typedata_t *)obj->type->typedata)->strings)
#define XSTRING_TYPE_HTAB(type) \
(((xstring_typedata_t *)type->typedata)->tab)
#define XSTRING_TYPE_STRINGS(type) \
(((xstring_typedata_t *)type->typedata)->strings)
extern int register_xstring(objmgr_t*, int,int);
#endif

32
src/include/zarray.h Normal file
View file

@ -0,0 +1,32 @@
#if !defined(_ZARRAY_H_)
#define _ZARRAY_H_ 1
#include "mylock.h"
#include "xlist.h"
typedef void (*zarray_item_killer_t)(void*);
typedef int (*zarray_iter_fn_t)(void*, void*);
typedef struct {
mylock_t lock;
int count;
int pos;
int caps;
int delta;
zarray_item_killer_t killer;
void** data;
} zarray_t;
extern int zarray_init(zarray_t*, int,
zarray_item_killer_t);
extern int zarray_store(zarray_t*, void*);
extern int zarray_clear(zarray_t*, int);
extern int zarray_iter_ex(zarray_t*, xlist_t*, void*);
extern int zarray_iter(zarray_t*, zarray_iter_fn_t, void*);
extern int zarray_del(zarray_t*, int);
extern int zarray_put(zarray_t*, int, void*);
extern void* zarray_get(zarray_t*, int);
extern void zarray_fini(zarray_t*);
#endif

629
src/lib/client.c Normal file
View file

@ -0,0 +1,629 @@
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/socket.h>
#include "client.h"
#include "controller.capnp.h"
#include "mylock.h"
#include "request.h"
#include "xce/types.h"
#include "xceapi.h"
#include "xcectx.h"
#include "xlist.h"
typedef enum {
API_CTX_INIT = 0,
API_CTX_RUN,
API_CTX_DOWN,
API_CTX_ERR
} api_ctx_state_t;
typedef struct {
xce_client_config_t* conf;
endpoint_t ep;
xce_ctx_t ctx;
} api_ctx_t;
int xcecli_ctx_init(xcecli_ctx_t* c,
xce_client_config_t* cfg)
{
api_ctx_t* ctx;
int rc;
if ((c == NULL) || (cfg == NULL)) {
return -EINVAL;
}
if (cfg->nmasters < 1) {
return -EINVAL;
}
ctx = (api_ctx_t*)calloc(1, sizeof(*ctx));
if (ctx == NULL) {
return -ENOMEM;
}
ctx->conf = cfg;
rc = xce_ctx_init(&(ctx->ctx),
ctx->conf->from,
ctx->conf->key);
if (rc < 0) {
free(ctx);
return rc;
}
endpoint_init(&(ctx->ep), AF_INET,
SOCK_STREAM, 0, 0);
xce_ctx_set_endpoint(&(ctx->ctx), &(ctx->ep));
*c = (void*)ctx;
return 0;
}
void xcecli_ctx_fini(xcecli_ctx_t c)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (ctx == NULL) {
return;
}
xce_ctx_fini(&(ctx->ctx));
endpoint_deref(&(ctx->ep));
free(ctx);
}
int xcecli_set_handler(xcecli_ctx_t c,
xce_request_handler_t handler)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if ((c == NULL) || (handler == NULL)) {
return -EINVAL;
}
return xce_ctx_set_handler(&(ctx->ctx), handler);
}
int xcecli_wakeup(xcecli_ctx_t c,
int status)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
return xce_wakeup(&(ctx->ctx), status);
}
int xcecli_try_wakeup(xcecli_ctx_t c,
int status)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
return xce_try_wakeup(&(ctx->ctx), status);
}
int xcecli_start(xcecli_ctx_t c)
{
int rc;
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
rc = endpoint_connect(&(ctx->ep),
ctx->conf->masters[0],
ctx->conf->master_ports[0]);
if (rc < 0) {
endpoint_deref(&(ctx->ep));
return rc;
}
return xce_ctx_start(&(ctx->ctx));
}
int xcecli_stop(xcecli_ctx_t c)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
xce_ctx_stop(&(ctx->ctx));
endpoint_deref(&(ctx->ep));
return 0;
}
endpoint_t* xcecli_get_my_endpoint(xcecli_ctx_t c)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return NULL;
}
return &(ctx->ep);
}
xce_peerinfo_t* xcecli_get_myinfo(xcecli_ctx_t c)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return NULL;
}
return &(ctx->ctx.myinfo);
}
int xcecli_hello(xcecli_ctx_t c,
char* msg)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
return xce_hello(&(ctx->ctx), msg);
}
int xcecli_shutdown(xcecli_ctx_t c)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
return xce_shutdown(&(ctx->ctx));
}
int xcecli_reslist(xcecli_ctx_t c,
xce_resource_t*** res)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
return xce_reslist(&(ctx->ctx), res);
}
int xcecli_join(xcecli_ctx_t c,
int role,
hostattrs_t* attrs)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (ctx == NULL) {
return -EINVAL;
}
return xce_join(&(ctx->ctx), role, attrs);
}
int xcecli_workerlist(xcecli_ctx_t c,
xce_worker_t*** workers)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (ctx == NULL) {
return -EINVAL;
}
return xce_workerlist(&(ctx->ctx), workers);
}
int xcecli_jobdispatch(xcecli_ctx_t c,
xce_job_dispatch_t* info)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
return xce_jobdispatch(&(ctx->ctx), info);
}
int xcecli_jobsubmit(xcecli_ctx_t c,
xce_job_submit_t* submit,
uint64_t* jobid)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
return xce_jobsubmit(&(ctx->ctx), submit, jobid);
}
int xcecli_joblist(xcecli_ctx_t c,
xce_job_t*** jobs)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
return xce_joblist(&(ctx->ctx), jobs);
}
int xcecli_clusterconf(xcecli_ctx_t c,
xce_clusterconf_t** conf)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
return xce_clusterconf(&(ctx->ctx), conf);
}
int xcecli_notify_jobfinish(xcecli_ctx_t c,
xce_jobfinish_t* jfinish)
{
api_ctx_t* ctx = (api_ctx_t*)c;
/* clang-format off */
xce_notify_data_t data = {
.event = NotifyData_data_jobFinishInfo,
.data = {
.finishinfo = jfinish
}
};
/* clang-format on */
if (c == NULL) {
return -EINVAL;
}
if (jfinish == NULL) {
return -EINVAL;
}
return xcecli_notify(ctx, &data);
}
int xcecli_update_resvals(xcecli_ctx_t c,
int nres,
xce_resval_t** vals)
{
api_ctx_t* ctx = (api_ctx_t*)c;
int rc;
if ((ctx == NULL) || (vals == NULL)) {
return -EINVAL;
}
rc = xce_update_resvals(&(ctx->ctx), nres, vals);
return rc;
}
int xcecli_update_jusage(xcecli_ctx_t c,
uint64_t jobid,
int npids,
int* pids,
int npgids,
int* pgids,
int nusage,
xce_rusage_t** usages)
{
api_ctx_t* ctx = (api_ctx_t*)c;
int rc;
if ((ctx == NULL) || (jobid == 0)) {
return -EINVAL;
}
rc = xce_update_jusage(&(ctx->ctx), jobid,
npids, pids, npgids, pgids,
nusage, usages);
return rc;
}
int xcecli_resval(xcecli_ctx_t c,
char* host,
char* res,
xce_resval_t*** val)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
if (res == NULL) {
return -EINVAL;
}
return xce_resval(&(ctx->ctx), host, res, val);
}
int xcecli_notify(xcecli_ctx_t c,
xce_notify_data_t* data)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return -EINVAL;
}
if (data == NULL) {
return -EINVAL;
}
return xce_notify(&(ctx->ctx), data);
}
int xcecli_notify_jobstart(xcecli_ctx_t c,
job_pidinfo_t* pidinfo)
{
api_ctx_t* ctx = (api_ctx_t*)c;
/* clang-format off */
xce_notify_data_t data = {
.event = NotifyData_data_jobPidInfo,
.data = {
.pidinfo = pidinfo
}
};
/* clang-format on */
if ((c == NULL) || (pidinfo == NULL)) {
return -EINVAL;
}
return xcecli_notify(ctx, &data);
}
int xcecli_notify_jobfail(xcecli_ctx_t c,
job_failinfo_t* failinfo)
{
api_ctx_t* ctx = (api_ctx_t*)c;
/* clang-format off */
xce_notify_data_t data = {
.event = NotifyData_data_jobFailInfo,
.data = {
.failinfo = failinfo
}
};
/* clang-format on */
if ((c == NULL) || (failinfo == NULL)) {
return -EINVAL;
}
return xcecli_notify(ctx, &data);
}
int xcecli_jobctrl(xcecli_ctx_t c,
xce_jobctrl_t* ctrlinfo)
{
api_ctx_t* ctx = (api_ctx_t*)c;
int rc;
if ((ctx == NULL) || (ctrlinfo == NULL)) {
return -EINVAL;
}
rc = xce_jobctrl(&(ctx->ctx), ctrlinfo);
return rc;
}
int xcecli_notify_jobstop(xcecli_ctx_t c,
uint64_t jobid)
{
api_ctx_t* ctx = (api_ctx_t*)c;
/* clang-format off */
xce_notify_data_t data = {
.event = NotifyData_data_stoppedJob,
.data = {
.stopped_job = jobid
}
};
/* clang-format on */
if ((c == NULL) || (jobid == 0)) {
return -EINVAL;
}
return xcecli_notify(ctx, &data);
}
int xcecli_notify_jobresume(xcecli_ctx_t c,
uint64_t jobid)
{
api_ctx_t* ctx = (api_ctx_t*)c;
/* clang-format off */
xce_notify_data_t data = {
.event = NotifyData_data_resumedJob,
.data = {
.resumed_job = jobid
}
};
/* clang-format on */
if ((c == NULL) || (jobid == 0)) {
return -EINVAL;
}
return xcecli_notify(ctx, &data);
}
int xcecli_notify_jobchkpt(xcecli_ctx_t c,
uint64_t jobid,
char* info)
{
api_ctx_t* ctx = (api_ctx_t*)c;
/* clang-format off */
xce_ckptinfo_t ckptinfo = {
.jobid = jobid,
.ckptinfo = info
};
xce_notify_data_t data = {
.event = NotifyData_data_ckptinfo,
.data = {
.ckptinfo = &ckptinfo
}
};
/* clang-format on */
if ((c == NULL) || (jobid == 0) || (info == NULL)) {
return -EINVAL;
}
return xcecli_notify(ctx, &data);
}
int xcecli_notify_jobpostdone(xcecli_ctx_t c,
uint64_t jobid)
{
api_ctx_t* ctx = (api_ctx_t*)c;
/* clang-format off */
xce_notify_data_t data = {
.event = NotifyData_data_postDoneJob,
.data = {
.pdone_job = jobid
}
};
/* clang-format on */
if ((c == NULL) || (jobid == 0)) {
return -EINVAL;
}
return xcecli_notify(ctx, &data);
}
int xcecli_queuectrl(xcecli_ctx_t c,
xce_queuectrl_t* ctrlinfo)
{
api_ctx_t* ctx = (api_ctx_t*)c;
int rc;
if ((ctx == NULL) || (ctrlinfo == NULL)) {
return -EINVAL;
}
rc = xce_queuectrl(&(ctx->ctx), ctrlinfo);
return rc;
}
int xcecli_runtask(xcecli_ctx_t c,
xce_taskrun_t* info)
{
api_ctx_t* ctx = (api_ctx_t*)c;
int rc;
if ((ctx == NULL) || (info == NULL)) {
return -EINVAL;
}
info->clientidx = -1; /* this field will be used by
* controller to trace back
* client
*/
rc = xce_runtask(&(ctx->ctx), info);
return rc;
}
int xcecli_notify_taskstart(xcecli_ctx_t c,
xce_task_pidinfo_t* pidinfo)
{
api_ctx_t* ctx = (api_ctx_t*)c;
/* clang-format off */
xce_notify_data_t data = {
.event = NotifyData_data_taskPidInfo,
.data = {
.taskinfo = pidinfo
}
};
/* clang-format on */
if ((c == NULL) || (pidinfo == NULL)) {
return -EINVAL;
}
return xcecli_notify(ctx, &data);
}
int xcecli_notify_taskfail(xcecli_ctx_t c,
xce_task_failinfo_t* failinfo)
{
api_ctx_t* ctx = (api_ctx_t*)c;
/* clang-format off */
xce_notify_data_t data = {
.event = NotifyData_data_taskFailInfo,
.data = {
.taskfailinfo = failinfo
}
};
/* clang-format on */
if ((c == NULL) || (failinfo == NULL)) {
return -EINVAL;
}
return xcecli_notify(ctx, &data);
}
int xcecli_notify_taskfinish(xcecli_ctx_t c,
xce_task_finish_t* info)
{
api_ctx_t* ctx = (api_ctx_t*)c;
/* clang-format off */
xce_notify_data_t data = {
.event = NotifyData_data_taskFinish,
.data = {
.taskfinish = info
}
};
/* clang-format on */
if ((c == NULL) || (info == NULL)) {
return -EINVAL;
}
return xcecli_notify(ctx, &data);
}
void xcecli_block_tasks(xcecli_ctx_t c)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return;
}
xce_block_tasks(&(ctx->ctx));
}
void xcecli_unblock_tasks(xcecli_ctx_t c)
{
api_ctx_t* ctx = (api_ctx_t*)c;
if (c == NULL) {
return;
}
xce_unblock_tasks(&(ctx->ctx));
}

119
src/lib/dataq.c Normal file
View file

@ -0,0 +1,119 @@
#include <stdlib.h>
#include "dataq.h"
int dataq_init(dataq_t* q,
data_item_killer_t killer)
{
q->head = q->tail = NULL;
q->killer = killer;
mylock_init(&(q->lock));
return 0;
}
static data_item_t* dataq_deq_head(dataq_t* q)
{
if (q->head != NULL) {
data_item_t* b = NULL;
b = q->head;
q->head = b->next;
b->next = NULL;
if (q->head == NULL) {
q->tail = NULL;
}
return b;
}
return NULL;
}
static data_item_t* dataq_deq_first_match(dataq_t* q,
data_item_match_fn_t f)
{
data_item_t* prev = NULL;
data_item_t* curr = q->head;
while (curr != NULL) {
if ((*f)(curr)) { // Found the item to remove
if (prev == NULL) {
// Removing the head item
q->head = curr->next;
if (q->head == NULL) {
// Queue became empty after removing head
q->tail = NULL;
}
// else: tail remains unchanged (it wasn't the head)
} else {
// Removing an item after prev (middle or tail)
prev->next = curr->next;
if (curr == q->tail) { // Check if we are removing the tail
// We removed the tail item, prev is the new tail
q->tail = prev;
}
// else: tail remains unchanged (it was further down the list)
}
curr->next = NULL; // Isolate the removed item
return curr; // Return the removed item
}
// Move to the next item
prev = curr;
curr = curr->next;
}
return NULL;
}
data_item_t* dataq_deq(dataq_t* q,
data_item_match_fn_t f)
{
data_item_t* b = NULL;
mylock_lock(&(q->lock));
if (f == NULL) {
b = dataq_deq_head(q);
} else {
b = dataq_deq_first_match(q, f);
}
mylock_unlock(&(q->lock));
return b;
}
int dataq_enq(dataq_t* q, data_item_t* b)
{
int rc = 0;
b->next = NULL;
mylock_lock(&(q->lock));
if (q->tail != NULL) {
q->tail->next = b;
}
if (q->head == NULL) {
q->head = b;
}
q->tail = b;
mylock_unlock(&(q->lock));
return rc;
}
void dataq_fini(dataq_t* q)
{
data_item_t* it;
while ((it = dataq_deq_head(q)) != NULL) {
if (q->killer != NULL) {
(q->killer)(it);
}
// Note: dataq_deq_head already isolates 'it' (it->next = NULL)
}
q->head = q->tail = NULL; // Explicitly set just in case.
q->killer = NULL;
return;
}

136
src/lib/hook.c Normal file
View file

@ -0,0 +1,136 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "hook.h"
#include "utils.h"
int xce_hook_init(hooksys_t* s,
int maxtypes)
{
int i;
if ((s == NULL) || (maxtypes <= 0)) {
return -EINVAL;
}
s->maxtypes = 0;
s->hooks = (xlist_t*)calloc(maxtypes, sizeof(xlist_t));
if (s->hooks == NULL) {
return -ENOMEM;
}
s->maxtypes = maxtypes;
for (i = 0; i < s->maxtypes; i++) {
xlist_init(&(s->hooks[i]), 8);
}
return 0;
}
int xce_add_hook(hooksys_t* s,
int typ,
hook_fn_t fn,
void* data)
{
hook_item_t* it;
if (s == NULL) {
return -EINVAL;
}
if (fn == NULL) {
return -EINVAL;
}
if ((typ < 0) || (typ >= s->maxtypes)) {
return -EINVAL;
}
it = (hook_item_t*)calloc(1, sizeof(*it));
if (it == NULL) {
return -ENOMEM;
}
it->fn = fn;
it->data = data;
xlist_store(&(s->hooks[typ]), it);
return 0;
}
/* HOOK_BEFORE_EVENT returns
* negative value will cause
* fail
*/
int xce_run_hooks(hooksys_t* s,
int type,
int situation,
int detail,
...)
{
xlist_t* l;
int i;
int rc = 0;
if (s == NULL) {
return -EINVAL;
}
if ((type < 0) || (type >= s->maxtypes)) {
return -EINVAL;
}
l = &(s->hooks[type]);
for (i = 0; i < l->count; i++) {
hook_item_t* it = l->data[i];
va_list ap;
if (it == NULL) {
continue;
}
va_start(ap, detail);
rc = (*(it->fn))(type, situation, detail,
it->data, ap);
va_end(ap);
if ((situation == HOOK_BEFORE_EVENT) && (rc < 0)) {
break;
}
}
return rc;
}
static int free_hook_item(void *data1,
void *data2) {
if (data1 == NULL) {
return -EINVAL;
}
free(data1);
return 0;
}
void xce_hook_fini(hooksys_t* s)
{
int i;
if (s == NULL) {
return;
}
if (s->hooks == NULL) {
return;
}
for (i = 0; i < s->maxtypes; i++) {
xlist_iter(&(s->hooks[i]),
(xlist_iter_fn_t)free_hook_item,
NULL);
xlist_fini(&(s->hooks[i]));
}
FREEUP(s->hooks);
}

215
src/lib/htab.c Normal file
View file

@ -0,0 +1,215 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "htab.h"
#include "utils.h"
#define HASH_KEY_HASH(t, key) \
(((t)->fn.hash != NULL) ? ((t)->fn.hash)(key) : (unsigned long)key)
#define HASH_KEY_CMP(t, k1, k2) \
(((t)->fn.cmp != NULL) ? ((t)->fn.cmp)((k1), (k2)) : ((k1) != (k2)))
#define HASH_KEY_COPY(t, key) \
(((t)->fn.copy != NULL) ? ((t)->fn.copy)(key) : (key))
#define HASH_KEY_FREE(t, key) \
do { \
if (((t)->fn.free != NULL) && ((key) != NULL)) { \
(t)->fn.free(key); \
} \
} while (0)
static unsigned int hash_code(const char* key)
{
unsigned int hc = 5381;
int c;
while ((c = *key++)) {
hc = ((hc << 5) + hc) + c;
}
return hc;
}
static unsigned int string_hash(void* data)
{
return hash_code((const char*)data);
}
static int string_cmp(void* d1,
void* d2)
{
return (int)strcmp((char*)d1, (char*)d2);
}
static void* string_dup(void* data)
{
return (void*)strdup((char*)data);
}
static void string_free(void* data)
{
if (data != NULL) {
free(data);
}
}
hash_key_fn_t string_hash_key = {
.hash = (hash_key_hash_fn_t)string_hash,
.cmp = (hash_key_cmp_fn_t)string_cmp,
.copy = (hash_key_copy_fn_t)string_dup,
.free = (hash_key_free_fn_t)string_free
};
hash_key_fn_t int_hash_key = {
.hash = NULL,
.cmp = NULL,
.copy = NULL,
.free = NULL
};
int ht_init(htab_t* t,
int nslots,
hash_key_fn_t fn)
{
if ((t == NULL) || (nslots <= 1)) {
return -EINVAL;
}
mylock_init(&(t->lock));
t->slots = (hent_t**)calloc(nslots, sizeof(hent_t*));
if (t->slots == NULL) {
return -ENOMEM;
}
t->nslots = nslots;
t->fn = fn;
return 0;
}
void ht_fini(htab_t* t)
{
int i;
hent_t* e;
if (t == NULL) {
return;
}
for (i = 0; i < t->nslots; i++) {
while ((e = t->slots[i]) != NULL) {
t->slots[i] = e->next;
e->next = NULL;
HASH_KEY_FREE(t, e->key);
free(e);
}
}
free(t->slots);
return;
}
hent_t* ht_get(htab_t* t,
void* key)
{
unsigned int hc;
hent_t* e;
if (t == NULL) {
SET_ERROR(EINVAL);
return NULL;
}
hc = HASH_KEY_HASH(t, key) % (t->nslots);
mylock_lock(&(t->lock));
e = t->slots[hc];
while (e != NULL) {
if (HASH_KEY_CMP(t, e->key, key) == 0) {
break;
}
e = e->next;
}
mylock_unlock(&(t->lock));
return e;
}
hent_t* ht_add(htab_t* t,
void* key)
{
unsigned int hc;
hent_t* e;
if ((t == NULL) || (key == NULL)) {
return NULL;
}
e = ht_get(t, key);
if (e != NULL) {
return e;
}
e = (hent_t*)calloc(1, sizeof(*e));
if (e == NULL) {
return NULL;
}
e->key = HASH_KEY_COPY(t, key);
if (e->key == NULL) {
free(e);
return NULL;
}
e->data = -1;
hc = HASH_KEY_HASH(t, key) % (t->nslots);
mylock_init(&(t->lock));
e->next = t->slots[hc];
t->slots[hc] = e;
mylock_unlock(&(t->lock));
return e;
}
int ht_del(htab_t* t,
void* key)
{
unsigned int hc;
hent_t** e;
int deleted = 0;
if ((t == NULL) || (key == NULL)) {
return -EINVAL;
}
hc = HASH_KEY_HASH(t, key) % (t->nslots);
mylock_init(&(t->lock));
e = &(t->slots[hc]);
while ((*e) != NULL) {
if (HASH_KEY_CMP(t, (*e)->key, key) == 0) {
hent_t* e1 = *e;
*e = e1->next;
HASH_KEY_FREE(t, e1->key);
free(e1);
deleted = 1;
break;
}
e = &((*e)->next);
}
mylock_unlock(&(t->lock));
if (deleted) {
return 1;
}
return -ENOENT;
}

211
src/lib/kvmgr.c Normal file
View file

@ -0,0 +1,211 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "htab.h"
#include "kvmgr.h"
#include "objmgr.h"
#include "utils.h"
#include "xce/types.h"
#include "zarray.h"
int kvmgr_init(kvmgr_t* mgr,
hash_key_fn_t keyfn,
int nslots,
int delta,
zarray_item_killer_t killer)
{
ht_init(&(mgr->htab), nslots, keyfn);
zarray_init(&(mgr->data), delta, killer);
mylock_init(&(mgr->lock));
return 0;
}
void kvmgr_fini(kvmgr_t* mgr)
{
ht_fini(&(mgr->htab));
zarray_fini(&(mgr->data));
mylock_fini(&(mgr->lock));
}
static void* kvmgr_lock_(kvmgr_t* mgr,
void* key,
int op)
{
hent_t* e = NULL;
int32_t idx;
void* ptr;
e = ht_get(&(mgr->htab), key);
if (e == NULL) {
SET_ERROR(ENOENT);
return NULL;
}
idx = e->data;
if (idx < 0) {
SET_ERROR(ENOENT);
return NULL;
}
ptr = (void*)zarray_get(&(mgr->data), idx);
return obj_ref(ptr, op);
}
void* kvmgr_lock(kvmgr_t* mgr,
void* key,
int op)
{
void* ptr = NULL;
if (mgr == NULL) {
SET_ERROR(EINVAL);
return NULL;
}
/* clang-format off */
if ((op != OBJREF_NOP) &&
(op != OBJREF_READ) &&
(op != OBJREF_UPDATE)) {
SET_ERROR(EINVAL);
return NULL;
}
/* clang-format on */
mylock_lock(&(mgr->lock));
ptr = kvmgr_lock_(mgr, key, op);
mylock_unlock(&(mgr->lock));
return ptr;
}
static int32_t kvmgr_add_(kvmgr_t* mgr,
void* key,
void* p)
{
hent_t* e = NULL;
int idx;
e = ht_get(&(mgr->htab), key);
if (e != NULL) {
return -EEXIST;
}
idx = zarray_store(&(mgr->data), p);
if (idx < 0) {
return idx;
}
e = ht_add(&(mgr->htab),
(void*)key);
if (e == NULL) {
zarray_del(&(mgr->data), idx);
return -errno;
}
e->data = idx;
return idx;
}
int32_t kvmgr_add(kvmgr_t* mgr,
void* key,
void* p)
{
int32_t idx;
if ((mgr == NULL) || (p == NULL)) {
return -EINVAL;
}
mylock_lock(&(mgr->lock));
idx = kvmgr_add_(mgr, key, p);
mylock_unlock(&(mgr->lock));
return idx;
}
static void kvmgr_del_(kvmgr_t* mgr,
void* key)
{
hent_t* e = NULL;
int idx;
e = ht_get(&(mgr->htab), key);
if (e == NULL) {
return;
}
idx = e->data;
if (idx < 0) {
return;
}
zarray_del(&(mgr->data), idx);
return;
}
void kvmgr_del(kvmgr_t* mgr,
void* key)
{
if (mgr == NULL) {
return;
}
mylock_lock(&(mgr->lock));
kvmgr_del_(mgr, key);
mylock_unlock(&(mgr->lock));
}
static int add_config_(xlist_t* l, void* data)
{
xce_config_t* config;
if (data == NULL) {
return -EINVAL;
}
config = (xce_config_t*)obj_ref(data, OBJREF_READ);
return xlist_store(l, config);
}
int kvmgr_publish(kvmgr_t* mgr,
xlist_action_fn_t fn,
void* arg)
{
xlist_t l;
int rc = 0;
int i;
xlist_init(&l, 128);
mylock_lock(&(mgr->lock));
zarray_iter(&(mgr->data),
(zarray_iter_fn_t)add_config_,
&l);
mylock_unlock(&(mgr->lock));
rc = (*fn)(&l, arg);
for (i = 0; i < l.count; i++) {
xce_config_t* config = l.data[i];
DEREF_OBJ(config);
}
xlist_fini(&l);
return rc;
}
int kvmgr_iter(kvmgr_t* mgr,
xlist_t* l,
void* arg)
{
int rc = 0;
mylock_lock(&(mgr->lock));
rc = zarray_iter_ex(&(mgr->data), l, arg);
mylock_unlock(&(mgr->lock));
return rc;
}

69
src/lib/meson.build Normal file
View file

@ -0,0 +1,69 @@
capnp = find_program('capnp')
gen_srcs = custom_target(
'controllercapnp.[ch]',
output:['controller.capnp.c', 'controller.capnp.h'],
input: '../schema/controller.capnp',
command: [capnp, 'compile','-o' ,'c:lib', '-I', '../schema','--src-prefix', '../schema', '@INPUT@']
)
libxce_src = [ gen_srcs[0],
'client.c',
'dataq.c',
'hook.c',
'htab.c',
'kvmgr.c',
'mylock.c',
'netio.c',
'objmgr.c',
'request.c',
'threshold.c',
'utils.c',
'vtaskmgr.c',
'window.c',
'xceapi.c',
'xcectx.c',
'xlist.c',
'xstring.c',
'zarray.c'
]
incdir = include_directories('../include')
build_inc = include_directories('.')
capnpc_c_prog = find_program('capnpc-c')
# debug('capnpc_c_prog %s\n', capnpc_c_prog)
thread_dep = dependency('threads')
c_capnproto_dep = dependency('c-capnproto')
zlog_dep = dependency('zlog')
unity_dep = dependency('unity')
libxce_deps = [c_capnproto_dep, zlog_dep, thread_dep]
libxce = static_library('xce',
libxce_src,
include_directories: [incdir, build_inc],
dependencies: libxce_deps,
install: true)
libxce_dep = declare_dependency(link_with: libxce)
libxce_test_src = ['testsuite/test.c',
'testsuite/test_error.c',
'testsuite/test_htab.c',
'testsuite/test_htab_int.c',
'testsuite/test_utils.c',
'testsuite/test_xstring.c',
'testsuite/test_zarray.c'
]
libxce_test_deps = [libxce_deps, unity_dep, libxce_dep]
libxce_test = executable('xcelib_test',
libxce_test_src,
include_directories: [incdir, build_inc],
dependencies: libxce_test_deps,
install: true)
test('libxce test', libxce_test)

212
src/lib/mylock.c Normal file
View file

@ -0,0 +1,212 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "mylock.h"
int mylock_init(mylock_t* l)
{
if (l == NULL) {
return -EINVAL;
}
return pthread_mutex_init(l, NULL);
}
void mylock_fini(mylock_t* l)
{
if (l == NULL) {
return;
}
pthread_mutex_destroy(l);
}
int mylock_try(mylock_t* l)
{
if (l == NULL) {
return -EINVAL;
}
return pthread_mutex_trylock(l);
}
int mylock_lock(mylock_t* l)
{
if (l == NULL) {
return -EINVAL;
}
return pthread_mutex_lock(l);
}
int mylock_unlock(mylock_t* l)
{
if (l == NULL) {
return -EINVAL;
}
return pthread_mutex_unlock(l);
}
int cbuf_init(cbuf_t* b,
int cap,
int isize)
{
if ((b == NULL) || (cap <= 0) || (isize <= 0)) {
return -EINVAL;
}
b->ncap = cap;
b->isize = isize;
b->data = (void*)calloc(cap, isize);
if (b->data == NULL) {
return -EINVAL;
}
b->head = 0;
b->len = 0;
pthread_mutex_init(&(b->mutex), NULL);
pthread_cond_init(&(b->condget), NULL);
pthread_cond_init(&(b->condput), NULL);
return 0;
}
void cbuf_fini(cbuf_t* b)
{
if (b == NULL) {
return;
}
if (b->data != NULL) {
free(b->data);
b->data = NULL;
}
pthread_mutex_destroy(&(b->mutex));
pthread_cond_destroy(&(b->condput));
pthread_cond_destroy(&(b->condget));
}
int cbuf_put(cbuf_t* b,
void* it)
{
int i;
if ((b == NULL) || (it == NULL)) {
return -EINVAL;
}
pthread_mutex_lock(&(b->mutex));
while (b->len == b->ncap) {
pthread_cond_wait(&(b->condput),
&(b->mutex));
}
i = (b->head + b->len) % b->ncap;
memcpy((void*)((char*)b->data) + b->isize * i,
it, b->isize);
b->len++;
pthread_cond_signal(&(b->condget));
pthread_mutex_unlock(&(b->mutex));
return 0;
}
int cbuf_tryput(cbuf_t* b,
void* it)
{
int i;
int rc = 0;
if ((b == NULL) || (it == NULL)) {
return -EINVAL;
}
pthread_mutex_lock(&(b->mutex));
if (b->len < b->ncap) {
i = (b->head + b->len) % b->ncap;
memcpy((void*)((char*)b->data) + b->isize * i,
it, b->isize);
b->len++;
pthread_cond_signal(&(b->condget));
} else {
rc = -EAGAIN;
}
pthread_mutex_unlock(&(b->mutex));
return rc;
}
int cbuf_get(cbuf_t* b,
void* it)
{
if ((b == NULL) || (it == NULL)) {
return -EINVAL;
}
pthread_mutex_lock(&(b->mutex));
while (b->len == 0) {
pthread_cond_wait(&(b->condget),
&(b->mutex));
}
memcpy(it, (void*)((char*)b->data) + b->isize * b->head,
b->isize);
b->head = (b->head + 1) % b->ncap;
b->len--;
pthread_cond_signal(&(b->condput));
pthread_mutex_unlock(&(b->mutex));
return 0;
}
int my_rwlock_init(my_rwlock_t *l) {
if ( l == NULL) {
return -EINVAL;
}
return pthread_rwlock_init(l, NULL);
}
void my_rwlock_fini(my_rwlock_t *l) {
if (l == NULL) {
return;
}
pthread_rwlock_destroy(l);
}
int my_rwlock_unlock(my_rwlock_t *l) {
if (l == NULL) {
return -EINVAL;
}
return pthread_rwlock_unlock(l);
}
int my_rwlock_rlock(my_rwlock_t *l) {
if (l == NULL) {
return -EINVAL;
}
return pthread_rwlock_rdlock(l);
}
int my_rwlock_wlock(my_rwlock_t *l) {
if (l==NULL) {
return -EINVAL;
}
return pthread_rwlock_wrlock(l);
}

687
src/lib/netio.c Normal file
View file

@ -0,0 +1,687 @@
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <unistd.h>
#include "dataq.h"
#include "netio.h"
#include "request.h"
#include "utils.h"
static int iomgr_update_poll(iomgr_t*, endpoint_t*, int);
static void endpoint_fini(endpoint_t*);
static int socket_create(int domain,
int type,
int port,
int backlog)
{
int sock;
int opt = 1;
if ((domain < 0) || (type < 0)) {
return -EINVAL;
}
sock = socket(domain, type, 0);
if (sock < 0) {
SET_ERROR(errno);
return -errno;
}
fcntl(sock, F_SETFD, (fcntl(sock, F_GETFD) | FD_CLOEXEC));
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
close(sock);
return -1;
}
if (port > 0) {
struct sockaddr_in sin;
memset((char*)&sin, 0, sizeof(sin));
sin.sin_family = domain;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
int rc;
SET_ERROR(errno);
rc = -errno;
(void)close(sock);
return rc;
}
if (backlog > 0) {
if (listen(sock, backlog) < 0) {
int rc;
SET_ERROR(errno);
rc = -errno;
(void)close(sock);
return rc;
}
}
}
return sock;
}
static int socket_connect(int sock,
char* host,
int port)
{
struct sockaddr_in server;
struct hostent* hp;
int rc;
server.sin_family = AF_INET;
hp = gethostbyname(host);
if (hp == NULL) {
SET_ERROR(errno);
rc = -errno;
return rc;
}
memcpy((char*)&server.sin_addr, (char*)hp->h_addr, (int)hp->h_length);
server.sin_port = htons(port);
rc = connect(sock, (struct sockaddr*)&server, sizeof(server));
if (rc < 0) {
SET_ERROR(errno);
return -errno;
}
return rc;
}
static int socket_accept(int sock)
{
socklen_t len;
int s;
struct sockaddr_in from;
len = sizeof(from);
s = accept(sock, (struct sockaddr*)&from, &len);
if (s < 0) {
SET_ERROR(errno);
return -errno;
}
fcntl(s, F_SETFD, (fcntl(s, F_GETFD) | FD_CLOEXEC));
return s;
}
int netio_write(int fd,
char* data,
int sz)
{
int nc = 0;
while (sz > 0) {
int rc;
rc = write(fd, data + nc, sz);
if (rc < 0) {
SET_ERROR(errno);
return -errno;
}
sz -= rc;
nc += rc;
}
return nc;
}
int netio_read(int fd,
char* data,
int sz)
{
int nc = 0;
while (sz > 0) {
int rc;
rc = read(fd, data + nc, sz);
if (rc < 0) {
SET_ERROR(errno);
return -errno;
}
if (rc == 0) {
/* network read return 0, it seems remote
* size has tear down the connection
*/
return -EPIPE;
}
sz -= rc;
nc += rc;
}
return nc;
}
int write_packet(int fd,
io_packet_t* pkt)
{
int rc;
rc = netio_write(fd, (char*)&(pkt->sz),
sizeof(pkt->sz));
if (rc < 0) {
return -errno;
}
rc = netio_write(fd, pkt->data, pkt->sz);
if (rc < 0) {
return -errno;
}
return rc;
}
int alloc_packet(io_packet_t* pkt)
{
if (pkt->sz <= 0) {
SET_ERROR(EINVAL);
return -EINVAL;
}
pkt->data = (char*)malloc(pkt->sz);
if (pkt->data == NULL) {
SET_ERROR(ENOMEM);
return -ENOMEM;
}
return 1;
}
int read_packet(int fd,
io_packet_t* pkt)
{
int rc;
rc = netio_read(fd, (char*)&(pkt->sz),
sizeof(pkt->sz));
if (rc < 0) {
return rc;
}
rc = alloc_packet(pkt);
if (rc < 0) {
return rc;
}
rc = netio_read(fd, pkt->data, pkt->sz);
if (rc < 0) {
free_packet(pkt);
}
return rc;
}
void free_packet(io_packet_t* pkt)
{
if (pkt->data != NULL) {
free(pkt->data);
pkt->data = NULL;
}
}
#define MAX_EPOLL_EVENTS (5)
static void* io_worker(void* args)
{
iomgr_t* iomgr = (iomgr_t*)args;
while (1) {
int nfds = -1;
int i;
struct epoll_event events[MAX_EPOLL_EVENTS];
nfds = epoll_wait(iomgr->epoll_fd, events,
MAX_EPOLL_EVENTS, -1);
if (nfds == -1) {
if (errno == EINTR) {
continue;
}
perror("epoll");
return NULL;
}
for (i = 0; i < nfds; i++) {
endpoint_t* p = (endpoint_t*)events[i].data.ptr;
if (p->handler != NULL) {
(p->handler)(&events[i]);
}
}
pthread_testcancel();
}
return NULL;
}
static int endpoint_calc_flags(endpoint_t* ep)
{
int flags = EPOLLIN;
if (ep->outq.head != NULL) {
flags = flags | EPOLLOUT;
}
return flags;
}
endpoint_t* endpoint_get()
{
endpoint_t* ep;
ep = (endpoint_t*)calloc(1, sizeof(*ep));
if (ep == NULL) {
SET_ERROR(errno);
return ep;
}
ep->fd = -1;
ep->idx = -1;
ep->iomgr = NULL;
ep->busy = 0;
ep->needfree = 1;
mylock_init(&(ep->lock));
return endpoint_ref(ep);
}
static void outq_item_killer(data_item_t* it)
{
if (it != NULL) {
ioctx_t* ctx = ITPTR_TO_IOCTX(it);
ioctx_deref(ctx, 1);
}
}
int endpoint_init(endpoint_t* ep,
int domain,
int type,
int port,
int backlog)
{
int fd = -1;
if (ep == NULL) {
SET_ERROR(EINVAL);
return -EINVAL;
}
fd = socket_create(domain, type,
port, backlog);
if (fd < 0) {
return -errno;
}
ep->flags = 0;
ep->fd = fd;
ep->owner = NULL;
ep->data = NULL;
ep->iomgr = NULL;
ep->busy = 0;
ep->needfree = 0;
dataq_init(&(ep->outq),
outq_item_killer);
mylock_init(&(ep->lock));
endpoint_ref(ep);
return fd;
}
int endpoint_connect(endpoint_t* ep,
char* host,
int port)
{
int rc = -1;
rc = socket_connect(ep->fd, host, port);
if (rc < 0) {
return rc;
}
ep->flags = 0;
return rc;
}
int endpoint_accept(endpoint_t* ep,
endpoint_t* ep2)
{
int sock = -1;
sock = socket_accept(ep->fd);
if (sock < 0) {
return sock;
}
ep2->fd = sock;
ep2->flags = 0;
return sock;
}
int endpoint_set_handler(endpoint_t* ep,
msghandler_t h,
void* owner)
{
if (ep->fd < 0) {
SET_ERROR(EINVAL);
return -EINVAL;
}
mylock_lock(&(ep->lock));
ep->handler = h;
ep->owner = owner;
mylock_unlock(&(ep->lock));
return 1;
}
int endpoint_enq(endpoint_t* ep,
data_item_t* it)
{
int rc = 0;
int flags;
if ((ep == NULL) || (it == NULL)) {
SET_ERROR(EINVAL);
return -EINVAL;
}
mylock_lock(&(ep->lock));
rc = dataq_enq(&(ep->outq), it);
flags = endpoint_calc_flags(ep);
if (flags != ep->flags) {
if (ep->iomgr != NULL) {
int rc1;
mylock_lock(&(ep->iomgr->lock));
rc1 = iomgr_update_poll(ep->iomgr,
ep, flags);
mylock_unlock(&(ep->iomgr->lock));
if (rc1 >= 0) {
ep->flags = flags;
} else {
WARN("rc1=%d < 0", rc1);
}
}
}
mylock_unlock(&(ep->lock));
return rc;
}
data_item_t* endpoint_deq(endpoint_t* ep)
{
data_item_t* it = NULL;
int flags;
if (ep == NULL) {
SET_ERROR(EINVAL);
return NULL;
}
mylock_lock(&(ep->lock));
it = dataq_deq(&(ep->outq), NULL);
flags = endpoint_calc_flags(ep);
if (flags != ep->flags) {
if (ep->iomgr != NULL) {
int rc;
mylock_lock(&(ep->iomgr->lock));
rc = iomgr_update_poll(ep->iomgr,
ep, flags);
mylock_unlock(&(ep->iomgr->lock));
if (rc >= 0) {
ep->flags = flags;
}
}
}
mylock_unlock(&(ep->lock));
return it;
}
endpoint_t* endpoint_ref(endpoint_t* ep)
{
mylock_lock(&(ep->lock));
ep->refcount++;
mylock_unlock(&(ep->lock));
return ep;
}
void endpoint_deref(endpoint_t* ep)
{
uint32_t refcount;
mylock_lock(&(ep->lock));
ep->refcount--;
refcount = ep->refcount;
mylock_unlock(&(ep->lock));
if (refcount == 0) {
endpoint_fini(ep);
}
}
uint64_t endpoint_getseq(endpoint_t* ep)
{
uint64_t seq;
mylock_lock(&(ep->lock));
seq = ep->seq++;
mylock_unlock(&(ep->lock));
return seq;
}
void endpoint_block_tasks(endpoint_t* ep)
{
TRACE("%s[%ld] block tasks for endpoint %p",
__func__, pthread_self(), ep);
mylock_lock(&(ep->lock));
ep->busy = 1;
mylock_unlock(&(ep->lock));
}
void endpoint_unblock_tasks(endpoint_t* ep)
{
TRACE("%s[%ld] unblock tasks for endpoint %p",
__func__, pthread_self(), ep);
mylock_lock(&(ep->lock));
ep->busy = 0;
mylock_unlock(&(ep->lock));
}
int endpoint_is_task_blocked(endpoint_t* ep)
{
int busy;
mylock_lock(&(ep->lock));
busy = ep->busy;
mylock_unlock(&(ep->lock));
TRACE("%s[%ld] endpoint %p task %s",
__func__, pthread_self(),
ep, (busy != 0) ? "blocked" : "not blocked");
return (busy != 0);
}
static void endpoint_fini(endpoint_t* ep)
{
int needfree = ep->needfree;
dataq_fini(&(ep->outq));
FREEUP(ep->data);
if (ep->fd >= 0) {
close(ep->fd);
}
ep->flags = 0;
ep->handler = NULL;
ep->owner = NULL;
if (needfree) {
FREEUP(ep);
}
}
int iomgr_init(iomgr_t* iomgr)
{
mylock_init(&(iomgr->lock));
iomgr->epoll_fd = epoll_create1(0);
if (iomgr->epoll_fd < 0) {
SET_ERROR(errno);
return -errno;
}
return 0;
}
static int iomgr_update_poll(iomgr_t* iomgr,
endpoint_t* ep,
int flags)
{
struct epoll_event ev;
ev.events = flags;
ev.data.ptr = ep;
return epoll_ctl(iomgr->epoll_fd,
EPOLL_CTL_MOD,
ep->fd, &ev);
}
int iomgr_monitor(iomgr_t* iomgr,
endpoint_t* ep)
{
struct epoll_event ev;
int rc;
int flags;
flags = EPOLLIN;
ev.events = flags;
ev.data.ptr = ep;
mylock_lock(&(ep->lock));
ep->iomgr = iomgr;
mylock_lock(&(iomgr->lock));
rc = epoll_ctl(iomgr->epoll_fd, EPOLL_CTL_ADD,
ep->fd, &ev);
mylock_unlock(&(iomgr->lock));
if (rc >= 0) {
ep->flags = flags;
}
mylock_unlock(&(ep->lock));
return rc;
}
int iomgr_unmonitor(iomgr_t* iomgr,
endpoint_t* ep)
{
int rc;
mylock_lock(&(iomgr->lock));
rc = epoll_ctl(iomgr->epoll_fd, EPOLL_CTL_DEL,
ep->fd, NULL);
if (rc < 0) {
SET_ERROR(errno);
rc = -errno;
}
mylock_unlock(&(iomgr->lock));
return rc;
}
int iomgr_start(iomgr_t* iomgr)
{
int rc;
rc = pthread_create(&(iomgr->worker), NULL, &io_worker, iomgr);
return rc;
}
int iomgr_fini(iomgr_t* iomgr)
{
return 0;
}
int iomgr_stop(iomgr_t* iomgr)
{
int rc;
void* res;
if (iomgr->worker == 0) {
return 0;
}
rc = pthread_cancel(iomgr->worker);
if (rc != 0) {
SET_ERROR(errno);
return -errno;
}
rc = pthread_join(iomgr->worker, &res);
if (rc != 0) {
SET_ERROR(errno);
return -errno;
}
if (res == PTHREAD_CANCELED) {
iomgr->worker = 0;
return 0;
}
return -1;
}

322
src/lib/objmgr.c Normal file
View file

@ -0,0 +1,322 @@
#include <errno.h>
#include <stdlib.h>
#include "htab.h"
#include "objmgr.h"
#include "utils.h"
#include "zarray.h"
static objmgr_t* objmgr_default = NULL;
static void objtype_killer(objtype_t* typeval)
{
if (typeval == NULL) {
return;
}
if (typeval->fn_type_fini == NULL) {
return;
}
typeval->fn_type_fini(typeval);
}
int objmgr_init(objmgr_t* mgr)
{
if (mgr == NULL) {
return -EINVAL;
}
mylock_init(&(mgr->lock));
ht_init(&(mgr->names), 32,
string_hash_key);
zarray_init(&(mgr->types), 32,
(zarray_item_killer_t)objtype_killer);
return 0;
}
void objmgr_fini(objmgr_t* mgr)
{
if (mgr == NULL) {
return;
}
zarray_fini(&(mgr->types));
ht_fini(&(mgr->names));
mylock_fini(&(mgr->lock));
}
static int objmgr_register_internal(objmgr_t* mgr,
objtype_t* type)
{
hent_t* e = NULL;
int idx;
e = ht_get(&(mgr->names), (void*)type->type);
if (e != NULL) {
return e->data;
}
e = ht_add(&(mgr->names), (void*)type->type);
if (e == NULL) {
return -ENOMEM;
}
idx = zarray_store(&(mgr->types), type);
if (idx < 0) {
ht_del(&(mgr->names), (void*)type->type);
return idx;
}
e->data = idx;
return idx;
}
int obj_init(objmgr_t* mgr,
objtype_t* type,
int32_t exdata,
myobj_t* obj)
{
obj->type = type;
obj->nref = 1;
obj->nread = 0;
obj->nwrite = 0;
obj->exdata = exdata;
obj->magic = OBJ_MAGIC;
my_rwlock_init(&(obj->rwlock));
mylock_init(&(obj->lock));
return 1;
}
int objmgr_register(objmgr_t* mgr,
objtype_t* type)
{
int rc = 0;
/* clang-format off */
if ((mgr == NULL) ||
(type == NULL) ||
(type->type == NULL) ||
(type->fn_create == NULL)) {
return -EINVAL;
}
/* clang-format on */
mylock_init(&(type->lock));
mylock_lock(&(mgr->lock));
rc = objmgr_register_internal(mgr, type);
mylock_unlock(&(mgr->lock));
return rc;
}
static void* create_obj_ex(objmgr_t* mgr,
int type,
va_list ap)
{
objtype_t* typeval = NULL;
void* obj;
if ((type < 0) || (type >= mgr->types.caps)) {
SET_ERROR(EINVAL);
return NULL;
}
typeval = (objtype_t*)zarray_get(&(mgr->types), type);
if (typeval == NULL) {
SET_ERROR(EINVAL);
return NULL;
}
obj = typeval->fn_create(mgr, typeval, ap);
return obj;
}
void* create_obj_by_typeid(objmgr_t* mgr,
int type,
...)
{
va_list ap;
void* p = NULL;
va_start(ap, type);
p = create_obj_ex(mgr, type, ap);
va_end(ap);
return p;
}
void* create_obj_by_typename(objmgr_t* mgr,
char* type,
...)
{
hent_t* e;
va_list ap;
void* p = NULL;
mylock_lock(&(mgr->lock));
e = ht_get(&(mgr->names), (void*)type);
mylock_unlock(&(mgr->lock));
if (e == NULL) {
SET_ERROR(EINVAL);
return NULL;
}
if (e->data < 0) {
SET_ERROR(EINVAL);
return NULL;
}
va_start(ap, type);
p = create_obj_ex(mgr, e->data, ap);
va_end(ap);
return p;
}
int typeid_of_name(objmgr_t* mgr,
char* type)
{
hent_t* e;
int typeid;
mylock_lock(&(mgr->lock));
e = ht_get(&(mgr->names), (void*)type);
if (e == NULL) {
typeid = -ENOENT;
} else {
typeid = e->data;
}
mylock_unlock(&(mgr->lock));
return typeid;
}
void* obj_ref(void* obj, int op)
{
myobj_t* myobj;
if (obj == NULL) {
SET_ERROR(EINVAL);
return NULL;
}
myobj = TO_MYOBJ(obj);
if (myobj->magic != OBJ_MAGIC) {
SET_ERROR(EINVAL);
return NULL;
}
switch (op) {
case OBJREF_READ:
my_rwlock_rlock(&(myobj->rwlock));
break;
case OBJREF_UPDATE:
my_rwlock_wlock(&(myobj->rwlock));
break;
default:
break;
}
mylock_lock(&(myobj->lock));
switch (op) {
case OBJREF_READ:
myobj->nread++;
break;
case OBJREF_UPDATE:
myobj->nwrite++;
break;
default:
break;
}
myobj->nref++;
mylock_unlock(&(myobj->lock));
return obj;
}
void obj_deref(void* obj)
{
myobj_t* myobj;
int nc;
objtype_t* typeval;
int release_rwlock = 0;
if (obj == NULL) {
SET_ERROR(EINVAL);
return;
}
myobj = TO_MYOBJ(obj);
if (myobj->magic != OBJ_MAGIC) {
SET_ERROR(EINVAL);
return;
}
/* the object lock should be held */
mylock_lock(&(myobj->lock));
myobj->nref--;
nc = myobj->nref;
if ((myobj->nread > 0) || (myobj->nwrite > 0)) {
release_rwlock = 1;
if (myobj->nread > 0) {
myobj->nread--;
} else {
myobj->nwrite--;
}
}
mylock_unlock(&(myobj->lock));
if (release_rwlock) {
my_rwlock_unlock(&(myobj->rwlock));
}
if (nc > 0) {
return;
}
typeval = myobj->type;
if (typeval == NULL) {
return;
}
if (typeval->fn_fini != NULL) {
typeval->fn_fini(obj);
}
return;
}
objmgr_t* objmgr_get_default()
{
return objmgr_default;
}
int objmgr_set_default(objmgr_t* mgr)
{
objmgr_default = mgr;
return 0;
}
myobj_t *obj_alloc(size_t size) {
myobj_t *obj;
if (size <= 0) {
SET_ERROR(EINVAL);
return NULL;
}
obj = (myobj_t *)calloc(1, sizeof(*obj) + size);
return obj;
}

931
src/lib/request.c Normal file
View file

@ -0,0 +1,931 @@
#include <errno.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include "mylock.h"
#include "netio.h"
#include "request.h"
#include "typemap.h"
#include "utils.h"
#include "xce/types.h"
ioctx_t* ioctx_alloc(endpoint_t* ep,
xce_peerinfo_t* peer)
{
ioctx_t* ctx;
ctx = (ioctx_t*)calloc(1, sizeof(*ctx));
if (ctx == NULL) {
errno = -ENOMEM;
return NULL;
}
ctx->ep = endpoint_ref(ep);
ctx->from = peer;
ctx->nrefs++;
return ctx;
}
int ioctx_ref(ioctx_t* ctx)
{
int old = ctx->nrefs;
ctx->nrefs++;
return old;
}
static void ioctx_kill(ioctx_t* ctx,
int free_ctx)
{
if (ctx == NULL) {
return;
}
endpoint_deref(ctx->ep);
free_packet(&(ctx->pkt));
capn_free(&(ctx->c));
if (free_ctx) {
free(ctx);
}
}
void ioctx_deref(ioctx_t* ctx,
int free_ctx)
{
if (ctx == NULL) {
return;
}
if (ctx->nrefs == 0) {
WARN("Something wrong. Have you forgotten to call ioctx_ref()?");
return;
}
ctx->nrefs--;
if (ctx->nrefs == 0) {
ioctx_kill(ctx, free_ctx);
}
}
int ioctx_encode(ioctx_t* ctx,
xce_request_t* req)
{
struct capn_segment* cs;
Request_ptr rp;
int rc;
capn_init_malloc(&(ctx->c));
cs = capn_root(&(ctx->c)).seg;
encode_Request(cs, &(ctx->rq), req);
cs = capn_root(&(ctx->c)).seg;
rp = new_Request(cs);
write_Request(&(ctx->rq), rp);
capn_setp(capn_root(&(ctx->c)), 0, rp.p);
ctx->pkt.sz = capn_size(&(ctx->c));
rc = alloc_packet(&(ctx->pkt));
if (rc < 0) {
return rc;
}
capn_write_mem(&(ctx->c),
(uint8_t*)ctx->pkt.data,
ctx->pkt.sz, 0);
return 0;
}
int ioctx_decode(ioctx_t* ctx,
xce_request_t* req)
{
Request_ptr rp;
capn_init_mem(&(ctx->c), (const uint8_t*)ctx->pkt.data,
ctx->pkt.sz, 0);
rp.p = capn_getp(capn_root(&(ctx->c)), 0, 1);
read_Request(&(ctx->rq), rp);
decode_Request(req, &(ctx->rq));
return 0;
}
int ioctx_flush(ioctx_t* ctx, int fd)
{
int rc;
rc = write_packet(fd, &(ctx->pkt));
return rc;
}
void init_reply_by_req(xce_reply_t* reply,
xce_request_t* req)
{
reply->seq = req->seq;
reply->opcode = req->opcode;
}
int xce_request(ioctx_t* ctx,
xce_request_t* req)
{
int rc;
req->seq = endpoint_getseq(ctx->ep);
req->from = ctx->from;
rc = ioctx_encode(ctx, req);
if (rc < 0) {
return rc;
}
endpoint_enq(ctx->ep, &(ctx->link));
return 0;
}
int xce_reply_with_ctx(ioctx_t* ctx,
xce_peerinfo_t* from,
xce_reply_t* reply)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_reply,
.body_which = Request_body_replymsg,
};
/* clang-format on */
int rc;
TRACE("%s seq %lu opcode %d status %d data which %d",
__func__, reply->seq, reply->opcode,
reply->status, reply->data_which);
request.from = from;
request.body.replymsg = reply;
request.seq = endpoint_getseq(ctx->ep);
rc = ioctx_encode(ctx, &request);
if (rc < 0) {
return rc;
}
endpoint_enq(ctx->ep, &(ctx->link));
return 0;
}
int xce_reply(endpoint_t* ep,
xce_peerinfo_t* from,
xce_reply_t* reply)
{
ioctx_t* ctx;
ctx = ioctx_alloc(ep, from);
if (ctx == NULL) {
return -ENOMEM;
}
return xce_reply_with_ctx(ctx, from, reply);
}
int xce_nop_req(ioctx_t* ctx)
{
xce_request_t request = {
.opcode = OPCode_nop,
.body_which = Request_body_nomsg
};
if (ctx == NULL) {
return -EINVAL;
}
return xce_request(ctx, &request);
}
int xce_hello_req(ioctx_t* ctx,
char* msg)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_hello,
.body_which = Request_body_hellomsg,
.body = {
.hellomsg = msg
}
};
/* clang-format on */
if ((ctx == NULL) || (msg == NULL)) {
return -EINVAL;
}
return xce_request(ctx, &request);
}
int xce_join_req(ioctx_t* ctx,
int role,
hostattrs_t* attrs)
{
/* clang-format off */
xce_joindata_t joinmsg = {
.role = role
};
xce_request_t request = {
.opcode = OPCode_join,
.body_which = Request_body_joinmsg,
.body = {
.joinmsg = &joinmsg
}
};
if ((role != HostRole_client) &&
(role != HostRole_worker) &&
(role != HostRole_scheduler)) {
return -EINVAL;
}
/* clang-format on */
if (role == HostRole_worker) {
if (attrs == NULL) {
return -EINVAL;
}
joinmsg.data_which = JoinData_data_attrs;
joinmsg.data.attrs = attrs;
}
return xce_request(ctx, &request);
}
int xce_shutdown_req(ioctx_t* ctx)
{
int rc;
dataq_t* outq;
xce_request_t request = {
.opcode = OPCode_shutdown,
.body_which = Request_body_nomsg
};
if (ctx == NULL) {
return -EINVAL;
}
rc = xce_request(ctx, &request);
if (rc < 0) {
return rc;
}
outq = &(ctx->ep->outq);
while (!DATAQ_EMPTY(outq)) {
sleep(1);
}
return 0;
}
int xce_pushconfig_req(endpoint_t* ep,
xce_peerinfo_t* from,
xce_configdata_t* config)
{
int rc = 0;
xce_request_t request = {
.opcode = OPCode_push,
.body_which = Request_body_configpushmsg
};
ioctx_t* ctx = NULL;
if ((ep == NULL) || (config == NULL)) {
return -EINVAL;
}
ctx = ioctx_alloc(ep, from);
if (ctx == NULL) {
return -ENOMEM;
}
request.body.configpushmsg = config;
rc = xce_request(ctx, &request);
return rc;
}
static int xce_push_req(endpoint_t* ep,
xce_peerinfo_t* from,
xce_data_t* data)
{
int rc = 0;
ioctx_t* ctx = NULL;
xce_request_t request = {
.opcode = OPCode_push,
.body_which = Request_body_pushmsg
};
if ((ep == NULL) || (from == NULL) || (data == NULL)) {
return -EINVAL;
}
ctx = ioctx_alloc(ep, from);
if (ctx == NULL) {
return -ENOMEM;
}
request.body.pushmsg = data;
rc = xce_request(ctx, &request);
return rc;
}
int xce_push_data_req(endpoint_t* ep,
xce_peerinfo_t* from,
xce_data_t* data,
xce_check_fn_t checkf,
void* checkarg,
int pktlimit)
{
int nrows = 0;
int pos = 0;
int rc = 0;
xce_data_t data1;
int checkstatus = 0;
if ((ep == NULL) || (from == NULL) || (data == NULL)) {
return -EINVAL;
}
data1.table = data->table;
switch (data->table) {
case Data_data_schedjobs:
nrows = data->data.jobs->n_total;
data1.data.jobs = (xce_jobs_data_t*)calloc(1, sizeof(xce_jobs_data_t));
if (data1.data.jobs == NULL) {
rc = -ENOMEM;
}
break;
case Data_data_schedworkers:
nrows = data->data.workers->n_total;
data1.data.workers = (xce_workers_data_t*)calloc(1, sizeof(xce_workers_data_t));
if (data1.data.workers == NULL) {
rc = -ENOMEM;
}
break;
default:
rc = -EINVAL;
break;
}
if (rc < 0) {
return rc;
}
if (pktlimit <= 0) {
pktlimit = nrows;
}
do {
int nc = nrows - pos;
if (nc > pktlimit) {
nc = pktlimit;
}
if (checkf != NULL) {
checkstatus = (*checkf)(checkarg);
if (checkstatus < 0) {
nc = 0;
}
}
switch (data->table) {
case Data_data_schedjobs:
data1.data.jobs->n_total = data->data.jobs->n_total;
data1.data.jobs->pos = pos;
data1.data.jobs->count = nc;
if (nc == 0) {
data1.data.jobs->jobs = NULL;
} else {
data1.data.jobs->jobs = &(data->data.jobs->jobs[pos]);
}
break;
case Data_data_schedworkers:
data1.data.workers->n_total = data->data.workers->n_total;
data1.data.workers->pos = pos;
data1.data.workers->count = nc;
if (nc == 0) {
data1.data.workers->workers = NULL;
} else {
data1.data.workers->workers = &(data->data.workers->workers[pos]);
}
break;
default:
break;
}
rc = xce_push_req(ep, from, &data1);
if (rc < 0) {
break;
}
pos += nc;
} while ((pos < nrows) && (checkstatus >= 0));
switch (data->table) {
case Data_data_schedjobs:
FREEUP(data1.data.jobs);
break;
case Data_data_schedworkers:
FREEUP(data1.data.workers);
break;
default:
break;
}
return rc;
}
int xce_get_req(ioctx_t* ctx,
xce_get_t* get)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_get,
.body_which = Request_body_getmsg,
.body = {
.getmsg = get
}
};
/* clang-format on */
return xce_request(ctx, &request);
}
int xce_reply_get(endpoint_t* ep,
xce_peerinfo_t* from,
xce_reply_t* reply,
xce_check_fn_t checkf,
void* checkarg,
int pktlimit)
{
int rc = 0;
int nrows = 0;
int pos = 0;
/* clang-format off */
xce_data_t getdata = {
.table = reply->data.getdata->table
};
xce_reply_t reply1 = {
.seq = reply->seq,
.opcode = reply->opcode,
.status = reply->status,
.data_which = reply->data_which,
.data = {
.getdata = &getdata
}
};
/* clang-format on */
int checkstatus = 0;
xce_data_t* data = reply->data.getdata;
if ((ep == NULL) || (from == NULL) || (reply == NULL)) {
return -EINVAL;
}
switch (getdata.table) {
case Data_data_schedjobs:
case Data_data_jobs:
nrows = data->data.jobs->n_total;
getdata.data.jobs = (xce_jobs_data_t*)calloc(1, sizeof(xce_jobs_data_t));
break;
case Data_data_schedworkers:
case Data_data_workers:
nrows = data->data.workers->n_total;
getdata.data.workers = (xce_workers_data_t*)calloc(1, sizeof(xce_workers_data_t));
break;
case Data_data_resources:
nrows = data->data.resources->n_total;
getdata.data.resources = (xce_resource_data_t*)calloc(1, sizeof(xce_resource_data_t));
break;
case Data_data_resvals:
nrows = data->data.resvals->n_total;
getdata.data.resvals = (xce_resval_data_t*)calloc(1, sizeof(xce_resval_data_t));
break;
default:
rc = -EINVAL;
break;
}
if (rc < 0) {
/* FIXME we need to reply no data */
return rc;
}
if (pktlimit <= 0) {
pktlimit = nrows;
}
do {
int nc = nrows - pos;
if (nc > pktlimit) {
nc = pktlimit;
}
if (checkf != NULL) {
checkstatus = (*checkf)(checkarg);
if (checkstatus < 0) {
nc = 0;
}
}
switch (getdata.table) {
case Data_data_schedjobs:
case Data_data_jobs:
getdata.data.jobs->n_total = data->data.jobs->n_total;
getdata.data.jobs->pos = pos;
getdata.data.jobs->count = nc;
if (nc == 0) {
getdata.data.jobs->jobs = NULL;
} else {
getdata.data.jobs->jobs = &(data->data.jobs->jobs[pos]);
}
break;
case Data_data_schedworkers:
case Data_data_workers:
getdata.data.workers->n_total = data->data.workers->n_total;
getdata.data.workers->pos = pos;
getdata.data.workers->count = nc;
if (nc == 0) {
getdata.data.workers->workers = NULL;
} else {
getdata.data.workers->workers = &(data->data.workers->workers[pos]);
}
break;
case Data_data_resources:
getdata.data.resources->n_total = data->data.resources->n_total;
getdata.data.resources->pos = pos;
getdata.data.workers->count = nc;
if (nc == 0) {
getdata.data.resources->resources = NULL;
} else {
getdata.data.resources->resources = &(data->data.resources->resources[pos]);
}
break;
case Data_data_resvals:
getdata.data.resvals->n_total = data->data.resvals->n_total;
getdata.data.resvals->pos = pos;
getdata.data.resvals->count = nc;
if (nc == 0) {
getdata.data.resvals->vals = NULL;
} else {
getdata.data.resvals->vals = &(data->data.resvals->vals[pos]);
}
break;
default:
/* should never goes here */
break;
}
rc = xce_reply(ep, from, &reply1);
if (rc < 0) {
break;
}
pos += nc;
} while ((pos < nrows) && (checkstatus >= 0));
switch (getdata.table) {
case Data_data_schedjobs:
case Data_data_jobs:
FREEUP(getdata.data.jobs);
break;
case Data_data_schedworkers:
case Data_data_workers:
FREEUP(getdata.data.workers);
break;
case Data_data_resources:
FREEUP(getdata.data.resources);
break;
case Data_data_resvals:
FREEUP(getdata.data.resvals);
break;
default:
break;
}
return rc;
}
int extract_data(dataset_t* dataset,
xce_data_t* getdata)
{
int ntotal;
int rc = 0;
int pos = 0;
int count = 0;
TRACE("%s ...", __func__);
switch (getdata->table) {
case Data_data_schedjobs:
case Data_data_jobs:
if (getdata->data.jobs->count <= 0) {
return 1;
}
ntotal = getdata->data.jobs->n_total;
pos = getdata->data.jobs->pos;
count = getdata->data.jobs->count;
if (dataset->rows == NULL) {
dataset->rows = (xce_job_t**)calloc(ntotal, sizeof(xce_job_t*));
dataset->nrows = 0;
}
memcpy((void*)(((char*)dataset->rows) + sizeof(xce_job_t*) * pos),
getdata->data.jobs->jobs, count * sizeof(xce_job_t*));
memset(getdata->data.jobs->jobs, 0x0, count * sizeof(xce_job_t*));
break;
case Data_data_schedworkers:
case Data_data_workers:
if (getdata->data.workers->count <= 0) {
return 1;
}
ntotal = getdata->data.workers->n_total;
if (dataset->rows == NULL) {
dataset->rows = (xce_worker_t**)calloc(ntotal, sizeof(xce_worker_t*));
dataset->nrows = 0;
}
pos = getdata->data.workers->pos;
count = getdata->data.workers->count;
memcpy((void*)(((char*)dataset->rows) + sizeof(xce_worker_t*) * pos),
getdata->data.workers->workers, count * sizeof(xce_worker_t*));
memset(getdata->data.workers->workers, 0x0, count * sizeof(xce_worker_t*));
break;
case Data_data_resources:
if (getdata->data.resources->count <= 0) {
return 1;
}
ntotal = getdata->data.resources->n_total;
if (dataset->rows == NULL) {
dataset->rows = (xce_resource_t**)calloc(ntotal, sizeof(xce_resource_t*));
dataset->nrows = 0;
}
pos = getdata->data.resources->pos;
count = getdata->data.resources->count;
memcpy((void*)(((char*)dataset->rows) + sizeof(xce_resource_t*) * pos),
getdata->data.resources->resources, count * sizeof(xce_resource_t*));
memset(getdata->data.resources->resources, 0x0, count * sizeof(xce_resource_t*));
break;
case Data_data_resvals:
if (getdata->data.resvals->count <= 0) {
return 1;
}
ntotal = getdata->data.resvals->n_total;
if (dataset->rows == NULL) {
dataset->rows = (xce_resval_t**)calloc(ntotal, sizeof(xce_resval_t*));
dataset->nrows = 0;
}
pos = getdata->data.resvals->pos;
count = getdata->data.resvals->count;
memcpy((void*)(((char*)dataset->rows) + sizeof(xce_resval_t*) * pos),
getdata->data.resvals->vals, count * sizeof(xce_resval_t*));
memset(getdata->data.resvals->vals, 0x0, count * sizeof(xce_resval_t*));
break;
default:
rc = -EINVAL;
break;
}
if (rc < 0) {
return rc;
}
dataset->nrows += count;
if (dataset->nrows < ntotal) {
return 0;
}
return 1;
}
int xce_jobdispatch_req(ioctx_t* ctx,
xce_job_dispatch_t* info)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_jobdispatch,
.body_which = Request_body_dispatchmsg,
.body = {
.dispatchmsg = info
}
};
/* clang-format on */
/* clang-format off */
if ((ctx == NULL) ||
(info == NULL)) {
return -EINVAL;
}
/* clang-format on */
return xce_request(ctx, &request);
}
int xce_notify_req(ioctx_t* ctx,
xce_notify_data_t* data)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_notify,
.body_which = Request_body_notifymsg,
.body = {
.notifymsg = data
}
};
/* clang-forn on */
if ((ctx == NULL) || (data == NULL)) {
return -EINVAL;
}
return xce_request(ctx, &request);
}
int xce_jobsubmit_req(ioctx_t* ctx,
xce_job_submit_t* submit)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_jobsub,
.body_which = Request_body_jobsubmsg,
.body = {
.jobsubmsg = submit
}
};
/*clang-format on*/
/* clang-format off */
if ((ctx == NULL) ||
(submit == NULL)) {
return -EINVAL;
}
/* clang-format on */
return xce_request(ctx, &request);
}
int xce_startjob_req(ioctx_t* ctx,
xce_job_exec_t* execinfo)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_startjob,
.body_which = Request_body_jobstartmsg,
.body = {
.jobstartmsg = execinfo
}
};
/* clang-format on */
return xce_request(ctx, &request);
}
int xce_clusterconf_req(ioctx_t* ctx)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_clusterconf,
.body_which = Request_body_nomsg
};
/* clang-format on */
return xce_request(ctx, &request);
}
int xce_update_req(ioctx_t* ctx,
xce_update_data_t* data)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_update,
.body_which = Request_body_updatemsg,
.body = {
.updatemsg = data
}
};
/* clang-format on */
if ((ctx == NULL) || (data == NULL)) {
return -EINVAL;
}
return xce_request(ctx, &request);
}
int xce_jobctrl_req(ioctx_t* ctx,
xce_jobctrl_t* ctrinfo)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_jobcontrol,
.body_which = Request_body_jobctrlmsg,
.body = {
.jobctrlmsg = ctrinfo
}
};
/* clang-format on */
if ((ctx == NULL) || (ctrinfo == NULL)) {
return -EINVAL;
}
if (ctrinfo->jobid == 0) {
return -EINVAL;
}
switch (ctrinfo->action) {
case JobControl_u_siginfo:
break;
case JobControl_u_ckptoption:
if (ctrinfo->u.ckptoption->method == NULL) {
ctrinfo->u.ckptoption->method = "default";
}
break;
default:
return -EINVAL;
break;
}
return xce_request(ctx, &request);
}
int xce_queuectrl_req(ioctx_t* ctx,
xce_queuectrl_t* ctrlinfo)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_queuecontrol,
.body_which = Request_body_queuectrlmsg,
.body = {
.queuectrlmsg = ctrlinfo
}
};
/* clang-format on */
if ((ctx == NULL) || (ctrlinfo == NULL)) {
return -EINVAL;
}
if ((ctrlinfo->queue == NULL) || (strlen(ctrlinfo->queue) == 0)) {
return -EINVAL;
}
if (ctrlinfo->action == QUEUE_DO_NONE) {
return 0;
}
if ((ctrlinfo->action < 0) || (ctrlinfo->action > QUEUE_ACTIVE)) {
return -EINVAL;
}
return xce_request(ctx, &request);
}
int xce_runtask_req(ioctx_t* ctx,
xce_taskrun_t* runinfo)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_runtasks,
.body_which = Request_body_runtaskmsg,
.body = {
.runtaskmsg = runinfo
}
};
/* clang-format on */
if ((ctx == NULL) || (runinfo == NULL)) {
return -EINVAL;
}
if (runinfo->nhosts <= 0) {
return -EINVAL;
}
return xce_request(ctx, &request);
}

35
src/lib/testsuite/test.c Normal file
View file

@ -0,0 +1,35 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "unity.h"
extern void test_xstrings(void);
extern void test_zarray(void);
extern void test_ht_string(void);
extern void test_ht_int(void);
extern void test_error(void);
extern void test_utils(void);
void setUp(void)
{
return;
}
void tearDown(void)
{
return;
}
int main(int argc, char* argv[])
{
UNITY_BEGIN();
test_ht_string();
test_ht_int();
test_zarray();
test_xstrings();
test_error();
test_utils();
return UNITY_END();
}

View file

@ -0,0 +1,44 @@
#include <stdio.h>
#include <stdlib.h>
#include "xce/errnox.h"
#include "unity.h"
#include "utils.h"
static void test_error_setget(void) {
int myerrno =1;
ectx_t *e;
SET_ERROR(myerrno);
e = get_ectx();
TEST_ASSERT_TRUE(e != NULL);
TEST_ASSERT_TRUE(errno == myerrno);
TEST_ASSERT_TRUE(e->file != NULL);
TEST_ASSERT_TRUE(e->func != NULL);
TEST_ASSERT_TRUE(strcmp(e->file, __FILE__) == 0);
TEST_ASSERT_TRUE(strcmp(e->func, __func__) == 0);
}
#if 0
static void test_strerror_r(void) {
char errmsg1[256];
char errmsg2[256];
int errors[] ={ENOENT, EINVAL, E_XCE_BAD_JOB, E_XCE_BAD_WORKER, 0};
int i;
for(i = 0; errors[i] != 0; i ++) {
strerror_r(errors[i], errmsg1, sizeof(errmsg1));
xce_strerror_r(errors[i], errmsg2, sizeof(errmsg2));
TEST_ASSERT_TRUE(strcmp(errmsg1, errmsg2) == 0);
}
}
#endif
void test_error(void) {
printf("\n>> error test\n\n");
RUN_TEST(test_error_setget);
#if 0
RUN_TEST(test_strerror_r);
#endif
}

View file

@ -0,0 +1,50 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "unity.h"
#include "htab.h"
static htab_t htab;
static char *s = "Hello,world";
static void test_ht_add_string(void) {
hent_t *e = NULL;
e = ht_add(&(htab), (void *)s);
TEST_ASSERT_NOT_NULL(e);
return;
}
static void test_ht_get_string(void) {
hent_t *e = NULL;
e = ht_get(&htab, (void *)s);
TEST_ASSERT_NOT_NULL(e);
TEST_ASSERT_TRUE(0 == strcmp(e->key, s));
return;
}
static void test_ht_del_string(void) {
hent_t *e = NULL;
ht_del(&htab, (void *)s);
e = ht_get(&htab, (void *)s);
TEST_ASSERT_TRUE( e == NULL);
return;
}
void test_ht_string(void) {
printf("\n>> htab test string\n\n");
ht_init(&htab, 13, string_hash_key);
RUN_TEST(test_ht_add_string);
RUN_TEST(test_ht_get_string);
RUN_TEST(test_ht_del_string);
}

View file

@ -0,0 +1,52 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "unity.h"
#include "htab.h"
static htab_t htab;
uint64_t key = (uint64_t)0xfabcde6666666666;
static void test_ht_add_string(void) {
hent_t *e = NULL;
e = ht_add(&(htab), (void *)key);
TEST_ASSERT_NOT_NULL(e);
return;
}
static void test_ht_get_string(void) {
hent_t *e = NULL;
e = ht_get(&htab, (void *)key);
TEST_ASSERT_NOT_NULL(e);
TEST_ASSERT_TRUE((uint64_t)e->key == (uint64_t)key);
return;
}
static void test_ht_del_string(void) {
hent_t *e = NULL;
ht_del(&htab, (void *)key);
e = ht_get(&htab, (void *)key);
TEST_ASSERT_TRUE( e == NULL);
return;
}
void test_ht_int(void) {
printf("\n>> htab test int\n\n");
ht_init(&htab, 13, int_hash_key);
RUN_TEST(test_ht_add_string);
RUN_TEST(test_ht_get_string);
RUN_TEST(test_ht_del_string);
}

View file

@ -0,0 +1,105 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "unity.h"
#include "utils.h"
#include "xce/types.h"
static void test_timewindow_config_dup()
{
/* clang-format off */
xce_timewindow_config_t win1 = {
.nsegs = 2,
.segs = (xce_timewindow_seg_config_t*[]) {
&(xce_timewindow_seg_config_t) {
.tz = "GMT-8",
.open = &(xce_timewindow_time_t) {
.day = 0,
.hour = 9,
.min = 0 },
.close = &(xce_timewindow_time_t) {
.day = 0,
.hour = 17,
.min = 59 } },
&(xce_timewindow_seg_config_t) {
.tz = "GMT-8",
.open = &(xce_timewindow_time_t) {
.day = 5,
.hour = 21,
.min = 0 },
.close = &(xce_timewindow_time_t) {
.day = 7,
.hour = 20,
.min = 59 } } }
};
/* clang-format on */
xce_timewindow_config_t* win2 = NULL;
win2 = dup_timewindow_config(&win1);
TEST_ASSERT_TRUE(win2 != NULL);
TEST_ASSERT_TRUE(win2->nsegs == 2);
TEST_ASSERT_TRUE((strcmp(win2->segs[0]->tz, "GMT-8") == 0));
TEST_ASSERT_TRUE(win2->segs[0]->open->day == 0);
TEST_ASSERT_TRUE(win2->segs[0]->open->hour == 9);
TEST_ASSERT_TRUE(win2->segs[0]->open->min == 0);
TEST_ASSERT_TRUE(win2->segs[0]->close->day == 0);
TEST_ASSERT_TRUE(win2->segs[0]->close->hour == 17);
TEST_ASSERT_TRUE(win2->segs[0]->close->min == 59);
TEST_ASSERT_TRUE((strcmp(win2->segs[1]->tz, "GMT-8") == 0));
TEST_ASSERT_TRUE(win2->segs[1]->open->day == 5);
TEST_ASSERT_TRUE(win2->segs[1]->open->hour == 21);
TEST_ASSERT_TRUE(win2->segs[1]->open->min == 0);
TEST_ASSERT_TRUE(win2->segs[1]->close->day == 7);
TEST_ASSERT_TRUE(win2->segs[1]->close->hour == 20);
TEST_ASSERT_TRUE(win2->segs[1]->close->min == 59);
free_timewindow_config(win2);
return;
}
void test_dup_threshold()
{
/* clang-format off */
xce_res_threshold_t* threshold[2] = {
&(xce_res_threshold_t) {
.name = "r15s",
.sched = 1.0,
.stop = 5.0 },
&(xce_res_threshold_t) {
.name = "r1m",
.sched = 0.9,
.stop = 4.5 }
};
/* clang-format on */
xce_res_threshold_t** threshold2 = NULL;
threshold2 = dup_resource_thresholds(threshold, 2);
TEST_ASSERT_TRUE(threshold2 != NULL);
TEST_ASSERT_TRUE(strcmp(threshold[0]->name, threshold2[0]->name) == 0);
TEST_ASSERT_TRUE(strcmp(threshold[1]->name, threshold2[1]->name) == 0);
TEST_ASSERT_TRUE(float_equal(threshold[0]->sched,
threshold2[0]->sched));
TEST_ASSERT_TRUE(float_equal(threshold[0]->stop,
threshold2[0]->stop));
TEST_ASSERT_TRUE(float_equal(threshold[1]->sched,
threshold2[1]->sched));
TEST_ASSERT_TRUE(float_equal(threshold[1]->stop,
threshold2[1]->stop));
free_resource_thresholds(threshold2, 2);
return;
}
void test_utils(void)
{
printf("\n>> utils test\n\n");
RUN_TEST(test_timewindow_config_dup);
RUN_TEST(test_dup_threshold);
}

View file

@ -0,0 +1,128 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "objmgr.h"
#include "unity.h"
#include "xstring.h"
void test_xstring_create(void)
{
objmgr_t mgr;
char* s1 = "Hello,world";
char* s2 = NULL;
int rc = 0;
myobj_t* obj;
objmgr_init(&mgr);
register_xstring(&mgr,4,4);
TEST_ASSERT_EQUAL(1, mgr.types.count);
s2 = create_obj_by_typename(&mgr, "xstring", s1);
TEST_ASSERT_NOT_NULL(s2);
obj = TO_MYOBJ(s2);
TEST_ASSERT_EQUAL(1, XSTRING_OBJ_TYPE_STRINGS(obj).count);
rc = strcmp(s1, s2);
TEST_ASSERT_EQUAL(0, rc);
objmgr_fini(&mgr);
}
void test_xstring_ref(void)
{
objmgr_t mgr;
char* s1 = NULL;
char* s2 = NULL;
myobj_t* obj;
objmgr_init(&mgr);
register_xstring(&mgr,4,4);
TEST_ASSERT_EQUAL(1, mgr.types.count);
s1 = create_obj_by_typename(&mgr, "xstring",
"Hello,world");
TEST_ASSERT_NOT_NULL(s1);
obj = TO_MYOBJ(s1);
TEST_ASSERT_EQUAL(1, XSTRING_OBJ_TYPE_STRINGS(obj).count);
s2 = (char*)obj_ref(s1, OBJREF_READ);
TEST_ASSERT_EQUAL(s1, s2);
TEST_ASSERT_EQUAL(2, obj->nref);
objmgr_fini(&mgr);
}
void test_xstring_deref(void)
{
objmgr_t mgr;
char* s1 = "Hello,world";
char* s2 = NULL;
int rc = 0;
myobj_t* obj;
objmgr_init(&mgr);
register_xstring(&mgr,4,4);
TEST_ASSERT_EQUAL(1, mgr.types.count);
s2 = create_obj_by_typename(&mgr, "xstring", s1);
TEST_ASSERT_NOT_NULL(s2);
rc = strcmp(s1, s2);
TEST_ASSERT_EQUAL(0, rc);
if (rc == 0) {
objtype_t *typeval;
obj = TO_MYOBJ(s2);
typeval = obj->type;
obj_deref(s2);
TEST_ASSERT_EQUAL(0, XSTRING_TYPE_STRINGS(typeval).count);
}
objmgr_fini(&mgr);
}
void test_xstring_share(void)
{
objmgr_t mgr;
char* s1 = "Hello,world";
char* s2 = NULL;
char* s3 = NULL;
int rc = 0;
objmgr_init(&mgr);
register_xstring(&mgr,4,4);
TEST_ASSERT_EQUAL(1, mgr.types.count);
s2 = create_obj_by_typename(&mgr, "xstring", s1);
TEST_ASSERT_NOT_NULL(s2);
rc = strcmp(s1, s2);
TEST_ASSERT_EQUAL(0, rc);
s3 = create_obj_by_typename(&mgr, "xstring", s1);
TEST_ASSERT_EQUAL(s2, s3);
if (1) {
myobj_t* obj;
obj = TO_MYOBJ(s3);
TEST_ASSERT_EQUAL(2, obj->nref);
}
objmgr_fini(&mgr);
}
void test_xstrings(void)
{
printf("\n>> xstring test\n\n");
RUN_TEST(test_xstring_create);
RUN_TEST(test_xstring_ref);
RUN_TEST(test_xstring_deref);
RUN_TEST(test_xstring_share);
return;
}

View file

@ -0,0 +1,102 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "unity.h"
#include "zarray.h"
static void test_zarray_create(void) {
zarray_t array;
zarray_init(&array, 8, NULL);
TEST_ASSERT_EQUAL(0,array.count);
TEST_ASSERT_NULL(array.data);
}
static void test_zarray_store(void) {
zarray_t array;
int idx;
char *s1 = "hello";
char *s2 = NULL;
zarray_init(&array, 8, NULL);
idx = zarray_store(&array, (void *)s1);
TEST_ASSERT_TRUE(idx >= 0);
s2 = (char *)zarray_get(&array, idx);
TEST_ASSERT_NOT_NULL(s2);
TEST_ASSERT_EQUAL(0, strcmp(s1, s2));
zarray_fini(&(array));
}
static void test_zarray_del(void) {
zarray_t array;
int idx;
char *s1 = "hello";
zarray_init(&array, 8, NULL);
idx = zarray_store(&array, (void *)s1);
TEST_ASSERT_TRUE(idx >= 0);
TEST_ASSERT_TRUE(array.count == 1);
zarray_del(&array, idx);
TEST_ASSERT_TRUE(zarray_get(&array, idx) == NULL);
TEST_ASSERT_TRUE(array.count == 0);
zarray_fini(&array);
}
static void test_zarray_put(void) {
zarray_t array;
int idx;
char *s1 = "hello";
char *s2 = "test";
zarray_init(&array, 8, NULL);
idx = zarray_store(&array, (void *)s1);
TEST_ASSERT_TRUE(idx >= 0);
TEST_ASSERT_TRUE(array.count == 1);
TEST_ASSERT_TRUE(zarray_get(&array, idx) != NULL);
TEST_ASSERT_TRUE(strcmp((char *)zarray_get(&array, idx), s1) == 0);
zarray_put(&array, idx, (void *)s2);
TEST_ASSERT_TRUE(zarray_get(&array, idx) != NULL);
TEST_ASSERT_TRUE(strcmp((char *)zarray_get(&array, idx), s2) == 0);
zarray_fini(&array);
}
static int sum_(void *arg1, void *arg2) {
int *pv = (int *)arg1;
int x = (int)((long)arg2);
(*pv) += x;
return 0;
}
static void test_zarray_iter(void) {
zarray_t array;
int i;
int val = 0;
zarray_init(&array, 10, NULL);
for(i = 0; i < 10; i ++) {
zarray_store(&array, (void *)(long)i);
}
zarray_iter(&array, (zarray_iter_fn_t)sum_, &val);
TEST_ASSERT_TRUE(val == 45);
zarray_fini(&(array));
}
void test_zarray(void) {
printf("\n>> zarray test\n\n");
RUN_TEST(test_zarray_create);
RUN_TEST(test_zarray_store);
RUN_TEST(test_zarray_del);
RUN_TEST(test_zarray_put);
RUN_TEST(test_zarray_iter);
}

81
src/lib/threshold.c Normal file
View file

@ -0,0 +1,81 @@
#include <errno.h>
#include <stdlib.h>
#include "utils.h"
#include "xce/errnox.h"
#include "xce/types.h"
static void kill_thresholds(xce_res_threshold_t** thresholds,
int count)
{
int i;
if (thresholds == NULL) {
return;
}
if (count > 0) {
for (i = 0; i < count; i++) {
xce_res_threshold_t* it = thresholds[i];
if (it == NULL) {
continue;
}
FREEUP(it->name);
FREEUP(it);
}
}
FREEUP(thresholds);
}
void free_resource_thresholds(xce_res_threshold_t** thresholds,
int count)
{
kill_thresholds(thresholds, count);
}
xce_res_threshold_t** dup_resource_thresholds(xce_res_threshold_t** src,
int count)
{
xce_res_threshold_t** thresholds = NULL;
int i;
if ((src == NULL) || (count <= 0)) {
errno = EINVAL;
return NULL;
}
thresholds = (xce_res_threshold_t**)calloc(count, sizeof(xce_res_threshold_t*));
if (thresholds == NULL) {
errno = ENOMEM;
return NULL;
}
for (i = 0; i < count; i++) {
xce_res_threshold_t* it = (xce_res_threshold_t*)calloc(1, sizeof(*it));
if (it == NULL) {
kill_thresholds(thresholds, i);
errno = ENOMEM;
return NULL;
}
thresholds[i] = it;
it->name = strdup(src[i]->name);
if (it->name == NULL) {
kill_thresholds(thresholds, i + 1);
errno = ENOMEM;
return NULL;
}
it->sched = src[i]->sched;
it->stop = src[i]->stop;
}
return thresholds;
}

371
src/lib/utils.c Executable file
View file

@ -0,0 +1,371 @@
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__GLIBC__) && (__GLIBC__ == 2 && __GLIBC_MINOR__ < 28)
#include <pthread.h>
#else
#include <threads.h>
#endif
#include <sys/param.h>
#include <unistd.h>
#if defined(__linux__)
#include <execinfo.h>
#endif
#include "config.h"
#include "controller.capnp.h"
#include <capnp_c.h>
#include "utils.h"
#include "xce/errnox.h"
#include "xce/types.h"
static capn_text chars_to_text_internal(const char* chars)
{
capn_text data = {
.len = strlen(chars),
.str = chars,
.seg = NULL,
};
return data;
}
capn_text chars_to_text(const char* chars)
{
if (chars == NULL) {
chars = "";
}
return chars_to_text_internal(chars);
}
#define ARGV_INCR_DELTA (16)
#define FILL_ARGV(rc, argv, argc, maxargc, delta, s) \
do { \
(rc) = 0; \
char* s1; \
if (((argc) >= (maxargc))) { \
char** p; \
int nc, i; \
nc = (maxargc) + (delta); \
p = (char**)realloc((argv), nc * sizeof(char*)); \
if (p == NULL) { \
(rc) = -ENOMEM; \
break; \
} \
for (i = (maxargc); i < nc; i++) { \
p[i] = NULL; \
} \
(argv) = p; \
(maxargc) = nc; \
} \
s1 = strdup(s); \
if (s1 == NULL) { \
(rc) = -ENOMEM; \
break; \
} \
(argv)[argc] = s1; \
(argc)++; \
} while (0)
#define FREE_ARGV(argv, argc) \
do { \
int i; \
if ((argv) == NULL) { \
break; \
} \
for (i = 0; i < (argc); i++) { \
if ((argv)[i] != NULL) { \
free((argv)[i]); \
(argv)[i] = NULL; \
} \
} \
free(argv); \
} while (0)
int parse_argv(char* input,
char*** argv)
{
int max_argc = 0;
char* arg = NULL;
int i = 0;
int in_quotes = 0;
char quote_char = 0;
int argc = 0;
int rc = 0;
rc = 0;
arg = (char*)malloc(strlen(input) + 1);
if (arg == NULL) {
return -ENOMEM;
}
*argv = NULL;
while (*input) {
if (in_quotes) {
if (*input == quote_char) {
in_quotes = 0;
} else if (*input == '\\') {
input++;
if (*input) {
arg[i++] = *input;
}
} else {
arg[i++] = *input;
}
} else {
if (isspace(*input)) {
if (i > 0) {
arg[i] = '\0';
FILL_ARGV(rc, *argv, argc, max_argc,
ARGV_INCR_DELTA, arg);
if (rc < 0) {
FREE_ARGV(*argv, argc);
free(arg);
return rc;
}
i = 0;
}
} else if ((*input == '"') || (*input == '\'')) {
in_quotes = 1;
quote_char = *input;
} else if (*input == '\\') {
input++;
if (*input) {
arg[i++] = *input;
}
} else {
arg[i++] = *input;
}
}
input++;
}
if (i > 0) {
arg[i] = '\0';
FILL_ARGV(rc, *argv, argc, max_argc,
ARGV_INCR_DELTA, arg);
if (rc < 0) {
FREE_ARGV(*argv, argc);
free(arg);
return rc;
}
}
free(arg);
return argc;
}
void free_argv(char** argv, int argc)
{
FREE_ARGV(argv, argc);
}
#if 0
void freeup_kvs(int count,
xce_kv_t* vals)
{
int i;
if (vals == NULL) {
return;
}
for (i = 0; i < count; i++) {
if (vals[i].value.which != XceFieldValue_data_svalue) {
continue;
}
FREEUP(vals[i].value.u.svalue);
}
FREEUP(vals);
}
#endif
char* frame_symbol(int k)
{
#if defined(__linux__)
void* array[k + 1];
size_t size = backtrace(array, k + 1);
char** symbols = backtrace_symbols(array, size);
char* s = NULL;
if (symbols == NULL) {
return NULL;
}
s = strdup(symbols[MIN(size - 1, k)]);
free(symbols);
return s;
#else
return NULL;
#endif
}
int xce_vprintf(const char* fmt, va_list ap)
{
int rc = 0;
/* FIXME: */
return rc;
}
static _Thread_local ectx_t ectx;
void set_error(char* file,
char* func,
int line,
int code)
{
ectx.file = file;
ectx.func = func;
ectx.line = line;
ectx.code = code;
errno = code;
}
ectx_t* get_ectx()
{
return &ectx;
}
static char* xce_err_str[] = {
"invalid job",
"invalid worker",
"duplicated jobs",
"duplicated workers",
"bad opcode",
"unknown role",
"unknown resource",
"unknown queue",
"unknown group",
"internal error",
NULL
};
int xce_strerror_r(int errnum,
char* buf,
size_t bufsize)
{
if (errnum < XCE_ERRNO_BASE) {
return strerror_r(errnum, buf, bufsize);
}
if (errnum >= E_XCE_MAX) {
strncpy(buf, "unknown error", bufsize);
return -1;
}
strncpy(buf, xce_err_str[errnum - XCE_ERRNO_BASE],
bufsize);
return 0;
}
int copy_int_list(int** dst,
int* src,
int count)
{
int i;
FREEUP(*dst);
if (count == 0) {
return 0;
}
*dst = (int*)calloc(count, sizeof(int));
if ((*dst) == NULL) {
return -ENOMEM;
}
for (i = 0; i < count; i++) {
(*dst)[i] = (int)src[i];
}
return count;
}
int copy_strlist(xce_strlist_t* dst,
xce_strlist_t src)
{
if (!dst) {
return -1;
}
for (int i = 0; i < dst->count; i++) {
FREEUP(dst->data[i]);
}
FREEUP(dst->data);
dst->count = src.count;
if (dst->count == 0) {
return 0;
}
dst->data = (char**)calloc(dst->count, sizeof(char*));
if (dst->data == NULL) {
return -ENOMEM;
}
for (int i = 0; i < src.count; i++) {
if (src.data[i]) {
dst->data[i] = strndup(src.data[i], strlen(src.data[i]));
if (dst->data[i] == NULL) {
return -ENOMEM;
}
}
}
return 0;
}
void free_resval_with_idx_list(xce_val_with_idx_t*** vals,
int count)
{
xce_val_with_idx_t** resvals = *vals;
int i;
if (resvals == NULL) {
return;
}
if (count <= 0) {
return;
}
for (i = 0; i < count; i++) {
xce_val_with_idx_t* val = resvals[i];
if (val == NULL) {
continue;
}
if (val->val->which == Value_u_svalue) {
FREEUP(val->val->u.svalue);
}
FREEUP(val->val);
FREEUP(val);
}
FREEUP(resvals);
*vals = NULL;
}
void free_strlist(xce_strlist_t *l) {
int i;
if ( l == NULL) {
return;
}
if ((l->count <= 0) || (l->data == NULL)) {
return;
}
for(i = 0; i < l->count; i ++) {
FREEUP(l->data[i]);
}
FREEUP(l->data);
}

362
src/lib/vtaskmgr.c Normal file
View file

@ -0,0 +1,362 @@
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include "mylock.h"
#include "netio.h"
#include "utils.h"
#include "vtaskmgr.h"
static int bind_vtask(vtask_t*, vcpu_t*);
vtask_t* vtask_alloc()
{
vtask_t* task;
task = calloc(1, sizeof(*task));
return task;
}
int vtask_init(vtask_t* task,
vtask_func_t entry,
endpoint_t* ep)
{
int rc;
task->entry = entry;
task->vcpu = -1;
task->ctx.ep = endpoint_ref(ep);
rc = read_packet(ep->fd, &(task->ctx.pkt));
if (rc < 0) {
free_packet(&(task->ctx.pkt));
endpoint_deref(task->ctx.ep);
task->ctx.ep = NULL;
}
return rc;
}
void vtask_fini(vtask_t* task)
{
if (task == NULL) {
return;
}
ioctx_deref(&(task->ctx), 0);
return;
}
void vcpu_idle(vcpu_t* vcpu)
{
vtaskmgr_t* vtaskmgr = (vtaskmgr_t*)vcpu->owner;
vcpu->task = NULL;
cbuf_put(&(vtaskmgr->wbuf),
(void*)&(vcpu->cpuid));
cbuf_get(&(vcpu->wbuf),
(void*)&(vcpu->task));
return;
}
void run_task(vtask_t* task)
{
vtaskmgr_t *vtaskmgr;
if (task->entry != NULL) {
(task->entry)(task);
}
endpoint_unblock_tasks(task->ctx.ep);
vtaskmgr = (vtaskmgr_t *)task->owner;
if (vtaskmgr != NULL) {
/* wake up dispatcher */
vtaskmgr_wakeup(vtaskmgr);
}
return;
}
static void* vcpu_entry(void* arg)
{
vcpu_t* my = (vcpu_t*)arg;
while (1) {
if (my->task != NULL) {
vtask_t* t = my->task;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
my->task = NULL;
run_task(t);
vtask_fini(t);
free(t);
my->state = VCPU_IDLE;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
} else {
vcpu_idle(my);
}
pthread_testcancel();
}
return NULL;
}
int vcpu_init(vcpu_t* vcpu,
int cpuid,
void* owner)
{
vcpu->state = VCPU_IDLE;
vcpu->vcpu = 0;
vcpu->cpuid = cpuid;
vcpu->owner = owner;
vcpu->task = NULL;
cbuf_init(&(vcpu->wbuf), 1, sizeof(void*));
return 0;
}
int vcpu_start(vcpu_t* vcpu)
{
int rc;
rc = pthread_create(&(vcpu->vcpu), NULL,
&vcpu_entry, vcpu);
if (rc != 0) {
vcpu->state = VCPU_ERR;
return -errno;
}
return rc;
}
void vcpu_fini(vcpu_t* vcpu)
{
int rc;
void* res;
if (vcpu->vcpu) {
/* wakeup vcpu first */
bind_vtask(NULL, vcpu);
rc = pthread_cancel(vcpu->vcpu);
if (rc != 0) {
cbuf_fini(&(vcpu->wbuf));
return;
}
rc = pthread_join(vcpu->vcpu, &res);
if (rc != 0) {
cbuf_fini(&(vcpu->wbuf));
return;
}
}
cbuf_fini(&(vcpu->wbuf));
return;
}
static void taskq_item_killer(data_item_t* it)
{
if (it != NULL) {
vtask_t* task = ITPTR_TO_VTASK(it);
vtask_fini(task);
free(task);
}
}
int vtaskmgr_init(vtaskmgr_t* vtaskmgr,
int nvcpus)
{
int i;
if ((vtaskmgr == NULL) || (nvcpus <= 0)) {
return -EINVAL;
}
vtaskmgr->dispatcher = 0;
vtaskmgr->n_vcpus = nvcpus;
vtaskmgr->vcpus = (vcpu_t*)calloc(nvcpus,
sizeof(vcpu_t));
if (vtaskmgr->vcpus == NULL) {
return -ENOMEM;
}
for (i = 0; i < nvcpus; i++) {
vcpu_init(&(vtaskmgr->vcpus[i]),
i, vtaskmgr);
}
cbuf_init(&(vtaskmgr->wbuf),
nvcpus, sizeof(int));
cbuf_init(&(vtaskmgr->wtbuf),
1, sizeof(int));
dataq_init(&(vtaskmgr->taskq),
taskq_item_killer);
return 0;
}
static vcpu_t* pick_idle_vcpu(vtaskmgr_t* vtaskmgr)
{
int i;
cbuf_get(&(vtaskmgr->wbuf), &i);
if ((i < 0) || (i >= vtaskmgr->n_vcpus)) {
return NULL;
}
TRACE("%s pick idle cpu #%d",
__func__, i);
return &(vtaskmgr->vcpus[i]);
}
static int vtask_eligible(data_item_t* data)
{
vtask_t* task = ITPTR_TO_VTASK(data);
int eligible = 0;
if (task->ctx.ep == NULL) {
WARN("no endpoint for task 0x%p", task);
return 0;
}
eligible = !(endpoint_is_task_blocked(task->ctx.ep));
TRACE("%s vtask %p is %s",
__func__, task,
eligible?"eligible":"not eligible");
return eligible;
}
static vtask_t* pick_eligible_task(vtaskmgr_t* vtaskmgr)
{
data_item_t* data;
vtask_t* task = NULL;
data = dataq_deq(&(vtaskmgr->taskq), vtask_eligible);
if (data == NULL) {
return NULL;
}
task = ITPTR_TO_VTASK(data);
return task;
}
static int bind_vtask(vtask_t* task,
vcpu_t* vcpu)
{
TRACE("binding task %p to cpu#%d\n",
task, vcpu->cpuid);
if (task != NULL) {
endpoint_block_tasks(task->ctx.ep);
task->vcpu = vcpu->cpuid;
}
cbuf_put(&(vcpu->wbuf), (void*)&task);
return 0;
}
static void* vdispatcher_entry(void* arg)
{
vtaskmgr_t* vtaskmgr = (vtaskmgr_t*)arg;
vcpu_t* vcpu = NULL;
vtask_t* task = NULL;
while (1) {
pthread_testcancel();
if (vcpu == NULL) {
vcpu = pick_idle_vcpu(vtaskmgr);
if (vcpu == NULL) {
continue;
}
}
task = pick_eligible_task(vtaskmgr);
if (task != NULL) {
bind_vtask(task, vcpu);
vcpu = NULL;
task = NULL;
}
else {
vtaskmgr_wait(vtaskmgr);
}
}
return NULL;
}
int vtaskmgr_start(vtaskmgr_t* vtaskmgr)
{
int i, rc;
rc = pthread_create(&(vtaskmgr->dispatcher), NULL,
&vdispatcher_entry, vtaskmgr);
if (rc != 0) {
return -errno;
}
for (i = 0; i < vtaskmgr->n_vcpus; i++) {
vcpu_start(&(vtaskmgr->vcpus[i]));
}
return 0;
}
void vtaskmgr_wait(vtaskmgr_t *vtaskmgr) {
int dummy = 0;
cbuf_get(&(vtaskmgr->wtbuf), &dummy);
}
void vtaskmgr_wakeup(vtaskmgr_t *vtaskmgr) {
int dummy = 0;
cbuf_tryput(&(vtaskmgr->wtbuf), &dummy);
}
void vtaskmgr_fini(vtaskmgr_t* vtaskmgr)
{
int i;
void* res;
if (vtaskmgr->dispatcher != 0) {
pthread_cancel(vtaskmgr->dispatcher);
pthread_join(vtaskmgr->dispatcher, &res);
}
if (vtaskmgr->vcpus != NULL) {
for (i = 0; i < vtaskmgr->n_vcpus; i++) {
vcpu_fini(&(vtaskmgr->vcpus[i]));
}
free(vtaskmgr->vcpus);
}
dataq_fini(&(vtaskmgr->taskq));
cbuf_fini(&(vtaskmgr->wtbuf));
cbuf_fini(&(vtaskmgr->wbuf));
return;
}
int vtask_enq(vtaskmgr_t* vtaskmgr,
vtask_t* task)
{
int rc = 0;
ioctx_ref(&(task->ctx));
rc = dataq_enq(&(vtaskmgr->taskq),
&(task->ctx.link));
if (rc >= 0) {
/* wake up task dispatcher */
task->owner = vtaskmgr;
vtaskmgr_wakeup(vtaskmgr);
}
return rc;
}

126
src/lib/window.c Normal file
View file

@ -0,0 +1,126 @@
#include <errno.h>
#include <stdlib.h>
#include "utils.h"
#include "xce/errnox.h"
#include "xce/types.h"
static void kill_timewindow_time(xce_timewindow_time_t* t)
{
FREEUP(t);
}
static void kill_timewindow_seg_config(xce_timewindow_seg_config_t* s)
{
if (s == NULL) {
return;
}
FREEUP(s->tz);
kill_timewindow_time(s->open);
kill_timewindow_time(s->close);
FREEUP(s);
}
static void kill_timewindow_config(xce_timewindow_config_t* w)
{
int i;
if (w == NULL) {
return;
}
if (w->segs != NULL) {
for (i = 0; i < w->nsegs; i++) {
xce_timewindow_seg_config_t* seg = w->segs[i];
kill_timewindow_seg_config(seg);
}
FREEUP(w->segs);
}
FREEUP(w);
}
void free_timewindow_config(xce_timewindow_config_t* w)
{
kill_timewindow_config(w);
}
static xce_timewindow_seg_config_t* dup_timewindow_seg_config(xce_timewindow_seg_config_t* src)
{
xce_timewindow_seg_config_t* seg = NULL;
if (src == NULL) {
errno = EINVAL;
return NULL;
}
seg = (xce_timewindow_seg_config_t*)calloc(1, sizeof(*seg));
if (seg == NULL) {
errno = ENOMEM;
return NULL;
}
seg->tz = strdup(src->tz);
if (seg->tz == NULL) {
kill_timewindow_seg_config(seg);
errno = ENOMEM;
return NULL;
}
seg->open = (xce_timewindow_time_t*)calloc(1, sizeof(xce_timewindow_time_t));
seg->close = (xce_timewindow_time_t*)calloc(1, sizeof(xce_timewindow_time_t));
if ((seg->open == NULL) || (seg->close == NULL)) {
kill_timewindow_seg_config(seg);
errno = ENOMEM;
return NULL;
}
memcpy(seg->open, src->open, sizeof(xce_timewindow_time_t));
memcpy(seg->close, src->close, sizeof(xce_timewindow_time_t));
return seg;
}
xce_timewindow_config_t* dup_timewindow_config(xce_timewindow_config_t* src)
{
xce_timewindow_config_t* w;
int i;
if (src == NULL) {
errno = EINVAL;
return NULL;
}
w = (xce_timewindow_config_t*)calloc(1, sizeof(*w));
if (w == NULL) {
errno = ENOMEM;
return NULL;
}
w->segs = (xce_timewindow_seg_config_t**)calloc(src->nsegs,
sizeof(xce_timewindow_seg_config_t*));
if (w->segs == NULL) {
kill_timewindow_config(w);
errno = ENOMEM;
return NULL;
}
for (i = 0; i < src->nsegs; i++) {
w->segs[i] = dup_timewindow_seg_config(src->segs[i]);
if (w->segs[i] == NULL) {
kill_timewindow_config(w);
return NULL;
}
}
w->nsegs = src->nsegs;
return w;
}

667
src/lib/xceapi.c Normal file
View file

@ -0,0 +1,667 @@
#include <errno.h>
#include "utils.h"
#include "xceapi.h"
int xce_hello(xce_ctx_t* ctx,
char* msg)
{
ioctx_t* ioctx;
int rc, status;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_hello_req(ioctx, msg);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
return status;
}
int xce_shutdown(xce_ctx_t* ctx)
{
ioctx_t* ioctx;
int rc;
int status;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_shutdown_req(ioctx);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
return status;
}
int xce_get(xce_ctx_t* ctx,
int table,
void*** data)
{
ioctx_t* ioctx;
int rc;
int status;
xce_match_t condition = {
.type = MatchCondition_condition_matchall
};
xce_get_t get = {
.table = table,
.condition = &condition
};
dataset_t getreply = {
.table = table,
.nrows = 0,
.rows = NULL
};
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
ctx->reply.u.get = &getreply;
rc = xce_get_req(ioctx, &get);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
if (status >= 0) {
*data = getreply.rows;
rc = getreply.nrows;
} else {
rc = status;
}
ctx->reply.u.get = NULL;
return rc;
}
int xce_reslist(xce_ctx_t* ctx,
xce_resource_t*** res)
{
int table = Data_data_resources;
return xce_get(ctx, table, (void***)res);
}
int xce_resval(xce_ctx_t* ctx,
char* host,
char* res,
xce_resval_t*** vals)
{
ioctx_t* ioctx;
int rc;
int status;
/* clang-format off */
xce_reskey_t reskey = {
.resname = res,
.hostname = host
};
xce_match_t condition = {
.type = MatchCondition_condition_matchreskey,
.condition = {
.reskey = &reskey
}
};
xce_get_t get = {
.table = Data_data_resvals,
.condition = &condition
};
dataset_t getreply = {
.table = Data_data_resvals,
.nrows = 0,
.rows = NULL
};
/* clang-format on */
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
ctx->reply.u.get = &getreply;
rc = xce_get_req(ioctx, &get);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
if (status >= 0) {
*vals = (xce_resval_t**)getreply.rows;
rc = getreply.nrows;
} else {
rc = status;
}
ctx->reply.u.get = NULL;
return rc;
}
int xce_join(xce_ctx_t* ctx,
int role,
hostattrs_t* attrs)
{
ioctx_t* ioctx;
int rc, status;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_join_req(ioctx, role, attrs);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
return status;
}
int xce_workerlist(xce_ctx_t* ctx,
xce_worker_t*** workers)
{
int table = Data_data_workers;
return xce_get(ctx, table, (void***)workers);
}
int xce_free_workers(int nworkers,
xce_worker_t* workers)
{
return 0;
}
int xce_jobdispatch(xce_ctx_t* ctx,
xce_job_dispatch_t* info)
{
ioctx_t* ioctx;
int rc, status;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_jobdispatch_req(ioctx, info);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
return status;
}
int xce_notify(xce_ctx_t* ctx,
xce_notify_data_t* data)
{
ioctx_t* ioctx;
int rc;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_notify_req(ioctx, data);
return rc;
}
int xce_jobsubmit(xce_ctx_t* ctx,
xce_job_submit_t* submit,
uint64_t* jobid)
{
ioctx_t* ioctx;
int rc, status;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_jobsubmit_req(ioctx, submit);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
if (status >= 0) {
*jobid = ctx->reply.u.jobid;
}
return status;
}
int xce_joblist_ex(xce_ctx_t* ctx,
int sched,
xce_job_t*** jobs)
{
int table;
if (sched) {
table = Data_data_schedjobs;
} else {
table = Data_data_jobs;
}
return xce_get(ctx, table, (void***)jobs);
}
int xce_sched_joblist(xce_ctx_t* ctx,
xce_job_t*** jobs)
{
return xce_joblist_ex(ctx, 1, jobs);
}
int xce_joblist(xce_ctx_t* ctx,
xce_job_t*** jobs)
{
return xce_joblist_ex(ctx, 0, jobs);
}
int xce_varlist(xce_ctx_t* ctx,
xce_config_t*** vars)
{
#if 0
int table = XCETables_conf;
return xce_get(ctx, table, (void***)vars);
#endif
return 0;
}
int xce_queuelist(xce_ctx_t* ctx,
xce_queue_t*** queues)
{
#if 0
int table = XCETables_queues;
return xce_get(ctx, table, (void***)queues);
#else
return 0;
#endif
}
int xce_free_queues(int nqueues,
xce_queue_t* queues)
{
int i;
if (queues == NULL) {
return -EINVAL;
}
for (i = 0; i < nqueues; i++) {
FREEUP(queues[i].resreq);
}
return 0;
}
int xce_grouplist(xce_ctx_t* ctx,
int group_type,
xce_group_t*** groups)
{
#if 0
int table;
switch (group_type) {
case 0:
table = XCETables_ugroups;
break;
default:
table = XCETables_hgroups;
break;
}
return xce_get(ctx, table, (void***)groups);
#else
return 0;
#endif
}
int xce_free_groups(int ngroups,
xce_group_t* groups)
{
/* TODO */
return 0;
}
int xce_clusterconf(xce_ctx_t* ctx,
xce_clusterconf_t** conf)
{
ioctx_t* ioctx;
int rc, status;
if ((ctx == NULL) || (conf == NULL)) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_clusterconf_req(ioctx);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
if (status < 0) {
return status;
}
MOVE_PTR((*conf), ctx->reply.u.clusterconf);
return 0;
}
int xce_update_resvals(xce_ctx_t* ctx,
int count,
xce_resval_t** vals)
{
ioctx_t* ioctx;
int rc;
int status;
/* clang-format off */
xce_resval_list_t valist = {
.count = count,
.vals = vals
};
xce_update_data_t data = {
.table = Update_data_resvals,
.data = {
.resvals = &valist
}
};
/* clang-format on */
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_update_req(ioctx, &data);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
return status;
}
int xce_update_jusage(xce_ctx_t* ctx,
uint64_t jobid,
int npids,
int* pids,
int ngids,
int* pgids,
int nusage,
xce_rusage_t** usages)
{
ioctx_t* ioctx;
int rc;
int status;
/* clang-format off */
xce_job_rusages_t rusages = {
.jobid = jobid,
.npids = npids,
.pids = pids,
.pgids = pgids,
.count = nusage,
.usages = usages
};
xce_update_data_t data = {
.table = Update_data_jobrusages,
.data = {
.jobrusages = &rusages }
};
/* clang-format on */
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_update_req(ioctx, &data);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
return status;
}
int xce_jobctrl(xce_ctx_t* ctx,
xce_jobctrl_t* ctrl)
{
ioctx_t* ioctx;
int rc;
int status;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_jobctrl_req(ioctx, ctrl);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
return status;
}
int xce_queuectrl(xce_ctx_t* ctx,
xce_queuectrl_t* ctrl)
{
ioctx_t* ioctx;
int rc;
int status;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_queuectrl_req(ioctx, ctrl);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
return status;
}
int xce_runtask(xce_ctx_t* ctx,
xce_taskrun_t* runinfo)
{
ioctx_t* ioctx;
int rc;
int status;
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state != XCE_CTX_RUN) {
return -EINVAL;
}
ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo));
if (ioctx == NULL) {
return -ENOMEM;
}
rc = xce_runtask_req(ioctx, runinfo);
if (rc < 0) {
return rc;
}
rc = cbuf_get(&(ctx->wbuf), &status);
if (rc < 0) {
return rc;
}
return status;
}

371
src/lib/xcectx.c Normal file
View file

@ -0,0 +1,371 @@
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include "dataq.h"
#include "mylock.h"
#include "netio.h"
#include "typemap.h"
#include "utils.h"
#include "xcectx.h"
static int handle_get_reply(xce_ctx_t* ctx,
xce_reply_t* reply)
{
xce_data_t* getdata = reply->data.getdata;
dataset_t* dataset = ctx->reply.u.get;
return extract_data(dataset, getdata);
}
static int handle_sub_reply(xce_ctx_t* ctx,
xce_reply_t* reply)
{
if (reply->data_which != RequestReply_data_jobid) {
return -1;
}
ctx->reply.u.jobid = reply->data.jobid;
return 1;
}
static int handle_reply(xce_ctx_t* ctx,
xce_reply_t* reply)
{
int rc = 0;
if (reply->status < 0) {
return reply->status;
}
switch (reply->opcode) {
case OPCode_get:
rc = handle_get_reply(ctx, reply);
break;
case OPCode_jobsub:
rc = handle_sub_reply(ctx, reply);
break;
case OPCode_clusterconf:
rc = -1;
if (reply->data_which == RequestReply_data_clusterconf) {
MOVE_PTR(ctx->reply.u.clusterconf,
reply->data.clusterconf);
rc = 1;
}
break;
default:
rc = -ENOENT;
break;
}
return rc;
}
static int vtask_entry(vtask_t* task)
{
endpoint_t* ep = task->ctx.ep;
xce_ctx_t* ctx = NULL;
int rc = 0;
xce_request_t request;
if (ep == NULL) {
return -EINVAL;
}
ctx = (xce_ctx_t*)ep->owner;
if (ctx == NULL) {
return -EINVAL;
}
rc = ioctx_decode(&(task->ctx), &request);
if (rc < 0) {
return rc;
}
if (request.opcode == OPCode_reply) {
int need_wake = 1;
int status = request.body.replymsg->status;
need_wake = handle_reply(ctx, request.body.replymsg);
if (need_wake) {
rc = xce_wakeup(ctx, (int)status);
}
} else {
int callnext = 1;
if ((request.opcode == OPCode_push) && (request.body_which == Request_body_pushmsg)) {
if (ctx->dataset == NULL) {
ctx->dataset = (dataset_t*)calloc(1, sizeof(dataset_t));
ctx->dataset->table = request.body.pushmsg->table;
}
callnext = extract_data(ctx->dataset,
request.body.pushmsg);
if (callnext) {
FREEUP(request.body.pushmsg);
request.body_which = Request_body_datamsg;
MOVE_PTR(request.body.datamsg, ctx->dataset);
}
}
if (callnext) {
rc = (ctx->handler)(&request);
}
}
free_Request(&request);
return 0;
}
static int handle_input(endpoint_t* ep)
{
xce_ctx_t* ctx = (xce_ctx_t*)ep->owner;
vtask_t* task;
int rc = 0;
task = vtask_alloc();
if (task == NULL) {
return -ENOMEM;
}
rc = vtask_init(task, (vtask_func_t)&vtask_entry, ep);
if (rc < 0) {
SET_ERROR(-rc);
if (rc == -EPIPE) {
/* connection broken */
TRACE("broken pipe, ep %p", ep);
}
FREEUP(task);
return rc;
}
rc = vtask_enq(&(ctx->vtaskmgr), task);
if (rc < 0) {
return rc;
}
return 0;
}
static int handle_output(endpoint_t* ep)
{
data_item_t* it;
ioctx_t* ctx;
int rc;
it = endpoint_deq(ep);
if (it == NULL) {
return 0;
}
ctx = ITPTR_TO_IOCTX(it);
rc = ioctx_flush(ctx, ep->fd);
ioctx_deref(ctx, 1);
return rc;
}
static int handle_io(struct epoll_event* p)
{
endpoint_t* ep = (endpoint_t*)p->data.ptr;
int rc = 0;
if ((p->events & EPOLLIN) != 0) {
rc = handle_input(ep);
}
if (rc >= 0) {
if ((p->events & EPOLLOUT) != 0) {
rc = handle_output(ep);
}
}
if (rc < 0) {
xce_ctx_t* ctx = (xce_ctx_t*)ep->owner;
iomgr_t* iomgr = &(ctx->iomgr);
iomgr_unmonitor(iomgr, ep);
endpoint_deref(ep);
xce_try_wakeup(ctx, -EIO);
ctx->state = XCE_CTX_DOWN;
return rc;
}
return 0;
}
int xce_ctx_init(xce_ctx_t* ctx,
char* name,
char* key)
{
int rc;
if ((ctx == NULL) || (name == NULL) || (key == NULL)) {
return -EINVAL;
}
memset(ctx, 0x0, sizeof(*ctx));
ctx->state = XCE_CTX_ERR;
ctx->myinfo.name = strdup(name);
ctx->myinfo.key = strdup(key);
if ((ctx->myinfo.name == NULL) || (ctx->myinfo.key == NULL)) {
FREEUP(ctx->myinfo.name);
FREEUP(ctx->myinfo.key);
return -ENOMEM;
}
rc = cbuf_init(&(ctx->wbuf), 1, sizeof(int));
if (rc < 0) {
FREEUP(ctx->myinfo.name);
FREEUP(ctx->myinfo.key);
return rc;
}
iomgr_init(&(ctx->iomgr));
vtaskmgr_init(&(ctx->vtaskmgr), 4);
ctx->ep = NULL;
ctx->state = XCE_CTX_INIT;
return 0;
}
void xce_ctx_fini(xce_ctx_t* ctx)
{
if (ctx == NULL) {
return;
}
xce_ctx_stop(ctx);
vtaskmgr_fini(&(ctx->vtaskmgr));
iomgr_fini(&(ctx->iomgr));
cbuf_fini(&(ctx->wbuf));
FREEUP(ctx->myinfo.name);
FREEUP(ctx->myinfo.key);
return;
}
int xce_ctx_set_handler(xce_ctx_t* ctx,
xce_request_handler_t handler)
{
if ((ctx == NULL) || (handler == NULL)) {
return -EINVAL;
}
ctx->handler = handler;
return 0;
}
int xce_ctx_set_endpoint(xce_ctx_t* ctx,
endpoint_t* ep)
{
if ((ctx == NULL) || (ep == NULL)) {
return -EINVAL;
}
ctx->ep = ep;
return 0;
}
int xce_ctx_start(xce_ctx_t* ctx)
{
int rc;
if (ctx == NULL) {
return -EINVAL;
}
if ((ctx->state != XCE_CTX_INIT) || (ctx->ep == NULL)) {
return -EINVAL;
}
endpoint_set_handler(ctx->ep,
handle_io, ctx);
rc = iomgr_monitor(&(ctx->iomgr),
ctx->ep);
if (rc < 0) {
ctx->state = XCE_CTX_ERR;
return rc;
}
iomgr_start(&(ctx->iomgr));
vtaskmgr_start(&(ctx->vtaskmgr));
ctx->state = XCE_CTX_RUN;
return 0;
}
int xce_ctx_stop(xce_ctx_t* ctx)
{
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->ep != NULL) {
iomgr_unmonitor(&(ctx->iomgr),
ctx->ep);
ctx->ep = NULL;
}
iomgr_stop(&(ctx->iomgr));
ctx->state = XCE_CTX_DOWN;
return 0;
}
int xce_wakeup(xce_ctx_t* ctx,
int status)
{
int rc = 0;
if (ctx == NULL) {
return -EINVAL;
}
rc = cbuf_tryput(&(ctx->wbuf), &status);
if (rc == -EAGAIN) {
/* pending data in wbuf, this is normal */
rc = 0;
}
return rc;
}
int xce_try_wakeup(xce_ctx_t* ctx,
int status)
{
if (ctx == NULL) {
return -EINVAL;
}
return cbuf_tryput(&(ctx->wbuf), &status);
}
void xce_block_tasks(xce_ctx_t* ctx)
{
if (ctx == NULL) {
return;
}
endpoint_block_tasks(ctx->ep);
}
void xce_unblock_tasks(xce_ctx_t* ctx)
{
if (ctx == NULL) {
return;
}
endpoint_unblock_tasks(ctx->ep);
vtaskmgr_wakeup(&(ctx->vtaskmgr));
}

99
src/lib/xlist.c Normal file
View file

@ -0,0 +1,99 @@
#include <errno.h>
#include <stdlib.h>
#include "utils.h"
#include "xlist.h"
int xlist_init(xlist_t* l,
int delta)
{
if ((l == NULL) || (delta <= 0)) {
return -EINVAL;
}
l->delta = delta;
l->data = NULL;
l->count = 0;
l->caps = 0;
return 0;
}
static int xlist_ensure(xlist_t* l)
{
void* p;
int nc, i;
if (l->count < l->caps) {
return 1;
}
nc = l->caps + l->delta;
p = (void*)realloc(l->data, nc * sizeof(void*));
if (p == NULL) {
return -ENOMEM;
}
l->data = p;
for(i = l->caps; i < nc; i ++) {
l->data[i] = NULL;
}
l->caps = nc;
return 1;
}
int xlist_store(xlist_t* l,
void* data)
{
int rc;
if (l == NULL) {
return -EINVAL;
}
rc = xlist_ensure(l);
if (rc < 0) {
return rc;
}
l->data[l->count] = data;
l->count++;
return 1;
}
void xlist_clear(xlist_t *l) {
if (l == NULL) {
return;
}
l->count = 0;
}
int xlist_iter(xlist_t *l,
xlist_iter_fn_t fn,
void *data) {
int i;
if ((l == NULL) || (fn == NULL)) {
return -EINVAL;
}
for(i = 0; i < l->count; i ++) {
(*fn)((void *)l->data[i], data);
}
return 0;
}
void xlist_fini(xlist_t* l)
{
if (l == NULL) {
return;
}
FREEUP(l->data);
return;
}

147
src/lib/xstring.c Normal file
View file

@ -0,0 +1,147 @@
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "htab.h"
#include "utils.h"
#include "xstring.h"
static void* xstring_create(objmgr_t*, objtype_t*, va_list);
static void xstring_fini(void*);
static void xstring_type_fini(objtype_t*);
static xstring_typedata_t xstring_typedata;
static objtype_t xstring = {
.type = "xstring",
.fn_create = (obj_create_fn_t)xstring_create,
.fn_fini = xstring_fini,
.fn_type_fini = (objtype_fini_fn_t)xstring_type_fini,
.typedata = &xstring_typedata
};
static void xstring_obj_killer(myobj_t* obj)
{
if (obj == NULL) {
return;
}
memset(obj, 0x0, sizeof(*obj));
free(obj);
}
int register_xstring(objmgr_t* mgr,
int nslots,
int delta)
{
ht_init(&(xstring_typedata.tab), nslots,
string_hash_key);
zarray_init(&(xstring_typedata.strings), delta,
(zarray_item_killer_t)xstring_obj_killer);
return objmgr_register(mgr, &xstring);
}
static void* xstring_create(objmgr_t* mgr,
objtype_t* type,
va_list ap)
{
char* s = va_arg(ap, char*);
char* p = NULL;
myobj_t* obj = NULL;
hent_t* e = NULL;
xstring_typedata_t* typedata = NULL;
int32_t idx;
if (s == NULL) {
SET_ERROR(EINVAL);
return NULL;
}
typedata = (xstring_typedata_t*)type->typedata;
e = ht_get((htab_t*)&(typedata->tab), (void*)s);
if (e != NULL) {
idx = e->data;
obj = (myobj_t*)zarray_get(&(typedata->strings), idx);
if (obj != NULL) {
p = MYOBJ_TO_OBJ(char*, obj);
return obj_ref(p, OBJREF_NOP);
}
SET_ERROR(EINVAL);
return NULL;
}
obj = (myobj_t*)calloc(1, sizeof(*obj) + strlen(s) + 1);
if (obj == NULL) {
return NULL;
}
idx = zarray_store(&(typedata->strings), obj);
if (idx < 0) {
free(obj);
SET_ERROR(-idx);
return NULL;
}
obj_init(mgr, type, idx, obj);
p = MYOBJ_TO_OBJ(char*, obj);
strcpy(p, s);
e = ht_add((htab_t*)&(typedata->tab), (void*)s);
if (e == NULL) {
obj_deref(p);
return NULL;
}
e->data = idx;
return p;
}
/* this will ONLY be called by obj_deref() */
static void xstring_fini(void* s)
{
myobj_t* myobj;
objtype_t* typeval;
xstring_typedata_t* typedata;
int32_t idx;
if (s == NULL) {
return;
}
myobj = TO_MYOBJ(s);
typeval = myobj->type;
typedata = (xstring_typedata_t*)typeval->typedata;
if (typedata == NULL) {
return;
}
ht_del(&(typedata->tab), (void*)s);
idx = (int32_t)myobj->exdata;
if (idx >= 0) {
zarray_del(&(typedata->strings), idx);
}
return;
}
static void xstring_type_fini(objtype_t* typeval)
{
xstring_typedata_t* typedata = (xstring_typedata_t*)typeval->typedata;
if (typedata == NULL) {
return;
}
ht_fini(&(typedata->tab));
zarray_fini(&(typedata->strings));
}

277
src/lib/zarray.c Normal file
View file

@ -0,0 +1,277 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "utils.h"
#include "zarray.h"
int zarray_init(zarray_t* array,
int delta,
zarray_item_killer_t killer)
{
if ((array == NULL) || (delta <= 0)) {
return -EINVAL;
}
mylock_init(&(array->lock));
array->delta = delta;
array->data = NULL;
array->killer = killer;
array->count = 0;
array->caps = 0;
array->pos = 0;
return 0;
}
static int zarray_ensure_items(zarray_t* array,
int mincap)
{
int nc, i;
void* p;
if (mincap < array->caps) {
return 1;
}
nc = mincap;
if (nc < array->caps + array->delta) {
nc = array->caps + array->delta;
}
p = (void*)realloc(array->data, nc * sizeof(void*));
if (p == NULL) {
return -ENOMEM;
}
array->data = p;
for (i = array->caps; i < nc; i++) {
array->data[i] = NULL;
}
/* this will make we can get next free
* location quickly
*/
array->pos = array->caps;
array->caps = nc;
return 1;
}
int zarray_store(zarray_t* array,
void* data)
{
int rc, i;
if (array == NULL) {
return -EINVAL;
}
mylock_lock(&(array->lock));
rc = zarray_ensure_items(array, array->count + 1);
if (rc >= 0) {
int idx;
rc = -ENOMEM;
idx = array->pos;
for (i = 0; i < array->caps; i++) {
if (array->data[idx] == NULL) {
array->data[idx] = data;
array->count++;
rc = idx;
break;
}
idx++;
if (idx >= array->caps) {
idx = 0;
}
}
if (rc >= 0) {
array->pos = (rc + 1) % array->caps;
}
}
mylock_unlock(&(array->lock));
return rc;
}
int zarray_clear(zarray_t* array,
int idx)
{
if (array == NULL) {
return -EINVAL;
}
if ((idx < 0) || (idx >= array->caps)) {
return -EINVAL;
}
mylock_lock(&(array->lock));
array->data[idx] = NULL;
mylock_unlock(&(array->lock));
return 0;
}
void zarray_fini(zarray_t* array)
{
if (array == NULL) {
return;
}
if (array->data != NULL) {
int i;
if (array->killer != NULL) {
for (i = 0; i < array->caps; i++) {
if (array->data[i] != NULL) {
void* ptr = array->data[i];
array->data[i] = NULL;
(array->killer)(ptr);
}
}
}
free(array->data);
array->data = NULL;
}
}
int zarray_iter_ex(zarray_t* array,
xlist_t* l,
void* arg)
{
int i, j;
if ((array == NULL) || (l == NULL)) {
return -EINVAL;
}
mylock_lock(&(array->lock));
for (j = 0; j < l->count; j++) {
zarray_iter_fn_t f = (zarray_iter_fn_t)l->data[j];
if (f == NULL) {
continue;
}
for (i = 0; i < array->caps; i++) {
(*f)(arg, array->data[i]);
}
}
mylock_unlock(&(array->lock));
return 0;
}
int zarray_iter(zarray_t* array,
zarray_iter_fn_t f,
void* arg)
{
int rc;
xlist_t l;
if ((array == NULL) || (f == NULL)) {
return -EINVAL;
}
xlist_init(&l, 2);
xlist_store(&l, f);
rc = zarray_iter_ex(array, &l, arg);
xlist_fini(&l);
return rc;
}
int zarray_del(zarray_t* array,
int idx)
{
void* ptr = NULL;
if (array == NULL) {
return -EINVAL;
}
if ((idx < 0) && (idx >= array->caps)) {
return -EINVAL;
}
mylock_lock(&(array->lock));
ptr = array->data[idx];
array->data[idx] = NULL;
if (ptr != NULL) {
array->count--;
}
/* idx will be a usable position */
array->pos = idx;
mylock_unlock(&(array->lock));
if (array->killer != NULL) {
if (ptr != NULL) {
(array->killer)(ptr);
}
}
return 0;
}
int zarray_put(zarray_t* array,
int idx,
void* data)
{
int rc = 0;
/* clang-format off */
if ((array == NULL) ||
(idx < 0) ||
(data == NULL)) {
return -EINVAL;
}
/* clang-format on */
mylock_lock(&(array->lock));
rc = zarray_ensure_items(array, idx + 1);
if (rc >= 0) {
void* ptr = array->data[idx];
array->data[idx] = data;
rc = 0;
if (ptr != NULL) {
if (array->killer != NULL) {
array->killer(ptr);
}
} else {
array->count++;
}
}
mylock_unlock(&(array->lock));
return rc;
}
void* zarray_get(zarray_t* array,
int idx)
{
void* ptr = NULL;
/* clang-format off */
if ((array == NULL) ||
(idx < 0) ||
(idx >= array->caps)) {
SET_ERROR(EINVAL);
return NULL;
}
/* clang-format on */
mylock_lock(&(array->lock));
ptr = array->data[idx];
mylock_unlock(&(array->lock));
return ptr;
}

28
src/meson.build Normal file
View file

@ -0,0 +1,28 @@
project('xce',
['c'],
version: '0.0.1',
meson_version: '>=1.5',
default_options: [
'c_std=gnu17',
'c_args=-DDEBUG -O1'])
with_debug=false
if get_option('with_debug')
# add -DWITH_DEBUG=1
add_project_arguments('-DWITH_DEBUG=1', language: 'c')
with_debug=true
endif
if get_option('without_db')
add_project_arguments('-DWITHOUT_DB=1', language: 'c')
endif
add_project_arguments('-DVERSION_COMMIT_ID='+get_option('commit_id'), language: 'c')
include_dir = include_directories('include', 'include/xce')
subdir('lib')
# subdir('controller')
# subdir('worker')
# subdir('scheduler')

3
src/meson.options Normal file
View file

@ -0,0 +1,3 @@
option('with_debug', type: 'boolean', value: false, yield: true)
option('without_db', type: 'boolean', value: false, yield: true)
option('commit_id', type: 'string', value:'', yield: true)

69
src/schema/c.capnp Normal file
View file

@ -0,0 +1,69 @@
# Copyright (c) 2016 NetDEF, Inc. and contributors
# Licensed under the MIT License:
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
@0xc0183dd65ffef0f3;
annotation nameinfix @0x85a8d86d736ba637 (file): Text;
# add an infix (middle insert) for output file names
#
# "make" generally has implicit rules for compiling "foo.c" => "foo". This
# is very annoying with capnp since the rule will be "foo" => "foo.c", leading
# to a loop. $nameinfix (recommended parameter: "-gen") inserts its parameter
# before the ".c", so the filename becomes "foo-gen.c"
#
# Alternatively, add this Makefile rule to disable compiling "foo.capnp.c" -> "foo.capnp":
# %.capnp: ;
#
#
# ("foo" is really "foo.capnp", so it's foo.capnp-gen.c)
annotation fieldgetset @0xf72bc690355d66de (file): Void;
# generate getter & setter functions for accessing fields
#
# allows grabbing/putting values without de-/encoding the entire struct.
annotation donotinclude @0x8c99797357b357e9 (file): UInt64;
# do not generate an include directive for an import statement for the file with
# the given ID
annotation typedefto @0xcefaf27713042144 (struct, enum): Text;
# generate a typedef for the annotated struct or enum declaration
annotation namespace @0xf2c035025fec7c2b (file): Text;
# prefix structs with a name space string
annotation extraheader @0xbadb496d09cf4612 (file): Text;
# add extra preprocessor directives to the header
annotation extendedattribute @0xd187bca5c6844c24 (file): Text;
# add an extended attribute to each generated function
annotation codecgen @0xcccaac86283e2609 (file): Void;
# generate codec(encode/decode) to each type
annotation mapname @0xb9edf6fc2d8972b8 (*): Text;
# the mapped type name which will be encoded
annotation maplistcount @0xb6ea49eb8a9b0f9e (field): Text;
# the mapped list count field which will be encoded
annotation mapuniontag @0xdce06d41858f91ac (union, struct): Text;
# the mapped tag (which) of union

590
src/schema/controller.capnp Normal file
View file

@ -0,0 +1,590 @@
@0xdefcdf6377db2e8e;
using C = import "/c.capnp";
$C.fieldgetset;
$C.codecgen;
$C.extraheader("#include \"clusterconfig.h\"");
$C.extraheader("#include \"typemap.h\"");
enum OPCode {
nop @0;
reply @1;
hello @2;
join @3;
shutdown @4;
get @5;
push @6;
update @7;
jobdispatch @8;
startjob @9;
notify @10;
jobsub @11;
jobstatus @12;
jobrusage @13;
hostcontrol @14;
jobcontrol @15;
newschedjobs @16;
clusterconf @17;
queuecontrol @18;
runtasks @19;
}
struct PeerInfo $C.mapname("xce_peerinfo_t") {
host @0: Text $C.mapname("name");
key @1: Text;
}
struct StrList $C.mapname("xce_strlist_t") {
data @0: List(Text) $C.mapname("data") $C.maplistcount("count");
}
struct TimeWindowTime $C.mapname("xce_timewindow_time_t") {
day @0: UInt32 $C.mapname("day");
hour @1: UInt32 $C.mapname("hour");
min @2: UInt32 $C.mapname("min");
}
struct TimeWindowSeg $C.mapname("xce_timewindow_seg_config_t") {
timezone @0: Text $C.mapname("tz");
open @1: TimeWindowTime $C.mapname("open");
close @2: TimeWindowTime $C.mapname("close");
}
struct TimeWindow $C.mapname("xce_timewindow_config_t") {
segs @0: List(TimeWindowSeg) $C.mapname("segs") $C.maplistcount("nsegs");
}
struct Group $C.mapname("xce_group_t") {
name @0: Text $C.mapname("name");
members @1: List(Text) $C.mapname("members.data") $C.maplistcount("members.count");
exmembers @2: List(Text) $C.mapname("ex_members.data") $C.maplistcount("ex_members.count");
}
# This data structure will not be transfer in wire
# directly, it will be assembled by multiple Data packet
struct Dataset $C.mapname("dataset_t") {
table @0: UInt32;
nrows @1: UInt32;
rows @2: Void; # do NOT change this, it's place holder
}
struct ResKey $C.mapname("xce_reskey_t") {
resname @0: Text;
hostname @1: Text;
}
struct MatchCondition $C.mapname("xce_match_t") {
condition :union $C.mapuniontag("type") {
matchall @0: Void;
matchjid @1: UInt64 $C.mapname("jobid");
matchwname @2: Text $C.mapname("wname");
matchreskey @3: ResKey $C.mapname("reskey");
}
}
struct HostAttrs $C.mapname("hostattrs_t") {
type @0: Text $C.mapname("hosttype");
model @1: Text $C.mapname("hostmodel");
cpufactor @2: Float64;
maxcpus @3: Int32;
maxmem @4: Float64;
maxswap @5: Float64;
maxtmp @6: Float64;
ndisks @7: Int32;
}
struct Worker $C.mapname("xce_worker_t"){
name @0: Text;
attrs @1: HostAttrs;
status @2: UInt32;
dispatchWindow @3: TimeWindow $C.mapname("dispatch_window_config");
thresholds @4: List(Threshold) $C.mapname("thresholds") $C.maplistcount("nthresholds");
resvals @5: List(ValueWithIdx) $C.mapname("resvals_to_sched") $C.maplistcount("nresvals_to_sched");
}
enum HostRole {
client @0;
worker @1;
scheduler @2;
controller @3;
}
struct JoinData $C.mapname("xce_joindata_t") {
role @0: HostRole;
data :union {
nodata @1: Void;
attrs @2: HostAttrs;
}
}
struct Value $C.mapname("xce_val_t"){
u :union $C.mapuniontag("which") {
ivalue32 @0: Int32;
uvalue32 @1: UInt32;
ivalue64 @2: Int64;
uvalue64 @3: UInt64;
svalue @4: Text;
fvalue @5: Float64;
bvalue @6: Bool;
}
}
struct ValueWithIdx $C.mapname("xce_val_with_idx_t") {
idx @0: UInt32;
val @1: Value $C.mapname("val");
}
struct ConfigVar $C.mapname("xce_config_t") {
name @0: Text;
value @1: Text;
}
struct ResourceDistribution $C.mapname("res_distribution_t") {
value @0: Value;
hosts @1: List(Text) $C.maplistcount("nhosts");
}
struct Resource $C.mapname("xce_resource_t"){
name @0: Text;
desc @1: Text;
idx @2: Int32;
valtype @3: Int32;
ordtype @4: Int32;
flags @5: Int32;
interval @6: Int32;
lastReport @7: UInt64 $C.mapname("last_report");
distributions @8: List(ResourceDistribution) $C.maplistcount("ndistributions");
hostBased @9: Value $C.mapname("hbased_defined");
}
struct Threshold $C.mapname("xce_res_threshold_t"){
name @0: Text;
sched @1: Float64;
stop @2: Float64;
}
struct QueueConf $C.mapname("xce_queue_t") {
name @0: Text $C.mapname("queue");
attrs @1: UInt32;
status @2: UInt32;
priority @3: Int32;
acceptIntervals @4: Int32 $C.mapname("accept_interval");
schedDelay @5: Int32 $C.mapname("sched_delay");
resreq @6: Text;
users @7: Group $C.mapname("users");
hosts @8: Group $C.mapname("hosts");
thresholds @9: List(Threshold) $C.maplistcount("nthresholds");
preExec @10: Text $C.mapname("pre_exec");
postExec @11: Text $C.mapname("post_exec");
runWindow @12: TimeWindow $C.mapname("runwindow_config");
dispatchWindow @13: TimeWindow $C.mapname("dispatchwindow_config");
}
struct Conf4Sched $C.mapname("xce_conf4sched_t"){
clustername @0: Text;
configvars @1: List(ConfigVar) $C.mapname("confvars") $C.maplistcount("n_confvars");
resources @2: List(Resource) $C.maplistcount("n_resources");
queues @3: List(QueueConf) $C.maplistcount("n_queues");
ugroups @4: List(Group) $C.maplistcount("n_ugroups");
hgroups @5: List(Group) $C.maplistcount("n_hgroups");
resvals @6: List(ValueWithIdx) $C.mapname("resvals") $C.maplistcount("nresvals");
}
struct Conf4Worker $C.mapname("xce_conf4worker_t") {
clustername @0: Text;
configvars @1: List(ConfigVar) $C.mapname("confvars") $C.maplistcount("n_confvars");
}
struct ConfigData $C.mapname("xce_configdata_t") {
data :union $C.mapuniontag("data_which") {
schedconfig @0: Conf4Sched $C.mapname("conf4sched");
workerconfig @1: Conf4Worker $C.mapname("conf4worker");
}
}
struct JobPIDInfo $C.mapname("job_pidinfo_t"){
jobId @0: UInt64 $C.mapname("jobid");
pids @1: List(UInt32) $C.mapname("pids") $C.maplistcount("npids");
pgids @2: List(UInt32) $C.mapname("pgids") $C.maplistcount("npgids");
exdata @3: Text $C.mapname("exdata");
}
struct JobFail $C.mapname("job_failinfo_t"){
jobId @0: UInt64 $C.mapname("jobid");
code @1: Int32 $C.mapname("code");
desc @2: Text $C.mapname("detail");
stage @3: UInt32 $C.mapname("stage");
}
struct JobStartInfo $C.mapname("job_startinfo_t"){
exechome @0: Text;
execcwd @1: Text;
execuser @2: Text;
cmdline @3: Text;
exdata @4: Text;
launchtype @5: Text $C.mapname("launch_type");
qPreExec @6: Text $C.mapname("q_pre_exec");
qPostExec @7: Text $C.mapname("q_post_exec");
preExec @8: Text $C.mapname("job_pre_exec");
postExec @9: Text $C.mapname("job_post_exec");
}
struct Job $C.mapname("xce_job_t"){
jobid @0: UInt64;
queue @1: Text;
user @2: Text;
idx @3: UInt64;
subtime @4: UInt64 $C.mapname("sub_time");
queuetime @5: UInt64 $C.mapname("queue_time");
starttime @6: UInt64 $C.mapname("start_time");
finishtime @7: UInt64 $C.mapname("finish_time");
state @8: UInt32;
jobname @9: Text $C.mapname("job_name");
projectname @10: Text $C.mapname("project_name");
usergroup @11: Text $C.mapname("user_group");
desc @12: Text $C.mapname("job_description");
resreq @13: Text;
allocs @14: JobAlloc $C.mapname("allocs");
runtime @15: UInt32 $C.mapname("run_time");
pidinfo @16: JobPIDInfo;
startinfo @17: JobStartInfo $C.mapname("start_info");
mintasks @18: UInt32 $C.mapname("mintasks");
maxtasks @19: UInt32 $C.mapname("maxtasks");
}
struct SchedJob $C.mapname("xce_job_t"){
jobid @0: UInt64;
queue @1: Text;
user @2: Text;
idx @3: UInt64;
subtime @4: UInt64 $C.mapname("sub_time");
queuetime @5: UInt64 $C.mapname("queue_time");
starttime @6: UInt64 $C.mapname("start_time");
finishtime @7: UInt64 $C.mapname("finish_time");
state @8: UInt32;
jobname @9: Text $C.mapname("job_name");
projectname @10: Text $C.mapname("project_name");
usergroup @11: Text $C.mapname("user_group");
resreq @12: Text;
allocs @13: JobAlloc $C.mapname("allocs");
runtime @14: UInt32 $C.mapname("run_time");
mintasks @15: UInt32 $C.mapname("mintasks");
maxtasks @16: UInt32 $C.mapname("maxtasks");
}
struct JobData $C.mapname("xce_jobs_data_t") {
ntotal @0: UInt32 $C.mapname("n_total");
pos @1: UInt32;
jobs @2: List(Job) $C.maplistcount("count");
}
struct SchedJobData $C.mapname("xce_jobs_data_t") {
ntotal @0: UInt32 $C.mapname("n_total");
pos @1: UInt32;
jobs @2: List(SchedJob) $C.maplistcount("count");
}
struct WorkerData $C.mapname("xce_workers_data_t"){
ntotal @0: UInt32 $C.mapname("n_total");
pos @1: UInt32;
workers @2: List(Worker) $C.maplistcount("count");
}
struct ResourceData $C.mapname("xce_resource_data_t") {
ntotal @0: UInt32 $C.mapname("n_total");
pos @1: UInt32;
resources @2: List(Resource) $C.maplistcount("count");
}
struct ResourceVal $C.mapname("xce_resval_t") {
name @0: Text $C.mapname("name");
host @1: Text $C.mapname("host");
val @2: Value $C.mapname("val");
}
struct ResourceVals $C.mapname("xce_resval_data_t") {
ntotal @0: UInt32 $C.mapname("n_total");
pos @1: UInt32;
vals @2: List(ResourceVal) $C.mapname("vals") $C.maplistcount("count");
}
struct Data $C.mapname("xce_data_t"){
data :union $C.mapuniontag("table") {
schedjobs @0: SchedJobData $C.mapname("jobs");
schedworkers @1: WorkerData $C.mapname("workers");
jobs @2: JobData $C.mapname("jobs");
workers @3: WorkerData $C.mapname("workers");
resources @4: ResourceData $C.mapname("resources");
resvals @5: ResourceVals $C.mapname("resvals");
}
}
struct Get $C.mapname("xce_get_t") {
table @0: UInt32;
condition @1: MatchCondition;
}
struct ResValList $C.mapname("xce_resval_list_t") {
vals @0: List(ResourceVal) $C.mapname("vals") $C.maplistcount("count");
}
struct ResUsage $C.mapname("xce_rusage_t") {
name @0: Text $C.mapname("resname");
value @1: Float64 $C.mapname("value");
}
struct JobRusages $C.mapname("xce_job_rusages_t") {
jobid @0: UInt64 $C.mapname("jobid");
pids @1: List(Int32) $C.mapname("pids") $C.maplistcount("npids");
pgids @2: List(Int32) $C.mapname("pgids") $C.maplistcount("npgids");
usages @3: List(ResUsage) $C.mapname("usages") $C.maplistcount("count");
}
struct Update $C.mapname("xce_update_data_t") {
data :union $C.mapuniontag("table") {
nodata @0: Void;
resvals @1: ResValList $C.mapname("resvals");
jobrusages @2: JobRusages $C.mapname("jobrusages");
}
}
struct ResAlloc $C.mapname("xce_alloc_t"){
name @0: Text $C.mapname("resname");
resvId @1: Text $C.mapname("reserve");
instid @2: UInt32;
value @3: Float64;
from @4: UInt64; # alloc start time
duration @5: Int64;
}
struct HostAlloc $C.mapname("xce_host_alloc_t"){
host @0: Text;
allocs @1: List(ResAlloc) $C.mapname("allocs") $C.maplistcount("nallocs");
}
struct JobAlloc $C.mapname("xce_job_alloc_t"){
jobid @0: UInt64;
allocs @1: List(HostAlloc) $C.mapname("allocs") $C.maplistcount("nhosts");
}
struct JobDispatch $C.mapname("xce_job_dispatch_t"){
allocs @0: List(JobAlloc) $C.maplistcount("njobs");
}
struct HostLaunch $C.mapname("xce_host_launch_t") {
host @0: Text $C.mapname("host");
nranks @1: UInt32 $C.mapname("nranks");
}
struct JobLaunch $C.mapname("xce_launch_t") {
hosts @0: List(HostLaunch) $C.mapname("hosts") $C.maplistcount("nhosts");
}
struct JobExecInfo $C.mapname("xce_job_exec_t"){
jobid @0: UInt64;
startinfo @1: JobStartInfo $C.mapname("start_info");
launchinfo @2: JobLaunch $C.mapname("launchinfo");
}
struct JobFinishInfo $C.mapname("xce_jobfinish_t") {
jobid @0: UInt64;
code @1: Int32 $C.mapname("exit_code");
}
struct TaskPidInfo $C.mapname("xce_task_pidinfo_t") {
jobid @0: UInt64 $C.mapname("jobid");
host @1: Text $C.mapname("host");
taskidx @2: Int32 $C.mapname("taskidx");
pids @3: List(UInt32) $C.mapname("pids") $C.maplistcount("npids");
pgids @4: List(UInt32) $C.mapname("pgids") $C.maplistcount("npgids");
exdata @5: Text $C.mapname("exdata");
clientidx @6: UInt32 $C.mapname("clientidx");
}
struct TaskFailInfo $C.mapname("xce_task_failinfo_t") {
jobid @0: UInt64 $C.mapname("jobid");
host @1: Text $C.mapname("host");
taskidx @2: Int32 $C.mapname("taskidx");
code @3: Int32 $C.mapname("code");
detail @4: Text $C.mapname("detail");
clientidx @5: Int32 $C.mapname("clientidx");
}
struct TaskFinish $C.mapname("xce_task_finish_t") {
jobid @0: UInt64 $C.mapname("jobid");
host @1: Text $C.mapname("host");
taskidx @2: UInt32 $C.mapname("taskidx");
exitcode @3: Int32 $C.mapname("exit_code");
clientidx @4: Int32 $C.mapname("clientidx");
}
struct NotifyData $C.mapname("xce_notify_data_t"){
data :union $C.mapuniontag("event") $C.mapname("data"){
jobPidInfo @0: JobPIDInfo $C.mapname("pidinfo");
jobFailInfo @1: JobFail $C.mapname("failinfo");
jobDispatchFail @2: JobFail $C.mapname("dispatchfail");
jobFinishInfo @3: JobFinishInfo $C.mapname("finishinfo");
schedStartJob @4: UInt64 $C.mapname("sched_start_job");
schedExitJob @5: UInt64 $C.mapname("sched_exit_job");
schedFailJob @6: UInt64 $C.mapname("sched_fail_job");
schedUpdateJob @7: SchedJob $C.mapname("sched_update_job");
schedUpdateResvals @8: ResValList $C.mapname("sched_update_resvals");
stoppedJob @9: UInt64 $C.mapname("stopped_job");
resumedJob @10: UInt64 $C.mapname("resumed_job");
ckptinfo @11: CheckpointInfo $C.mapname("ckptinfo");
schedUpdateQueue @12: QueueConf $C.mapname("sched_update_queue");
taskPidInfo @13: TaskPidInfo $C.mapname("taskinfo");
taskFailInfo @14: TaskFailInfo $C.mapname("taskfailinfo");
taskFinish @15: TaskFinish $C.mapname("taskfinish");
postDoneJob @16: UInt64 $C.mapname("pdone_job");
}
}
struct ClusterConf $C.mapname("xce_clusterconf_t") {
name @0: Text;
resources @1: List(Resource) $C.mapname("reslist.res") $C.maplistcount("reslist.count");
queues @2: List(QueueConf) $C.mapname("qlist.queues") $C.maplistcount("qlist.count");
workers @3: List(Worker) $C.mapname("wlist.workers") $C.maplistcount("wlist.count");
}
struct JobSubmit $C.mapname("xce_job_submit_t") {
queue @0: Text;
user @1: Text;
cmdline @2: Text;
resreq @3: Text;
exdata @4: Text;
mintasks @5: UInt32;
maxtasks @6: UInt32;
}
struct JobSignal $C.mapname("xce_signal_t") {
signo @0: UInt32 $C.mapname("signo");
force @1: Int32 $C.mapname("force");
}
struct CheckpointOptions $C.mapname("xce_ckpt_options_t"){
kill @0: UInt32 $C.mapname("kill");
method @1: Text $C.mapname("method");
}
struct CheckpointInfo $C.mapname("xce_ckptinfo_t") {
jobid @0: UInt64;
ckptinfo @1: Text;
}
struct JobControl $C.mapname("xce_jobctrl_t") {
jobid @0: UInt64 $C.mapname("jobid");
u :union $C.mapuniontag("action") $C.mapname("u") {
siginfo @1: JobSignal;
ckptoption @2: CheckpointOptions;
}
}
struct QueueControl $C.mapname("xce_queuectrl_t") {
action @0: UInt32 $C.mapname("action");
queue @1: Text $C.mapname("queue");
}
struct RequestReply $C.mapname("xce_reply_t"){
seq @0: UInt64;
opcode @1: OPCode;
status @2: Int32;
data : union {
nodata @3: Void;
debugmsg @4: Text;
getdata @5: Data;
jobid @6: UInt64;
clusterconf @7: ClusterConf;
}
}
struct TaskHost $C.mapname("xce_taskhost_t") {
host @0: Text;
ntasks @1: UInt32;
exechome @2: Text;
execcwd @3: Text;
execuser @4: Text;
cmdline @5: Text;
exdata @6: Text;
launchtype @7: Text $C.mapname("launch_type");
}
struct RunTask $C.mapname("xce_taskrun_t") {
clientidx @0: Int32 $C.mapname("clientidx");
hosts @1: List(TaskHost) $C.mapname("taskhosts") $C.maplistcount("nhosts");
jobid @2: UInt64 $C.mapname("jobid");
}
struct Request $C.mapname("xce_request_t"){
opcode @0: OPCode;
seq @1: UInt64;
from @2: PeerInfo;
body : union {
nomsg @3: Void;
replymsg @4: RequestReply;
hellomsg @5: Text;
joinmsg @6: JoinData;
configpushmsg @7: ConfigData;
pushmsg @8: Data;
getmsg @9: Get;
datamsg @10: Dataset;
dispatchmsg @11: JobDispatch;
jobstartmsg @12: JobExecInfo;
notifymsg @13: NotifyData;
jobsubmsg @14: JobSubmit;
updatemsg @15: Update;
jobctrlmsg @16: JobControl;
queuectrlmsg @17: QueueControl;
runtaskmsg @18: RunTask;
}
}
struct HashZArrayConfig $C.mapname("hash_zarray_config_t") {
nHashSlots @0: UInt32 $C.mapname("nhash_slots");
delta @1: UInt32 $C.mapname("delta");
}
struct ResmgrConfig $C.mapname("resmgr_config_t") {
nHashSlots @0: UInt32 $C.mapname("nhash_slots");
delta @1: UInt32 $C.mapname("delta");
instDelta @2: UInt32 $C.mapname("inst_delta");
}
struct MasterCandidate $C.mapname("master_candidate_t") {
name @0: Text $C.mapname("name");
host @1: Text $C.mapname("host");
port @2: UInt32 $C.mapname("port");
}
struct HostConfig $C.mapname("xce_hostconfig_t") {
name @0: Text $C.mapname("name");
model @1: Text $C.mapname("hostmodel");
type @2: Text $C.mapname("hosttype");
mxj @3: UInt32 $C.mapname("mxj");
resources @4: List(ConfigVar) $C.mapname("resources") $C.maplistcount("nresources");
thresholds @5: List(Threshold) $C.mapname("thresholds") $C.maplistcount("nthresholds");
dispatchwindows @6: TimeWindow $C.mapname("dispatchwindow");
}
struct ClusterConfig $C.mapname("cluster_config_t") {
clusterName @0: Text $C.mapname("clustername");
port @1: UInt32 $C.mapname("port");
candidates @2: List(MasterCandidate) $C.mapname("candidates") $C.maplistcount("ncandidates");
heartbeatInterval @3: UInt32 $C.mapname("heartbeat_interval");
inactiveHeartbeatCount @4: UInt32 $C.mapname("inactive_heartbeat_count");
fetchJobInterval @5: UInt32 $C.mapname("fetch_job_interval");
netioTimeout @6: UInt32 $C.mapname("netio_timeout");
vcpus @7: UInt32 $C.mapname("vcpus");
resources @8: List(Resource) $C.mapname("resources") $C.maplistcount("nres");
queues @9: List(QueueConf) $C.mapname("queues") $C.maplistcount("nqueues");
ugroups @10: List(Group) $C.mapname("ugroups") $C.maplistcount("nugroups");
hgroups @11: List(Group) $C.mapname("hgroups") $C.maplistcount("nhgroups");
hostConfigs @12: List(HostConfig) $C.mapname("hconfigs") $C.maplistcount("nhconfigs");
jobmgr @13: HashZArrayConfig;
workermgr @14: HashZArrayConfig;
qmgr @15: HashZArrayConfig;
resmgr @16: ResmgrConfig;
xstrings @17: HashZArrayConfig;
}

2501
src/unity/unity.c Normal file

File diff suppressed because it is too large Load diff

698
src/unity/unity.h Normal file
View file

@ -0,0 +1,698 @@
/* =========================================================================
Unity - A Test Framework for C
ThrowTheSwitch.org
Copyright (c) 2007-24 Mike Karlesky, Mark VanderVoord, & Greg Williams
SPDX-License-Identifier: MIT
========================================================================= */
#ifndef UNITY_FRAMEWORK_H
#define UNITY_FRAMEWORK_H
#define UNITY
#define UNITY_VERSION_MAJOR 2
#define UNITY_VERSION_MINOR 6
#define UNITY_VERSION_BUILD 0
#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD)
#ifdef __cplusplus
extern "C"
{
#endif
#include "unity_internals.h"
/*-------------------------------------------------------
* Test Setup / Teardown
*-------------------------------------------------------*/
/* These functions are intended to be called before and after each test.
* If using unity directly, these will need to be provided for each test
* executable built. If you are using the test runner generator and/or
* Ceedling, these are optional. */
void setUp(void);
void tearDown(void);
/* These functions are intended to be called at the beginning and end of an
* entire test suite. suiteTearDown() is passed the number of tests that
* failed, and its return value becomes the exit code of main(). If using
* Unity directly, you're in charge of calling these if they are desired.
* If using Ceedling or the test runner generator, these will be called
* automatically if they exist. */
void suiteSetUp(void);
int suiteTearDown(int num_failures);
/*-------------------------------------------------------
* Test Reset and Verify
*-------------------------------------------------------*/
/* These functions are intended to be called before during tests in order
* to support complex test loops, etc. Both are NOT built into Unity. Instead
* the test runner generator will create them. resetTest will run teardown and
* setup again, verifying any end-of-test needs between. verifyTest will only
* run the verification. */
void resetTest(void);
void verifyTest(void);
/*-------------------------------------------------------
* Configuration Options
*-------------------------------------------------------
* All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above.
* Integers/longs/pointers
* - Unity attempts to automatically discover your integer sizes
* - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in <stdint.h>
* - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in <limits.h>
* - If you cannot use the automatic methods above, you can force Unity by using these options:
* - define UNITY_SUPPORT_64
* - set UNITY_INT_WIDTH
* - set UNITY_LONG_WIDTH
* - set UNITY_POINTER_WIDTH
* Floats
* - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons
* - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT
* - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats
* - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons
* - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default)
* - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE
* - define UNITY_DOUBLE_TYPE to specify something other than double
* - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors
* Output
* - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired
* - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure
* Optimization
* - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge
* - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests.
* Test Cases
* - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script
* Parameterized Tests
* - you'll want to create a define of TEST_CASE(...), TEST_RANGE(...) and/or TEST_MATRIX(...) which basically evaluates to nothing
* Tests with Arguments
* - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity
*-------------------------------------------------------
* Basic Fail and Ignore
*-------------------------------------------------------*/
#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message))
#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL)
#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message))
#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL)
#define TEST_MESSAGE(message) UnityMessage((message), __LINE__)
#define TEST_ONLY()
#ifdef UNITY_INCLUDE_PRINT_FORMATTED
#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), ##__VA_ARGS__)
#endif
/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails.
* This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */
#define TEST_PASS() TEST_ABORT()
#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0)
/*-------------------------------------------------------
* Build Directives
*-------------------------------------------------------
* These macros do nothing, but they are useful for additional build context.
* Tools (like Ceedling) can scan for these directives and make use of them for
* per-test-executable #include search paths and linking. */
/* Add source files to a test executable's compilation and linking. Ex: TEST_SOURCE_FILE("sandwiches.c") */
#define TEST_SOURCE_FILE(a)
/* Customize #include search paths for a test executable's compilation. Ex: TEST_INCLUDE_PATH("src/module_a/inc") */
#define TEST_INCLUDE_PATH(a)
/*-------------------------------------------------------
* Test Asserts (simple)
*-------------------------------------------------------*/
/* Boolean */
#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE")
#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE")
#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE")
#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE")
#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL")
#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL")
#define TEST_ASSERT_EMPTY(pointer) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, " Expected Empty")
#define TEST_ASSERT_NOT_EMPTY(pointer) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty")
/* Integers (of all sizes) */
#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL)
#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL)
#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL)
#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL)
/* Integer Not Equal To (of all sizes) */
#define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL)
/* Integer Greater Than/ Less Than (of all sizes) */
#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL)
/* Integer Ranges (of all sizes) */
#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL)
/* Integer Array Ranges (of all sizes) */
#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
/* Structs and Strings */
#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL)
/* Arrays */
#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
/* Arrays Compared To Single Value */
#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL)
/* Floating Point (If Enabled) */
#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
/* Double (If Enabled) */
#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
/* Shorthand */
#ifdef UNITY_SHORTHAND_AS_OLD
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
#endif
#ifdef UNITY_SHORTHAND_AS_INT
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
#ifdef UNITY_SHORTHAND_AS_MEM
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
#ifdef UNITY_SHORTHAND_AS_RAW
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal")
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
#endif
#ifdef UNITY_SHORTHAND_AS_NONE
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
/*-------------------------------------------------------
* Test Asserts (with additional messages)
*-------------------------------------------------------*/
/* Boolean */
#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message))
#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message))
#define TEST_ASSERT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, (message))
#define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message))
/* Integers (of all sizes) */
#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message))
#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message))
/* Integer Not Equal To (of all sizes) */
#define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message))
/* Integer Greater Than/ Less Than (of all sizes) */
#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message))
/* Integer Ranges (of all sizes) */
#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message))
/* Integer Array Ranges (of all sizes) */
#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
/* Structs and Strings */
#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message))
#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message))
/* Arrays */
#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
/* Arrays Compared To Single Value*/
#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message))
/* Floating Point (If Enabled) */
#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message))
/* Double (If Enabled) */
#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message))
/* Shorthand */
#ifdef UNITY_SHORTHAND_AS_OLD
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message))
#endif
#ifdef UNITY_SHORTHAND_AS_INT
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message)
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
#ifdef UNITY_SHORTHAND_AS_MEM
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message)
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
#ifdef UNITY_SHORTHAND_AS_RAW
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message)
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message)
#endif
#ifdef UNITY_SHORTHAND_AS_NONE
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
/* end of UNITY_FRAMEWORK_H */
#ifdef __cplusplus
}
#endif
#endif

1183
src/unity/unity_internals.h Normal file

File diff suppressed because it is too large Load diff

56
src/xce.nix Normal file
View file

@ -0,0 +1,56 @@
{
lib,
stdenv,
pkgs,
myCommitId,
withDebug? false,
withAsan? false,
withoutDb? false,
...
}:
stdenv.mkDerivation {
pname = "xce";
version = "0.0.1";
src = ./.;
nativeBuildInputs = [
pkgs.meson
pkgs.ninja
pkgs.capnproto
pkgs.pkg-config
pkgs.cmake
pkgs.go
pkgs.openssl
pkgs.libtirpc
pkgs.readline
pkgs.ncurses
pkgs.capnpc
pkgs.which
pkgs.findutils
pkgs.libuv
pkgs.elogind
pkgs.sqlite
pkgs.hwloc
pkgs.linux-pam
pkgs.zlog_with_pkgconf
pkgs.unity-test
];
build-system = [ pkgs.meson ];
dontStrip = (withDebug || withAsan);
separateDebugInfo = (withDebug || withAsan);
impureEnvVars = [ "HOME" ];
mesonFlags =[
(lib.optional withDebug "-Dwith_debug=true")
(lib.optional withAsan "-Db_sanitize=address")
(lib.optional withoutDb "-Dwithout_db=true")
("-Dcommit_id=" + myCommitId)
# (lib.optional (!with_debug) "-Dbuildtype=release")
];
}