1 /******************************************************************************* 2 3 Set of files which are reopened upon calling the reopenAll() method. The 4 extension cooperates with the SignalExt, allowing the registered set of 5 files to be reopened when a specific signal is received by the application. 6 The constructor provides a convenient means to configure this behaviour. 7 8 Copyright: 9 Copyright (c) 2009-2016 dunnhumby Germany GmbH. 10 All rights reserved. 11 12 License: 13 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 14 Alternatively, this file may be distributed under the terms of the Tango 15 3-Clause BSD License (see LICENSE_BSD.txt for details). 16 17 *******************************************************************************/ 18 19 module ocean.util.app.ext.ReopenableFilesExt; 20 21 22 23 24 import ocean.meta.types.Qualifiers; 25 26 import ocean.core.Verify; 27 28 import ocean.util.app.model.IApplication; 29 import ocean.util.app.model.IApplicationExtension; 30 31 import ocean.util.app.ext.SignalExt; 32 import ocean.util.app.ext.UnixSocketExt; 33 34 import ocean.util.app.ext.model.ISignalExtExtension; 35 36 import core.sys.posix.signal : SIGHUP; 37 38 import ocean.io.device.File; 39 40 41 public class ReopenableFilesExt : IApplicationExtension, ISignalExtExtension 42 { 43 import ocean.application.components.OpenFiles; 44 45 /// TODO 46 private OpenFiles files; 47 48 49 /*************************************************************************** 50 51 The code of the signal to trigger reopening the files, when used with 52 the SignalExt. See onSignal(). 53 54 ***************************************************************************/ 55 56 private int reopen_signal; 57 58 59 /*************************************************************************** 60 61 Constructor. 62 63 Optionally registers this extension with the signal extension and 64 activates the handling of the specified signal, which will cause the 65 registered files to be reopened. For this to happen, a non-null 66 `signal_ext` and a non-zero `reopen_signal` must be supplied. 67 68 Params: 69 signal_ext = SignalExt instance to register with (defaults to null) 70 reopen_signal = signal to trigger reopening of registered files 71 (defaults to SIGHUP, and considered only if non-zero and 72 `signal_ext` is non-null) 73 74 ***************************************************************************/ 75 76 public this ( SignalExt signal_ext = null, int reopen_signal = SIGHUP ) 77 { 78 this.files = new OpenFiles; 79 80 if (signal_ext && reopen_signal) 81 { 82 this.setupSignalHandler(signal_ext, reopen_signal); 83 } 84 } 85 86 87 /*************************************************************************** 88 89 Registers this extension with the signal extension and activates the 90 handling of the specified signal, which will cause the registered files 91 to be reopened. 92 93 Params: 94 signal_ext = SignalExt instance 95 reopen_signal = signal to trigger reopening of registered files 96 97 ***************************************************************************/ 98 99 public void setupSignalHandler ( SignalExt signal_ext, 100 int reopen_signal = SIGHUP ) 101 { 102 verify(signal_ext !is null); 103 verify(this.reopen_signal == this.reopen_signal.init, 104 "Either pass SignalExt to constructor or to setupSignalHandler, " ~ 105 "not to both."); 106 107 this.reopen_signal = reopen_signal; 108 signal_ext.register(this.reopen_signal); 109 signal_ext.registerExtension(this); 110 } 111 112 113 /*************************************************************************** 114 115 Registers this extension with the unix socket extension and activates the 116 handling of the specified unix socket command, which will cause reopening 117 files specified as arguments to the command. 118 119 Params: 120 unix_socket_ext = UnixSocketExt instance to register with 121 reopen_command = command to trigger reopening of the registered 122 file (passed as arguments to the command). 123 124 ***************************************************************************/ 125 126 public void setupUnixSocketHandler ( UnixSocketExt unix_socket_ext, 127 istring reopen_command = "reopen_files" ) 128 { 129 verify(unix_socket_ext !is null); 130 131 unix_socket_ext.addHandler(reopen_command, 132 &this.socketReloadCommand); 133 } 134 135 136 /*************************************************************************** 137 138 Registers the specified file, to be reopened when reopenAll() is called. 139 140 Params: 141 file = file to add to the set of reopenable files 142 143 ***************************************************************************/ 144 145 public void register ( File file ) 146 { 147 this.files.register(file); 148 } 149 150 151 /*************************************************************************** 152 153 Reopens all registered files. 154 155 ***************************************************************************/ 156 157 public void reopenAll ( ) 158 { 159 this.files.reopenAll(); 160 } 161 162 163 /*************************************************************************** 164 165 Reopens all registered files with the given path 166 167 Params: 168 file_path = path of the file to open 169 170 Returns: 171 true if the file was registered and reopen, false otherwise. 172 173 ***************************************************************************/ 174 175 public bool reopenFile ( cstring file_path ) 176 { 177 return this.files.reopenFile(file_path); 178 } 179 180 /*************************************************************************** 181 182 Signal handler. Called by SignalExt when a signal occurs. Reopens all 183 log files. 184 185 Params: 186 signal = signal which fired 187 188 ***************************************************************************/ 189 190 public void onSignal ( int signal ) 191 { 192 if ( signal == this.reopen_signal ) 193 { 194 this.reopenAll(); 195 } 196 } 197 198 /**************************************************************************** 199 200 Reopen command to trigger from the Unix Domain socket. It reads 201 the file names to reload and reloads the appropriate files. 202 203 Params: 204 args = list of arguments received from the socket - should contain 205 names of the files to rotate. 206 send_response = delegate to send the response to the client 207 208 *****************************************************************************/ 209 210 private void socketReloadCommand ( cstring[] args, 211 scope void delegate ( cstring response ) send_response ) 212 { 213 if (args.length == 0) 214 { 215 send_response("ERROR: missing name of the file to rotate.\n"); 216 return; 217 } 218 219 foreach (filename; args) 220 { 221 if (!this.reopenFile(filename)) 222 { 223 send_response("ERROR: Could not rotate the file '"); 224 send_response(filename); 225 send_response("'\n"); 226 return; 227 } 228 } 229 230 send_response("ACK\n"); 231 } 232 233 /*************************************************************************** 234 235 Required by ISignalExtExtension. 236 237 Returns: 238 a number to provide ordering to extensions 239 240 ***************************************************************************/ 241 242 override public int order ( ) 243 { 244 return -1; 245 } 246 247 248 /*************************************************************************** 249 250 Unused IApplicationExtension method. 251 252 We just need to provide an "empty" implementation to satisfy the 253 interface. 254 255 ***************************************************************************/ 256 257 override public void preRun ( IApplication app, istring[] args ) 258 { 259 // Unused 260 } 261 262 263 /// ditto 264 override public void postRun ( IApplication app, istring[] args, int status ) 265 { 266 // Unused 267 } 268 269 270 /// ditto 271 override public void atExit ( IApplication app, istring[] args, int status, 272 ExitException exception ) 273 { 274 // Unused 275 } 276 277 278 /// ditto 279 override public ExitException onExitException ( IApplication app, istring[] args, 280 ExitException exception ) 281 { 282 // Unused 283 return exception; 284 } 285 }