diff --git a/include/villas/advio.h b/include/villas/advio.h index afbf3b14b..15c56ebd8 100644 --- a/include/villas/advio.h +++ b/include/villas/advio.h @@ -26,7 +26,11 @@ #include -#include "crypt.h" +#include + +#ifdef __cplusplus +extern "C"{ +#endif struct advio { CURL *curl; @@ -81,3 +85,7 @@ void arewind(AFILE *file); int adownload(AFILE *af, int resume); int aupload(AFILE *af, int resume); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/api.h b/include/villas/api.h index b56627306..6a9a1a37b 100644 --- a/include/villas/api.h +++ b/include/villas/api.h @@ -33,6 +33,10 @@ #include "api/session.h" +#ifdef __cplusplus +extern "C"{ +#endif + /* Forward declarations */ struct lws; struct super_node; @@ -81,3 +85,7 @@ int api_stop(struct api *a); int api_ws_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); int api_http_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/villas/api/session.h b/include/villas/api/session.h index 55835a8b4..65dfac659 100644 --- a/include/villas/api/session.h +++ b/include/villas/api/session.h @@ -30,6 +30,10 @@ #include #include +#ifdef __cplusplus +extern "C"{ +#endif + enum api_version { API_VERSION_UNKOWN = 0, API_VERSION_1 = 1 @@ -70,3 +74,7 @@ int api_session_destroy(struct api_session *s); int api_session_run_command(struct api_session *s, json_t *req, json_t **resp); char * api_session_name(struct api_session *s); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/atomic.h b/include/villas/atomic.h index 0eba94d48..2ae1a84be 100644 --- a/include/villas/atomic.h +++ b/include/villas/atomic.h @@ -21,7 +21,9 @@ * along with this program. If not, see . *********************************************************************************/ -#include "common.h" +#pragma once + +#include #ifdef __cplusplus @@ -37,4 +39,4 @@ typedef std::atomic atomic_state; typedef _Atomic enum state atomic_state; -#endif +#endif /* __cplusplus */ diff --git a/include/villas/bitset.h b/include/villas/bitset.h index 757774361..7e61147cd 100644 --- a/include/villas/bitset.h +++ b/include/villas/bitset.h @@ -26,6 +26,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + struct bitset { char *set; size_t dimension; @@ -62,4 +66,8 @@ int bitset_test(struct bitset *b, size_t bit); int bitset_cmp(struct bitset *a, struct bitset *b); /** Return an human readable representation of the bit set */ -char * bitset_dump(struct bitset *b); +char *bitset_dump(struct bitset *b); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/buffer.h b/include/villas/buffer.h index 8899f5fb0..77f679d67 100644 --- a/include/villas/buffer.h +++ b/include/villas/buffer.h @@ -29,9 +29,13 @@ #include "common.h" +#ifdef __cplusplus +extern "C" { +#endif + struct buffer { enum state state; - + char *buf; size_t len; size_t size; @@ -40,11 +44,15 @@ struct buffer { int buffer_init(struct buffer *b, size_t size); int buffer_destroy(struct buffer *b); - + void buffer_clear(struct buffer *b); int buffer_append(struct buffer *b, const char *data, size_t len); int buffer_parse_json(struct buffer *b, json_t **j); -int buffer_append_json(struct buffer *b, json_t *j); \ No newline at end of file +int buffer_append_json(struct buffer *b, json_t *j); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/villas/common.h b/include/villas/common.h index 41457b2e7..64de9bb8c 100644 --- a/include/villas/common.h +++ b/include/villas/common.h @@ -23,6 +23,10 @@ #pragma once +#ifdef __cplusplus +extern "C"{ +#endif + /* Common states for most objects in VILLASnode (paths, nodes, hooks, plugins) */ enum state { STATE_DESTROYED = 0, @@ -36,3 +40,13 @@ enum state { STATE_UNLOADED = 5, /* alias for STATE_STARTED used by struct plugin */ STATE_CLOSED = 5 /* alias for STATE_STARTED used by struct io */ }; + +/** Callback to destroy list elements. + * + * @param data A pointer to the data which should be freed. + */ +typedef int (*dtor_cb_t)(void *); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/compat.h b/include/villas/compat.h index ad574fda2..1cac42afb 100644 --- a/include/villas/compat.h +++ b/include/villas/compat.h @@ -20,8 +20,14 @@ * along with this program. If not, see . *********************************************************************************/ +#pragma once + #include +#ifdef __cplusplus +extern "C" { +#endif + #if JANSSON_VERSION_HEX < 0x020A00 size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags); #endif @@ -43,3 +49,7 @@ size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags); #define htobe32(x) OSSwapHostToBigInt32(x) #define htobe64(x) OSSwapHostToBigInt64(x) #endif /* __MACH__ */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/config.h.in b/include/villas/config.h.in index 68d56ee8c..419f0fa61 100644 --- a/include/villas/config.h.in +++ b/include/villas/config.h.in @@ -26,6 +26,10 @@ #pragma once +#ifdef __cplusplus +extern "C"{ +#endif + /* Paths */ #define PLUGIN_PATH PREFIX "/share/villas/node/plugins" #define WEB_PATH PREFIX "/share/villas/node/web" @@ -56,3 +60,7 @@ /* Required kernel version */ #define KERNEL_VERSION_MAJ 3 #define KERNEL_VERSION_MIN 6 + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/config_helper.h b/include/villas/config_helper.h index 6be9afe4b..abed550f7 100644 --- a/include/villas/config_helper.h +++ b/include/villas/config_helper.h @@ -27,14 +27,18 @@ #include "sample.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Convert a libconfig object to a jansson object */ -json_t * config_to_json(config_setting_t *cfg); +json_t *config_to_json(config_setting_t *cfg); /* Convert a jansson object into a libconfig object. */ int json_to_config(json_t *json, config_setting_t *parent); /* Create a JSON object from command line parameters. */ -json_t * json_load_cli(int argc, char *argv[]); +json_t *json_load_cli(int argc, char *argv[]); int json_object_extend_str(json_t *orig, const char *str); @@ -42,3 +46,7 @@ void json_object_extend_key_value(json_t *obj, const char *key, const char *valu /* Merge two JSON objects recursively. */ int json_object_extend(json_t *orig, json_t *merge); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/crypt.h b/include/villas/crypt.h index 9b5c7843b..29b99410e 100644 --- a/include/villas/crypt.h +++ b/include/villas/crypt.h @@ -25,9 +25,17 @@ #include #include +#ifdef __cplusplus +extern "C"{ +#endif + /** Calculate SHA1 hash of complete file \p f and place it into \p sha1. * * @param sha1[out] Must be SHA_DIGEST_LENGTH (20) in size. * @retval 0 Everything was okay. */ int sha1sum(FILE *f, unsigned char *sha1); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/villas/format_type.h b/include/villas/format_type.h index 805b930a3..d1a4a7cb5 100644 --- a/include/villas/format_type.h +++ b/include/villas/format_type.h @@ -25,6 +25,10 @@ #include +#ifdef __cplusplus +extern "C"{ +#endif + /* Forward declarations */ struct sample; struct io; @@ -104,3 +108,7 @@ struct format_type { }; struct format_type * format_type_lookup(const char *name); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/villas/formats/csv.h b/include/villas/formats/csv.h index d32c93f52..f9f944131 100644 --- a/include/villas/formats/csv.h +++ b/include/villas/formats/csv.h @@ -25,6 +25,9 @@ #include +#ifdef __cplusplus +extern "C" { +#endif /* Forward declarations. */ struct sample; @@ -32,3 +35,7 @@ void csv_header(struct io *io); int csv_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample *smps[], unsigned cnt); int csv_sprint(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample *smps[], unsigned cnt); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/formats/json-reserve.h b/include/villas/formats/json-reserve.h index 71280af59..f6e6c227b 100644 --- a/include/villas/formats/json-reserve.h +++ b/include/villas/formats/json-reserve.h @@ -24,6 +24,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct sample; struct io; @@ -33,3 +37,7 @@ int json_reserve_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, str int json_reserve_print(struct io *io, struct sample *smps[], unsigned cnt); int json_reserve_scan(struct io *io, struct sample *smps[], unsigned cnt); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/formats/json.h b/include/villas/formats/json.h index 50fb60aee..ea73e0ff6 100644 --- a/include/villas/formats/json.h +++ b/include/villas/formats/json.h @@ -24,6 +24,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct sample; @@ -32,3 +36,7 @@ int json_sscan(struct io *io, char *buf, size_t len, size_t *wbytes, struct samp int json_print(struct io *io, struct sample *smps[], unsigned cnt); int json_scan(struct io *io, struct sample *smps[], unsigned cnt); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/formats/msg.h b/include/villas/formats/msg.h index c10498c12..c69e21bbc 100644 --- a/include/villas/formats/msg.h +++ b/include/villas/formats/msg.h @@ -22,6 +22,10 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declaration */ struct msg; struct sample; @@ -53,3 +57,7 @@ int msg_to_sample(struct msg *msg, struct sample *smp); /** Copy fields form \p smp into \p msg. */ int msg_from_sample(struct msg *msg, struct sample *smp); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/formats/msg_format.h b/include/villas/formats/msg_format.h index 45930fae8..1dc4f87b5 100644 --- a/include/villas/formats/msg_format.h +++ b/include/villas/formats/msg_format.h @@ -25,6 +25,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /** The current version number for the message format */ #define MSG_VERSION 2 @@ -90,3 +94,7 @@ struct msg uint32_t i; /**< Integer values. */ } data[]; } __attribute__((packed)); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/formats/protobuf.h b/include/villas/formats/protobuf.h index 49f171555..d6dda00dc 100644 --- a/include/villas/formats/protobuf.h +++ b/include/villas/formats/protobuf.h @@ -25,6 +25,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct sample; @@ -33,3 +37,7 @@ int protobuf_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct /** Read struct sample's from buffer \p buf into samples \p smps. */ int protobuf_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample *smps[], unsigned cnt); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/formats/raw.h b/include/villas/formats/raw.h index 7d0b1e3b9..3ee518b2f 100644 --- a/include/villas/formats/raw.h +++ b/include/villas/formats/raw.h @@ -25,6 +25,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct sample; @@ -58,3 +62,7 @@ int raw_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct samp /** Read struct sample's from buffer \p buf into samples \p smps. */ int raw_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample *smps[], unsigned cnt); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/formats/villas_binary.h b/include/villas/formats/villas_binary.h index 79dd248e4..8fd4428c3 100644 --- a/include/villas/formats/villas_binary.h +++ b/include/villas/formats/villas_binary.h @@ -25,6 +25,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations. */ struct sample; struct msg; @@ -39,3 +43,7 @@ int villas_binary_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, s /** Read struct sample's from buffer \p buf into samples \p smps. */ int villas_binary_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample *smps[], unsigned cnt); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/formats/villas_human.h b/include/villas/formats/villas_human.h index 01ced6032..c372b14ef 100644 --- a/include/villas/formats/villas_human.h +++ b/include/villas/formats/villas_human.h @@ -25,6 +25,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct io; struct sample; @@ -33,3 +37,7 @@ void villas_human_header(struct io *io); int villas_human_print(struct io *io, struct sample *smps[], unsigned cnt); int villas_human_scan(struct io *io, struct sample *smps[], unsigned cnt); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/villas/hash_table.h b/include/villas/hash_table.h new file mode 100644 index 000000000..d8a79f873 --- /dev/null +++ b/include/villas/hash_table.h @@ -0,0 +1,75 @@ +/** A generic hash table + * + * @author Steffen Vogel + * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include +#include + +#include + +struct hash_table_entry { + void *key; + void *data; + + struct hash_table_entry *next; +}; + +/** A thread-safe hash table using separate chaing with linked lists. */ +struct hash_table { + enum state state; + + struct hash_table_entry **table; + + size_t size; + pthread_mutex_t lock; +}; + +/** Initialize a new hash table. + * + */ +int hash_table_init(struct hash_table *ht, size_t size); + +/** Destroy a hash table. + * + * + */ +int hash_table_destroy(struct hash_table *ht, dtor_cb_t dtor, bool release); + +/** Insert a new key/value pair into the hash table. + * + */ +int hash_table_insert(struct hash_table *ht, void *key, void *data); + +/** Delete a key from the hash table. + * + * + */ +int hash_table_delete(struct hash_table *ht, void *key); + +/** Perform a lookup in the hash table. + * + * @retval != NULL The value for the given key. + * @retval NULL The given key is not stored in the hash table. + */ +void * hash_table_lookup(struct hash_table *ht, void *key); + +/** Dump the contents of the hash table in a human readable format to stdout. */ +void hash_table_dump(struct hash_table *ht); diff --git a/include/villas/hist.h b/include/villas/hist.h index 935908576..477470956 100644 --- a/include/villas/hist.h +++ b/include/villas/hist.h @@ -28,6 +28,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + #define HIST_HEIGHT (LOG_WIDTH - 55) #define HIST_SEQ 17 @@ -103,3 +107,7 @@ int hist_dump_json(struct hist *h, FILE *f); /** Build a libjansson / JSON object of the histogram. */ json_t * hist_json(struct hist *h); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/hook.h b/include/villas/hook.h index eadd4c281..e80f6a46a 100644 --- a/include/villas/hook.h +++ b/include/villas/hook.h @@ -34,8 +34,12 @@ #pragma once -#include "hook_type.h" -#include "common.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* Forward declarations */ struct path; @@ -96,3 +100,7 @@ int hook_cmp_priority(const void *a, const void *b); * } */ int hook_parse_list(struct list *list, json_t *cfg, struct path *p, struct node *n); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/hook_type.h b/include/villas/hook_type.h index 6c6d7ec70..de1331a2e 100644 --- a/include/villas/hook_type.h +++ b/include/villas/hook_type.h @@ -39,6 +39,10 @@ #include +#ifdef __cplusplus +extern "C"{ +#endif + /* Forward declarations */ struct hook; struct sample; @@ -74,3 +78,6 @@ struct hook_type { struct hook_type * hook_type_lookup(const char *name); +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/villas/io.h b/include/villas/io.h index d24705a61..c9e8a07a6 100644 --- a/include/villas/io.h +++ b/include/villas/io.h @@ -23,9 +23,13 @@ #pragma once -#include "advio.h" -#include "common.h" -#include "node.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* Forward declarations */ struct sample; @@ -134,3 +138,7 @@ int io_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample * @retval <0 Something went wrong. */ int io_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct sample *smps[], unsigned cnt); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/kernel/if.h b/include/villas/kernel/if.h index 4a6068ad5..1d6420098 100644 --- a/include/villas/kernel/if.h +++ b/include/villas/kernel/if.h @@ -33,6 +33,10 @@ #include +#ifdef __cplusplus +extern "C"{ +#endif + #define IF_IRQ_MAX 3 /**< Maxmimal number of IRQs of an interface */ #ifndef SO_MARK @@ -121,4 +125,8 @@ int if_get_irqs(struct interface *i); */ int if_set_affinity(struct interface *i, int affinity); + +#ifdef __cplusplus +} +#endif /** @} */ diff --git a/include/villas/kernel/kernel.h b/include/villas/kernel/kernel.h index 6b39dc40c..265e125f4 100644 --- a/include/villas/kernel/kernel.h +++ b/include/villas/kernel/kernel.h @@ -28,6 +28,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct version; @@ -85,6 +89,10 @@ int kernel_get_page_size(); int kernel_get_hugepage_size(); /** Set SMP affinity of IRQ */ -int kernel_irq_setaffinity(unsigned irq, uintmax_t new, uintmax_t *old); +int kernel_irq_setaffinity(unsigned irq, uintmax_t new , uintmax_t *old ); + +#ifdef __cplusplus +} +#endif /** @} */ diff --git a/include/villas/kernel/nl-private.h b/include/villas/kernel/nl-private.h index 968cdb209..ded3b0a97 100644 --- a/include/villas/kernel/nl-private.h +++ b/include/villas/kernel/nl-private.h @@ -1,5 +1,9 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + #define SCH_NETEM_ATTR_DIST 0x2000 struct rtnl_netem_corr @@ -43,3 +47,7 @@ struct rtnl_netem }; void *rtnl_tc_data(struct rtnl_tc *tc); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/kernel/nl.h b/include/villas/kernel/nl.h index 879312cd9..894df4f9f 100644 --- a/include/villas/kernel/nl.h +++ b/include/villas/kernel/nl.h @@ -29,6 +29,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** Get index of outgoing interface for given destination address. * * @retval >=0 Interface index of outgoing interface. @@ -37,9 +41,13 @@ int nl_get_egress(struct nl_addr *addr); /** Get or create global netlink socket. */ -struct nl_sock * nl_init(); +struct nl_sock *nl_init(); /** Close and free global netlink socket. */ void nl_shutdown(); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/kernel/rt.h b/include/villas/kernel/rt.h index f1c8b5bc6..c6c5c0e9b 100644 --- a/include/villas/kernel/rt.h +++ b/include/villas/kernel/rt.h @@ -26,6 +26,10 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + int rt_init(int priority, int affinity); int rt_set_affinity(int affinity); @@ -43,4 +47,8 @@ int rt_lock_memory(); */ int rt_is_preemptible(); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/kernel/tc.h b/include/villas/kernel/tc.h index a64439be8..0b5afbbc3 100644 --- a/include/villas/kernel/tc.h +++ b/include/villas/kernel/tc.h @@ -37,6 +37,10 @@ #include +#ifdef __cplusplus +extern "C"{ +#endif + typedef uint32_t tc_hdl_t; struct interface; @@ -72,4 +76,8 @@ int tc_prio(struct interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl */ int tc_mark(struct interface *i, struct rtnl_cls **cls, tc_hdl_t flowid, uint32_t mark); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/kernel/tc_netem.h b/include/villas/kernel/tc_netem.h index 78dc10951..b6d0a86c4 100644 --- a/include/villas/kernel/tc_netem.h +++ b/include/villas/kernel/tc_netem.h @@ -37,6 +37,10 @@ #include +#ifdef __cplusplus +extern "C"{ +#endif + typedef uint32_t tc_hdl_t; struct interface; @@ -70,4 +74,8 @@ int tc_netem(struct interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hd int tc_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/list.h b/include/villas/list.h index f3dd82bc8..ab79d6774 100644 --- a/include/villas/list.h +++ b/include/villas/list.h @@ -8,7 +8,22 @@ * * @file * @author Steffen Vogel - * @copyright 20177, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC +* + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . *********************************************************************************/ #pragma once @@ -17,7 +32,11 @@ #include #include -#include "common.h" +#include + +#ifdef __cplusplus +extern "C"{ +#endif #define LIST_CHUNKSIZE 16 @@ -46,12 +65,6 @@ __attribute__((destructor(105))) static void UNIQUE(__dtor)() { \ #define list_first(list) list_at(list, 0) #define list_last(list) list_at(list, (list)->length-1) -/** Callback to destroy list elements. - * - * @param data A pointer to the data which should be freed. - */ -typedef int (*dtor_cb_t)(void *); - /** Callback to search or sort a list. */ typedef int (*cmp_cb_t)(const void *, const void *); @@ -120,3 +133,7 @@ int list_set(struct list *l, int index, void *value); * @retval >=0 Entry \p value was found at returned index. */ ssize_t list_index(struct list *l, void *value); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/log_config.h b/include/villas/log_config.h index 86c2281ba..d7322fd0a 100644 --- a/include/villas/log_config.h +++ b/include/villas/log_config.h @@ -29,9 +29,18 @@ struct log; #include "log.h" +#ifdef __cplusplus +extern "C"{ +#endif + /** Parse logging configuration. */ int log_parse(struct log *l, json_t *cfg); /** Print configuration error and exit. */ void jerror(json_error_t *err, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); + + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/villas/mapping.h b/include/villas/mapping.h index 498d0e455..5bee741f6 100644 --- a/include/villas/mapping.h +++ b/include/villas/mapping.h @@ -25,9 +25,13 @@ #include -#include "stats.h" -#include "common.h" -#include "list.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* Forward declarations */ struct stats; @@ -93,3 +97,7 @@ int mapping_parse(struct mapping_entry *e, json_t *cfg, struct list *nodes); int mapping_parse_str(struct mapping_entry *e, const char *str, struct list *nodes); int mapping_parse_list(struct list *l, json_t *cfg, struct list *nodes); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/memory.h b/include/villas/memory.h index 9514d748d..54da2bbc0 100644 --- a/include/villas/memory.h +++ b/include/villas/memory.h @@ -21,10 +21,14 @@ * along with this program. If not, see . *********************************************************************************/ +#pragma once + #include #include -#pragma once +#ifdef __cplusplus +extern "C" { +#endif #define HUGEPAGESIZE (1 << 21) @@ -59,15 +63,15 @@ enum memblock_flags { /** Descriptor of a memory block. Associated block always starts at * &m + sizeof(struct memblock). */ struct memblock { - struct memblock* prev; - struct memblock* next; + struct memblock *prev; + struct memblock *next; size_t len; /** #include -#include "node_type.h" -#include "sample.h" -#include "list.h" -#include "queue.h" -#include "common.h" +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C"{ +#endif struct node_direction { int enabled; @@ -160,5 +164,8 @@ int node_fd(struct node *n); struct memtype * node_memtype(struct node *n, struct memtype *parent); +#ifdef __cplusplus +} +#endif /** @} */ diff --git a/include/villas/node_type.h b/include/villas/node_type.h index 6de269f52..b34eb8d8f 100644 --- a/include/villas/node_type.h +++ b/include/villas/node_type.h @@ -24,6 +24,10 @@ * @{ *********************************************************************************/ +#ifdef __cplusplus +extern "C"{ +#endif + #pragma once #include @@ -85,6 +89,14 @@ struct node_type { */ int (*parse)(struct node *n, json_t *cfg); + /** Check the current node configuration for plausability and errors. + * + * @param n A pointer to the node object. + * @retval 0 Success. Node configuration is good. + * @retval <0 Error. The node configuration is bogus. + */ + int (*check)(struct node *n); + /** Parse node from command line arguments. */ int (*parse_cli)(struct node *n, int argc, char *argv[]); @@ -172,4 +184,8 @@ const char * node_type_name(struct node_type *vt); struct node_type * node_type_lookup(const char *name); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/nodes/amqp.h b/include/villas/nodes/amqp.h index e23154108..b343190c1 100644 --- a/include/villas/nodes/amqp.h +++ b/include/villas/nodes/amqp.h @@ -35,6 +35,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct format_type; @@ -81,4 +85,8 @@ int amqp_read(struct node *n, struct sample *smps[], unsigned cnt); /** @see node_type::write */ int amqp_write(struct node *n, struct sample *smps[], unsigned cnt); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/nodes/cbuilder.h b/include/villas/nodes/cbuilder.h index c90e73db1..2513fb94e 100644 --- a/include/villas/nodes/cbuilder.h +++ b/include/villas/nodes/cbuilder.h @@ -33,6 +33,10 @@ #include +#ifdef __cplusplus +extern "C"{ +#endif + /* Forward declaration */ struct cbuilder; @@ -65,4 +69,8 @@ struct cbuilder { int eventfd; /**< Eventfd for synchronizing cbuilder_read() / cbuilder_write() access. */ }; +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/nodes/comedi.h b/include/villas/nodes/comedi.h index 311874ca6..3aa01f5b3 100644 --- a/include/villas/nodes/comedi.h +++ b/include/villas/nodes/comedi.h @@ -35,6 +35,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + // whether to use read() or mmap() kernel interface #define COMEDI_USE_READ (1) //#define COMEDI_USE_READ (0) @@ -45,20 +49,19 @@ struct comedi_chanspec { }; struct comedi_direction { - int subdevice; ///< Comedi subdevice - int buffer_size; ///< Comedi's kernel buffer size in kB - int sample_size; ///< Size of a single measurement sample - int sample_rate_hz; ///< Sample rate in Hz - bool present; ///< Config present - bool enabled; ///< Card is started successfully - bool running; ///< Card is actively transfering samples - struct timespec started; ///< Timestamp when sampling started - struct timespec last_debug; ///< Timestamp of last debug output - size_t counter; ///< Number of villas samples transfered + int subdevice; ///< Comedi subdevice + int buffer_size; ///< Comedi's kernel buffer size in kB + int sample_size; ///< Size of a single measurement sample + int sample_rate_hz; ///< Sample rate in Hz + bool present; ///< Config present + bool enabled; ///< Card is started successfully + bool running; ///< Card is actively transfering samples + struct timespec started; ///< Timestamp when sampling started + struct timespec last_debug; ///< Timestamp of last debug output + size_t counter; ///< Number of villas samples transfered struct comedi_chanspec *chanspecs; ///< Range and maxdata config of channels - unsigned *chanlist; ///< Channel list in comedi's packed format - size_t chanlist_len; ///< Number of channels for this direction - + unsigned *chanlist; ///< Channel list in comedi's packed format + size_t chanlist_len; ///< Number of channels for this direction char* buffer; char* bufptr; @@ -70,8 +73,8 @@ struct comedi { comedi_t *dev; #if COMEDI_USE_READ - char* buf; - char* bufptr; + char *buf; + char *bufptr; #else char *map; size_t bufpos; @@ -100,3 +103,7 @@ int comedi_read(struct node *n, struct sample *smps[], unsigned cnt); int comedi_write(struct node *n, struct sample *smps[], unsigned cnt); /** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/nodes/file.h b/include/villas/nodes/file.h index da105b0b8..498afb0a4 100644 --- a/include/villas/nodes/file.h +++ b/include/villas/nodes/file.h @@ -33,6 +33,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define FILE_MAX_PATHLEN 512 struct file { @@ -85,3 +89,7 @@ int file_read(struct node *n, struct sample *smps[], unsigned cnt); int file_write(struct node *n, struct sample *smps[], unsigned cnt); /** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/nodes/iec61850.h b/include/villas/nodes/iec61850.h index 7dd31e4c2..9f7944b4b 100644 --- a/include/villas/nodes/iec61850.h +++ b/include/villas/nodes/iec61850.h @@ -38,6 +38,10 @@ #include #include +#ifdef __cplusplus +extern "C"{ +#endif + enum iec61850_type { /* According to IEC 61850-7-2 */ IEC61850_TYPE_BOOLEAN, @@ -107,4 +111,8 @@ int iec61850_receiver_stop(struct iec61850_receiver *r); int iec61850_receiver_destroy(struct iec61850_receiver *r); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/nodes/iec61850_sv.h b/include/villas/nodes/iec61850_sv.h index 8b43644e1..7213c20fb 100644 --- a/include/villas/nodes/iec61850_sv.h +++ b/include/villas/nodes/iec61850_sv.h @@ -40,6 +40,10 @@ #include #include +#ifdef __cplusplus +extern "C"{ +#endif + struct iec61850_sv { char *interface; int app_id; @@ -97,4 +101,8 @@ int iec61850_sv_write(struct node *n, struct sample *smps[], unsigned cnt); int iec61850_sv_fd(struct node *n); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/nodes/influxdb.h b/include/villas/nodes/influxdb.h index 919725b55..3abbde1f9 100644 --- a/include/villas/nodes/influxdb.h +++ b/include/villas/nodes/influxdb.h @@ -31,6 +31,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct node; struct sample; @@ -63,4 +67,8 @@ int influxdb_close(struct node *n); /** @see node_type::write */ int influxdb_write(struct node *n, struct sample *smps[], unsigned cnt); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/nodes/loopback.h b/include/villas/nodes/loopback.h index cfbb5d33a..4cff73eb6 100644 --- a/include/villas/nodes/loopback.h +++ b/include/villas/nodes/loopback.h @@ -32,6 +32,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct node; struct sample; @@ -64,4 +68,8 @@ int loopback_read(struct node *n, struct sample *smps[], unsigned cnt); /** @see node_type::write */ int loopback_write(struct node *n, struct sample *smps[], unsigned cnt); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/nodes/mqtt.h b/include/villas/nodes/mqtt.h index 22d12dd61..40713c8b2 100644 --- a/include/villas/nodes/mqtt.h +++ b/include/villas/nodes/mqtt.h @@ -34,6 +34,10 @@ #include #include +#ifdef __cplusplus +extern "C"{ +#endif + /* Forward declarations */ struct format_type; struct mosquitto; @@ -96,4 +100,8 @@ int mqtt_read(struct node *n, struct sample *smps[], unsigned cnt); /** @see node_type::write */ int mqtt_write(struct node *n, struct sample *smps[], unsigned cnt); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/nodes/nanomsg.h b/include/villas/nodes/nanomsg.h index 81feb12bf..11b5d2a3e 100644 --- a/include/villas/nodes/nanomsg.h +++ b/include/villas/nodes/nanomsg.h @@ -33,6 +33,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** The maximum length of a packet which contains stuct msg. */ #define NANOMSG_MAX_PACKET_LEN 1500 @@ -72,4 +76,8 @@ int nanomsg_read(struct node *n, struct sample *smps[], unsigned cnt); /** @see node_type::write */ int nanomsg_write(struct node *n, struct sample *smps[], unsigned cnt); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/nodes/ngsi.h b/include/villas/nodes/ngsi.h index 67c9bc766..6160907a5 100644 --- a/include/villas/nodes/ngsi.h +++ b/include/villas/nodes/ngsi.h @@ -43,6 +43,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + struct node; struct ngsi { @@ -95,3 +99,7 @@ int ngsi_read(struct node *n, struct sample *smps[], unsigned cnt); int ngsi_write(struct node *n, struct sample *smps[], unsigned cnt); /** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/nodes/opal.h b/include/villas/nodes/opal.h index f39668e9e..10d96e514 100644 --- a/include/villas/nodes/opal.h +++ b/include/villas/nodes/opal.h @@ -31,8 +31,8 @@ #include -#include "node.h" -#include "msg.h" +#include +#include /* Define RTLAB before including OpalPrint.h for messages to be sent * to the OpalDisplay. Otherwise stdout will be used. */ @@ -41,6 +41,10 @@ #include "AsyncApi.h" #include "OpalGenAsyncParamCtrl.h" +#ifdef __cplusplus +extern "C" { +#endif + struct opal { int reply; int mode; @@ -85,4 +89,8 @@ int opal_read(struct node *n, struct sample *smps[], unsigned cnt); /** @see node_type::write */ int opal_write(struct node *n, struct sample *smps[], unsigned cnt); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/nodes/shmem.h b/include/villas/nodes/shmem.h index dc156064f..0426645ce 100644 --- a/include/villas/nodes/shmem.h +++ b/include/villas/nodes/shmem.h @@ -36,6 +36,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** Node-type for shared memory communication. * @see node_type */ @@ -66,3 +70,7 @@ int shmem_read(struct node *n, struct sample *smps[], unsigned cnt); int shmem_write(struct node *n, struct sample *smps[], unsigned cnt); /** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/nodes/signal_generator.h b/include/villas/nodes/signal_generator.h index 7c669aa16..18d0c0b48 100644 --- a/include/villas/nodes/signal_generator.h +++ b/include/villas/nodes/signal_generator.h @@ -32,6 +32,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct node; struct sample; @@ -90,3 +94,7 @@ int signal_generator_read(struct node *n, struct sample *smps[], unsigned cnt); enum signal_generator_type signal_generator_lookup_type(const char *type); /** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/nodes/socket.h b/include/villas/nodes/socket.h index 345792823..6cccdf848 100644 --- a/include/villas/nodes/socket.h +++ b/include/villas/nodes/socket.h @@ -50,6 +50,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct format_type; @@ -155,3 +159,7 @@ int socket_parse_addr(const char *str, struct sockaddr *sa, enum socket_layer la int socket_compare_addr(struct sockaddr *x, struct sockaddr *y); /** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/nodes/stats.h b/include/villas/nodes/stats.h index 27caf6621..89a161656 100644 --- a/include/villas/nodes/stats.h +++ b/include/villas/nodes/stats.h @@ -33,6 +33,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct node; struct sample; @@ -51,7 +55,7 @@ struct stats_node { int stats_node_init(struct super_node *sn); /** @see node_type::print */ -char * stats_node_print(struct node *n); +char *stats_node_print(struct node *n); /** @see node_type::parse */ int stats_node_parse(struct node *n, json_t *cfg); @@ -65,4 +69,8 @@ int stats_node_stop(struct node *n); /** @see node_type::read */ int stats_node_read(struct node *n, struct sample *smps[], unsigned cnt); +#ifdef __cplusplus +} +#endif + /** @} */ diff --git a/include/villas/nodes/test_rtt.h b/include/villas/nodes/test_rtt.h index a0e14e533..20f204410 100644 --- a/include/villas/nodes/test_rtt.h +++ b/include/villas/nodes/test_rtt.h @@ -33,6 +33,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct test_rtt; struct node; @@ -81,3 +85,7 @@ int test_rtt_read(struct node *n, struct sample *smps[], unsigned cnt); int test_rtt_write(struct node *n, struct sample *smps[], unsigned cnt); /** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/nodes/websocket.h b/include/villas/nodes/websocket.h index 6c61053b1..0e5097a17 100644 --- a/include/villas/nodes/websocket.h +++ b/include/villas/nodes/websocket.h @@ -38,6 +38,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define DEFAULT_WEBSOCKET_QUEUELEN (DEFAULT_QUEUELEN * 64) #define DEFAULT_WEBSOCKET_SAMPLELEN DEFAULT_SAMPLELEN @@ -114,3 +118,7 @@ int websocket_read(struct node *n, struct sample *smps[], unsigned cnt); int websocket_write(struct node *n, struct sample *smps[], unsigned cnt); /** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/nodes/zeromq.h b/include/villas/nodes/zeromq.h index afdf4a9b7..4f31de46e 100644 --- a/include/villas/nodes/zeromq.h +++ b/include/villas/nodes/zeromq.h @@ -35,6 +35,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #if ZMQ_BUILD_DRAFT_API && (ZMQ_VERSION_MAJOR > 4 || (ZMQ_VERSION_MAJOR == 4 && ZMQ_VERSION_MINOR >= 2)) #define ZMQ_BUILD_DISH 1 #endif @@ -104,3 +108,7 @@ int zeromq_read(struct node *n, struct sample *smps[], unsigned cnt); int zeromq_write(struct node *n, struct sample *smps[], unsigned cnt); /** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/path.h b/include/villas/path.h index 1db52dcf4..8df955f55 100644 --- a/include/villas/path.h +++ b/include/villas/path.h @@ -32,14 +32,18 @@ #include #include -#include "list.h" -#include "queue.h" -#include "pool.h" -#include "bitset.h" -#include "common.h" -#include "hook.h" -#include "mapping.h" -#include "task.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* Forward declarations */ struct stats; @@ -169,3 +173,7 @@ int path_uses_node(struct path *p, struct node *n); int path_parse(struct path *p, json_t *cfg, struct list *nodes); /** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/plugin.h b/include/villas/plugin.h index 6a58b2d57..a015c2e49 100644 --- a/include/villas/plugin.h +++ b/include/villas/plugin.h @@ -31,7 +31,21 @@ #include "node_type.h" #include "format_type.h" -/** @todo This is ugly as hell and broken on OS X / Clang anyway. */ +#ifdef __cplusplus +extern "C"{ +#endif + +/** (De-)Register a plugin by adding it to the global plugin list. + * + * We make use of GCC's / Clang's constructor/destructor function + * attributes to let the following code be executed by the loader. + * This works only when we compile libvillas as a shared library! + * + * The __attribute__((constructor)) / __attribute__((destructor)) + * is currently only supported by GCC and Clang + * + * See: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes + */ #define REGISTER_PLUGIN(p) \ __attribute__((constructor(110))) static void UNIQUE(__ctor)() {\ if (plugins.state == STATE_DESTROYED) \ @@ -95,3 +109,7 @@ void plugin_dump(enum plugin_type type); /** Find registered and loaded plugin with given name and type. */ struct plugin * plugin_lookup(enum plugin_type type, const char *name); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/pool.h b/include/villas/pool.h index 15d7833db..d09b6452c 100644 --- a/include/villas/pool.h +++ b/include/villas/pool.h @@ -28,9 +28,13 @@ #include #include -#include "queue.h" -#include "common.h" -#include "memory.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /** A thread-safe memory pool */ struct pool { @@ -92,3 +96,7 @@ INLINE int pool_put(struct pool *p, void *buf) { return queue_push(&p->queue, buf); } + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/queue.h b/include/villas/queue.h index ce1ab58d5..2c7b8c669 100644 --- a/include/villas/queue.h +++ b/include/villas/queue.h @@ -33,13 +33,16 @@ #pragma once - #include #include #include -#include "atomic.h" -#include "common.h" +#include +#include + +#ifdef __cplusplus +extern "C"{ +#endif /* Forward declarations */ struct memtype; @@ -112,3 +115,7 @@ int queue_pull_many(struct queue *q, void *ptr[], size_t cnt); * @return -1 on failure. */ int queue_close(struct queue *q); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/queue_signalled.h b/include/villas/queue_signalled.h index 4f9e012b4..2d2a44fb3 100644 --- a/include/villas/queue_signalled.h +++ b/include/villas/queue_signalled.h @@ -27,6 +27,10 @@ #include "queue.h" +#ifdef __cplusplus +extern "C"{ +#endif + enum queue_signalled_flags { /* Mode */ QUEUE_SIGNALLED_AUTO = (0 << 0), /**< We will choose the best method available on the platform */ @@ -80,3 +84,7 @@ int queue_signalled_close(struct queue_signalled *qs); /** Returns a file descriptor which can be used with poll / select to wait for new data */ int queue_signalled_fd(struct queue_signalled *qs); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/sample.h b/include/villas/sample.h index 149fcc4f5..83e4e6334 100644 --- a/include/villas/sample.h +++ b/include/villas/sample.h @@ -23,11 +23,7 @@ #pragma once -#include "atomic.h" - -#ifdef __cplusplus -extern "C" { -#endif +#include #include #include @@ -35,6 +31,10 @@ extern "C" { #include #include +#ifdef __cplusplus +extern "C"{ +#endif + /* Forward declarations */ struct pool; diff --git a/include/villas/signal.h b/include/villas/signal.h index 56502e8f3..09487bda7 100644 --- a/include/villas/signal.h +++ b/include/villas/signal.h @@ -25,6 +25,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Forward declarations */ struct list; struct node; @@ -46,3 +50,7 @@ int signal_parse(struct signal *s, json_t *cfg); int signal_parse_list(struct list *list, json_t *cfg); int signal_get_offset(const char *str, struct node *n); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/stats.h b/include/villas/stats.h index e0e46f941..2ee375889 100644 --- a/include/villas/stats.h +++ b/include/villas/stats.h @@ -21,13 +21,16 @@ * along with this program. If not, see . *********************************************************************************/ -#ifndef _STATS_H_ -#define _STATS_H_ +#pragma once #include #include -#include "hist.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif /* Forward declarations */ struct sample; @@ -86,4 +89,6 @@ void stats_print(struct stats *s, FILE *f, enum stats_format fmt, int verbose); enum stats_id stats_lookup_id(const char *name); -#endif /* _STATS_H_ */ +#ifdef __cplusplus +} +#endif diff --git a/include/villas/super_node.h b/include/villas/super_node.h index 064c31cc9..71d172e63 100644 --- a/include/villas/super_node.h +++ b/include/villas/super_node.h @@ -23,11 +23,15 @@ #pragma once -#include "list.h" -#include "api.h" -#include "web.h" -#include "log.h" -#include "common.h" +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /** Global configuration */ struct super_node { @@ -83,3 +87,7 @@ int super_node_stop(struct super_node *sn); /** Desctroy configuration object. */ int super_node_destroy(struct super_node *sn); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/table.h b/include/villas/table.h index f11a0d5d9..18998b2c4 100644 --- a/include/villas/table.h +++ b/include/villas/table.h @@ -25,6 +25,12 @@ * @{ */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + struct table_column { int width; /**< Width of the column. */ char *title; /**< The title as shown in the table header. */ @@ -55,3 +61,7 @@ void table_row(struct table *t, ...); void table_footer(struct table *t); /** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/task.h b/include/villas/task.h index 141f2f7e2..07eadcb50 100644 --- a/include/villas/task.h +++ b/include/villas/task.h @@ -28,6 +28,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /** We can choose between two periodic task implementations */ //#define PERIODIC_TASK_IMPL NANOSLEEP #define TIMERFD 1 @@ -73,3 +77,7 @@ int task_set_rate(struct task *t, double rate); * Note: currently not supported on all platforms. */ int task_fd(struct task *t); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/timing.h b/include/villas/timing.h index 1ef49e123..dad07fad1 100644 --- a/include/villas/timing.h +++ b/include/villas/timing.h @@ -28,6 +28,10 @@ #include +#ifdef __cplusplus +extern "C"{ +#endif + /** Get delta between two timespec structs */ struct timespec time_diff(const struct timespec *start, const struct timespec *end); @@ -45,3 +49,7 @@ double time_to_double(const struct timespec *ts); /** Convert double containing seconds after 1970 to timespec. */ struct timespec time_from_double(double secs); + +#ifdef __cplusplus +} +#endif diff --git a/include/villas/utils.h b/include/villas/utils.h index ac753be84..942087fbb 100644 --- a/include/villas/utils.h +++ b/include/villas/utils.h @@ -33,6 +33,11 @@ #include #include +#ifdef __cplusplus +extern "C"{ +#endif + + #ifdef __GNUC__ #define LIKELY(x) __builtin_expect((x),1) #define UNLIKELY(x) __builtin_expect((x),0) @@ -275,3 +280,8 @@ pid_t spawn(const char *name, char *const argv[]); /** Determines the string length as printed on the screen (ignores escable sequences). */ size_t strlenp(const char *str); + + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/villas/web.h b/include/villas/web.h index a299146e4..c7b06ea95 100644 --- a/include/villas/web.h +++ b/include/villas/web.h @@ -25,7 +25,11 @@ #include -#include "common.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif /* Forward declarations */ struct api; @@ -60,3 +64,7 @@ int web_stop(struct web *w); /** Parse HTTPd and WebSocket related options */ int web_parse(struct web *w, json_t *cfg); + +#ifdef __cplusplus +} +#endif diff --git a/lib/Makefile.villas.inc b/lib/Makefile.villas.inc index ff375a743..120161f72 100644 --- a/lib/Makefile.villas.inc +++ b/lib/Makefile.villas.inc @@ -31,6 +31,7 @@ LIB_SRCS += $(addprefix lib/kernel/, kernel.c rt.c) \ queue_signalled.c memory.c memory_ib.c advio.c plugin.c node_type.c stats.c \ mapping.c shmem.c config_helper.c crypt.c compat.c \ log_helper.c task.c buffer.c table.c bitset.c signal.c \ + hash_table.c \ ) LIB_LDFLAGS += -shared diff --git a/lib/hash_table.c b/lib/hash_table.c new file mode 100644 index 000000000..2fb88aa88 --- /dev/null +++ b/lib/hash_table.c @@ -0,0 +1,202 @@ +/** A generic hash table + * + * @author Steffen Vogel + * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include + +#include +#include + +static int hash_table_hash(struct hash_table *ht, void *key) +{ + uintptr_t ptr = (uintptr_t) key; + + return ptr % ht->size; +} + +int hash_table_init(struct hash_table *ht, size_t size) +{ + int ret; + size_t len = sizeof(struct hash_table_entry *) * size; + + assert(ht->state == STATE_DESTROYED); + + ret = pthread_mutex_init(&ht->lock, NULL); + if (ret) + return ret; + + ht->table = alloc(len); + + memset(ht->table, 0, len); + + ht->size = size; + ht->state = STATE_INITIALIZED; + + return 0; +} + +int hash_table_destroy(struct hash_table *ht, dtor_cb_t dtor, bool release) +{ + int ret; + struct hash_table_entry *cur, *next; + + assert(ht->state == STATE_INITIALIZED); + + pthread_mutex_lock(&ht->lock); + + for (int i = 0; i < ht->size; i++) { + for (cur = ht->table[i]; cur; cur = next) { + if (dtor) + dtor(cur->data); + + if (release) + free(cur->data); + + next = cur->next; + + free(cur); + } + } + + pthread_mutex_unlock(&ht->lock); + + ret = pthread_mutex_destroy(&ht->lock); + if (ret) + return ret; + + free(ht->table); + + ht->state = STATE_DESTROYED; + + return 0; +} + +int hash_table_insert(struct hash_table *ht, void *key, void *data) +{ + int ret, ikey = hash_table_hash(ht, key); + struct hash_table_entry *hte, *cur; + + assert(ht->state == STATE_INITIALIZED); + + pthread_mutex_lock(&ht->lock); + + /* Check that the key is not already in the table */ + for (cur = ht->table[ikey]; + cur && cur->key != key; + cur = cur->next); + + if (cur) + ret = -1; + else { + hte = alloc(sizeof(struct hash_table_entry)); + if (hte) { + hte->key = key; + hte->data = data; + hte->next = NULL; + + if ((cur = ht->table[ikey])) + hte->next = ht->table[ikey]; + + ht->table[ikey] = hte; + + ret = 0; + } + else + ret = -1; + } + + pthread_mutex_unlock(&ht->lock); + + return ret; +} + +#include + +int hash_table_delete(struct hash_table *ht, void *key) +{ + int ret, ikey = hash_table_hash(ht, key); + struct hash_table_entry *cur, *prev; + + assert(ht->state == STATE_INITIALIZED); + + pthread_mutex_lock(&ht->lock); + + for (prev = NULL, + cur = ht->table[ikey]; + cur && cur->key != key; + prev = cur, + cur = cur->next); + + if (cur) { + if (prev) + prev->next = cur->next; + else + ht->table[ikey] = cur->next; + + free(cur); + + ret = 0; + } + else + ret = -1; /* not found */ + + pthread_mutex_unlock(&ht->lock); + + return ret; +} + +void * hash_table_lookup(struct hash_table *ht, void *key) +{ + int ikey = hash_table_hash(ht, key); + struct hash_table_entry *hte; + + assert(ht->state == STATE_INITIALIZED); + + pthread_mutex_lock(&ht->lock); + + for (hte = ht->table[ikey]; + hte && hte->key != key; + hte = hte->next); + + void *data = hte ? hte->data : NULL; + + pthread_mutex_unlock(&ht->lock); + + return data; +} + +void hash_table_dump(struct hash_table *ht) +{ + struct hash_table_entry *hte; + + assert(ht->state == STATE_INITIALIZED); + + pthread_mutex_lock(&ht->lock); + + for (int i = 0; i < ht->size; i++) { + printf("%i: ", i); + for (hte = ht->table[i]; hte; hte = hte->next) + printf("%p->%p ", hte->key, hte->data); + printf("\n"); + } + + pthread_mutex_unlock(&ht->lock); +} diff --git a/lib/memory.c b/lib/memory.c index 4877ee01a..246be848a 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -147,7 +147,11 @@ static void * memory_hugepage_alloc(struct memtype *m, size_t len, size_t alignm static int memory_hugepage_free(struct memtype *m, void *ptr, size_t len) { - len = ALIGN(len, HUGEPAGESIZE); /* ugly see: https://lkml.org/lkml/2015/3/27/171 */ + /** We must make sure that len is a multiple of the hugepage size + * + * See: https://lkml.org/lkml/2014/10/22/925 + */ + len = ALIGN(len, HUGEPAGESIZE); return munmap(ptr, len); } diff --git a/lib/node.c b/lib/node.c index 866cbe576..4b028c471 100644 --- a/lib/node.c +++ b/lib/node.c @@ -309,6 +309,10 @@ int node_check(struct node *n) if (ret) return ret; + ret = n->_vt->check ? n->_vt->check(n) : 0; + if (ret) + return ret; + n->state = STATE_CHECKED; return 0; diff --git a/packaging/docker/Dockerfile.dev b/packaging/docker/Dockerfile.dev index 6f10d1736..0561bacd3 100644 --- a/packaging/docker/Dockerfile.dev +++ b/packaging/docker/Dockerfile.dev @@ -78,7 +78,7 @@ RUN dnf -y install \ libiec61850-devel \ librabbitmq-devel \ mosquitto-devel \ - comedilib-devel + comedilib-devel comedilib # IB Verbs Dependencies RUN dnf -y install \ diff --git a/packaging/rpm/villas-node.spec b/packaging/rpm/villas-node.spec index 6570b0090..71a8a3255 100644 --- a/packaging/rpm/villas-node.spec +++ b/packaging/rpm/villas-node.spec @@ -14,7 +14,7 @@ BuildRequires: gcc pkgconfig make Requires: iproute module-init-tools -BuildRequires: openssl-devel libconfig-devel libnl3-devel libcurl-devel jansson-devel libwebsockets-devel zeromq-devel nanomsg-devel libiec61850-devel librabbitmq-devel mosquitto-devel comedilib-devel +BuildRequires: openssl-devel libconfig-devel libnl3-devel libcurl-devel jansson-devel libwebsockets-devel zeromq-devel nanomsg-devel libiec61850-devel librabbitmq-devel mosquitto-devel comedilib-devel comedilib Requires: openssl libconfig libnl3 libcurl jansson libwebsockets zeromq nanomsg libiec61850 librabbitmq mosquitto comedilib %description diff --git a/tests/unit/hash_table.c b/tests/unit/hash_table.c new file mode 100644 index 000000000..362c42e69 --- /dev/null +++ b/tests/unit/hash_table.c @@ -0,0 +1,71 @@ +/** Unit tests for hash table + * + * @author Steffen Vogel + * @copyright 2018, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLASnode + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include + +#include +#include + +static char *keys[] = { "able", "achieve", "acoustics", "action", "activity", "aftermath", "afternoon", "afterthought", "apparel", "appliance", "beginner", "believe", "bomb", "border", "boundary", "breakfast", "cabbage", "cable", "calculator", "calendar", "caption", "carpenter", "cemetery", "channel", "circle", "creator", "creature", "education", "faucet", "feather", "friction", "fruit", "fuel", "galley", "guide", "guitar", "health", "heart", "idea", "kitten", "laborer", "language" }; +static char *values[] = { "lawyer", "linen", "locket", "lumber", "magic", "minister", "mitten", "money", "mountain", "music", "partner", "passenger", "pickle", "picture", "plantation", "plastic", "pleasure", "pocket", "police", "pollution", "railway", "recess", "reward", "route", "scene", "scent", "squirrel", "stranger", "suit", "sweater", "temper", "territory", "texture", "thread", "treatment", "veil", "vein", "volcano", "wealth", "weather", "wilderness", "wren" }; + +Test(hash_table, hash_table_lookup) +{ + int ret; + struct hash_table ht = { .state = STATE_DESTROYED }; + + ret = hash_table_init(&ht, 20); + cr_assert(!ret); + + /* Insert */ + for (int i = 0; i < ARRAY_LEN(keys); i++) { + ret = hash_table_insert(&ht, keys[i], values[i]); + cr_assert(!ret); + } + + /* Lookup */ + for (int i = 0; i < ARRAY_LEN(keys); i++) { + char *value = hash_table_lookup(&ht, keys[i]); + cr_assert_eq(values[i], value); + } + + /* Inserting the same key twice should fail */ + ret = hash_table_insert(&ht, keys[0], values[0]); + cr_assert(ret); + + hash_table_dump(&ht); + + /* Removing an entry */ + ret = hash_table_delete(&ht, keys[0]); + cr_assert(!ret); + + /* Removing the same entry twice should fail */ + ret = hash_table_delete(&ht, keys[0]); + cr_assert(ret); + + /* After removing, we should be able to insert it again */ + ret = hash_table_insert(&ht, keys[0], values[0]); + cr_assert(!ret); + + ret = hash_table_destroy(&ht, NULL, false); + cr_assert(!ret); +}