1 // Written in D programming language
2 /**
3 *   Module describes application startup options.
4 *
5 *   Copyright: © 2014 DSoftOut
6 *   License: Subject to the terms of the MIT license, as written in the included LICENSE file.
7 *   Authors: Zaramzan <shamyan.roman@gmail.com>
8 *            NCrashed <ncrashed@gmail.com>
9 */
10 module server.options;
11 
12 import std.path;
13 import std.array;
14 import std.getopt;
15 import std.range;
16 
17 import server.config;
18 import dlogg.log;
19 import util;
20 
21 private enum PGATOR_VERSION = import("current-pgator.version");
22 private enum PGATOR_BACKEND_VERSION = import("current-pgator-backend.version");
23 
24 /**
25 *   Application startup options. The main purpose is
26 *   to parse and store options about daemon mode,
27 *   configuration file path and some other options that
28 *   needed in application startup.
29 *
30 *   As the class is immutable, it can be passed between
31 *   threads safely.
32 */
33 immutable class Options
34 {
35     /**
36     *   Application $(B args) arguments parsing.
37     *   
38     *   Options are: daemon or terminal mode, help message
39     *   request, configuration file path and request for
40     *   default configuration file generation.
41     */
42 	this(string[] args)
43 	{	
44 	    bool pDaemon, pHelp, pVersion;
45 	    string pConfigName, pGenPath;
46 	    string pPidFile = buildPath("/var/run", APPNAME, APPNAME~".pid");
47 	    string pLockFile = buildPath("/var/run", APPNAME, APPNAME~".lock");
48 	    
49         getopt(args, std.getopt.config.passThrough,
50                          "daemon",     &pDaemon,
51                          "help|h",     &pHelp,
52                          "config",     &pConfigName,
53                          "genConfig",  &pGenPath,
54                          "pidfile",    &pPidFile,
55                          "lockfile",   &pLockFile,
56                          "version",    &pVersion);
57         
58         mDaemon     = pDaemon;
59         mHelp       = pHelp;
60         mConfigName = pConfigName;
61         mGenPath    = pGenPath;
62         mPidFile    = pPidFile;
63         mLockFile   = pLockFile;
64         mVersion    = pVersion;
65 	}
66 	
67 	/**
68 	*  Verbose creation from native D types.
69 	*  Params:
70 	*  daemon      = is program should start in daemon mode
71 	*  help        = is program should show help message and exit
72 	*  configName  = configuration file name
73 	*  genPath     = is program should generate config at specified path and exit
74 	*  showVersion = is program should show it version 
75 	*/
76 	this(bool daemon, bool help, string configName, string genPath
77 	    , string pidFile, string lockFile, bool showVersion) pure nothrow
78 	{
79 	    mDaemon     = daemon;
80 	    mHelp       = help;
81 	    mConfigName = configName;
82 	    mGenPath    = genPath;
83         mPidFile    = pidFile;
84         mLockFile   = lockFile;
85         mVersion    = showVersion;
86 	}
87 	
88 	/**
89 	*  Returns all paths where application should try to find
90 	*  configuration file.
91 	*
92 	*  Note: Application should use this when and only when
93 	*        configName is not set.
94 	*/
95 	InputRange!string configPaths() @property
96 	{	
97 	    auto builder = appender!(string[]);
98 	    builder.put(buildPath("~/.config", APPNAME, DEF_CONF_NAME).expandTilde);
99 	    
100 	    version(Posix)
101 	    {
102 	        builder.put(buildPath("/etc", DEF_CONF_NAME));
103 	    }
104 	    version(Windows)
105 	    {
106 	        builder.put(buildPath(".", DEF_CONF_NAME));
107 	    }
108 	    
109 		return builder.data.inputRangeObject;
110 	}
111 	
112 	@property pure nothrow @safe
113 	{
114     	/// Configuration full file name
115     	string configName() 
116     	{
117     		return buildNormalizedPath(mConfigName);
118     	}
119     	
120     	/// Path where to generate configuration
121     	string genConfigPath()
122     	{
123     	    return buildNormalizedPath(mGenPath);
124     	}
125     	
126     	/// Is application should run in daemon mode
127     	bool daemon()
128     	{
129     	    return mDaemon;
130     	}
131     	
132     	/// Is application should show help message and exit
133     	bool help()
134     	{
135     	    return mHelp;
136     	}
137     	
138     	/// Path to file where daemon puts it pid
139     	string pidFile()
140     	{
141     	    return mPidFile;
142     	}
143     	
144     	/// Path to file that checked to no exists in daemon mode
145     	string lockFile()
146     	{
147     	    return mLockFile;
148     	}
149     	
150     	/// Is program should show it version and exit
151     	bool showVersion()
152     	{
153     	    return mVersion;
154     	}
155 	}
156 	
157 	/// Application help message
158     enum helpMsg = "Server that transforms JSON-RPC calls into SQL queries for PostgreSQL.\n\n"
159     ~ versionMsg ~ "\n"
160     "   pgator [arguments]\n"
161     "   arguments =\n"
162     "    --daemon          - runs in daemon mode (detached from tty).\n"
163     "                        Linux only.\n"
164     "    --config=<string> - specifies config file name in\n"
165     "                        config directory.\n"
166     "   --genConfig=<path> - generates default config at the path\n"           
167     "   --help             - prints this message\n"
168     "   --pidfile=<path>   - specifies path to file where pid is written\n"
169     "                        to in daemon mode. Default: /var/run/pgator/pgator.pid\n"
170     "   --lockfile=<path>  - specifies path to file which prevents running\n"
171     "                        multiple instances in daemon mode.\n" 
172     "                        Default: /var/run/pgator/pgator.lock\n"
173     "   --version          - shows program version";
174     
175     /// Application version message
176     enum versionMsg = 
177     "build-version: " ~ PGATOR_VERSION ~ 
178     "backend-version: " ~ PGATOR_BACKEND_VERSION;
179     
180     /**
181     *   Creates new options with updated configuration $(B path).
182     */
183 	immutable(Options) updateConfigPath(string path) pure nothrow
184 	{
185 	    return new immutable Options(daemon, help, path, genConfigPath, pidFile, lockFile, showVersion);
186 	}
187 	
188 	private
189 	{
190     	enum DEF_CONF_NAME = APPNAME~".conf";
191     	
192     	bool mDaemon;
193     	bool mHelp;
194     	bool mVersion;
195     	
196     	string mConfigName;
197     	string mGenPath;
198     	string mPidFile;
199     	string mLockFile;
200 	}
201 }