internal: add send index 22/208522/4 accepted/tizen/unified/20190627.014814 submit/tizen/20190626.110347
authorAdrian Szyndela <adrian.s@samsung.com>
Wed, 29 May 2019 14:17:49 +0000 (16:17 +0200)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Wed, 26 Jun 2019 10:40:30 +0000 (10:40 +0000)
This adds indexes:
- main index for send rules;
- additional index for send prefix rules;
- indexes for send rules for each user;
- additional indexes for send prefix rules for each user.

Change-Id: I45a4b3625fe67a9fff7525d04ae6ebf8879e14f1

src/internal/policy.hpp
src/internal/storage_backend_serialized.cpp

index 9f1575e..71fd8ae 100644 (file)
@@ -167,6 +167,8 @@ namespace ldp_xml_parser
                                   const boost::string_ref &_name,
                                   bool _is_name_prefix,
                                   Decision decision) const;
+
+               const KdbusBusNames &getNames() const { return names; }
        };
 
        class MatchItemSend : public MatchItemSR {
index d9439ce..ef0855b 100644 (file)
 #include <boost/tokenizer.hpp>
 #include <cerrno>
 #include <fcntl.h>
+#include <map>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 using namespace FB;
+using ldp_xml_parser::MatchItemSend;
 
 namespace ldp_serialized {
 
@@ -36,6 +38,8 @@ namespace ldp_serialized {
 // 1MB. Adjustable
 #define MAX_SFILE_SIZE (1024 * 1024)
 
+typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
+
 template <typename T>
 struct type_helper;
 
@@ -50,18 +54,136 @@ class StorageBackendSerialized::StorageBackendSerializedImpl {
        void releaseMMap();
        void releaseFD();
 
+       typedef std::pair<const ItemSend *, unsigned> ItemWithScore;    // a pair: Item, index of Item
+       typedef std::vector<ItemWithScore> ItemsWithScore;                              // items
+       typedef std::pair<unsigned, ItemsWithScore> HighestScoreWithItems;      // value for index map: highest index for items, items
+       typedef std::map<boost::string_ref, HighestScoreWithItems> MapIndex;
+       typedef std::vector<ItemWithScore> SendPrefixIndex;
+
+       MapIndex sendIndex; // context default
+       SendPrefixIndex sendPrefixIndex; // context default prefix rules
+       std::map<uid_t, MapIndex> userSendIndex;
+       std::map<uid_t, SendPrefixIndex> userSendPrefixIndex;
+
 public:
        bool init(const char *filename, bool verify);
        bool init(const FB::File *f);
        bool initFromXML(const char *config_name);
        void release();
 
+       void createSendIndex();
+       ldp_xml_parser::DecisionItem getDecisionFromSendIndex(const MatchItemSend &item, const MapIndex &index, const SendPrefixIndex &prefixIndex);
+       ldp_xml_parser::DecisionItem getDecisionFromSendIndex(const MatchItemSend &item);
+       ldp_xml_parser::DecisionItem getDecisionFromSendIndex(const MatchItemSend &item, uid_t uid);
+
        void printContent() const;
 
        template <typename T, typename M = typename type_helper<T>::policy_set_type>
        const M *getPolicySet();
 };
 
+inline boost::string_ref s(const flatbuffers::String *str) {
+       return boost::string_ref(str->c_str(), str->size());
+}
+
+template <typename T, typename I>
+bool match(const T &match, const I *i) {
+       return match.match(makeMessageType(i->type()),
+                                          s(i->interface()),
+                                          s(i->path()),
+                                          s(i->member()),
+                                          s(i->name()),
+                                          i->is_name_prefix(),
+                                          makeDecision(i->decision()->decision()));
+}
+
+ldp_xml_parser::DecisionItem StorageBackendSerialized::StorageBackendSerializedImpl::getDecisionFromSendIndex(const MatchItemSend &item,
+               const MapIndex &index, const SendPrefixIndex &prefixIndex) {
+       ldp_xml_parser::DecisionItem decision(ldp_xml_parser::Decision::ANY);
+
+       ItemWithScore currentBest(nullptr, 0);
+
+       auto updateCurrentBest = [&currentBest, &item, &index](boost::string_ref name) {
+               // check if there are any rules for the name
+               auto fit = index.find(name);
+               if (fit == index.end())
+                       return;
+
+               // check if there's any chance to get better score
+               // fit->second.first is the highest score from vector fit->second.second
+               if (fit->second.first <= currentBest.second)
+                       return;
+
+               // look for better score
+               for (const auto &it: fit->second.second) {
+                       if (it.second > currentBest.second && match(item, it.first))
+                               currentBest = it;
+               }
+       };
+
+       // iterate over names
+       for (const auto &name: item.getNames()) {
+               // find and check the no-prefix rules
+               updateCurrentBest(name);
+
+               // check the prefix rules
+               for (const auto &prefixItem: prefixIndex) {
+                       if (prefixItem.second > currentBest.second && match(item, prefixItem.first))
+                               currentBest = prefixItem;
+               }
+       }
+
+       // check no-name rules
+       updateCurrentBest("");
+
+       if (currentBest.first)
+               decision = makeDecisionItem(currentBest.first->decision());
+
+       return decision;
+}
+
+ldp_xml_parser::DecisionItem StorageBackendSerialized::StorageBackendSerializedImpl::getDecisionFromSendIndex(const MatchItemSend &item) {
+       return getDecisionFromSendIndex(item, sendIndex, sendPrefixIndex);
+}
+
+ldp_xml_parser::DecisionItem StorageBackendSerialized::StorageBackendSerializedImpl::getDecisionFromSendIndex(const MatchItemSend &item, uid_t uid) {
+       return getDecisionFromSendIndex(item, userSendIndex[uid], userSendPrefixIndex[uid]);
+}
+
+void StorageBackendSerialized::StorageBackendSerializedImpl::createSendIndex() {
+       // helper for adding items to indexes
+       auto add = [](MapIndex &index, SendPrefixIndex &prefixIndex, boost::string_ref key, ItemWithScore value) {
+               if (value.first->is_name_prefix()) {
+                       prefixIndex.push_back(value);
+               } else {
+                       index[key].second.push_back(value);
+                       // we insert items in increasing score order, so we just update the highest score on each add
+                       index[key].first = value.second;
+               }
+       };
+
+       // context default index
+       const auto *policy = file->m_send_set()->context_default();
+       unsigned cnt = 1;
+
+       const auto *v = policy->items();
+       for (auto it = v->begin(); it != v->end(); ++it)
+               add(sendIndex, sendPrefixIndex,
+                               boost::string_ref(it->name()->c_str(), it->name()->size()),
+                               ItemWithScore(*it, cnt++));
+
+       // users index
+       for (const auto &uidPolicy: *file->m_send_set()->user()) {
+               cnt = 1;
+               for (const auto it: *uidPolicy->policy()->items()) {
+                       add(userSendIndex[uidPolicy->id()],
+                                       userSendPrefixIndex[uidPolicy->id()],
+                                       boost::string_ref(it->name()->c_str(), it->name()->size()),
+                                       ItemWithScore(it, cnt++));
+               }
+       }
+}
+
 void StorageBackendSerialized::StorageBackendSerializedImpl::releaseMMap() {
        assert(MAP_FAILED != mem);
        assert(0 != length);
@@ -138,13 +260,17 @@ bool StorageBackendSerialized::StorageBackendSerializedImpl::init(const char *fi
        mmapGuard.dismiss();
 
        file = GetFile(mem);
-       return file != nullptr;
+       bool res = file != nullptr;
+       if (res)
+               createSendIndex();
+       return res;
 }
 
 bool StorageBackendSerialized::StorageBackendSerializedImpl::init(const FB::File *f) {
        assert(nullptr == file);
 
        file = f;
+       createSendIndex();
        return true;
 }
 
@@ -206,21 +332,6 @@ void StorageBackendSerialized::printContent() const {
        pimpl->printContent();
 }
 
-inline boost::string_ref s(const flatbuffers::String *str) {
-       return boost::string_ref(str->c_str(), str->size());
-}
-
-template <typename T, typename I>
-bool match(const T &match, const I *i) {
-       return match.match(makeMessageType(i->type()),
-                                          s(i->interface()),
-                                          s(i->path()),
-                                          s(i->member()),
-                                          s(i->name()),
-                                          i->is_name_prefix(),
-                                          makeDecision(i->decision()->decision()));
-}
-
 template <> bool match(const ldp_xml_parser::MatchItemAccess &match, const FB::ItemAccess *item) {
        return match.match(makeBusAccessType(item->type()), item->uid(), item->gid());
 }
@@ -235,8 +346,6 @@ ldp_xml_parser::DecisionItem getDecisionItem(const T &item, const P *policy) {
        return ldp_xml_parser::Decision::ANY;
 }
 
-typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
-
 const DecisionItem *getDecisionItemFromTree(const FB::PolicyOwnNode *node,
                                                                                        tokenizer &tokens,
                                                                                        tokenizer::iterator &iterator) {
@@ -288,6 +397,19 @@ ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextMan
        return getDecisionItem(item, pimpl->getPolicySet<T>()->context_mandatory());
 }
 
+template <>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextDefault(const MatchItemSend &item) const {
+       return pimpl->getDecisionFromSendIndex(item);
+}
+
+template <>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemUser(uid_t uid, const MatchItemSend &item) const {
+       auto *policyPair = pimpl->getPolicySet<MatchItemSend>()->user()->LookupByKey(uid);
+       if (nullptr == policyPair)
+               return ldp_xml_parser::Decision::ANY;
+       return pimpl->getDecisionFromSendIndex(item, uid);
+}
+
 template <typename T>
 ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextDefault(const T &item) const {
        return getDecisionItem(item, pimpl->getPolicySet<T>()->context_default());