Fix SVACE defects
[platform/core/security/key-manager.git] / src / manager / client-async / descriptor-set.cpp
1 /*
2  *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16 /*
17  * @file       descriptor-set.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21
22 #include "descriptor-set.h"
23 #include <dpl/errno_string.h>
24 #include <dpl/log/log.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 namespace CKM {
29
30 DescriptorSet::DescriptorSet() : m_dirty(true), m_fds(NULL)
31 {
32 }
33
34 DescriptorSet::~DescriptorSet()
35 {
36         purge();
37
38         delete[] m_fds;
39 }
40
41 void DescriptorSet::purge()
42 {
43         for (auto it : m_descriptors)
44                 close(it.first);
45
46         m_descriptors.clear();
47         m_dirty = true;
48 }
49
50 void DescriptorSet::add(int fd, short events, Callback &&callback)
51 {
52         // map operator[] requires empty DescriptorData constructor
53         auto it = m_descriptors.find(fd);
54
55         if (it == m_descriptors.end()) {
56                 m_descriptors.insert(std::make_pair(fd, DescriptorData(events,
57                                                                                         std::move(callback))));
58         } else {
59                 it->second.events = events;
60                 it->second.callback = std::move(callback);
61         }
62
63         m_dirty = true;
64 }
65
66 void DescriptorSet::remove(int fd, bool close_fd)
67 {
68         if (0 != m_descriptors.erase(fd)) {
69                 if (close_fd)
70                         close(fd);
71
72                 m_dirty = true;
73         }
74 }
75
76 void DescriptorSet::wait(int timeout_ms)
77 {
78         if (!rebuildPollfd())
79                 return;
80
81         // wait
82         int ret = TEMP_FAILURE_RETRY(poll(m_fds, m_descriptors.size(), timeout_ms));
83
84         if (ret == 0) {
85                 ThrowMsg(Timeout, "Poll timeout");
86         } else if (ret < 0) {
87                 int err = errno;
88                 ThrowMsg(InternalError, "Poll failed " << GetErrnoString(err));
89         }
90
91         notify(ret);
92 }
93
94 bool DescriptorSet::rebuildPollfd()
95 {
96         if (m_dirty) {
97                 delete[] m_fds;
98                 m_fds = NULL;
99
100                 if (m_descriptors.empty()) {
101                         LogWarning("Nothing to wait for");
102                         return false;
103                 }
104
105                 m_fds = new pollfd[m_descriptors.size()];
106                 size_t idx = 0;
107
108                 for (const auto &it : m_descriptors) {
109                         m_fds[idx].fd = it.first;
110                         m_fds[idx].events = it.second.events;
111                         idx++;
112                 }
113
114                 m_dirty = false;
115         }
116
117         return true;
118 }
119
120 void DescriptorSet::notify(int descCount)
121 {
122         size_t size = m_descriptors.size();
123
124         for (size_t idx = 0; idx < size; ++idx) {
125                 const pollfd &pfd = m_fds[idx];
126
127                 if (pfd.revents == 0)
128                         continue;
129
130                 /*
131                  * Descriptors can be added/removed inside observer callback but:
132                  * 1. m_fds is not affected. It will be regenerated in next wait()
133                  * 2. No m_descriptors iterator will be invalidated
134                  * 3. m_descriptors size is stored in local variable
135                  */
136                 m_descriptors.at(pfd.fd).callback(pfd.fd, pfd.revents);
137                 descCount--;
138
139                 // no more descriptors to check
140                 if (descCount == 0)
141                         break;
142         }
143
144         if (descCount != 0)
145                 ThrowMsg(InternalError, "Number of notified descriptors do not match");
146 }
147
148 } /* namespace CKM */