~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/plugins/contrib/PythonPlugins/XmlRpcEmbedder/xmlrpc_embedder.cpp

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "stdint.h"
 
2
 
 
3
#include "xmlrpc_embedder.h"
 
4
#include <wx/listimpl.cpp>
 
5
#include <wx/arrimpl.cpp>
 
6
#include "ExecHiddenMSW.h"
 
7
//WX_DEFINE_OBJARRAY(XmlRpcInstanceCollection);
 
8
WX_DEFINE_LIST(XmlRpcJobQueue);
 
9
 
 
10
using namespace std;
 
11
using namespace XmlRpc;
 
12
 
 
13
int ID_XMLRPC_PROC=wxNewId();
 
14
 
 
15
 
 
16
class ExecAsyncJob: public XmlRpcJob
 
17
{
 
18
public:
 
19
    ExecAsyncJob(XmlRpcInstance *inst, const wxString &method, const XmlRpc::XmlRpcValue &inarg, wxEvtHandler *hndlr, int id=wxID_ANY): XmlRpcJob(inst,hndlr,id)
 
20
    {
 
21
        m_method=wxString(method.mb_str(wxConvUTF8),wxConvUTF8);
 
22
        m_inarg=inarg;
 
23
    }
 
24
    virtual bool operator()()
 
25
    {
 
26
        if(xmlrpc_instance->Exec(m_method,m_inarg,m_result))
 
27
        {
 
28
            XmlRpcResponseEvent pe(id,xmlrpc_instance,parent,XMLRPC_STATE_RESPONSE,m_result);
 
29
            ::wxPostEvent(parent,pe);
 
30
            return true;
 
31
        } else
 
32
        {
 
33
            XmlRpcResponseEvent pe(id,xmlrpc_instance,parent,XMLRPC_STATE_REQUEST_FAILED,m_result);
 
34
            ::wxPostEvent(parent,pe);
 
35
            return true;
 
36
        }
 
37
    }
 
38
protected:
 
39
    wxString m_method;
 
40
    XmlRpc::XmlRpcValue m_inarg;
 
41
    XmlRpc::XmlRpcValue m_result;
 
42
};
 
43
 
 
44
 
 
45
//////////////////////////////////////////////////////////////////////////////////
 
46
//////////////////////////////////////////////////////////////////////////////////
 
47
// class XmlRpcJob
 
48
//////////////////////////////////////////////////////////////////////////////////
 
49
//////////////////////////////////////////////////////////////////////////////////
 
50
 
 
51
 
 
52
//IMPLEMENT_DYNAMIC_CLASS(XmlRpcJob, wxThread)
 
53
 
 
54
XmlRpcJob::XmlRpcJob(XmlRpcInstance *xmlrpc_instance, wxEvtHandler *p, int id, bool selfdestroy):
 
55
wxThread(wxTHREAD_JOINABLE)
 
56
{
 
57
    parent=p;
 
58
    this->id=id;
 
59
    this->xmlrpc_instance=xmlrpc_instance;
 
60
    finished=false;
 
61
    started=false;
 
62
    killonexit=selfdestroy;
 
63
}
 
64
 
 
65
void XmlRpcJob::Abort()
 
66
{
 
67
    if(this->IsAlive())
 
68
        this->Kill();
 
69
}
 
70
 
 
71
XmlRpcJob::~XmlRpcJob()
 
72
{
 
73
    Abort();
 
74
}
 
75
 
 
76
//void *XmlRpcJob::Entry()
 
77
//{
 
78
//    wxMessageBox(_("entered thread"));
 
79
//    XmlRpcNotifyUIEvent pe(id,xmlrpc_instance,parent,PYSTATE_STARTEDJOB);
 
80
//    ::wxPostEvent(xmlrpc_instance,pe);
 
81
//    if((*this)())
 
82
//        pe.SetState(PYSTATE_FINISHEDJOB);
 
83
//    else
 
84
//        pe.SetState(PYSTATE_ABORTEDJOB);
 
85
//    ::wxPostEvent(xmlrpc_instance,pe);
 
86
//    Exit();
 
87
//    return NULL;
 
88
//}
 
89
 
 
90
void *XmlRpcJob::Entry()
 
91
{
 
92
//    wxMutexGuiEnter();
 
93
    wxCommandEvent pe(wxEVT_XMLRPC_STARTED,0);
 
94
    parent->AddPendingEvent(pe);
 
95
//    wxMutexGuiLeave();
 
96
    if((*this)())
 
97
    {
 
98
        wxCommandEvent pe(wxEVT_XMLRPC_FINISHED,0);
 
99
        xmlrpc_instance->AddPendingEvent(pe);
 
100
    }
 
101
    else
 
102
    {
 
103
        wxCommandEvent pe(wxEVT_XMLRPC_ABORTED,0);
 
104
        xmlrpc_instance->AddPendingEvent(pe);
 
105
    }
 
106
    Exit();
 
107
    return NULL;
 
108
}
 
109
 
 
110
 
 
111
const char REQUEST_BEGIN[] =
 
112
  "<?xml version=\"1.0\"?>\r\n"
 
113
  "<methodCall><methodName>";
 
114
const char REQUEST_END_METHODNAME[] = "</methodName>\r\n";
 
115
const char PARAMS_TAG[] = "<params>";
 
116
const char PARAMS_ETAG[] = "</params>";
 
117
const char PARAM_TAG[] = "<param>";
 
118
const char PARAM_ETAG[] =  "</param>";
 
119
const char REQUEST_END[] = "</methodCall>\r\n";
 
120
const char METHODRESPONSE_TAG[] = "<methodResponse>";
 
121
const char FAULT_TAG[] = "<fault>";
 
122
 
 
123
class XmlRpcPipeClient
 
124
{
 
125
public:
 
126
    XmlRpcPipeClient(wxProcess *proc)
 
127
    {
 
128
        m_proc=proc;
 
129
        m_error_lock=false;
 
130
        m_istream=proc->GetInputStream();
 
131
        m_ostream=proc->GetOutputStream();
 
132
        m_estream=proc->GetErrorStream();
 
133
    }
 
134
    bool set_error(const std::string &s,XmlRpc::XmlRpcValue& result)
 
135
    {
 
136
        result.setSize(1);
 
137
        result[0] = s;
 
138
        m_error_lock=true;
 
139
        return false;
 
140
    }
 
141
    bool clear_error()
 
142
    {
 
143
        m_error_lock=false;
 
144
    }
 
145
    bool execute(const char* method, XmlRpc::XmlRpcValue const& params, XmlRpc::XmlRpcValue& result)
 
146
    {
 
147
        if(m_error_lock)
 
148
        {
 
149
            result[0] = "XmlRpc pipe client is in an error state. Clear the error or reset the server.";
 
150
            return false;
 
151
        }
 
152
        std::string msg;
 
153
        if(!generateRequest(method,params,msg))
 
154
            return set_error("Bad request value for method call "+std::string(method),result);
 
155
        uint32_t r_size=msg.size(); //TODO: Is it safer to use uint64_t (would need to use long long on the python side)
 
156
        char *cr_size = (char*)&r_size;
 
157
        for(uint32_t i=0;i<sizeof(uint32_t);++i)
 
158
        {
 
159
            do
 
160
            {
 
161
                m_ostream->PutC(cr_size[i]);
 
162
                if(m_ostream->GetLastError()!=wxSTREAM_NO_ERROR && m_ostream->GetLastError()!=wxSTREAM_EOF)
 
163
                    return set_error("Broken stream attempting to write request size to pipe",result);
 
164
            } while (m_ostream->LastWrite()!=1);
 
165
        }
 
166
        for(uint32_t i=0;i<msg.size();++i)
 
167
        {
 
168
            do
 
169
            {
 
170
                m_ostream->PutC(msg[i]);
 
171
                if(m_ostream->GetLastError()!=wxSTREAM_NO_ERROR && m_ostream->GetLastError()!=wxSTREAM_EOF)
 
172
                    return set_error("Broken stream attempting to write request to pipe",result);
 
173
            } while (m_ostream->LastWrite()!=1);
 
174
        }
 
175
 
 
176
        //NOW WAIT FOR THE REPLY
 
177
        //FIRST RETRIEVE A SINGLE CHARACTER "M" THAT DENOTES THE START OF THE REPLY
 
178
        //TODO: CHANGE 'M' TO 0 AND ACTUALLY CHECK IT!!!
 
179
        char ch;
 
180
        bool eof;
 
181
        do
 
182
        {
 
183
            ch=m_istream->GetC();
 
184
            eof = m_istream->GetLastError()==wxSTREAM_EOF;
 
185
            if(eof)
 
186
                wxMilliSleep(10); //Delay might be necessary to avoid a freeze on MS windows
 
187
        } while(eof);
 
188
        if(m_istream->GetLastError()!=wxSTREAM_NO_ERROR && m_istream->GetLastError()!=wxSTREAM_EOF)
 
189
            return set_error("Broken stream attempting to read message char 'M' from pipe",result);
 
190
 
 
191
        // THEN GET THE SIZE OF THE MESSAGE AS UNSIGNED 32 BIT INT
 
192
        for(uint32_t i=0;i<sizeof(uint32_t);i++)
 
193
        {
 
194
            do
 
195
            {
 
196
                ((char*)(&r_size))[i]=m_istream->GetC();
 
197
                eof = m_istream->GetLastError()==wxSTREAM_EOF;
 
198
                if(eof)
 
199
                    wxMilliSleep(10); //Delay might be necessary to avoid a freeze on MS windows
 
200
            } while(eof);
 
201
            if(m_istream->GetLastError()!=wxSTREAM_NO_ERROR && m_istream->GetLastError()!=wxSTREAM_EOF)
 
202
                return set_error("broken stream attempting to read size of buffer",result);
 
203
        }
 
204
 
 
205
        // FINALLY RETRIEVE THE ACTUAL MESSAGE
 
206
        std::string buf;
 
207
        buf.resize(r_size+1);
 
208
        for(uint32_t i=0;i<r_size;i++)
 
209
        {
 
210
            do
 
211
            {
 
212
                buf[i]=m_istream->GetC();
 
213
                eof = m_istream->GetLastError()==wxSTREAM_EOF;
 
214
                if(eof)
 
215
                    wxMilliSleep(10); //Delay might be necessary to avoid a freeze on MS windows
 
216
            } while(eof);
 
217
            if(m_istream->GetLastError()!=wxSTREAM_NO_ERROR && m_istream->GetLastError()!=wxSTREAM_EOF)
 
218
                return set_error(std::string(wxString::Format(_T("broken stream attempting to read buffer - chars read %i of %i"),i,r_size).utf8_str()),result);
 
219
        }
 
220
        buf[r_size]=0;
 
221
 
 
222
        // NOW CONVERT THE XML INTO AN XMLRPCVALUE
 
223
        if(parseResponse(buf, result))
 
224
        {
 
225
            return true;
 
226
        }
 
227
        wxString s = wxString::Format(_T("error parsing read buffer - chars read %i\n"),r_size);
 
228
        std::string out = std::string(s.utf8_str()) + std::string(buf);
 
229
        return set_error(out,result);
 
230
    }
 
231
 
 
232
    // Converts the response xml into a result value
 
233
    bool parseResponse(std::string _response, XmlRpcValue& result)
 
234
    {
 
235
      // Parse response xml into result
 
236
      int offset = 0;
 
237
      bool _isFault=false;
 
238
      if ( ! XmlRpcUtil::findTag(METHODRESPONSE_TAG,_response,&offset)) {
 
239
        XmlRpcUtil::error("Error in XmlRpcClient::parseResponse: Invalid response - no methodResponse. Response:\n%s", _response.c_str());
 
240
        return false;
 
241
      }
 
242
 
 
243
      // Expect either <params><param>... or <fault>...
 
244
      if ((XmlRpcUtil::nextTagIs(PARAMS_TAG,_response,&offset) &&
 
245
           XmlRpcUtil::nextTagIs(PARAM_TAG,_response,&offset)) ||
 
246
          XmlRpcUtil::nextTagIs(FAULT_TAG,_response,&offset) && (_isFault = true))
 
247
      {
 
248
        if ( ! result.fromXml(_response, &offset)) {
 
249
          XmlRpcUtil::error("Error in XmlRpcClient::parseResponse: Invalid response value. Response:\n%s", _response.c_str());
 
250
          _response = "";
 
251
          return false;
 
252
        }
 
253
      } else {
 
254
        XmlRpcUtil::error("Error in XmlRpcClient::parseResponse: Invalid response - no param or fault tag. Response:\n%s", _response.c_str());
 
255
        _response = "";
 
256
        return false;
 
257
      }
 
258
 
 
259
      _response = "";
 
260
      return result.valid();
 
261
    }
 
262
    // Encode the request to call the specified method with the specified parameters into xml
 
263
    bool generateRequest(const char* methodName, XmlRpcValue const& params, std::string &request)
 
264
    {
 
265
      std::string body = REQUEST_BEGIN;
 
266
      body += methodName;
 
267
      body += REQUEST_END_METHODNAME;
 
268
 
 
269
      // If params is an array, each element is a separate parameter
 
270
      if (params.valid()) {
 
271
        body += PARAMS_TAG;
 
272
        if (params.getType() == XmlRpcValue::TypeArray)
 
273
        {
 
274
          for (int i=0; i<params.size(); ++i) {
 
275
            body += PARAM_TAG;
 
276
            body += params[i].toXml();
 
277
            body += PARAM_ETAG;
 
278
          }
 
279
        }
 
280
        else
 
281
        {
 
282
          body += PARAM_TAG;
 
283
          body += params.toXml();
 
284
          body += PARAM_ETAG;
 
285
        }
 
286
 
 
287
        body += PARAMS_ETAG;
 
288
      }
 
289
      body += REQUEST_END;
 
290
 
 
291
      std::string header;
 
292
      XmlRpcUtil::log(4, "XmlRpcClient::generateRequest: header is %d bytes, content-length is %d.",
 
293
                      header.length(), body.length());
 
294
 
 
295
      request = body;
 
296
      return true;
 
297
    }
 
298
 
 
299
private:
 
300
    bool m_error_lock;
 
301
    wxProcess *m_proc;
 
302
    wxInputStream *m_istream;
 
303
    wxOutputStream *m_ostream;
 
304
    wxInputStream *m_estream;
 
305
};
 
306
 
 
307
 
 
308
//////////////////////////////////////////////////////////////////////////////////
 
309
//////////////////////////////////////////////////////////////////////////////////
 
310
// class XmlRpcInstance
 
311
//////////////////////////////////////////////////////////////////////////////////
 
312
//////////////////////////////////////////////////////////////////////////////////
 
313
 
 
314
//IMPLEMENT_DYNAMIC_CLASS(XmlRpcInstance, wxEvtHandler)
 
315
 
 
316
IMPLEMENT_CLASS(XmlRpcInstance, wxEvtHandler)
 
317
 
 
318
 
 
319
BEGIN_EVENT_TABLE(XmlRpcInstance, wxEvtHandler)
 
320
//    EVT_PY_NOTIFY_UI(XmlRpcInstance::OnJobNotify)
 
321
    EVT_COMMAND(0, wxEVT_XMLRPC_FINISHED, XmlRpcInstance::OnJobNotify)
 
322
    EVT_COMMAND(0, wxEVT_XMLRPC_ABORTED, XmlRpcInstance::OnJobNotify)
 
323
    EVT_END_PROCESS(ID_XMLRPC_PROC, XmlRpcInstance::OnEndProcess)
 
324
END_EVENT_TABLE()
 
325
 
 
326
//XmlRpcInstance::XmlRpcInstance()
 
327
//{
 
328
//    // create python process
 
329
//    // create xmlrpc client
 
330
//    // get & store methods from the xmlrpc server
 
331
//    // set running state flag
 
332
//}
 
333
 
 
334
XmlRpcInstance::~XmlRpcInstance()
 
335
{
 
336
    // kill python process if still running
 
337
    if (!m_proc_dead) //TODO: killing while job running could cause probs...
 
338
    {
 
339
        m_proc->Detach();
 
340
        if(wxProcess::Exists(m_proc_id))
 
341
            wxProcess::Kill(m_proc_id,wxSIGKILL,wxKILL_CHILDREN);
 
342
    }
 
343
    // check if any running jobs, kill them
 
344
    // delete the client
 
345
    wxMutexLocker ml(exec_mutex); //TODO: This may result in huge delays?
 
346
    if(m_client)
 
347
        delete m_client;
 
348
    if(m_pipeclient)
 
349
        delete m_pipeclient;
 
350
    m_client=0;
 
351
    m_pipeclient=0;
 
352
}
 
353
 
 
354
XmlRpcInstance::XmlRpcInstance(const wxString &processcmd, int port, const wxString &hostaddress, wxWindow *parent)
 
355
{
 
356
    m_parent=parent;
 
357
    m_port=port;
 
358
    m_proc=0;
 
359
    m_client=0;
 
360
    m_pipeclient=0;
 
361
    m_proc_dead=true;
 
362
    m_hostaddress=hostaddress;
 
363
    m_paused=false;
 
364
    m_proc_killlevel=0;
 
365
    m_jobrunning=false;
 
366
    // Launch process
 
367
    if (processcmd!=wxEmptyString)
 
368
        LaunchProcess(processcmd); //TODO: The command for the interpreter process should come from the manager (and be stored in a config file)
 
369
}
 
370
 
 
371
long XmlRpcInstance::LaunchProcess(const wxString &processcmd)
 
372
{
 
373
//    std::cout<<"PyCC: LAUNCHING PROCESS"<<std::endl;
 
374
    if(!m_proc_dead)
 
375
        return -1;
 
376
    if(m_proc) //this should never happen
 
377
        m_proc->Detach(); //self cleanup
 
378
    m_proc=new wxProcess(this,ID_XMLRPC_PROC);
 
379
    if(m_port==-1)
 
380
        m_proc->Redirect();
 
381
//    m_proc->Redirect(); //TODO: this only needs to be done on windows and buffers must be flushed periodically if there is any I/O to/from the process
 
382
#ifdef __WXMSW__
 
383
    //by default wxExecute shows the terminal window on MSW (redirecting would hide it, but that breaks the process if buffers are not flushed periodically)
 
384
    if(m_port==-1)
 
385
        m_proc_id=wxExecute(processcmd,wxEXEC_ASYNC/*|wxEXEC_MAKE_GROUP_LEADER*/,m_proc);
 
386
    else
 
387
        m_proc_id=wxExecuteHidden(processcmd,wxEXEC_ASYNC|wxEXEC_MAKE_GROUP_LEADER,m_proc);
 
388
//        m_proc_id=wxExecute(processcmd,wxEXEC_ASYNC/*|wxEXEC_MAKE_GROUP_LEADER*/,m_proc);
 
389
#else
 
390
    m_proc_id=wxExecute(processcmd,wxEXEC_ASYNC|wxEXEC_MAKE_GROUP_LEADER,m_proc);
 
391
#endif /*__WXMSW__*/
 
392
    if(m_proc_id>0)
 
393
    {
 
394
//        std::cout<<"PyCC: LAUNCHING PROCESS SUCCEEDED"<<std::endl;
 
395
        m_proc_dead=false;
 
396
        m_proc_killlevel=0;
 
397
 
 
398
        // Setup XMLRPC client and use introspection API to look up the supported methods
 
399
        if(m_port==-1)
 
400
            m_pipeclient = new XmlRpcPipeClient(m_proc);
 
401
        else
 
402
            m_client = new XmlRpc::XmlRpcClient(m_hostaddress.char_str(), m_port);
 
403
    }
 
404
    return m_proc_id;
 
405
}
 
406
 
 
407
XmlRpcInstance::XmlRpcInstance(const XmlRpcInstance &copy)
 
408
{
 
409
    m_parent=copy.m_parent;
 
410
    m_paused=copy.m_paused;
 
411
    m_queue=copy.m_queue;
 
412
    m_hostaddress=copy.m_hostaddress;
 
413
    m_port=copy.m_port;
 
414
    m_proc=copy.m_proc;
 
415
    m_proc_id=copy.m_proc_id;
 
416
    m_proc_killlevel=copy.m_proc_killlevel;
 
417
    m_proc_dead=copy.m_proc_dead;
 
418
}
 
419
 
 
420
bool XmlRpcInstance::Exec(const wxString &method, const XmlRpc::XmlRpcValue &inarg, XmlRpc::XmlRpcValue &result)
 
421
{
 
422
    if(!IsDead())
 
423
    {
 
424
        wxMutexLocker ml(exec_mutex);
 
425
        if(m_client)
 
426
            return m_client->execute(method.utf8_str(), inarg, result);
 
427
        else if(m_pipeclient)
 
428
            return m_pipeclient->execute(method.utf8_str(), inarg, result);
 
429
    }
 
430
    result.setSize(1);
 
431
    result[0] = "XmlRpc server is not connected.";
 
432
    return false;
 
433
}
 
434
 
 
435
bool XmlRpcInstance::ExecAsync(const wxString &method, const XmlRpc::XmlRpcValue &inarg, wxEvtHandler *hndlr, int id)
 
436
{
 
437
    return AddJob(new ExecAsyncJob(this,method,inarg,hndlr,id));
 
438
}
 
439
 
 
440
void XmlRpcInstance::CleanupTerminatedProcess()
 
441
{
 
442
    if(m_proc!=0)
 
443
    {
 
444
        ClearJobs();
 
445
        delete m_proc;
 
446
        m_proc=0;
 
447
        m_proc_id=-1;
 
448
        m_proc_killlevel=0;
 
449
    }
 
450
}
 
451
 
 
452
void XmlRpcInstance::OnEndProcess(wxProcessEvent &event)
 
453
{
 
454
//    std::cout<<"PYCC: PROCESS DIED!!"<<std::endl;
 
455
    //TODO: m_exitcode=event.GetExitCode();
 
456
    m_proc_dead=true;
 
457
    wxCommandEvent ce(wxEVT_XMLRPC_PROC_END,0);
 
458
    if(m_parent)
 
459
        m_parent->AddPendingEvent(ce);
 
460
    if(m_jobrunning)
 
461
        return;
 
462
    CleanupTerminatedProcess();
 
463
//    XmlRpcMgr::Get().Remove(this);
 
464
}
 
465
 
 
466
void XmlRpcInstance::Break()
 
467
{
 
468
    if(!m_jobrunning)
 
469
        return;
 
470
    long pid=GetPid();
 
471
    if(wxProcess::Exists(pid))
 
472
    {
 
473
#ifdef __WXMSW__
 
474
        //TODO: Verify that this actually works
 
475
        // Use the WIN32 native call to send a CTRL+C signal
 
476
        GenerateConsoleCtrlEvent(CTRL_C_EVENT,pid); //may need to #include <Windows.h> and link to Kernel32.dll
 
477
        // also need to check whether the pid is valid or something else needs to be used.
 
478
#else
 
479
        wxProcess::Kill(pid,wxSIGINT); //,wxKILL_CHILDREN?
 
480
#endif
 
481
    }
 
482
}
 
483
 
 
484
 
 
485
void XmlRpcInstance::KillProcess(bool force)
 
486
{
 
487
    if(m_proc_dead)
 
488
        return;
 
489
    long pid=GetPid();
 
490
//    if(m_proc_killlevel==0)
 
491
//    {
 
492
//        m_proc_killlevel=1;
 
493
//        if(wxProcess::Exists(pid))
 
494
//            wxProcess::Kill(pid,wxSIGTERM);
 
495
//        return;
 
496
//    }
 
497
    if(m_proc_killlevel==0)
 
498
    {
 
499
        if(wxProcess::Exists(pid))
 
500
        {
 
501
            wxProcess::Kill(pid,wxSIGKILL,wxKILL_CHILDREN);
 
502
        }
 
503
    }
 
504
}
 
505
 
 
506
bool XmlRpcInstance::NextJob()
 
507
{
 
508
    if(m_queue.GetCount()<=0)
 
509
        return false;
 
510
    XmlRpcJob *newjob=m_queue.GetFirst()->GetData();
 
511
    if(!newjob->finished && !newjob->started)
 
512
    {
 
513
       if(newjob->Create()!=wxTHREAD_NO_ERROR)
 
514
        {
 
515
            wxMessageBox(_T("PYCC: Error creating a new thread. Unable to continue."));
 
516
            m_queue.DeleteObject(newjob);
 
517
            delete newjob;
 
518
            return false;
 
519
        }
 
520
        newjob->started=true;
 
521
        newjob->Run();
 
522
        m_jobrunning=true;
 
523
    }
 
524
    return true;
 
525
}
 
526
 
 
527
 
 
528
bool XmlRpcInstance::AddJob(XmlRpcJob *job)
 
529
{
 
530
    m_queue.Append(job);
 
531
    if(m_paused)
 
532
        return true;
 
533
    NextJob();
 
534
    return true;
 
535
}
 
536
 
 
537
void XmlRpcInstance::ClearJobs()
 
538
{
 
539
    int i = m_queue.GetCount()-1;
 
540
    while(i>=0)
 
541
    {
 
542
        XmlRpcJob *job=m_queue.Item(i)->GetData();
 
543
        if(job && !job->started && !job->finished)
 
544
        {
 
545
            m_queue.DeleteObject(job);
 
546
            delete job;
 
547
        }
 
548
        i--;
 
549
    }
 
550
 
 
551
}
 
552
 
 
553
void XmlRpcInstance::OnJobNotify(wxCommandEvent &event)
 
554
{
 
555
    XmlRpcJob *job=m_queue.GetFirst()->GetData();
 
556
#ifdef __WXMSW__
 
557
    if(job->IsAlive())
 
558
        job->Wait();
 
559
#else
 
560
    job->Wait();
 
561
#endif
 
562
    m_jobrunning=false;
 
563
    m_queue.DeleteObject(job);
 
564
    if(job->killonexit)
 
565
    {
 
566
        delete job;
 
567
        job=NULL;
 
568
    }
 
569
    if(m_paused)
 
570
        return;
 
571
    if(m_proc_dead)
 
572
        CleanupTerminatedProcess();
 
573
    NextJob();
 
574
}
 
575
 
 
576
//XmlRpcMgr::XmlRpcMgr()
 
577
//{
 
578
//}
 
579
//
 
580
//XmlRpcMgr::~XmlRpcMgr()
 
581
//{
 
582
//    m_Interpreters.Clear();
 
583
//}
 
584
//
 
585
//XmlRpcInstance *XmlRpcMgr::LaunchProcess(const wxString &cmd,int port,const wxString &address)
 
586
//{
 
587
//    XmlRpcInstance *p=new XmlRpcInstance(cmd,address,port);
 
588
//    if(p)
 
589
//        m_Interpreters.Add(p);
 
590
//    return p;
 
591
//}
 
592
//
 
593
//void XmlRpcMgr::Remove(XmlRpcInstance *p)
 
594
//{
 
595
////    m_Interpreters.Remove(*p);
 
596
////    for (size_t i=0; i<m_Interpreters.GetCount(); ++i)
 
597
////    {
 
598
////        if (m_Interpreters.Item(i) == *p)
 
599
////        {
 
600
////            m_Interpreters.RemoveAt(i);
 
601
////            return;
 
602
////        }
 
603
////    }
 
604
//}
 
605
//
 
606
//XmlRpcMgr &XmlRpcMgr::Get()
 
607
//{
 
608
//    if (theSingleInstance.get() == 0)
 
609
//      theSingleInstance.reset(new XmlRpcMgr);
 
610
//    return *theSingleInstance;
 
611
//}
 
612
//
 
613
//std::auto_ptr<XmlRpcMgr> XmlRpcMgr::theSingleInstance;
 
614
//