23 #include <core/exceptions/system.h>
24 #include <core/threading/mutex.h>
25 #include <core/threading/mutex_locker.h>
26 #include <core/threading/refc_rwlock.h>
27 #include <interface/interface.h>
28 #include <interface/mediators/interface_mediator.h>
29 #include <interface/mediators/message_mediator.h>
30 #include <utils/misc/strndup.h>
31 #include <utils/time/clock.h>
32 #include <utils/time/time.h>
57 :
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.",
94 :
Exception(
"Message of type '%s' cannot be enqueued in interface of type '%s'",
111 :
Exception(
"The interface %s (instance serial %u) is invalid. You cannot call %s anymore.",
235 write_access_ =
false;
238 next_message_id_ = 0;
240 fieldinfo_list_ = NULL;
241 messageinfo_list_ = NULL;
243 timestamp_ =
new Time(0, 0);
244 local_read_timestamp_ =
new Time(0, 0);
245 auto_timestamping_ =
true;
246 owner_ = strdup(
"?");
248 memset(hash_, 0, INTERFACE_HASH_SIZE_);
249 memset(hash_printable_, 0, INTERFACE_HASH_SIZE_ * 2 + 1);
258 data_mutex_ =
new Mutex();
267 delete message_queue_;
273 fieldinfo_list_ = fieldinfo_list_->
next;
275 finfol = fieldinfo_list_;
280 messageinfo_list_ = messageinfo_list_->
next;
282 minfol = messageinfo_list_;
285 delete local_read_timestamp_;
297 const unsigned char *
309 return hash_printable_;
318 memcpy(hash_, ihash, INTERFACE_HASH_SIZE_);
319 for (
size_t s = 0; s < INTERFACE_HASH_SIZE_; ++s) {
320 snprintf(&hash_printable_[s * 2], 3,
"%02X", hash_[s]);
340 const char * enumtype,
348 newinfo->
name = name;
350 newinfo->
value = value;
352 newinfo->
next = NULL;
356 fieldinfo_list_ = newinfo;
359 while (infol->
next != NULL) {
362 infol->
next = newinfo;
382 newinfo->
next = NULL;
386 messageinfo_list_ = newinfo;
389 while (infol->
next != NULL) {
392 infol->
next = newinfo;
400 std::list<const char *>
403 std::list<const char *> types;
406 while (cur != NULL) {
407 types.push_back(cur->
type);
421 return INTERFACE_HASH_SIZE_;
440 return write_access_;
478 *local_read_timestamp_ = *timestamp_;
496 if (!write_access_) {
502 bool do_notify =
false;
505 if (auto_timestamping_)
507 long sec = 0, usec = 0;
542 Interface::set_type_id(
const char *type,
const char *
id)
544 strncpy(type_,
type, INTERFACE_TYPE_SIZE_);
545 strncpy(id_,
id, INTERFACE_ID_SIZE_);
546 snprintf(uid_, INTERFACE_UID_SIZE_ + 1,
"%s::%s", type_, id_);
549 type_[INTERFACE_TYPE_SIZE_] = 0;
550 id_[INTERFACE_ID_SIZE_] = 0;
551 uid_[INTERFACE_UID_SIZE_] = 0;
558 Interface::set_instance_serial(
unsigned short instance_serial)
560 instance_serial_ = instance_serial;
568 Interface::set_mediators(InterfaceMediator *iface_mediator, MessageMediator *msg_mediator)
570 interface_mediator_ = iface_mediator;
571 message_mediator_ = msg_mediator;
580 Interface::set_memory(
unsigned int serial,
void *real_ptr,
void *data_ptr)
583 mem_real_ptr_ = real_ptr;
592 Interface::set_readwrite(
bool write_access, RefCountRWLock *rwlock)
594 write_access_ = write_access;
602 Interface::set_owner(
const char *owner)
608 owner_ = strdup(
owner);
625 return ((strncmp(type_, comp.type_,
sizeof(type_)) == 0)
626 && (strncmp(id_, comp.id_,
sizeof(id_)) == 0));
636 return (strncmp(this->type_, interface_type,
sizeof(this->type_)) == 0);
688 return instance_serial_;
717 if (auto_timestamping_)
718 throw Exception(
"Auto timestamping enabled, cannot "
719 "set explicit timestamp");
721 throw Exception(
"Timestamp can only be set on writing "
748 auto_timestamping_ = enabled;
785 return (*timestamp_ != local_read_timestamp_);
857 return interface_mediator_->
writer(
this);
863 std::list<std::string>
866 return interface_mediator_->
readers(
this);
889 message->set_interface(
this);
890 message->
set_id(next_msg_id());
892 message_mediator_->
transmit(message);
893 unsigned int msgid = message->
id();
925 if (message == NULL) {
931 mcopy->set_interface(
this);
932 mcopy->
set_id(next_msg_id());
934 unsigned int msgid = mcopy->
id();
955 if (!write_access_) {
958 "Cannot work on message queue on "
959 "reading instance of an interface (append).");
963 message_queue_->
append(message);
979 if (!write_access_) {
982 "Cannot work on message queue on "
983 "reading instance of an interface (remove msg).");
986 return message_queue_->
remove(message);
997 if (!write_access_) {
1000 "Cannot work on message queue on "
1001 "reading instance of an interface (remove id).");
1004 return message_queue_->
remove(message_id);
1014 if (!write_access_) {
1017 "Cannot work on message queue on "
1018 "reading instance of an interface (size).");
1021 return message_queue_->
size();
1031 if (!write_access_) {
1034 "Cannot work on message queue on "
1035 "reading instance of an interface (empty).");
1038 return message_queue_->
empty();
1048 if (!write_access_) {
1051 "Cannot work on message queue on "
1052 "reading instance of an interface (flush).");
1055 message_queue_->
flush();
1067 if (!write_access_) {
1070 "Cannot work on message queue on "
1071 "reading instance of an interface (lock).");
1074 message_queue_->
lock();
1088 if (!write_access_) {
1091 "Cannot work on message queue on "
1092 "reading instance of an interface "
1093 "(msgq_try_lock).");
1106 if (!write_access_) {
1109 "Cannot work on message queue on "
1110 "reading instance of an interface (unlock).");
1113 message_queue_->
unlock();
1128 if (!write_access_) {
1131 "Cannot work on message queue on "
1132 "reading instance of an interface (begin).");
1135 return message_queue_->
begin();
1150 if (!write_access_) {
1153 "Cannot work on message queue on "
1154 "reading instance of an interface (end).");
1157 return message_queue_->
end();
1169 if (!write_access_) {
1172 "Cannot work on message queue on "
1173 "reading instance of an interface (first).");
1175 return message_queue_->
first();
1184 if (!write_access_) {
1187 "Cannot work on message queue on "
1188 "reading instance of an interface (pop).");
1191 message_queue_->
pop();
1230 data_mutex_->
lock();
1232 if (buffers_ != NULL) {
1241 throw Exception(errno,
"Resizing buffers for interface %s failed", uid_);
1256 return num_buffers_;
1265 if (buffer >= num_buffers_) {
1270 data_mutex_->
lock();
1272 void *buf = (
char *)buffers_ + buffer *
data_size;
1291 if (buffer >= num_buffers_) {
1295 data_mutex_->
lock();
1296 void *buf = (
char *)buffers_ + buffer *
data_size;
1307 if (buffer >= num_buffers_) {
1311 data_mutex_->
lock();
1312 void *buf = (
char *)buffers_ + buffer *
data_size;
1314 *local_read_timestamp_ = *timestamp_;
1329 if (buffer >= num_buffers_) {
1333 data_mutex_->
lock();
1334 void *buf = (
char *)buffers_ + buffer *
data_size;
1348 if (buffer >= num_buffers_) {
1353 void * buf = (
char *)buffers_ + buffer *
data_size;
1366 if (buffer >= num_buffers_) {
1374 void * buf = (
char *)buffers_ + buffer *
data_size;
1393 #define xstr(s) str(s)
1394 if ((ec = regcomp(&re,
1395 "^([a-zA-Z0-9]{1," xstr(INTERFACE_TYPE_SIZE_)
"})::"
1396 "([a-zA-Z0-9 _/\\.-]{1," xstr(
1397 INTERFACE_ID_SIZE_)
"})$",
1401 regerror(ec, &re, errbuf, 1024);
1402 throw Exception(
"Failed to created regular expression to parse UID (%s)", errbuf);
1404 regmatch_t matches[3];
1405 if (regexec(&re,
uid, 3, matches, 0) != 0) {
1407 throw Exception(
"Failed to match UID %s, format error.",
uid);
1410 type.assign(&(
uid[matches[1].rm_so]), matches[1].rm_eo - matches[1].rm_so);
1411 id.assign(&(
uid[matches[2].rm_so]), matches[2].rm_eo - matches[2].rm_so);
This is supposed to be the central clock in Fawkes.
static Clock * instance()
Clock initializer.
Base class for exceptions in Fawkes.
Interface field iterator.
This exception is thrown if an interface is invalid and it is attempted to call read()/write().
InterfaceInvalidException(const Interface *interface, const char *method)
Constructor.
This exception is thrown if a message has been queued in the interface which is not recognized by the...
InterfaceInvalidMessageException(const Interface *interface, const Message *message)
Constructor.
This exception is thrown if a write has been attempted on a read-only interface.
InterfaceMessageEnqueueException(const char *type, const char *id)
Constructor.
This exception is thrown if a write has been attempted on a read-only interface.
InterfaceWriteDeniedException(const char *type, const char *id, const char *msg)
Constructor.
Base class for all Fawkes BlackBoard interfaces.
std::list< std::string > readers() const
Get owner names of reading interface instances.
bool msgq_try_lock()
Try to lock message queue.
void copy_shared_to_buffer(unsigned int buffer)
Copy data from private memory to buffer.
interface_data_ts_t * data_ts
Pointer to data casted to timestamp struct.
const char * hash_printable() const
Get printable interface hash.
const void * datachunk() const
Get data chunk.
void mark_data_changed()
Mark data as changed.
bool operator==(Interface &comp) const
Check equality of two interfaces.
void set_validity(bool valid)
Mark this interface invalid.
unsigned int msgq_enqueue_copy(Message *message)
Enqueue copy of message at end of queue.
void copy_private_to_buffer(unsigned int buffer)
Copy data from private memory to buffer.
const char * type() const
Get type of interface.
void set_auto_timestamping(bool enabled)
Enable or disable automated timestamping.
virtual ~Interface()
Destructor.
void msgq_pop()
Erase first message from queue.
void read_from_buffer(unsigned int buffer)
Copy data from buffer to private memory.
std::string writer() const
Get owner name of writing interface instance.
void * data_ptr
Pointer to local memory storage.
const Time * timestamp() const
Get timestamp of last write.
Message * msgq_first()
Get the first message from the message queue.
Time buffer_timestamp(unsigned int buffer)
Get time of a buffer.
bool changed() const
Check if data has been changed.
void resize_buffers(unsigned int num_buffers)
Resize buffer array.
InterfaceFieldIterator fields_end()
Invalid iterator.
size_t hash_size() const
Get size of interface hash.
bool is_writer() const
Check if this is a writing instance.
void msgq_remove(Message *message)
Remove message from queue.
const unsigned char * hash() const
Get interface hash.
void msgq_append(Message *message)
Enqueue message.
MessageQueue::MessageIterator msgq_end()
Get end iterator for message queue.
unsigned int msgq_size()
Get size of message queue.
void write()
Write from local copy into BlackBoard memory.
const char * id() const
Get identifier of interface.
void add_fieldinfo(interface_fieldtype_t type, const char *name, size_t length, void *value, const char *enumtype=0, const interface_enum_map_t *enum_map=0)
Add an entry to the field info list.
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
void set_hash(unsigned char *ihash)
Set hash.
bool data_changed
Indicator if data has changed.
unsigned int data_size
Minimal data size to hold data storage.
unsigned int mem_serial() const
Get memory serial of interface.
bool msgq_empty()
Check if queue is empty.
void set_from_chunk(void *chunk)
Set from a raw data chunk.
void msgq_lock()
Lock message queue.
const char * uid() const
Get unique identifier of interface.
bool is_valid() const
Check validity of interface.
unsigned short serial() const
Get instance serial of interface.
void msgq_flush()
Flush all messages.
unsigned int num_readers() const
Get the number of readers.
void read()
Read from BlackBoard into local copy.
int compare_buffers(unsigned int buffer)
Compare buffer to private memory.
void msgq_unlock()
Unlock message queue.
static void parse_uid(const char *uid, std::string &type, std::string &id)
Parse UID to type and ID strings.
void set_clock(Clock *clock)
Set clock to use for timestamping.
unsigned int num_fields()
Get the number of fields in the interface.
unsigned int datasize() const
Get data size.
std::list< const char * > get_message_types()
Obtain a list of textual representations of the message types available for this interface.
unsigned int num_buffers() const
Get number of buffers.
bool has_writer() const
Check if there is a writer for the interface.
unsigned int msgq_enqueue(Message *message)
Enqueue message at end of queue.
void add_messageinfo(const char *name)
Add an entry to the message info list.
const char * owner() const
Get owner of interface.
bool oftype(const char *interface_type) const
Check if interface is of given type.
MessageQueue::MessageIterator msgq_begin()
Get start iterator for message queue.
void set_timestamp(const Time *t=NULL)
Set timestamp.
virtual bool message_valid(const Message *message) const =0
Check if the message is valid and can be enqueued.
Message queue used in interfaces.
MessageIterator end()
Get iterator to element beyond end of message queue list.
void append(Message *msg)
Append message to queue.
void unlock()
Unlock message queue.
void pop()
Erase first message from queue.
void flush()
Delete all messages from queue.
void lock()
Lock message queue.
void remove(const Message *msg)
Remove message from queue.
bool empty() const
Check if message queue is empty.
MessageIterator begin()
Get iterator to first element in message queue.
bool try_lock()
Try to lock message queue.
unsigned int size() const
Get number of messages in queue.
Message * first()
Get first message from queue.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
void set_id(unsigned int message_id)
Set message ID.
virtual Message * clone() const
Clone this message.
unsigned int id() const
Get message ID.
Mutex mutual exclusion lock.
void lock()
Lock this mutex.
void unlock()
Unlock the mutex.
A NULL pointer was supplied where not allowed.
void unlock()
Release the lock.
void lock_for_read()
Aquire a reader lock.
void lock_for_write()
Aquire a writer lock.
void unref()
Decrement reference count and conditionally delete this instance.
void ref()
Increment reference count.
A class for handling time.
void set_clock(Clock *clock)
Set clock for this instance.
void get_timestamp(long &sec, long &usec) const
Get time stamp.
Time & stamp()
Set this time to the current time.
void set_time(const timeval *tv)
Sets the time.
Fawkes library namespace.
std::map< int, std::string > interface_enum_map_t
Map of enum integer to string values.
interface_fieldtype_t
Interface field type.
Timestamp data, must be present and first entries for each interface data structs!...
int64_t timestamp_usec
additional time microseconds
int64_t timestamp_sec
time in seconds since Unix epoch
const char * type
the type of the message
interface_messageinfo_t * next
the next field, NULL if last
Interface field info list.
const char * enumtype
text representation of enum type
void * value
Current value of this field.
size_t length
Length of field (array, string)
const char * name
Name of this field.
interface_fieldtype_t type
type of this field
const interface_enum_map_t * enum_map
Map of possible enum values.
interface_fieldinfo_t * next
next field, NULL if last