summaryrefslogtreecommitdiff
path: root/cpp/include/Ice/Service.h
blob: 7528b8311747110461ee49fc7c40c4fa8630d6ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
// **********************************************************************
//
// Copyright (c) 2003-2018 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************

#ifndef ICE_SERVICE_H
#define ICE_SERVICE_H

#include <Ice/Initialize.h>
#include <Ice/LoggerUtil.h>

#ifdef _WIN32
#   include <winsvc.h>
#endif

namespace Ice
{

/**
 * A singleton class comparable to Ice::Application but also provides the low-level, platform-specific
 * initialization and shutdown procedures common to system services.
 * \headerfile Ice/Ice.h
 */
class ICE_API Service
{
public:

    Service();
    virtual ~Service();

    /**
     * Shutdown the service. The default implementation invokes shutdown()
     * on the communicator.
     */
    virtual bool shutdown();

    /**
     * Notify the service about a signal interrupt. The default
     * implementation invokes shutdown().
     */
    virtual void interrupt();

    /**
     * The primary entry point for services. This function examines
     * the given argument vector for reserved options and takes the
     * appropriate action. The reserved options are shown below.
     *
     * Win32:
     *
     * --service NAME
     *
     * Unix:
     *
     * --daemon [--nochdir] [--noclose]
     *
     * If --service or --daemon are specified, the program runs as
     * a service, otherwise the program runs as a regular foreground
     * process. Any service-specific (and Ice-specific) options
     * are stripped from argv (just as for Ice::initialize()).
     *
     * @param argc Specifies the number of arguments in argv.
     * @param argv The command-line arguments.
     * @param initData Configuration data for the new Communicator.
     * @param version Indicates the Ice version with which the application is compatible. If not
     * specified, the version of the Ice installation is used.
     * @return The application's exit status: EXIT_FAILURE or EXIT_SUCCESS.
     */
    int main(int argc, const char* const argv[], const InitializationData& initData = InitializationData(),
             int version = ICE_INT_VERSION);

#ifdef _WIN32
    /**
     * The primary entry point for services. This function examines
     * the given argument vector for reserved options and takes the
     * appropriate action. The reserved options are shown below.
     *
     * Win32:
     *
     * --service NAME
     *
     * Unix:
     *
     * --daemon [--nochdir] [--noclose]
     *
     * If --service or --daemon are specified, the program runs as
     * a service, otherwise the program runs as a regular foreground
     * process. Any service-specific (and Ice-specific) options
     * are stripped from argv (just as for Ice::initialize()).
     *
     * @param argc Specifies the number of arguments in argv.
     * @param argv The command-line arguments.
     * @param initData Configuration data for the new Communicator.
     * @param version Indicates the Ice version with which the application is compatible. If not
     * specified, the version of the Ice installation is used.
     * @return The application's exit status: EXIT_FAILURE or EXIT_SUCCESS.
     */
    int main(int argc, const wchar_t* const argv[], const InitializationData& initData = InitializationData(),
             int version = ICE_INT_VERSION);
#endif

    /**
     * The primary entry point for services. This function examines
     * the given argument vector for reserved options and takes the
     * appropriate action. The reserved options are shown below.
     *
     * Win32:
     *
     * --service NAME
     *
     * Unix:
     *
     * --daemon [--nochdir] [--noclose]
     *
     * If --service or --daemon are specified, the program runs as
     * a service, otherwise the program runs as a regular foreground
     * process. Any service-specific (and Ice-specific) options
     * are stripped from argv (just as for Ice::initialize()).
     *
     * @param args The command-line arguments.
     * @param initData Configuration data for the new Communicator.
     * @param version Indicates the Ice version with which the application is compatible. If not
     * specified, the version of the Ice installation is used.
     * @return The application's exit status: EXIT_FAILURE or EXIT_SUCCESS.
     */
    int main(const StringSeq& args, const InitializationData& initData = InitializationData(),
             int version = ICE_INT_VERSION);

    /**
     * Obtains the communicator created by the service.
     * @return The service's communicator.
     */
    Ice::CommunicatorPtr communicator() const;

    /**
     * Obtains the Service singleton.
     * @return A pointer to this service.
     */
    static Service* instance();

    /**
     * Indicates whether the program is running as a Win32 service or Unix daemon.
     * @return True if the program is running as a service, false otherwise.
     */
    bool service() const;

    /**
     * Obtains the program name. If the program is running as a Win32
     * service, the return value is the service name. Otherwise the
     * return value is the executable name (i.e., argv[0]).
     * @return The service name.
     */
    std::string name() const;

    /**
     * Determines whether the operating system supports running the
     * program as a Win32 service or Unix daemon.
     * @return True if the system supports services, false otherwise.
     */
    bool checkSystem() const;

    /**
     * Alternative entry point for services that use their own
     * command-line options. Instead of invoking main(), the
     * program processes its command-line options and invokes
     * run(). To run as a Win32 service or Unix daemon, the
     * program must first invoke configureService() or
     * configureDaemon(), respectively.
     *
     * @param argc Specifies the number of arguments in argv.
     * @param argv The command-line arguments.
     * @param initData Configuration data for the new Communicator.
     * @param version Indicates the Ice version with which the application is compatible. If not
     * specified, the version of the Ice installation is used.
     * @return The application's exit status: EXIT_FAILURE or EXIT_SUCCESS.
     */
#ifdef _WIN32
    int run(int argc, const wchar_t* const argv[], const InitializationData& initData = InitializationData(),
            int version = ICE_INT_VERSION);
#endif

    /**
     * Alternative entry point for services that use their own
     * command-line options. Instead of invoking main(), the
     * program processes its command-line options and invokes
     * run(). To run as a Win32 service or Unix daemon, the
     * program must first invoke configureService() or
     * configureDaemon(), respectively.
     *
     * @param argc Specifies the number of arguments in argv.
     * @param argv The command-line arguments.
     * @param initData Configuration data for the new Communicator.
     * @param version Indicates the Ice version with which the application is compatible. If not
     * specified, the version of the Ice installation is used.
     * @return The application's exit status: EXIT_FAILURE or EXIT_SUCCESS.
     */
    int run(int argc, const char* const argv[], const InitializationData& initData = InitializationData(),
            int version = ICE_INT_VERSION);

#ifdef _WIN32

    /**
     * Configures the program to run as a Win32 service with the given name.
     * @param name The service name.
     */
    void configureService(const std::string& name);

    /// \cond INTERNAL
    static void setModuleHandle(HMODULE);
    /// \endcond

#else

    /**
     * Configures the program to run as a Unix daemon. The first
     * argument indicates whether the daemon should change its
     * working directory to the root directory. The second
     * argument indicates whether extraneous file descriptors are
     * closed. If the value of the last argument is not an empty
     * string, the daemon writes its process ID to the given
     * filename.
     *
     * @param changeDirectory True if the daemon should change its working directory to the root directory,
     * false otherwise.
     * @param closeFiles True if the daemon should close unnecessary file descriptors (i.e., stdin, stdout, etc.),
     * false otherwise.
     * @param pidFile If a non-empty string is provided, the daemon writes its process ID to the given file.
     */
    void configureDaemon(bool changeDirectory, bool closeFiles, const std::string& pidFile);

#endif

    /**
     * Invoked by the signal handler when it catches a signal.
     * @param sig The signal that was caught.
     */
    virtual void handleInterrupt(int sig);

protected:

    /**
     * Prepares a service for execution, including the creation and
     * activation of object adapters and servants.
     * @param argc Specifies the number of arguments in argv.
     * @param argv The command-line arguments.
     * @param status The exit status, which is returned by main
     * @return True if startup was successful, false otherwise.
     */
    virtual bool start(int argc, char* argv[], int& status) = 0;

    /**
     * Blocks until the service shuts down. The default implementation
     * invokes waitForShutdown() on the communicator.
     */
    virtual void waitForShutdown();

    /**
     * Cleans up resources after shutting down.
     */
    virtual bool stop();

    /**
     * Initializes a communicator.
     * @param argc Specifies the number of arguments in argv.
     * @param argv The command-line arguments.
     * @param initData Configuration data for the new Communicator.
     * @param version Indicates the Ice version with which the application is compatible. If not
     * specified, the version of the Ice installation is used.
     * @return The new communicator instance.
     */
    virtual Ice::CommunicatorPtr initializeCommunicator(int& argc, char* argv[], const InitializationData& initData,
                                                        int version);

    /**
     * Logs a system error, which includes a description of the
     * current system error code.
     * @param msg The log message.
     */
    virtual void syserror(const std::string& msg);

    /**
     * Logs an error.
     * @param msg The log message.
     */
    virtual void error(const std::string& msg);

    /**
     * Logs a warning.
     * @param msg The log message.
     */
    virtual void warning(const std::string& msg);

    /**
     * Logs trace information.
     * @param msg The log message.
     */
    virtual void trace(const std::string& msg);

    /**
     * Logs a literal message.
     * @param msg The log message.
     */
    virtual void print(const std::string& msg);

    /**
     * Enables the signal handler to invoke interrupt() when a signal occurs.
     */
    void enableInterrupt();

    /**
     * Ignore signals.
     */
    void disableInterrupt();

    /**
     * Logger utility class for a system error.
     */
    typedef LoggerOutput<Service, Service*, &Service::syserror> ServiceSysError;

    /**
     * Logger utility class for an error.
     */
    typedef LoggerOutput<Service, Service*, &Service::error> ServiceError;

    /**
     * Logger utility class for a warning.
     */
    typedef LoggerOutput<Service, Service*, &Service::warning> ServiceWarning;

    /**
     * Logger utility class for a trace message.
     */
    typedef LoggerOutput<Service, Service*, &Service::trace> ServiceTrace;

    /**
     * Logger utility class for a literal message.
     */
    typedef LoggerOutput<Service, Service*, &Service::print> ServicePrint;

private:

    Ice::LoggerPtr _logger;
    Ice::CommunicatorPtr _communicator;
    bool _nohup;
    bool _service;
    std::string _name;

    static Service* _instance;

#ifdef _WIN32

    int runService(int, const char* const[], const InitializationData&);
    void terminateService(DWORD);
    bool waitForServiceState(SC_HANDLE, DWORD, SERVICE_STATUS&);
    void showServiceStatus(const std::string&, SERVICE_STATUS&);

    SERVICE_STATUS_HANDLE _statusHandle;
    std::vector<std::string> _serviceArgs;
    InitializationData _initData;

public:

    /// \cond INTERNAL
    void serviceMain(int, const wchar_t* const[]);
    void control(int);
    /// \endcond

#else

    int runDaemon(int, char*[], const InitializationData&, int);

    bool _changeDirectory;
    bool _closeFiles;
    std::string _pidFile;

#endif
};

} // End of namespace Ice

#endif