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 %s) is invalid. You cannot call %s anymore.",
113 interface->serial().get_string().c_str(),
241 write_access_ =
false;
244 next_message_id_ = 0;
246 fieldinfo_list_ = NULL;
247 messageinfo_list_ = NULL;
249 timestamp_ =
new Time(0, 0);
250 local_read_timestamp_ =
new Time(0, 0);
251 auto_timestamping_ =
true;
252 owner_ = strdup(
"?");
255 memset(hash_, 0, INTERFACE_HASH_SIZE_);
256 memset(hash_printable_, 0, INTERFACE_HASH_SIZE_ * 2 + 1);
265 data_mutex_ =
new Mutex();
274 delete message_queue_;
280 fieldinfo_list_ = fieldinfo_list_->
next;
282 finfol = fieldinfo_list_;
287 messageinfo_list_ = messageinfo_list_->
next;
289 minfol = messageinfo_list_;
292 delete local_read_timestamp_;
304 const unsigned char *
316 return hash_printable_;
325 memcpy(hash_, ihash, INTERFACE_HASH_SIZE_);
326 for (
size_t s = 0; s < INTERFACE_HASH_SIZE_; ++s) {
327 snprintf(&hash_printable_[s * 2], 3,
"%02X", hash_[s]);
347 const char * enumtype,
355 newinfo->
name = name;
357 newinfo->
value = value;
359 newinfo->
next = NULL;
363 fieldinfo_list_ = newinfo;
366 while (infol->
next != NULL) {
369 infol->
next = newinfo;
389 newinfo->
next = NULL;
393 messageinfo_list_ = newinfo;
396 while (infol->
next != NULL) {
399 infol->
next = newinfo;
407 std::list<const char *>
410 std::list<const char *> types;
413 while (cur != NULL) {
414 types.push_back(cur->
type);
428 return INTERFACE_HASH_SIZE_;
447 return write_access_;
485 *local_read_timestamp_ = *timestamp_;
503 if (!write_access_) {
509 bool has_changed =
false;
512 if (auto_timestamping_)
514 long sec = 0, usec = 0;
551 Interface::set_type_id(
const char *type,
const char *
id)
553 strncpy(type_,
type, INTERFACE_TYPE_SIZE_);
554 strncpy(id_,
id, INTERFACE_ID_SIZE_);
555 snprintf(uid_, INTERFACE_UID_SIZE_ + 1,
"%s::%s", type_, id_);
558 type_[INTERFACE_TYPE_SIZE_] = 0;
559 id_[INTERFACE_ID_SIZE_] = 0;
560 uid_[INTERFACE_UID_SIZE_] = 0;
567 Interface::set_instance_serial(
const Uuid &instance_serial)
569 instance_serial_ = instance_serial;
577 Interface::set_mediators(InterfaceMediator *iface_mediator, MessageMediator *msg_mediator)
579 interface_mediator_ = iface_mediator;
580 message_mediator_ = msg_mediator;
589 Interface::set_memory(
unsigned int serial,
void *real_ptr,
void *data_ptr)
592 mem_real_ptr_ = real_ptr;
601 Interface::set_readwrite(
bool write_access, RefCountRWLock *rwlock)
603 write_access_ = write_access;
611 Interface::set_owner(
const char *owner)
617 owner_ = strdup(
owner);
634 return ((strncmp(type_, comp.type_,
sizeof(type_)) == 0)
635 && (strncmp(id_, comp.id_,
sizeof(id_)) == 0));
645 return (strncmp(this->type_, interface_type,
sizeof(this->type_)) == 0);
697 return instance_serial_;
726 if (auto_timestamping_)
727 throw Exception(
"Auto timestamping enabled, cannot "
728 "set explicit timestamp");
730 throw Exception(
"Timestamp can only be set on writing "
757 auto_timestamping_ = enabled;
816 return (*timestamp_ != local_read_timestamp_);
888 return interface_mediator_->
writer(
this);
894 std::list<std::string>
897 return interface_mediator_->
readers(
this);
922 message->set_interface(
this, proxy);
923 message->
set_id(next_msg_id());
925 message_mediator_->
transmit(message);
926 unsigned int msgid = message->
id();
958 if (message == NULL) {
964 mcopy->set_interface(
this);
965 mcopy->
set_id(next_msg_id());
967 unsigned int msgid = mcopy->
id();
988 if (!write_access_) {
991 "Cannot work on message queue on "
992 "reading instance of an interface (append).");
996 message_queue_->
append(message);
1012 if (!write_access_) {
1015 "Cannot work on message queue on "
1016 "reading instance of an interface (remove msg).");
1019 return message_queue_->
remove(message);
1030 if (!write_access_) {
1033 "Cannot work on message queue on "
1034 "reading instance of an interface (remove id).");
1037 return message_queue_->
remove(message_id);
1047 if (!write_access_) {
1050 "Cannot work on message queue on "
1051 "reading instance of an interface (size).");
1054 return message_queue_->
size();
1064 if (!write_access_) {
1067 "Cannot work on message queue on "
1068 "reading instance of an interface (empty).");
1071 return message_queue_->
empty();
1081 if (!write_access_) {
1084 "Cannot work on message queue on "
1085 "reading instance of an interface (flush).");
1088 message_queue_->
flush();
1100 if (!write_access_) {
1103 "Cannot work on message queue on "
1104 "reading instance of an interface (lock).");
1107 message_queue_->
lock();
1121 if (!write_access_) {
1124 "Cannot work on message queue on "
1125 "reading instance of an interface "
1126 "(msgq_try_lock).");
1139 if (!write_access_) {
1142 "Cannot work on message queue on "
1143 "reading instance of an interface (unlock).");
1146 message_queue_->
unlock();
1161 if (!write_access_) {
1164 "Cannot work on message queue on "
1165 "reading instance of an interface (begin).");
1168 return message_queue_->
begin();
1183 if (!write_access_) {
1186 "Cannot work on message queue on "
1187 "reading instance of an interface (end).");
1190 return message_queue_->
end();
1202 if (!write_access_) {
1205 "Cannot work on message queue on "
1206 "reading instance of an interface (first).");
1208 return message_queue_->
first();
1217 if (!write_access_) {
1220 "Cannot work on message queue on "
1221 "reading instance of an interface (pop).");
1224 message_queue_->
pop();
1263 data_mutex_->
lock();
1265 if (buffers_ != NULL) {
1274 throw Exception(errno,
"Resizing buffers for interface %s failed", uid_);
1289 return num_buffers_;
1298 if (buffer >= num_buffers_) {
1303 data_mutex_->
lock();
1305 void *buf = (
char *)buffers_ + buffer *
data_size;
1324 if (buffer >= num_buffers_) {
1328 data_mutex_->
lock();
1329 void *buf = (
char *)buffers_ + buffer *
data_size;
1340 if (buffer >= num_buffers_) {
1344 data_mutex_->
lock();
1345 void *buf = (
char *)buffers_ + buffer *
data_size;
1347 *local_read_timestamp_ = *timestamp_;
1362 if (buffer >= num_buffers_) {
1366 data_mutex_->
lock();
1367 void *buf = (
char *)buffers_ + buffer *
data_size;
1381 if (buffer >= num_buffers_) {
1386 void * buf = (
char *)buffers_ + buffer *
data_size;
1399 if (buffer >= num_buffers_) {
1407 void * buf = (
char *)buffers_ + buffer *
data_size;
1426 #define xstr(s) str(s)
1427 if ((ec = regcomp(&re,
1428 "^([a-zA-Z0-9]{1," xstr(INTERFACE_TYPE_SIZE_)
"})::"
1429 "([a-zA-Z0-9 _/\\.-]{1," xstr(
1430 INTERFACE_ID_SIZE_)
"})$",
1434 regerror(ec, &re, errbuf, 1024);
1435 throw Exception(
"Failed to created regular expression to parse UID (%s)", errbuf);
1437 regmatch_t matches[3];
1438 if (regexec(&re,
uid, 3, matches, 0) != 0) {
1440 throw Exception(
"Failed to match UID %s, format error.",
uid);
1443 type.assign(&(
uid[matches[1].rm_so]), matches[1].rm_eo - matches[1].rm_so);
1444 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.
bool data_refreshed
Indicator if data can be considered "current", i.e.
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.
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.
unsigned int msgq_enqueue(Message *message, bool proxy=false)
Enqueue message at end of queue.
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 the current data is different from the last call to write() This must is automatically u...
unsigned int data_size
Minimal data size to hold data storage.
unsigned int mem_serial() const
Get memory serial of interface.
Uuid serial() const
Get instance 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.
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.
void mark_data_refreshed()
Mark data as refreshed.
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.
bool refreshed() const
Check if data has been refreshed.
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.
A convenience class for universally unique identifiers (UUIDs).
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