pipe_handle.cc 5.42 KB
Newer Older
1
/*
2
** Copyright 2012-2014 Merethis
3
**
4
** This file is part of Centreon Perl Connector.
5
**
6
** Centreon Perl Connector is free software: you can redistribute it
7
8
9
10
** and/or modify it under the terms of the GNU Affero General Public
** License as published by the Free Software Foundation, either version
** 3 of the License, or (at your option) any later version.
**
11
** Centreon Perl Connector is distributed in the hope that it will be
12
13
14
15
16
** useful, but WITHOUT ANY WARRANTY; without even the implied warranty
** of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public
17
** License along with Centreon Perl Connector. If not, see
18
19
20
** <http://www.gnu.org/licenses/>.
*/

21
22
#include <cerrno>
#include <cstring>
23
#include <set>
24
#include <unistd.h>
25
26
#include "com/centreon/concurrency/locker.hh"
#include "com/centreon/concurrency/mutex.hh"
27
28
#include "com/centreon/connector/perl/pipe_handle.hh"
#include "com/centreon/exceptions/basic.hh"
29
#include "com/centreon/logging/logger.hh"
30
31
32
33

using namespace com::centreon;
using namespace com::centreon::connector::perl;

34
35
36
37
38
39
40
41
42
/**************************************
*                                     *
*           Local Objects             *
*                                     *
**************************************/

static std::multiset<int>* gl_fds(NULL);
static concurrency::mutex* gl_fdsm(NULL);

43
44
45
46
47
48
49
50
51
52
53
/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Constructor.
 *
 *  @param[in] fd File descriptor.
 */
54
pipe_handle::pipe_handle(int fd) : _fd(-1) {
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  set_fd(fd);
}

/**
 *  Copy constructor.
 *
 *  @param[in] ph Object to copy.
 */
pipe_handle::pipe_handle(pipe_handle const& ph) : handle(ph) {
  _internal_copy(ph);
}

/**
 *  Destructor.
 */
pipe_handle::~pipe_handle() throw () {
  close();
}

/**
 *  Assignment operator.
 *
 *  @param[in] ph Object to copy.
 *
 *  @return This object.
 */
pipe_handle& pipe_handle::operator=(pipe_handle const& ph) {
  if (this != &ph) {
    handle::operator=(ph);
    close();
    _internal_copy(ph);
  }
  return (*this);
}

/**
 *  Close the file descriptor.
 */
void pipe_handle::close() throw () {
  if (_fd >= 0) {
95
96
97
98
99
100
    {
      concurrency::locker lock(gl_fdsm);
      std::multiset<int>::iterator it(gl_fds->find(_fd));
      if (it != gl_fds->end())
        gl_fds->erase(it);
    }
101
102
103
104
    if (::close(_fd) != 0) {
      char const* msg(strerror(errno));
      log_error(logging::medium) << "could not close pipe FD: " << msg;
    }
105
106
107
108
109
    _fd = -1;
  }
  return ;
}

110
111
112
113
114
115
116
117
118
/**
 *  Close all handles.
 */
void pipe_handle::close_all_handles() {
  concurrency::locker lock(gl_fdsm);
  for (std::multiset<int>::const_iterator
         it(gl_fds->begin()),
         end(gl_fds->end());
       it != end;
119
120
       ++it) {
    int retval;
121
    do {
122
123
124
125
126
127
128
129
      retval = ::close(*it);
    } while ((retval != 0) && (EINTR == errno));
    if (retval != 0) {
      char const* msg(strerror(errno));
      gl_fds->erase(gl_fds->begin(), it);
      throw (basic_error() << msg);
    }
  }
130
131
132
133
  gl_fds->clear();
  return ;
}

134
135
136
137
138
139
140
141
142
/**
 *  Get the native handle associated with this pipe handle.
 *
 *  @return Pipe FD.
 */
int pipe_handle::get_native_handle() throw () {
  return (_fd);
}

143
144
145
146
147
148
149
150
151
152
153
/**
 *  Initialize static members of the pipe_handle class.
 */
void pipe_handle::load() {
  if (!gl_fds) {
    gl_fds = new std::multiset<int>();
    gl_fdsm = new concurrency::mutex();
  }
  return ;
}

154
155
156
157
158
159
160
161
/**
 *  Read data from the file descriptor.
 *
 *  @param[out] data Destination buffer.
 *  @param[in]  size Maximum number of bytes to read.
 *
 *  @return Number of bytes actually read.
 */
162
unsigned long pipe_handle::read(void* data, unsigned long size) {
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  ssize_t rb(::read(_fd, data, size));
  if (rb < 0) {
    char const* msg(strerror(errno));
    throw (basic_error() << "could not read from pipe: " << msg);
  }
  return (rb);
}

/**
 *  Set file descriptor.
 *
 *  @param[in] fd New class file descriptor.
 */
void pipe_handle::set_fd(int fd) {
  close();
  _fd = fd;
179
  if (_fd >= 0) {
180
181
182
183
184
185
186
187
188
189
190
191
192
193
    concurrency::locker lock(gl_fdsm);
    gl_fds->insert(fd);
  }
  return ;
}

/**
 *  Cleanup static ressources used by the pipe_handle class.
 */
void pipe_handle::unload() {
  delete gl_fds;
  gl_fds = NULL;
  delete gl_fdsm;
  gl_fdsm = NULL;
194
195
196
197
198
199
200
201
202
203
204
  return ;
}

/**
 *  Write data to the pipe.
 *
 *  @param[in] data Source buffer.
 *  @param[in] size Maximum number of bytes to write.
 *
 *  @return Actual number of bytes written.
 */
205
unsigned long pipe_handle::write(void const* data, unsigned long size) {
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  ssize_t wb(::write(_fd, data, size));
  if (wb <= 0) {
    char const* msg(strerror(errno));
    throw (basic_error() << "could not write to pipe: " << msg);
  }
  return (wb);
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  Copy internal data members.
 *
 *  @param[in] ph Object to copy.
 */
void pipe_handle::_internal_copy(pipe_handle const& ph) {
  if (ph._fd >= 0) {
    _fd = dup(ph._fd);
    if (_fd < 0) {
      char const* msg(strerror(errno));
      throw (basic_error() << "could not duplicate pipe: " << msg);
    }
232
233
234
235
    {
      concurrency::locker lock(gl_fdsm);
      gl_fds->insert(_fd);
    }
236
237
238
239
240
  }
  else
    _fd = -1;
  return ;
}