PageRenderTime 63ms CodeModel.GetById 41ms app.highlight 20ms RepoModel.GetById 0ms app.codeStats 0ms

/dali/dfuplus/main.cpp

https://github.com/narpaldhillon/HPCC-Platform
C++ | 337 lines | 291 code | 26 blank | 20 comment | 47 complexity | 8645c5361d0fb729676f7b6f71a4ec3f MD5 | raw file
  1/*##############################################################################
  2
  3    Copyright (C) 2011 HPCC Systems.
  4
  5    All rights reserved. This program is free software: you can redistribute it and/or modify
  6    it under the terms of the GNU Affero General Public License as
  7    published by the Free Software Foundation, either version 3 of the
  8    License, or (at your option) any later version.
  9
 10    This program is distributed in the hope that it will be useful,
 11    but WITHOUT ANY WARRANTY; without even the implied warranty of
 12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13    GNU Affero General Public License for more details.
 14
 15    You should have received a copy of the GNU Affero General Public License
 16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 17############################################################################## */
 18
 19#pragma warning (disable : 4786)
 20#include <build-config.h>
 21#include "daftcfg.hpp"
 22#include "dfuerror.hpp"
 23#include "dfuplus.hpp"
 24#if defined( __linux__) || defined(__FreeBSD__)
 25#include "termios.h"
 26#endif
 27
 28void printVersion()
 29{
 30    printf("DFU Version: %d %s\n", DAFT_VERSION, BUILD_TAG);
 31}
 32
 33void handleSyntax()
 34{
 35    StringBuffer out;
 36
 37    out.append("Usage:\n");
 38    out.append("    dfuplus action=[spray|replicate|despray|copy|dkc|remove|rename|list|\n");
 39    out.append("                    addsuper|removesuper|listsuper|copysuper|dafilesrv|\n");
 40    out.append("                    savexml|add|status|abort|resubmit|monitor] {<options>}\n");
 41    out.append("    general options:\n");
 42    out.append("        server=<esp-server-url> \n");
 43    out.append("        username=<user-name>\n");
 44    out.append("        password=<password>\n");
 45    out.append("        overwrite=0|1\n");
 46    out.append("        replicate=1|0\n");
 47    out.append("        replicateoffset=N -- node relative offset to find replicate (default 1)\n");
 48    out.append("        partlist=<part-list> -- for one or more parts   \n");
 49    out.append("        @filename -- read options from filename \n");
 50    out.append("        nowait=0|1 -- return immediately without waiting for completion.\n");
 51    out.append("        connect=<nn> -- restrict to nn connections at a time.\n");
 52    out.append("        transferbuffersize=<n> -- use buffer of size n bytes when transferring data.\n");
 53    out.append("        throttle=<nnn> -- restrict the entire transfer speed to nnn Mbits/second\n");
 54    out.append("        norecover=0|1 -- don't create or restore from recovery information\n");
 55    out.append("        nosplit=0|1 -- optional, don't split a file part to multiple target parts\n");
 56    out.append("        compress=0|1 -- optional, compress target\n");
 57    out.append("        encrypt=<password> -- optional, encrypt target\n");
 58    out.append("        decrypt=<password> -- optional, decrypt source\n");
 59    out.append("        push=0|1 -- optional override pull/push default\n");
 60    out.append("        jobname=<jobname> -- specify the jobname for spray, despray, dkc, copy, rename and replicate.\n");
 61    out.append("    spray options:\n");
 62    out.append("        srcip=<source-machine-ip>\n");
 63    out.append("        srcfile=<source-file-path>\n");
 64    out.append("        srcxml=<xml-file> -- replaces srcip and srcfile\n");
 65    out.append("        dstname=<destination-logical-name>\n");
 66    out.append("        dstcluster=<cluster-name>\n");
 67    out.append("        format=fixed|csv|xml|variable|recfmv|recfmvb\n");
 68    out.append("        prefix=filename{:length},filesize{:[B|L][1-8]}\n");
 69    out.append("        options for fixed:\n");
 70    out.append("            recordsize=<record-size>\n");
 71    out.append("        options for csv:\n");
 72    out.append("            encoding=ascii|utf8|utf8n|utf16|utf16le|utf16be|utf32|utf32le|utf32be -- optional, default is ascii\n");
 73    out.append("            maxrecordsize=<max-record-size> -- optional, default is 8192\n");
 74    out.append("            separator=<separator> -- optional, default is \\,\n");
 75    out.append("            terminator=<terminator> -- optional, default is \\r,\\r\\n\n");
 76    out.append("            quote=<quote> -- optional, default is '\n");
 77    out.append("        options for xml:\n");
 78    out.append("            rowtag=rowTag -- required\n");
 79    out.append("            encoding=utf8|utf8n|utf16|utf16le|utf16be|utf32|utf32le|utf32be -- optional, default is utf8\n");
 80    out.append("            maxrecordsize=<max-record-size> -- optional, default is 8192\n");
 81    out.append("    replicate options:\n");
 82    out.append("        srcname=<source-logical-name>\n");
 83    out.append("        cluster=<cluster-name>     -- replicates to (additional) cluster\n");
 84    out.append("        repeatlast=0|1             -- repeats last part on every node (requires cluster)\n");
 85    out.append("        onlyrepeated=0|1           -- ignores parts not repeated (e.g. by repeatlast)\n");
 86    out.append("    despray options:\n");
 87    out.append("        srcname=<source-logical-name>\n");
 88    out.append("        dstip=<destination-machine-ip>\n");
 89    out.append("        dstfile=<destination-file-path>\n");
 90    out.append("        dstxml=<xml-file> -- replaces dstip and dstfile\n");
 91    out.append("        splitprefix=... use prefix (same format as /prefix) to split file up\n");
 92    out.append("        wrap=0|1 -- desprays as multiple files\n");
 93    out.append("        multicopy=0|1   -- each destination part gets whole file\n");
 94    out.append("    copy options:\n");
 95    out.append("        srcname=<source-logical-name>\n");
 96    out.append("        dstname=<destination-logical-name>\n");
 97    out.append("        dstcluster=<cluster-name>\n");
 98    out.append("        dstclusterroxie=No|Yes <destination cluster is a roxie cluster> -- optional\n");
 99    out.append("        srcdali=<foreign-dali-ip> -- optional\n");
100    out.append("        srcusername=<username-for-accessing-srcdali> -- optional\n");
101    out.append("        srcpassword=<password-for-accessing-srcdali> -- optional\n");
102    out.append("        wrap=0|1 -- copies from a larger to smaller cluster without spliting parts\n");
103    out.append("        diffkeysrc=<old-key-name>   -- use keydiff/keypatch (src old name)\n");
104    out.append("        diffkeydst=<old-key-name>   -- use keydiff/keypatch (dst old name)\n");
105    out.append("        multicopy=0|1   -- each destination part gets whole file\n");
106    out.append("    dkc options:\n");
107    out.append("        srcname=<source-logical-name>\n");
108    out.append("        dstip=<destination-machine-ip>\n");
109    out.append("        dstfile=<destination-file-path>\n");
110    out.append("    remove options:\n");
111    out.append("        name=<logical-name>\n");
112    out.append("        names=<multiple-logical-names-separated-by-comma>\n");
113    out.append("        namelist=<logical-name-list-in-file>\n");
114    out.append("        nodelete=0|1    -- optional\n");
115    out.append("    rename options:\n");
116    out.append("        srcname=<source-logical-name>\n");
117    out.append("        dstname=<destination-logical-name>\n");
118    out.append("    list options:\n");
119    out.append("        name=<logical-name-mask>\n");
120    out.append("        saveto=<path and file name to save the result>\n");
121    out.append("            (more to be defined)\n");
122    out.append("    addsuper options:\n");
123    out.append("        superfile=<logical-name>\n");
124    out.append("        subfiles=<logical-name>{,<logical-name>}  -- no spaces between logical-names.\n");
125    out.append("        before=<logical-name> -- optional\n");
126    out.append("    removesuper options:\n");
127    out.append("        superfile=<logical-name>\n");
128    out.append("        subfiles=<logical-name>{,<logical-name> -- optional. Can be *, which means all subfiles\n");
129    out.append("        delete=1|0 -- optional. Whether or not actually remove the files.\n");
130    out.append("    copysuper options:\n");
131    out.append("        srcname=<source-super-name>\n");
132    out.append("        dstname=<destination-super-name>\n");
133    out.append("        dstcluster=<cluster-name>\n");
134    out.append("        srcdali=<foreign-dali-ip>\n");
135    out.append("        srcusername=<username-for-accessing-srcdali> -- optional\n");
136    out.append("        srcpassword=<password-for-accessing-srcdali> -- optional\n");
137    out.append("    listsuper options:\n");
138    out.append("        superfile=<logical-name>\n");
139    out.append("    savexml options:\n");
140    out.append("        srcname=<source-logical-name>\n");
141    out.append("        dstxml=<xml-file>\n");
142    out.append("    add options:\n");
143    out.append("        srcxml=<xml-file>\n");
144    out.append("        dstname=<destination-logical-name>\n");
145    out.append("        -- To add remote files from another dali directly, use these options instead of srcxml:\n");
146    out.append("        srcname=<source-logical-name>\n");
147    out.append("        srcdali=<source-dali-ip>\n");
148    out.append("        srcusername=<user-name-for-source-dali>\n");
149    out.append("        srcpassword=<password-for-source-dali>\n");
150    out.append("    status options:\n");
151    out.append("        wuid=<dfu-workunit-id>\n");
152    out.append("    abort options:\n");
153    out.append("        wuid=<dfu-workunit-id>\n");
154    out.append("    resubmit options:\n");
155    out.append("        wuid=<dfu-workunit-id>\n");
156    out.append("    monitor options:  \n");
157    out.append("        event=<eventn-name> \n");
158    out.append("        lfn=<logical-name> -- either specify lfn or ip/file\n");
159    out.append("        ip=<ip-for-file>\n");
160    out.append("        file=<filename>\n");
161    out.append("        sub=0|1\n");
162    out.append("        shotlimit=<number>\n");
163    out.append("    dafilesrv options:  \n");
164    out.append("        idletimeout=<idle-timeout-secs> -- how long idle before stops \n");
165
166    printf("%s",out.str());
167}
168
169bool build_globals(int argc, const char *argv[], IProperties * globals)
170{
171    int i;
172
173    for(i = 0; i < argc; i++)
174    {
175        if(argv[i] != NULL && argv[i][0] == '@' && argv[i][1] != '\0')
176        {
177            globals->loadFile(argv[i]+1);
178        }
179    }
180
181    for (i = 1; i < argc; i++)
182    {
183        if (strchr(argv[i],'='))
184        {
185            globals->loadProp(argv[i]);
186        }
187    }
188
189    StringBuffer tmp;
190    if(globals->hasProp("encrypt")) {
191        encrypt(tmp.clear(),globals->queryProp("encrypt") );  // basic encryption at this stage
192        globals->setProp("encrypt",tmp.str());
193    }
194    if(globals->hasProp("decrypt")) {
195        encrypt(tmp.clear(),globals->queryProp("decrypt") );  // basic encryption at this stage
196        globals->setProp("decrypt",tmp.str());
197    }
198
199    return true;
200}
201
202void promptFor(const char *prompt, const char *prop, bool hide, IProperties * globals)
203{
204    StringBuffer result;
205    fprintf(stdout, "%s", prompt);
206    fflush(stdout);
207    if (hide)
208    {
209#ifdef _WIN32
210        HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);   
211        DWORD dwInputMode;
212        GetConsoleMode(hStdIn, &dwInputMode);   
213        SetConsoleMode(hStdIn, dwInputMode & ~ENABLE_LINE_INPUT & ~ENABLE_ECHO_INPUT);
214        loop
215        {
216            /* read a character from the console input */   
217            char ch;
218            DWORD dwRead;
219            if (!ReadFile(hStdIn, &ch, sizeof(ch), &dwRead, NULL))
220                break;
221            if (ch == '\n' || ch=='\r' || !ch)
222                break;
223            result.append(ch);
224        }
225        SetConsoleMode(hStdIn, dwInputMode); 
226#else
227        int fn = fileno(stdin);
228#ifdef __linux__        
229        struct termio t;
230        /* If ioctl fails, we're probably not connected to a terminal. */
231        if(!ioctl(fn, TCGETA, &t))
232        {
233            t.c_lflag &= ~ECHO;
234            ioctl(fn, TCSETA, &t);
235        }
236#endif
237        loop
238        {
239            char ch = fgetc(stdin);
240            if (ch == '\n' || ch=='\r' || !ch)
241                break;
242            result.append(ch);
243        }
244#ifdef __linux__        
245        if(!ioctl(fn, TCGETA, &t))
246        {
247            t.c_lflag |= ECHO;
248            ioctl(fn, TCSETA, &t);
249        }
250#endif
251#endif
252        printf("\n");
253    }
254    else
255    {
256        char buf[100];
257        if (fgets(buf, 100, stdin))
258            result.append(buf);
259        if (result.length() && result.charAt(result.length()-1)=='\n')
260            result.remove(result.length()-1, 1);
261    }
262    globals->setProp(prop, result);
263}
264
265
266int main(int argc, const char* argv[])
267{
268    InitModuleObjects();
269
270    if ((argc >= 2) && ((stricmp(argv[1], "/version") == 0) || (stricmp(argv[1], "-version") == 0))) 
271    {
272        printVersion();
273        return 0;
274    }
275
276    Owned<IFile> inifile = createIFile("dfuplus.ini");
277    if(argc < 2 && !(inifile->exists() && inifile->size() > 0))
278    {
279        handleSyntax();
280        return 0;
281    }
282
283    if ((argc >= 2) && ((argv[1][0]=='/' || argv[1][0]=='-') && (argv[1][1]=='?' || argv[1][1]=='h'))) 
284    {
285        handleSyntax();
286        return 0;
287    }
288
289    //queryLogMsgManager()->changeMonitorFilterOwn(queryStderrLogMsgHandler(), getPassNoneLogMsgFilter());
290
291    Owned<IProperties> globals = createProperties("dfuplus.ini", true);
292
293    if(!build_globals(argc, argv, globals))
294    {
295        fprintf(stderr, "ERROR: Invalid command syntax.\n");
296        releaseAtoms();
297        return DFUERR_InvalidCommandSyntax;
298    }
299
300
301
302    
303    const char* action = globals->queryProp("action");
304    if(!action || !*action)
305    {
306        handleSyntax();
307        fprintf(stderr, "\nERROR: please specify one action");
308        releaseAtoms();
309        return DFUERR_TooFewArguments;
310    }
311
312    const char* server = globals->queryProp("server");
313    if (!server || !*server) {
314        if (stricmp(action,"dafilesrv")==0)
315            globals->setProp("server","127.0.0.1"); // dummy
316        else { 
317            fprintf(stderr, "ERROR: Esp server url not specified.\n");
318            releaseAtoms();
319            return DFUERR_TooFewArguments;
320        }
321    }
322
323    try
324    {
325        Owned<CDfuPlusHelper> helper = new CDfuPlusHelper(LINK(globals.get()));
326        helper->doit();
327    }
328    catch(IException* e)
329    {
330        StringBuffer errmsg;
331        e->errorMessage(errmsg);
332        fprintf(stderr, "%s\n", errmsg.str());
333    }
334    
335    releaseAtoms();
336    return 0;
337}