Files
oopt-tai-implementations/tai_mux/platform_adapter.cpp
Wataru Ishida 45f93cee42 mux: overhaul by using TAI library framework
Signed-off-by: Wataru Ishida <ishida@nel-america.com>
2020-01-04 11:24:02 -08:00

153 lines
6.7 KiB
C++

#include "platform_adapter.hpp"
#include <algorithm>
namespace tai::mux {
static void notification_callback(void* context, tai_object_id_t oid, uint32_t attr_count, tai_attribute_t const * const attr_list) {
if ( context == nullptr || attr_list == nullptr ) {
return;
}
auto ctx = static_cast<NotificationContext*>(context);
if ( ctx->pa != nullptr ) {
ctx->pa->notify(ctx, oid, attr_count, attr_list);
}
}
void PlatformAdapter::notify(NotificationContext* ctx, tai_object_id_t real_oid, uint32_t attr_count, tai_attribute_t const * const attr_list) {
auto oid = ctx->muxed_oid;
std::vector<S_Attribute> attrs;
for ( int i = 0; i < attr_count; i++ ) {
auto src = attr_list[i];
auto meta = tai_metadata_get_attr_metadata(ctx->object_type, src.id);
if ( meta == nullptr ) {
continue;
}
auto dst = std::make_shared<Attribute>(meta, src);
auto ret = convert_oid(ctx->object_type, oid, dst, dst, true);
if ( ret != TAI_STATUS_SUCCESS ) {
ERROR("failed to convert oid of attribute: %d", src.id);
continue;
}
attrs.emplace_back(dst);
}
{
std::vector<tai_attribute_t> raw_attrs;
std::transform(attrs.begin(), attrs.end(), std::back_inserter(raw_attrs), [](S_Attribute a) { return *a->raw(); });
std::unique_lock<std::mutex> lk(ctx->mutex);
ctx->real_handler.notify(ctx->real_handler.context, oid, raw_attrs.size(), raw_attrs.data());
}
}
tai_status_t PlatformAdapter::convert_oid(const tai_object_type_t& type, const tai_object_id_t& id, const S_ConstAttribute src, const S_Attribute dst, bool reversed) {
return convert_oid(type, id, src->raw(), const_cast<tai_attribute_t* const>(dst->raw()), reversed);
}
tai_status_t PlatformAdapter::convert_oid(const tai_object_type_t& type, const tai_object_id_t& id, const tai_attribute_t * const src, tai_attribute_t * const dst, bool reversed) {
auto meta = tai_metadata_get_attr_metadata(type, src->id);
const tai_object_map_list_t *oml;
S_ModuleAdapter adapter;
if ( get_mapping(id, &adapter, nullptr) != 0 ) {
return TAI_STATUS_FAILURE;
}
auto convert = [&](tai_object_id_t s) -> tai_object_id_t {
if ( reversed ) {
return get_reverse_mapping(s, adapter);
}
tai_object_id_t oid;
if ( get_mapping(s, nullptr, &oid) < 0 ) {
return TAI_NULL_OBJECT_ID;
}
return oid;
};
switch (meta->attrvaluetype) {
case TAI_ATTR_VALUE_TYPE_OID:
dst->value.oid = convert(src->value.oid);
if ( dst->value.oid == TAI_NULL_OBJECT_ID ) {
return TAI_STATUS_FAILURE;
}
break;
case TAI_ATTR_VALUE_TYPE_OBJLIST:
for ( auto i = 0 ; i < src->value.objlist.count; i++ ) {
dst->value.objlist.list[i] = convert(src->value.objlist.list[i]);
if ( dst->value.objlist.list[i] == TAI_NULL_OBJECT_ID ) {
return TAI_STATUS_FAILURE;
}
}
break;
case TAI_ATTR_VALUE_TYPE_OBJMAPLIST:
oml = &src->value.objmaplist;
for ( auto i = 0 ; i < oml->count; i++ ) {
dst->value.objmaplist.list[i].key = convert(oml->list[i].key);
if ( dst->value.objmaplist.list[i].key == TAI_NULL_OBJECT_ID ) {
return TAI_STATUS_FAILURE;
}
for ( auto j = 0; j < oml->list[i].value.count; j++ ) {
dst->value.objmaplist.list[i].value.list[j] = convert(oml->list[i].value.list[j]);
if ( dst->value.objmaplist.list[i].value.list[j] == TAI_NULL_OBJECT_ID ) {
return TAI_STATUS_FAILURE;
}
}
}
break;
case TAI_ATTR_VALUE_TYPE_NOTIFICATION:
{
auto key = notification_key(id, src->id);
if ( reversed ) {
if ( m_notification_map.find(key) != m_notification_map.end() ) {
auto n = m_notification_map[key];
dst->value.notification.context = n->real_handler.context;
dst->value.notification.notify = n->real_handler.notify;
}
break;
}
if ( src->value.notification.notify != nullptr ) {
if ( m_notification_map.find(key) == m_notification_map.end() ) {
m_notification_map[key] = std::make_shared<NotificationContext>();
}
auto n = m_notification_map[key];
std::unique_lock<std::mutex> lk(n->mutex);
n->pa = this;
n->real_handler = src->value.notification;
n->muxed_oid = id;
n->object_type = type;
dst->value.notification.context = static_cast<void*>(n.get());
dst->value.notification.notify = notification_callback;
} else {
// notification context cleanup can't be handled here since the callback can still get
// called by the underneath TAI library.
// we'll clean the context after disabling the callback
}
}
}
return TAI_STATUS_SUCCESS;
}
tai_status_t PlatformAdapter::set(const tai_object_type_t& type, const tai_object_id_t& id, const tai_attribute_t* const attribute) {
S_ModuleAdapter adapter;
tai_object_id_t real_id;
if ( get_mapping(id, &adapter, &real_id) != 0 ) {
return TAI_STATUS_FAILURE;
}
auto meta = tai_metadata_get_attr_metadata(type, attribute->id);
if ( meta == nullptr ) {
return TAI_STATUS_FAILURE;
}
auto attr = std::make_shared<Attribute>(meta, attribute);
auto ret = convert_oid(type, id, attribute, const_cast<tai_attribute_t* const>(attr->raw()), false);
if ( ret != TAI_STATUS_SUCCESS ) {
return ret;
}
ret = adapter->set_attributes(type, real_id, 1, attr->raw());
if ( ret != TAI_STATUS_SUCCESS ) {
return ret;
}
if ( meta->attrvaluetype == TAI_ATTR_VALUE_TYPE_NOTIFICATION && attribute->value.notification.notify == nullptr ) {
auto key = notification_key(id, attribute->id);
m_notification_map.erase(key);
}
return TAI_STATUS_SUCCESS;
}
}