394 const mp::Package &frontend_package,
395 int &code, std::string &addinfo)
399 bp->m_close_package =
400 new mp::Package(bp->m_session, frontend_package.origin());
401 bp->m_close_package->copy_filter(frontend_package);
403 Package init_package(bp->m_session, frontend_package.origin());
405 init_package.copy_filter(frontend_package);
408 Z_GDU *init_pdu = actual_init_request.get();
410 assert(init_pdu->which == Z_GDU_Z3950);
411 assert(init_pdu->u.z3950->which == Z_APDU_initRequest);
413 Z_InitRequest *req = init_pdu->u.z3950->u.initRequest;
414 ODR_MASK_ZERO(req->options);
416 ODR_MASK_SET(req->options, Z_Options_search);
417 ODR_MASK_SET(req->options, Z_Options_present);
418 ODR_MASK_SET(req->options, Z_Options_namedResultSets);
419 ODR_MASK_SET(req->options, Z_Options_scan);
421 ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_1);
422 ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_2);
423 ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_3);
430 init_package.request() = init_pdu;
444 Z_GDU *
gdu = init_package.response().get();
446 if (
gdu &&
gdu->which == Z_GDU_Z3950
447 &&
gdu->u.z3950->which == Z_APDU_initResponse)
449 Z_InitResponse *res =
gdu->u.z3950->u.initResponse;
451 if (ODR_MASK_GET(res->options, Z_Options_namedResultSets))
458 if (*
gdu->u.z3950->u.initResponse->result
459 && !init_package.session().is_closed())
462 time(&bp->m_time_last_use);
463 bp->m_sequence_this = 0;
464 bp->m_result_set_sequence = 0;
472 gdu->u.z3950->u.initResponse->userInformationField;
473 if (uif && uif->which == Z_External_userInfo1)
475 Z_OtherInformation *ui = uif->u.userInfo1;
476 if (ui && ui->num_elements >= 1)
478 Z_OtherInformationUnit *unit = ui->list[0];
479 if (unit->which == Z_OtherInfo_externallyDefinedInfo &&
480 unit->information.externallyDefinedInfo &&
481 unit->information.externallyDefinedInfo->which ==
484 Z_DiagnosticFormat *diag =
485 unit->information.externallyDefinedInfo->u.diag1;
488 Z_DiagnosticFormat_s *ds = diag->elements[0];
490 Z_DiagnosticFormat_s_defaultDiagRec)
492 Z_DefaultDiagFormat *e =
493 ds->u.defaultDiagRec;
494 code = *e->condition;
495 if (e->which == Z_DefaultDiagFormat_v2Addinfo
498 addinfo = e->u.v2Addinfo;
501 e->which == Z_DefaultDiagFormat_v3Addinfo
504 addinfo = e->u.v3Addinfo;
513 if (!init_package.session().is_closed())
515 init_package.copy_filter(frontend_package);
516 init_package.session().close();
545 Z_InitRequest *req =
gdu->u.z3950->u.initRequest;
547 frontend->m_is_virtual =
true;
548 frontend->m_init_options = *req->options;
550 req->idAuthentication = 0;
554 BackendClassMap::const_iterator it;
565 frontend->m_backend_class = b;
569 frontend->m_backend_class = it->second;
578 bool create_first_one =
false;
580 boost::mutex::scoped_lock lock(bc->m_mutex_backend_class);
581 if (!bc->m_no_succeeded)
582 create_first_one =
true;
586 while (!bc->m_no_failed && !bc->m_no_succeeded && bc->m_no_init)
588 bc->m_cond_set_ready.wait(lock);
592 if (create_first_one)
599 bc->release_backend(backend);
601 yazpp_1::GDU init_response;
603 boost::mutex::scoped_lock lock(bc->m_mutex_backend_class);
605 init_response = bc->m_init_response;
608 if (init_response.get())
610 Z_GDU *response_gdu = init_response.get();
611 mp::util::transfer_referenceId(odr,
gdu->u.z3950,
612 response_gdu->u.z3950);
613 Z_InitResponse *init_res = response_gdu->u.z3950->u.initResponse;
614 Z_Options *server_options = init_res->options;
615 Z_Options *client_options = &frontend->m_init_options;
617 for (i = 0; i < 30; i++)
618 if (!ODR_MASK_GET(client_options, i))
619 ODR_MASK_CLEAR(server_options, i);
622 *init_res->preferredMessageSize > *req->preferredMessageSize)
623 *init_res->preferredMessageSize = *req->preferredMessageSize;
626 *init_res->maximumRecordSize > *req->maximumRecordSize)
627 *init_res->maximumRecordSize = *req->maximumRecordSize;
629 package.response() = init_response;
630 if (!*response_gdu->u.z3950->u.initResponse->result)
631 package.session().close();
636 odr.create_initResponse(
637 gdu->u.z3950, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR,
638 "session_shared: target closed connection during init");
639 *apdu->u.initResponse->result = 0;
640 package.response() = apdu;
641 package.session().close();
677 mp::Package &frontend_package,
678 mp::Package &search_package,
679 const Z_APDU *frontend_apdu,
681 Z_Records **z_records)
684 Z_APDU *apdu_req = zget_APDU(odr, Z_APDU_searchRequest);
685 Z_SearchRequest *req = apdu_req->u.searchRequest;
689 req->query =
m_query.get_Z_Query();
692 req->databaseNames = (
char**)
693 odr_malloc(odr, req->num_databaseNames *
sizeof(
char *));
694 Databases::const_iterator it =
m_databases.begin();
697 req->databaseNames[i++] = odr_strdup(odr, it->c_str());
699 if (frontend_apdu->which == Z_APDU_searchRequest)
700 req->preferredRecordSyntax =
701 frontend_apdu->u.searchRequest->preferredRecordSyntax;
703 search_package.request() = apdu_req;
705 search_package.move();
707 Z_GDU *
gdu = search_package.response().get();
708 if (!search_package.session().is_closed()
709 &&
gdu &&
gdu->which == Z_GDU_Z3950
710 &&
gdu->u.z3950->which == Z_APDU_searchResponse)
712 Z_SearchResponse *b_resp =
gdu->u.z3950->u.searchResponse;
713 *z_records = b_resp->records;
721 const char *addinfo =
"session_shared: "
722 "target closed connection during search";
723 if (frontend_apdu->which == Z_APDU_searchRequest)
724 f_apdu = odr.create_searchResponse(
725 frontend_apdu, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, addinfo);
726 else if (frontend_apdu->which == Z_APDU_presentRequest)
727 f_apdu = odr.create_presentResponse(
728 frontend_apdu, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, addinfo);
730 f_apdu = odr.create_close(
731 frontend_apdu, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, addinfo);
732 frontend_package.response() = f_apdu;
738 std::string &result_set_id,
740 bool out_of_sessions)
743 BackendInstanceList::const_iterator it = bc->m_backend_list.begin();
747 size_t max_sets = bc->m_named_result_sets ? bc->m_backend_set_max : 1;
748 for (; it != bc->m_backend_list.end(); it++)
750 if (!(*it)->m_in_use)
752 BackendSetList::iterator set_it = (*it)->m_sets.begin();
753 for (; set_it != (*it)->m_sets.end(); set_it++)
755 bool same_databases = mp::util::match((*set_it)->m_databases,
757 if ((max_sets > 1 || same_databases)
760 now < (*set_it)->m_time_last_use ||
761 now - (*set_it)->m_time_last_use >= bc->m_backend_set_ttl))
764 result_set_id = (*set_it)->m_result_set_id;
765 found_backend->m_sets.erase(set_it);
771 for (it = bc->m_backend_list.begin(); it != bc->m_backend_list.end(); it++)
773 if (!(*it)->m_in_use && (*it)->m_sets.size() < max_sets)
776 if (bc->m_named_result_sets)
778 result_set_id = boost::io::str(
779 boost::format(
"%1%") %
780 found_backend->m_result_set_sequence);
781 found_backend->m_result_set_sequence++;
784 result_set_id =
"default";
791 const Z_APDU *apdu_req,
793 yazpp_1::Yaz_Z_Query &query,
797 bool session_restarted =
false;
798 Z_OtherInformation *additionalSearchInfo = 0;
800 if (apdu_req->which == Z_APDU_searchRequest)
801 additionalSearchInfo = apdu_req->u.searchRequest->additionalSearchInfo;
804 std::string result_set_id;
805 bool out_of_sessions =
false;
808 boost::mutex::scoped_lock lock(bc->m_mutex_backend_class);
810 if ((
int) bc->m_backend_list.size() >=
m_p->m_session_max)
811 out_of_sessions =
true;
813 if (
m_p->m_optimize_search)
816 BackendInstanceList::const_iterator it = bc->m_backend_list.begin();
817 while (it != bc->m_backend_list.end())
819 bool restart =
false;
820 BackendSetList::const_iterator set_it = (*it)->m_sets.begin();
821 for (; set_it != (*it)->m_sets.end(); set_it++)
825 if (mp::util::match((*set_it)->m_databases, databases)
826 && query.match(&(*set_it)->m_query)
827 && (apdu_req->which != Z_APDU_searchRequest ||
828 yaz_compare_z_OtherInformation(
829 additionalSearchInfo,
830 (*set_it)->additionalSearchInfoRequest)))
834 bc->m_cond_set_ready.wait(lock);
842 bc->use_backend(found_backend);
849 it = bc->m_backend_list.begin();
854 override_set(found_backend, result_set_id, databases, out_of_sessions);
856 bc->use_backend(found_backend);
863 if (!out_of_sessions)
864 found_backend = bc->create_backend(package, code, addinfo);
872 code = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
873 addinfo =
"session_shared: all sessions in use";
878 code = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
879 if (addinfo.length() == 0)
880 addinfo =
"session_shared: could not create backend";
882 if (apdu_req->which == Z_APDU_searchRequest)
884 f_apdu = odr.create_searchResponse(
885 apdu_req, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, addinfo.c_str());
887 else if (apdu_req->which == Z_APDU_presentRequest)
889 f_apdu = odr.create_presentResponse(
890 apdu_req, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, addinfo.c_str());
894 f_apdu = odr.create_close(
895 apdu_req, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, addinfo.c_str());
897 package.response() = f_apdu;
900 if (bc->m_named_result_sets)
902 result_set_id = boost::io::str(
903 boost::format(
"%1%") % found_backend->m_result_set_sequence);
904 found_backend->m_result_set_sequence++;
907 result_set_id =
"default";
909 found_backend->timestamp();
914 additionalSearchInfo));
917 found_set->timestamp();
919 Z_Records *z_records = 0;
921 Package search_package(found_backend->m_session, package.origin());
922 search_package.copy_filter(package);
924 if (!new_set->search(package, search_package,
925 apdu_req, found_backend, &z_records))
927 bc->remove_backend(found_backend);
935 if (z_records->which == Z_Records_NSD)
940 else if (z_records->which == Z_Records_multipleNSD)
942 if (z_records->u.multipleNonSurDiagnostics->num_diagRecs >= 1
945 z_records->u.multipleNonSurDiagnostics->diagRecs[0]->which ==
946 Z_DiagRec_defaultFormat)
949 z_records->u.multipleNonSurDiagnostics->diagRecs[0]->u.defaultFormat);
953 if (
m_p->m_restart && !session_restarted &&
954 condition == YAZ_BIB1_TEMPORARY_SYSTEM_ERROR)
956 package.log(
"session_shared", YLOG_LOG,
"restart");
957 bc->remove_backend(found_backend);
958 session_restarted =
true;
959 found_backend.reset();
967 if (apdu_req->which == Z_APDU_searchRequest)
969 Z_APDU *f_apdu = odr.create_searchResponse(apdu_req,
971 Z_SearchResponse *f_resp = f_apdu->u.searchResponse;
972 *f_resp->searchStatus = Z_SearchResponse_none;
973 f_resp->records = z_records;
974 package.response() = f_apdu;
976 if (apdu_req->which == Z_APDU_presentRequest)
978 Z_APDU *f_apdu = odr.create_presentResponse(apdu_req,
980 Z_PresentResponse *f_resp = f_apdu->u.presentResponse;
981 f_resp->records = z_records;
982 package.response() = f_apdu;
984 bc->release_backend(found_backend);
989 if (
m_p->m_restart && !session_restarted && new_set->m_result_set_size < 0)
991 package.log(
"session_shared", YLOG_LOG,
"restart");
992 bc->remove_backend(found_backend);
993 session_restarted =
true;
994 found_backend.reset();
997 found_backend->m_sets.push_back(found_set);
1008 case Z_RPNStructure_simple:
1009 if (s->u.simple->which == Z_Operand_resultSetId)
1011 const char *
id = s->u.simple->u.resultSetId;
1017 ret = YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST;
1019 else if (!mp::util::match(fset_it->second->get_databases(),
1022 ret = YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST;
1026 yazpp_1::Yaz_Z_Query query = fset_it->second->get_query();
1027 Z_Query *q = yaz_copy_Z_Query(query.get_Z_Query(), o);
1028 if (q->which == Z_Query_type_1 || q->which == Z_Query_type_101)
1030 s->which = q->u.type_1->RPNStructure->which;
1031 s->u.simple = q->u.type_1->RPNStructure->u.simple;
1035 ret = YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST;
1040 case Z_RPNStructure_complex:
1052 Z_SearchRequest *req = apdu_req->u.searchRequest;
1053 FrontendSets::iterator fset_it =
1060 if (*req->replaceIndicator == 0)
1064 odr.create_searchResponse(
1066 YAZ_BIB1_RESULT_SET_EXISTS_AND_REPLACE_INDICATOR_OFF,
1068 package.response() = apdu;
1076 for (i = 0; i < req->num_databaseNames; i++)
1077 databases.push_back(req->databaseNames[i]);
1080 yazpp_1::Yaz_Z_Query query;
1081 query.set_Z_Query(req->query);
1083 Z_Query *q = query.get_Z_Query();
1084 if (q->which == Z_Query_type_1 || q->which == Z_Query_type_101)
1088 int diag =
result_set_ref(odr, databases, q->u.type_1->RPNStructure,
1093 odr.create_searchResponse(
1097 package.response() = apdu;
1100 query.set_Z_Query(q);
1106 get_set(package, apdu_req, databases, query, found_backend, found_set);
1111 Z_APDU *f_apdu = odr.create_searchResponse(apdu_req, 0, 0);
1112 Z_SearchResponse *f_resp = f_apdu->u.searchResponse;
1113 *f_resp->resultCount = found_set->m_result_set_size;
1114 f_resp->additionalSearchInfo = found_set->additionalSearchInfoResponse;
1115 package.response() = f_apdu;
1127 Z_PresentRequest *req = apdu_req->u.presentRequest;
1129 FrontendSets::iterator fset_it =
1135 odr.create_presentResponse(
1137 YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST,
1139 package.response() = apdu;
1144 Databases databases = fset->get_databases();
1145 yazpp_1::Yaz_Z_Query query = fset->get_query();
1151 get_set(package, apdu_req, databases, query, found_backend, found_set);
1155 Z_NamePlusRecordList *npr_res = 0;
1157 if (*req->resultSetStartPoint > 0
1158 && *req->resultSetStartPoint < INT_MAX
1159 && *req->numberOfRecordsRequested > 0
1160 && *req->numberOfRecordsRequested < INT_MAX
1161 && found_set->m_record_cache.lookup(odr, &npr_res,
1162 *req->resultSetStartPoint,
1163 *req->numberOfRecordsRequested,
1164 req->preferredRecordSyntax,
1165 req->recordComposition))
1167 Z_APDU *f_apdu_res = odr.create_presentResponse(apdu_req, 0, 0);
1168 Z_PresentResponse *f_resp = f_apdu_res->u.presentResponse;
1170 yaz_log(YLOG_LOG,
"Found " ODR_INT_PRINTF
"+" ODR_INT_PRINTF
1171 " records in cache %p",
1172 *req->resultSetStartPoint,
1173 *req->numberOfRecordsRequested,
1174 &found_set->m_record_cache);
1176 *f_resp->numberOfRecordsReturned = *req->numberOfRecordsRequested;
1177 *f_resp->nextResultSetPosition =
1178 *req->resultSetStartPoint + *req->numberOfRecordsRequested;
1180 f_resp->records = (Z_Records *) odr_malloc(odr,
sizeof(Z_Records));
1181 f_resp->records->which = Z_Records_DBOSD;
1182 f_resp->records->u.databaseOrSurDiagnostics = npr_res;
1183 package.response() = f_apdu_res;
1184 bc->release_backend(found_backend);
1188 found_backend->timestamp();
1190 Z_APDU *p_apdu = zget_APDU(odr, Z_APDU_presentRequest);
1191 Z_PresentRequest *p_req = p_apdu->u.presentRequest;
1192 p_req->preferredRecordSyntax = req->preferredRecordSyntax;
1193 p_req->resultSetId = odr_strdup(odr, found_set->m_result_set_id.c_str());
1194 *p_req->resultSetStartPoint = *req->resultSetStartPoint;
1195 *p_req->numberOfRecordsRequested = *req->numberOfRecordsRequested;
1196 p_req->preferredRecordSyntax = req->preferredRecordSyntax;
1197 p_req->recordComposition = req->recordComposition;
1199 Package present_package(found_backend->m_session, package.origin());
1200 present_package.copy_filter(package);
1202 present_package.request() = p_apdu;
1204 present_package.move();
1206 Z_GDU *
gdu = present_package.response().get();
1207 if (!present_package.session().is_closed()
1208 &&
gdu &&
gdu->which == Z_GDU_Z3950
1209 &&
gdu->u.z3950->which == Z_APDU_presentResponse)
1211 Z_PresentResponse *b_resp =
gdu->u.z3950->u.presentResponse;
1212 Z_APDU *f_apdu_res = odr.create_presentResponse(apdu_req, 0, 0);
1213 Z_PresentResponse *f_resp = f_apdu_res->u.presentResponse;
1215 f_resp->numberOfRecordsReturned = b_resp->numberOfRecordsReturned;
1216 f_resp->nextResultSetPosition = b_resp->nextResultSetPosition;
1217 f_resp->presentStatus= b_resp->presentStatus;
1218 f_resp->records = b_resp->records;
1219 f_resp->otherInfo = b_resp->otherInfo;
1220 package.response() = f_apdu_res;
1222 if (b_resp->records && b_resp->records->which == Z_Records_DBOSD)
1224 Z_NamePlusRecordList *npr =
1225 b_resp->records->u.databaseOrSurDiagnostics;
1227 if (*req->resultSetStartPoint > 0
1228 && npr->num_records + *req->resultSetStartPoint < INT_MAX)
1231 yaz_log(YLOG_LOG,
"Adding " ODR_INT_PRINTF
"+" ODR_INT_PRINTF
1232 " records to cache %p",
1233 *req->resultSetStartPoint,
1234 *f_resp->numberOfRecordsReturned,
1235 &found_set->m_record_cache);
1237 found_set->m_record_cache.add(
1238 odr, npr, *req->resultSetStartPoint,
1239 p_req->recordComposition);
1242 bc->release_backend(found_backend);
1246 bc->remove_backend(found_backend);
1247 Z_APDU *f_apdu_res =
1248 odr.create_presentResponse(
1249 apdu_req, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR,
1250 "session_shared: target closed connection during present");
1251 package.response() = f_apdu_res;
1260 std::string addinfo;
1267 code = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
1268 if (addinfo.length() == 0)
1269 addinfo =
"session_shared: could not create backend";
1270 Z_APDU *apdu = odr.create_scanResponse(
1271 apdu_req, code, addinfo.c_str());
1272 frontend_package.response() = apdu;
1276 Package scan_package(backend->m_session, frontend_package.origin());
1277 backend->timestamp();
1278 scan_package.copy_filter(frontend_package);
1279 scan_package.request() = apdu_req;
1280 scan_package.move();
1281 frontend_package.response() = scan_package.response();
1282 if (scan_package.session().is_closed())
1284 frontend_package.session().close();
1285 bc->remove_backend(backend);
1288 bc->release_backend(backend);
1474 Z_GDU *
gdu = package.request().get();
1476 if (
gdu &&
gdu->which == Z_GDU_Z3950 &&
gdu->u.z3950->which ==
1477 Z_APDU_initRequest && !f->m_is_virtual)
1479 m_p->init(package,
gdu, f);
1481 else if (!f->m_is_virtual)
1483 else if (
gdu &&
gdu->which == Z_GDU_Z3950)
1485 Z_APDU *apdu =
gdu->u.z3950;
1486 if (apdu->which == Z_APDU_initRequest)
1490 package.response() = odr.create_close(
1492 Z_Close_protocolError,
1495 package.session().close();
1497 else if (apdu->which == Z_APDU_close)
1501 package.response() = odr.create_close(
1503 Z_Close_peerAbort,
"received close from client");
1504 package.session().close();
1506 else if (apdu->which == Z_APDU_searchRequest)
1508 f->search(package, apdu);
1510 else if (apdu->which == Z_APDU_presentRequest)
1512 f->present(package, apdu);
1514 else if (apdu->which == Z_APDU_scanRequest)
1516 f->scan(package, apdu);
1522 package.response() = odr.create_close(
1523 apdu, Z_Close_protocolError,
1524 "unsupported APDU in filter_session_shared");
1526 package.session().close();
1529 m_p->release_frontend(package);
1535 for (ptr = ptr->children; ptr; ptr = ptr->next)
1537 if (ptr->type != XML_ELEMENT_NODE)
1539 if (!strcmp((
const char *) ptr->name,
"resultset"))
1541 const struct _xmlAttr *attr;
1542 for (attr = ptr->properties; attr; attr = attr->next)
1544 if (!strcmp((
const char *) attr->name,
"ttl"))
1545 m_p->m_resultset_ttl =
1546 mp::xml::get_int(attr->children, 30);
1547 else if (!strcmp((
const char *) attr->name,
"max"))
1549 m_p->m_resultset_max =
1550 mp::xml::get_int(attr->children, 10);
1552 else if (!strcmp((
const char *) attr->name,
"optimizesearch"))
1554 m_p->m_optimize_search =
1555 mp::xml::get_bool(attr->children,
true);
1557 else if (!strcmp((
const char *) attr->name,
"restart"))
1559 m_p->m_restart = mp::xml::get_bool(attr->children,
true);
1562 throw mp::filter::FilterException(
1563 "Bad attribute " + std::string((
const char *)
1567 else if (!strcmp((
const char *) ptr->name,
"session"))
1569 const struct _xmlAttr *attr;
1570 for (attr = ptr->properties; attr; attr = attr->next)
1572 if (!strcmp((
const char *) attr->name,
"ttl"))
1573 m_p->m_session_ttl =
1574 mp::xml::get_int(attr->children, 90);
1575 else if (!strcmp((
const char *) attr->name,
"max"))
1576 m_p->m_session_max =
1577 mp::xml::get_int(attr->children, 100);
1579 throw mp::filter::FilterException(
1580 "Bad attribute " + std::string((
const char *)
1584 else if (!strcmp((
const char *) ptr->name,
"init"))
1586 const struct _xmlAttr *attr;
1587 for (attr = ptr->properties; attr; attr = attr->next)
1589 if (!strcmp((
const char *) attr->name,
"maximum-record-size"))
1590 m_p->m_maximumRecordSize =
1591 mp::xml::get_int(attr->children, 0);
1592 else if (!strcmp((
const char *) attr->name,
1593 "preferred-message-size"))
1594 m_p->m_preferredMessageSize =
1595 mp::xml::get_int(attr->children, 0);
1596 else if (!strcmp((
const char *) attr->name,
1598 m_p->m_ignore_auth =
1599 mp::xml::get_bool(attr->children,
false);
1601 throw mp::filter::FilterException(
1602 "Bad attribute " + std::string((
const char *)
1608 throw mp::filter::FilterException(
"Bad element "
1609 + std::string((
const char *)