1 /*  $Id: test_gridclient_stress.cpp 574016 2018-11-05 16:55:15Z sadyrovr $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *   Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors:  Maxim Didenko
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
34 #include <connect/services/grid_client.hpp>
35 #include <connect/services/grid_client_app.hpp>
36 #include <connect/services/grid_app_version_info.hpp>
37 
38 #include <corelib/ncbiapp.hpp>
39 #include <corelib/ncbimisc.hpp>
40 #include <corelib/ncbi_system.hpp>
41 
42 #include <math.h>
43 #include <algorithm>
44 
45 #define GRID_APP_NAME "test_gridclient_stress"
46 
47 USING_NCBI_SCOPE;
48 
49 class CGridClientTestApp : public CGridClientApp
50 {
51 public:
52     virtual void Init(void);
53     virtual int Run(void);
54     virtual string GetProgramVersion(void) const;
55 
UseProgressMessage() const56     virtual bool UseProgressMessage() const
57     {
58         return false;
59     }
60 };
61 
GetProgramVersion(void) const62 string CGridClientTestApp::GetProgramVersion(void) const
63 {
64     return GRID_APP_VERSION_INFO;
65 }
66 
67 
Init(void)68 void CGridClientTestApp::Init(void)
69 {
70     CGridClientApp::Init();
71 
72     // Create command-line argument descriptions class
73     unique_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
74 
75     // Specify USAGE context
76     arg_desc->SetUsageContext(GetArguments().GetProgramBasename(),
77                               "Grid client sample");
78 
79     arg_desc->AddOptionalKey("jcount",
80                              "jcount",
81                              "Number of jobs to submit",
82                              CArgDescriptions::eInteger);
83 
84     arg_desc->AddOptionalKey("vsize",
85                              "vsize",
86                              "Size of the test vector",
87                              CArgDescriptions::eInteger);
88 
89 
90     // Setup arg.descriptions for this application
91     SetupArgDescriptions(arg_desc.release());
92 }
93 
Run(void)94 int CGridClientTestApp::Run(void)
95 {
96     const CArgs& args = GetArgs();
97 
98     unsigned jcount = 5;
99     int vsize = 10000;
100     if (args["jcount"]) {
101         jcount = args["jcount"].AsInteger();
102     }
103     if (args["vsize"]) {
104         vsize = args["vsize"].AsInteger();
105     }
106 
107     CNetScheduleAPI::EJobStatus status;
108     NcbiCout << "Submit " << jcount << " jobs..." << NcbiEndl;
109 
110     CGridClient& grid_client = GetGridClient();
111 
112     string input1 = "Hello ";
113     typedef map<string, vector<double>* > TJobs;
114     TJobs jobs;
115     for (unsigned i = 0; i < jcount; ++i) {
116         string ns_key;
117         vector<double>* dvec = new vector<double>;
118         CNcbiOstream& os = grid_client.GetOStream();
119         os << "doubles " << vsize << ' ';
120         srand( (unsigned)time( NULL ) );
121         for (int j = 0; j < vsize; ++j) {
122             double d = rand()*0.2;
123             os << d << ' ';
124             dvec->push_back(d);
125         }
126         string job_key = grid_client.Submit();
127         sort(dvec->begin(),dvec->end());
128         jobs[job_key] = dvec;
129 
130         if (i % 1000 == 0) {
131             NcbiCout << "." << flush;
132         }
133     }
134     NcbiCout << NcbiEndl << "Done." << NcbiEndl;
135 
136     NcbiCout << "Waiting for jobs..." << jobs.size() << NcbiEndl;
137     unsigned cnt = 0;
138     SleepMilliSec(100);
139 
140     while (jobs.size()) {
141         NON_CONST_ITERATE(TJobs, it, jobs) {
142             const string& jk = it->first;
143             grid_client.SetJobKey(jk);
144             vector<double>* dvec = it->second;
145 
146             status = grid_client.GetStatus();
147 
148             if (status == CNetScheduleAPI::eDone) {
149                 CNcbiIstream& is = grid_client.GetIStream();
150                 if (!is.good()) {
151                     LOG_POST("Input stream error while reading the "
152                         "size of the resulting vector");
153                     break;
154                 }
155                 int count;
156                 is >> count;
157                 vector<double> resvec;
158                 for (int i = 0; i < count; ++i) {
159                     if (!is.good()) {
160                         LOG_POST( "Input stream error. Index : " << i );
161                         break;
162                     }
163                     double d;
164                     is >> d;
165                     resvec.push_back(d);
166                 }
167                 if (resvec.size() == dvec->size()) {
168                     for(size_t i = 0; i < resvec.size(); ++i) {
169                         //cout << (*dvec)[i] << " --- " << resvec[i] << ";  ";
170                         if( fabs((*dvec)[i] - resvec[i])/resvec[i] > 0.001 ) {
171                             LOG_POST( "Test failed! Wrong vector element. Difference is  "
172                                       << fabs((*dvec)[i] - resvec[i]));
173                             break;
174                         }
175                     }
176                     cout << endl;
177                 }
178                 else {
179                     LOG_POST( "Test failed! Wrong vector size."  );
180                 }
181                 LOG_POST( "Job " << jk << " done." );
182                 delete dvec;
183                 jobs.erase(it);
184                 ++cnt;
185                 break;
186             }
187             else if (status == CNetScheduleAPI::eFailed) {
188                 LOG_POST( "Job " << jk << " failed : " << grid_client.GetErrorMessage() );
189                 delete dvec;
190                 jobs.erase(it);
191                 ++cnt;
192                 break;
193             }
194 
195             else if (status == CNetScheduleAPI::eCanceled) {
196                 NcbiCerr << "Job " << jk << " is canceled." << NcbiEndl;
197                 delete dvec;
198                 jobs.erase(it);
199                 ++cnt;
200                 break;
201             }
202 
203             ++cnt;
204             if (cnt % 1000 == 0) {
205                 NcbiCout << "Waiting for "
206                          << jobs.size()
207                          << " jobs."
208                          << NcbiEndl;
209                 // it is necessary to give system a rest periodically
210                 SleepMilliSec(2000);
211                 // check status of only first 1000 jobs
212                 // since the JS queue execution priority is FIFO
213                 break;
214             }
215         }
216 
217     }
218     return 0;
219 }
220 
221 
main(int argc,const char * argv[])222 int main(int argc, const char* argv[])
223 {
224     GRID_APP_CHECK_VERSION_ARGS();
225 
226     return CGridClientTestApp().AppMain(argc, argv, 0, eDS_Default,
227             GRID_APP_NAME ".ini");
228 }
229