24 #include <interface/interface.h>
26 #include <interface/mediators/interface_mediator.h>
27 #include <interface/mediators/message_mediator.h>
28 #include <core/threading/refc_rwlock.h>
29 #include <core/threading/mutex.h>
30 #include <core/exceptions/system.h>
31 #include <utils/time/clock.h>
32 #include <utils/time/time.h>
33 #include <utils/misc/strndup.h>
58 :
Exception(
"This interface instance '%s' of type '%s' is not opened for writing. %s",
75 :
Exception(
"This interface instance '%s' of type '%s' IS opened for writing, but "
76 "messages can only be enqueued on reading interfaces.", id, type)
92 :
Exception(
"Message of type '%s' cannot be enqueued in interface of type '%s'",
93 message->type(), interface->type())
110 :
Exception(
"The interface %s (instance serial %u) is invalid. You cannot call %s anymore.",
111 interface->uid(), interface->serial(), method)
233 __write_access =
false;
236 __next_message_id = 0;
238 __fieldinfo_list = NULL;
239 __messageinfo_list = NULL;
241 __timestamp =
new Time(0, 0);
242 __local_read_timestamp =
new Time(0, 0);
243 __auto_timestamping =
true;
245 memset(__hash, 0, __INTERFACE_HASH_SIZE);
246 memset(__hash_printable, 0, __INTERFACE_HASH_SIZE * 2 + 1);
255 __data_mutex =
new Mutex();
262 if ( __rwlock) __rwlock->
unref();
264 delete __message_queue;
265 if (__buffers) free(__buffers);
269 __fieldinfo_list = __fieldinfo_list->
next;
271 finfol = __fieldinfo_list;
276 __messageinfo_list = __messageinfo_list->
next;
278 minfol = __messageinfo_list;
281 delete __local_read_timestamp;
291 const unsigned char *
304 return __hash_printable;
314 memcpy(__hash, ihash, __INTERFACE_HASH_SIZE);
315 for (
size_t s = 0; s < __INTERFACE_HASH_SIZE; ++s) {
316 snprintf(&__hash_printable[s*2], 3,
"%02X", __hash[s]);
333 size_t length,
void *value,
const char *enumtype)
341 newinfo->
name = name;
343 newinfo->
value = value;
344 newinfo->
next = NULL;
346 if ( infol == NULL ) {
348 __fieldinfo_list = newinfo;
351 while ( infol->
next != NULL ) {
354 infol->
next = newinfo;
375 newinfo->
next = NULL;
377 if ( infol == NULL ) {
379 __messageinfo_list = newinfo;
382 while ( infol->
next != NULL ) {
385 infol->
next = newinfo;
394 std::list<const char *>
397 std::list<const char *> types;
400 while ( cur != NULL ) {
401 types.push_back(cur->
type);
416 return __INTERFACE_HASH_SIZE;
437 return __write_access;
475 __data_mutex->
lock();
478 *__local_read_timestamp = *__timestamp;
497 if ( ! __write_access ) {
502 __data_mutex->
lock();
505 if (__auto_timestamping) __timestamp->
stamp();
506 long sec = 0, usec = 0;
541 Interface::set_type_id(
const char *type,
const char *
id)
543 __type[__INTERFACE_TYPE_SIZE] = 0;
544 __id[__INTERFACE_ID_SIZE] = 0;
545 __uid[__INTERFACE_UID_SIZE] = 0;
546 strncpy(__type, type, __INTERFACE_TYPE_SIZE);
547 strncpy(__id,
id, __INTERFACE_ID_SIZE);
548 snprintf(__uid, __INTERFACE_UID_SIZE,
"%s::%s", type,
id);
556 Interface::set_instance_serial(
unsigned short instance_serial)
558 __instance_serial = instance_serial;
567 Interface::set_mediators(InterfaceMediator *iface_mediator,
568 MessageMediator *msg_mediator)
570 __interface_mediator = iface_mediator;
571 __message_mediator = msg_mediator;
581 Interface::set_memory(
unsigned int serial,
void *real_ptr,
void *data_ptr)
584 __mem_real_ptr = real_ptr;
594 Interface::set_readwrite(
bool write_access, RefCountRWLock *rwlock)
596 __write_access = write_access;
615 return ( (strncmp(__type, comp.__type,
sizeof(__type)) == 0) &&
616 (strncmp(__id, comp.__id,
sizeof(__id)) == 0) );
627 return (strncmp(this->__type, interface_type,
sizeof(this->__type)) == 0);
672 return __instance_serial;
704 if (__auto_timestamping)
throw Exception(
"Auto timestamping enabled, cannot "
705 "set explicit timestamp");
706 if (!__write_access)
throw Exception(
"Timestamp can only be set on writing "
712 __timestamp->
stamp();
735 __auto_timestamping = enabled;
750 return (*__timestamp != __local_read_timestamp);
832 if ( __write_access ) {
837 message->set_interface(
this);
838 message->
set_id(next_msg_id());
840 __message_mediator->
transmit(message);
841 unsigned int msgid = message->
id();
871 if ( __write_access ) {
874 if ( message == NULL ) {
880 mcopy->set_interface(
this);
881 mcopy->
set_id(next_msg_id());
882 __message_mediator->
transmit(mcopy);
883 unsigned int msgid = mcopy->
id();
901 Interface::msgq_append(
Message *message)
903 if ( ! __write_access ) {
905 "reading instance of an interface (append).");
908 __message_queue->
append(message);
925 if ( ! __write_access ) {
927 "reading instance of an interface (remove msg).");
930 return __message_queue->
remove(message);
942 if ( ! __write_access ) {
944 "reading instance of an interface (remove id).");
947 return __message_queue->
remove(message_id);
958 if ( ! __write_access ) {
960 "reading instance of an interface (size).");
963 return __message_queue->
size();
974 if ( ! __write_access ) {
976 "reading instance of an interface (empty).");
979 return __message_queue->
empty();
990 if ( ! __write_access ) {
992 "reading instance of an interface (flush).");
995 __message_queue->
flush();
1008 if ( ! __write_access ) {
1010 "reading instance of an interface (lock).");
1013 __message_queue->
lock();
1028 if ( ! __write_access ) {
1030 "Cannot work on message queue on "
1031 "reading instance of an interface "
1032 "(msgq_try_lock).");
1035 return __message_queue->
try_lock();
1046 if ( ! __write_access ) {
1048 "reading instance of an interface (unlock).");
1051 __message_queue->
unlock();
1066 if ( ! __write_access ) {
1068 "reading instance of an interface (begin).");
1071 return __message_queue->
begin();
1087 if ( ! __write_access ) {
1089 "Cannot work on message queue on "
1090 "reading instance of an interface (end).");
1093 return __message_queue->
end();
1106 if ( ! __write_access ) {
1108 "reading instance of an interface (first).");
1111 return __message_queue->
first();
1120 if ( ! __write_access ) {
1122 "reading instance of an interface (pop).");
1125 __message_queue->
pop();
1155 return __num_fields;
1168 __data_mutex->
lock();
1169 if (num_buffers == 0) {
1170 if (__buffers != NULL) {
1176 void *tmp = realloc(__buffers, num_buffers *
data_size);
1179 throw Exception(errno,
"Resizing buffers for interface %s failed", __uid);
1195 return __num_buffers;
1205 if (buffer >= __num_buffers) {
1207 buffer, 0, __num_buffers);
1212 __data_mutex->
lock();
1214 void *buf = (
char *)__buffers + buffer *
data_size;
1234 if (buffer >= __num_buffers) {
1236 buffer, 0, __num_buffers);
1240 __data_mutex->
lock();
1241 void *buf = (
char *)__buffers + buffer *
data_size;
1254 if (buffer >= __num_buffers) {
1256 buffer, 0, __num_buffers);
1259 __data_mutex->
lock();
1260 void *buf = (
char *)__buffers + buffer *
data_size;
1275 if (buffer >= __num_buffers) {
1277 buffer, 0, __num_buffers);
1280 __data_mutex->
lock();
1281 void *buf = (
char *)__buffers + buffer *
data_size;
1303 #define xstr(s) str(s)
1304 if ((ec = regcomp(&re,
1305 "^([a-zA-Z0-9]{1," xstr(__INTERFACE_TYPE_SIZE)
"})::"
1306 "([a-zA-Z0-9 _\\.-]{1," xstr(__INTERFACE_ID_SIZE)
"})$",
1307 REG_EXTENDED)) != 0) {
1309 regerror(ec, &re, errbuf, 1024);
1310 throw Exception(
"Failed to created regular expression to parse UID (%s)",
1313 regmatch_t matches[3];
1314 if (regexec(&re, uid, 3, matches, 0) != 0) {
1316 throw Exception(
"Failed to match UID %s, format error.", uid);
1319 *type = strndup(&(uid[matches[1].rm_so]), matches[1].rm_eo - matches[1].rm_so);
1320 *
id = strndup(&(uid[matches[2].rm_so]), matches[2].rm_eo - matches[2].rm_so);
void copy_private_to_buffer(unsigned int buffer)
Copy data from private memory to buffer.
Interface field iterator.
This exception is thrown if an interface is invalid and it is attempted to call read()/write().
int64_t timestamp_sec
time in seconds since Unix epoch
const char * type
the type of the message
virtual Message * clone() const
Clone this message.
MessageQueue::MessageIterator msgq_begin()
Get start iterator for message queue.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
unsigned short serial() const
Get instance serial of interface.
static Clock * instance()
Clock initializer.
This exception is thrown if a write has been attempted on a read-only interface.
bool msgq_empty()
Check if queue is empty.
InterfaceInvalidMessageException(const Interface *interface, const Message *message)
Constructor.
void unref()
Decrement reference count and conditionally delete this instance.
unsigned int num_readers() const
Get the number of readers.
const char * hash_printable() const
Get printable interface hash.
void lock_for_read()
Aquire a reader lock.
void set_hash(unsigned char *ihash)
Set hash.
Interface field info list.
unsigned int msgq_enqueue_copy(Message *message)
Enqueue copy of message at end of queue.
size_t hash_size() const
Get size of interface hash.
void set_auto_timestamping(bool enabled)
Enable or disable automated timestamping.
MessageIterator end()
Get iterator to element beyond end of message queue list.
void msgq_unlock()
Unlock message queue.
void unlock()
Unlock the mutex.
bool operator==(Interface &comp) const
Check equality of two interfaces.
const char * name
Name of this field.
interface_messageinfo_t * next
the next field, NULL if last
bool is_valid() const
Check validity of interface.
unsigned int data_size
Minimal data size to hold data storage.
This is supposed to be the central clock in Fawkes.
void msgq_remove(Message *message)
Remove message from queue.
interface_fieldinfo_t * next
next field, NULL if last
const unsigned char * hash() const
Get interface hash.
A class for handling time.
A NULL pointer was supplied where not allowed.
InterfaceMessageEnqueueException(const char *type, const char *id)
Constructor.
void write()
Write from local copy into BlackBoard memory.
unsigned int id() const
Get message ID.
Base class for all Fawkes BlackBoard interfaces.
This exception is thrown if a message has been queued in the interface which is not recognized by the...
bool msgq_try_lock()
Try to lock message queue.
unsigned int msgq_size()
Get size of message queue.
const char * uid() const
Get unique identifier of interface.
void * value
Current value of this field.
bool has_writer() const
Check if there is a writer for the interface.
unsigned int num_fields()
Get the number of fields in the interface.
const Time * timestamp() const
Get timestamp of last write.
const char * id() const
Get identifier of interface.
void lock_for_write()
Aquire a writer lock.
void add_messageinfo(const char *name)
Add an entry to the message info list.
void msgq_pop()
Erase first message from queue.
bool data_changed
Indicator if data has changed.
unsigned int datasize() const
Get data size.
void * data_ptr
Pointer to local memory storage.
void read_from_buffer(unsigned int buffer)
Copy data from buffer to private memory.
Base class for exceptions in Fawkes.
Message * msgq_first()
Get the first message from the message queue.
InterfaceWriteDeniedException(const char *type, const char *id, const char *msg)
Constructor.
static void parse_uid(const char *uid, char **type, char **id)
Parse UID to type and ID strings.
void set_clock(Clock *clock)
Set clock for this instance.
virtual bool message_valid(const Message *message) const =0
Check if the message is valid and can be enqueued.
void read()
Read from BlackBoard into local copy.
unsigned int mem_serial() const
Get memory serial of interface.
void flush()
Delete all messages from queue.
virtual ~Interface()
Destructor.
int64_t timestamp_usec
additional time microseconds
Message queue used in interfaces.
InterfaceInvalidException(const Interface *interface, const char *method)
Constructor.
interface_fieldtype_t type
type of this field
void copy_shared_to_buffer(unsigned int buffer)
Copy data from private memory to buffer.
unsigned int num_buffers() const
Get number of buffers.
bool try_lock()
Try to lock message queue.
void get_timestamp(long &sec, long &usec) const
Get time stamp.
void add_fieldinfo(interface_fieldtype_t type, const char *name, size_t length, void *value, const char *enumtype=0)
Add an entry to the field info list.
size_t length
Length of field (array, string)
bool changed() const
Check if data has been changed.
unsigned int msgq_enqueue(Message *message)
Enqueue message at end of queue.
MessageIterator begin()
Get iterator to first element in message queue.
InterfaceFieldIterator fields_end()
Invalid iterator.
void set_time(const timeval *tv)
Sets the time.
bool oftype(const char *interface_type) const
Check if interface is of given type.
void set_clock(Clock *clock)
Set clock to use for timestamping.
void resize_buffers(unsigned int num_buffers)
Resize buffer array.
const char * enumtype
text representation of enum type
bool empty() const
Check if message queue is empty.
void msgq_flush()
Flush all messages.
void append(Message *msg)
Append message to queue.
void msgq_lock()
Lock message queue.
int compare_buffers(unsigned int buffer)
Compare buffer to private memory.
void set_validity(bool valid)
Mark this interface invalid.
void lock()
Lock this mutex.
Time & stamp()
Set this time to the current time.
void remove(const Message *msg)
Remove message from queue.
void unlock()
Release the lock.
bool is_writer() const
Check if this is a writing instance.
const void * datachunk() const
Get data chunk.
void pop()
Erase first message from queue.
void unlock()
Unlock message queue.
interface_data_ts_t * data_ts
Pointer to data casted to timestamp struct.
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
Message * first()
Get first message from queue.
Mutex mutual exclusion lock.
void set_from_chunk(void *chunk)
Set from a raw data chunk.
unsigned int size() const
Get number of messages in queue.
void lock()
Lock message queue.
This exception is thrown if a write has been attempted on a read-only interface.
interface_fieldtype_t
Interface field type.
const char * type() const
Get type of interface.
void set_timestamp(const Time *t=NULL)
Set timestamp.
std::list< const char * > get_message_types()
Obtain a list of textual representations of the message types available for this interface.
void set_id(unsigned int message_id)
Set message ID.
MessageQueue::MessageIterator msgq_end()
Get end iterator for message queue.