Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2265 kivins 1
//---------------------------------------------------------------------------
2
 
3
#pragma warn -com
4
#include <LoggingMacros.h>
5
#pragma warn +com
6
 
7
#pragma hdrstop
8
 
9
#include "UdTransferManager.h"
10
#include "UdTransferThread.h"
11
#include "DataModule.h"
12
#include "UdTransferHistory.h"
13
#include "IDevice.h"
14
 
15
//---------------------------------------------------------------------------
16
 
17
namespace
18
{
19
    AnsiString GetSQLDateTime( TDateTime datetime )
20
    {
21
        AnsiString	sqldate;
22
        sqldate.sprintf("TO_DATE('%s','YYYY-MM-DD HH24:MI:SS')",
23
                        datetime.FormatString("yyyy-mm-dd hh:nn:ss").c_str());
24
        return sqldate;
25
    }
26
}
27
 
28
//---------------------------------------------------------------------------
29
 
30
#pragma package(smart_init)
31
 
32
UdTransferManager::UdTransferManager() :
33
    m_deviceSimulatorFactory( 0 )
34
{
35
    // Get required settings
36
 
37
    m_username = getenv("USERNAME");
38
    m_hostname = getenv("COMPUTERNAME");
39
 
40
    if( m_username.IsEmpty() )
41
    {
42
        char name[ 256 ];
43
        unsigned long size = sizeof( name );
44
        if( GetUserName( name, &size ) )
45
        {
46
            m_username = name;
47
        }
48
    }
49
    if( m_hostname.IsEmpty() )
50
    {
51
        char name[ 256 ];
52
        unsigned long size = sizeof( name );
53
        if( GetComputerName( name, &size ) )
54
        {
55
            m_hostname = name;
56
        }
57
    }
58
 
59
    m_tasksLock = new Syncobjs::TCriticalSection;
60
 
61
    // Load the device simulator library
62
 
63
    m_deviceSimulatorWrapperDll = ::LoadLibrary("DeviceSimulatorWrapperP.dll");
64
    if( m_deviceSimulatorWrapperDll == NULL )
65
    {
66
        MessageDlg("Failed to load library 'DeviceSimulatorWrapperP.dll'.\nDevice simulation functionality will not be available.",
67
            mtError, TMsgDlgButtons() << mbOK, 0 );
68
    }
69
    else
70
    {
71
        // Get a device factory instance
72
 
73
		m_getDeviceFactory = reinterpret_cast< getDeviceFactory_t >(
74
				::GetProcAddress( m_deviceSimulatorWrapperDll, "getDeviceFactory" ) );
75
        if( m_getDeviceFactory == NULL )
76
        {
77
            MessageDlg("Failed to get device factory from library 'DeviceSimulatorWrapperP.dll'.\nDevice simulation functionality will not be available.",
78
                mtError, TMsgDlgButtons() << mbOK, 0 );
79
        }
80
        else
81
        {
82
            m_deviceSimulatorFactory = m_getDeviceFactory();
83
        }
84
    }
85
}
86
//---------------------------------------------------------------------------
87
 
88
UdTransferManager::~UdTransferManager()
89
{
90
    UdTransferThreadItem thread = m_threads.begin();
91
    for( ; thread != m_threads.end(); thread++ )
92
    {
93
        if( (*thread).second != NULL )
94
        {
95
            (*thread).second->StopTransfer();
96
            delete (*thread).second;
97
        }
98
    }
99
    m_threads.clear();
100
    delete m_tasksLock;
101
 
102
    if( m_deviceSimulatorWrapperDll != NULL )
103
    {
104
        // Freeing the library deletes the factory instance
105
 
106
        FreeLibrary( m_deviceSimulatorWrapperDll );
107
        m_deviceSimulatorFactory = 0;
108
    }
109
}
110
//---------------------------------------------------------------------------
111
 
112
void UdTransferManager::AddNewTask( const UdTransferTask & task )
113
{
114
    // Add the new task to the database
115
 
116
    TADOQuery * txnquery = new TADOQuery(NULL);
117
    if( txnquery == NULL ) return;
118
 
119
    txnquery->Connection = Data_Module->IntegrationDBConnection;
120
 
121
    AnsiString sql_statement;
122
    sql_statement.sprintf("insert into TRANSFER_HISTORY "
123
                          "            (ADDED_TIME, USERNAME, HOSTNAME, STATUS, "
124
                          "             RAMP_TIME, SOURCE_PATH, BATCH_SIZE, "
125
                          "             DURATION, FREQUENCY, RECURRING, "
126
                          "             RAMP_TYPE, RAMP_GRADIENT, DESTINATION) "
127
                          "values      (sysdate, '%s', '%s', %d, "
128
                          "             %s, '%s', %d, "
129
                          "             %d, %d, %d, "
130
                          "             %d, %f, '%s') ",
131
                          m_username, m_hostname, (int)UdTransferPending,
132
                          GetSQLDateTime(task.rampTime), task.sourcePath, task.batchSize,
133
                          task.duration, task.frequency, task.recurring,
134
                          (int)task.rampType, task.gradient, task.destination);
135
    txnquery->SQL->Text = sql_statement;
136
    if( txnquery->ExecSQL() != 1 )
137
    {
138
        MERROR( "Failed to add new UD transfer task to the DB" );
139
    }
140
    txnquery->Close();
141
 
142
    // Now get its id and add it to our list
143
 
144
    sql_statement.sprintf("select TRANSFER_NO, ADDED_TIME "
145
                          "from   TRANSFER_HISTORY "
146
                          "where  USERNAME = '%s' and "
147
                          "       HOSTNAME = '%s' and "
148
                          "       STATUS = %d and "
149
                          "       RAMP_TIME = %s and "
150
                          "       BATCH_SIZE = %d and "
151
                          "       DURATION = %d and "
152
                          "       FREQUENCY = %d and "
153
                          "       RECURRING = %d and "
154
                          "       RAMP_TYPE = %d and "
155
                          "       RAMP_GRADIENT = %f "
156
                          "order by ADDED_TIME desc ",
157
                          m_username, m_hostname, (int)UdTransferPending,
158
                          GetSQLDateTime(task.rampTime), task.batchSize,
159
                          task.duration, task.frequency, task.recurring,
160
                          (int)task.rampType, task.gradient);
161
    txnquery->SQL->Text = sql_statement;
162
    txnquery->Open();
163
 
164
    UdTransferTask newTask( task );
165
    if( !txnquery->Eof )
166
    {
167
        newTask.id = txnquery->FieldByName("TRANSFER_NO")->AsInteger;
168
 
169
        m_tasksLock->Acquire();
170
        m_tasks.push_back( newTask );
171
        m_tasksLock->Release();
172
 
173
        if( !LaunchTask( newTask ) )
174
        {
175
            MERROR( "Failed to launch newly added task (" << newTask.id << ")" );
176
        }
177
    }
178
    else
179
    {
180
        MERROR( "Failed to retrieve ID of added UD transfer task" );
181
    }
182
 
183
    delete txnquery;
184
}
185
//---------------------------------------------------------------------------
186
 
187
void UdTransferManager::LoadPendingTasks()
188
{
189
    TADOQuery * txnquery = new TADOQuery(NULL);
190
    if( txnquery == NULL ) return;
191
 
192
    txnquery->Connection = Data_Module->IntegrationDBConnection;
193
 
194
    AnsiString sql_statement;
195
    sql_statement.sprintf("select TRANSFER_NO, BATCH_SIZE, DURATION, FREQUENCY, "
196
                          "       RECURRING, SOURCE_PATH, RAMP_TIME, RAMP_TYPE, "
197
                          "       RAMP_GRADIENT, STATUS, DESTINATION "
198
                          "from   TRANSFER_HISTORY "
199
                          "where  STATUS = %d and "
200
                          "       USERNAME = '%s' and "
201
                          "       HOSTNAME = '%s' ",
202
                          (int)UdTransferPending,
203
                          m_username,
204
                          m_hostname);
205
    txnquery->SQL->Text = sql_statement;
206
    txnquery->Open();
207
 
208
    UdTransferTask task;
209
    while( !txnquery->Eof )
210
    {
211
        task.id 	        = txnquery->FieldByName("TRANSFER_NO")->AsInteger;
212
        task.batchSize      = txnquery->FieldByName("BATCH_SIZE")->AsInteger;
213
        task.duration       = txnquery->FieldByName("DURATION")->AsInteger;
214
        task.frequency      = txnquery->FieldByName("FREQUENCY")->AsInteger;
215
        task.recurring      = (txnquery->FieldByName("RECURRING")->AsInteger > 0);
216
        task.sourcePath     = txnquery->FieldByName("SOURCE_PATH")->AsString;
217
        task.rampTime       = txnquery->FieldByName("RAMP_TIME")->AsDateTime;
218
        task.rampType       = (RampTestType)txnquery->FieldByName("RAMP_TYPE")->AsInteger;
219
        task.gradient       = txnquery->FieldByName("RAMP_GRADIENT")->AsFloat;
220
        task.state          = (UdTransferTaskState)txnquery->FieldByName("STATUS")->AsInteger;
221
        task.destination    = txnquery->FieldByName("DESTINATION")->AsString;
222
 
223
        m_tasksLock->Acquire();
224
        m_tasks.push_back( task );
225
        m_tasksLock->Release();
226
 
227
        txnquery->Next();
228
    }
229
 
230
    delete txnquery;
231
 
232
    if( !m_tasks.empty() )
233
    {
234
        // Ask user to start any previously pending tasks
235
 
236
        AnsiString msg;
237
        if( m_tasks.size() == 1 )
238
        {
239
            msg = "There is a UD task currently pending. Do you want to start it now?";
240
        }
241
        else
242
        {
243
            msg = "There are " + IntToStr(m_tasks.size()) + " UD transfer tasks currently pending.";
244
            msg += "\nDo you want to start them now?";
245
        }
246
 
247
        if( MessageDlg(msg, mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0 ) == mbYes )
248
        {
249
            m_tasksLock->Acquire();
250
            try {
251
                UdTransferTaskItem it = m_tasks.begin();
252
                for( ; it != m_tasks.end(); it++ )
253
                {
254
                    if( (*it).state == UdTransferPending )
255
                    {
256
                        LaunchTask( (*it) );
257
                    }
258
                }
259
            }
260
            __finally
261
            {
262
                m_tasksLock->Release();
263
            }
264
        }
265
    }
266
}
267
//---------------------------------------------------------------------------
268
 
269
void UdTransferManager::UpdateTask( const UdTransferTask & task,
270
                                    const AnsiString & comment )
271
{
272
    // Find our locally stored task
273
 
274
    m_tasksLock->Acquire();
275
    try {
276
        UdTransferTaskItem it = m_tasks.begin();
277
        for( ; it != m_tasks.end(); it++ )
278
        {
279
            if( (*it).id == task.id ) break;
280
        }
281
 
282
        if( (it != m_tasks.end()) ) // TODO: && ((*it) != task) )
283
        {
284
            bool taskDone = (((*it).state > UdTransferAborted) &&
285
                             (task.state <= UdTransferAborted));
286
 
287
            TADOQuery * txnquery = new TADOQuery(NULL);
288
            if( txnquery == NULL ) return;
289
 
290
            txnquery->Connection = Data_Module->IntegrationDBConnection;
291
 
292
            // Find parameters that have changed and add them to the update query
293
 
294
            std::stringstream stream;
295
            stream << "update TRANSFER_HISTORY set ";
296
            if( (*it).batchSize != task.batchSize )     stream << " BATCH_SIZE = " << task.batchSize << ",";
297
            if( (*it).duration != task.duration )       stream << " DURATION = " << task.duration << ",";
298
            if( (*it).frequency != task.frequency )     stream << " FREQUENCY = " << task.frequency << ",";
299
            if( (*it).recurring != task.recurring )     stream << " RECURRING = " << task.recurring << ",";
300
            if( (*it).sourcePath != task.sourcePath )   stream << " SOURCE_PATH = '" << task.sourcePath.c_str() << "',";
301
            if( (*it).destination != task.destination ) stream << " DESTINATION = '" << task.destination.c_str() << "',";
302
            if( (*it).state != task.state )             stream << " STATUS = " << task.state << ",";
303
            if( (*it).rampType != task.rampType )       stream << " RAMP_TYPE = " << task.rampType << ",";
304
            if( (*it).gradient != task.gradient )       stream << " RAMP_GRADIENT = " << task.gradient << ",";
305
            if( (*it).rampTime != task.rampTime )       stream << " RAMP_TIME = " << GetSQLDateTime(task.rampTime).c_str() << ",";
306
            if( !comment.IsEmpty() )                    stream << " COMMENTS = '" << comment.c_str() << "',";
307
            if( taskDone )                              stream << " END_TIME = sysdate,";
308
 
309
            AnsiString sql_statement, temp;
310
            temp = stream.str().c_str();
311
            temp.Delete(temp.Length(), 1); // Remove last comma
312
 
313
            sql_statement.sprintf("%s where TRANSFER_NO = %d",
314
                                    temp, task.id);
315
 
316
            txnquery->SQL->Text = sql_statement;
317
            if( txnquery->ExecSQL()!= 1 )
318
            {
319
                MERROR( "Failed to update transfer history on statement: " << sql_statement );
320
            }
321
 
322
            delete txnquery;
323
            (*it) = task;
324
 
325
            if( taskDone )
326
            {
327
                m_tasks.erase( it );
328
 
329
                UdTransferThreadItem thread = m_threads.find( task.id );
330
                if( thread != m_threads.end() )
331
                {
332
                    (*thread).second->StopTransfer();
333
                }
334
            }
335
        }
336
    }
337
    __finally
338
    {
339
        m_tasksLock->Release();
340
    }
341
 
342
    UdTransferHistoryForm->RefreshHistory();
343
}
344
//---------------------------------------------------------------------------
345
 
346
bool UdTransferManager::GetTaskDetails( UdTransferTask & task )
347
{
348
    bool found = false;
349
 
350
    m_tasksLock->Acquire();
351
    try {
352
        UdTransferTaskItem it = m_tasks.begin();
353
        for( ; it != m_tasks.end(); it++ )
354
        {
355
            if( (*it).id == task.id )
356
            {
357
                found = true;
358
                task = (*it);
359
                break;
360
            }
361
        }
362
    }
363
    __finally
364
    {
365
        m_tasksLock->Release();
366
    }
367
 
368
    return found;
369
}
370
//---------------------------------------------------------------------------
371
 
372
bool UdTransferManager::LaunchTask( const UdTransferTask & task )
373
{
374
    bool launched = false;
375
 
376
    // Ensure we haven't already got a thread for this task
377
 
378
    UdTransferThreadItem thread = m_threads.find( task.id );
379
    if( thread == m_threads.end() )
380
    {
381
        m_threads[task.id] = new UdTransferThread( task, this, m_deviceSimulatorFactory );
382
        launched = true;
383
    }
384
 
385
    return launched;
386
}
387
//---------------------------------------------------------------------------
388
 
389
bool UdTransferManager::GetTaskStatistics( const int & taskId,
390
                                           UdTransferStatistics & stats )
391
{
392
    bool found = false;
393
 
394
    // Check if we are currently processing the device, if so
395
    // request the stats from the task thread
396
 
397
    UdTransferThreadItem thread = m_threads.find( taskId );
398
    if( thread != m_threads.end() )
399
    {
400
        if( (*thread).second != NULL )
401
        {
402
            (*thread).second->GetTransferStatistics( stats );
403
            found = true;
404
        }
405
    }
406
 
407
    // Otherwise grab the info from the database
408
 
409
    if( !found )
410
    {
411
        TADOQuery * txnquery = new TADOQuery(NULL);
412
        if( txnquery == NULL ) return false;
413
 
414
        txnquery->Connection = Data_Module->IntegrationDBConnection;
415
 
416
        AnsiString sql_statement;
417
        sql_statement.sprintf("select ADDED_TIME, END_TIME, NUMBER_FILES, NUMBER_BYTES, BATCH_HISTORY "
418
                              "from   TRANSFER_HISTORY "
419
                              "where  TRANSFER_NO = %d",
420
                              taskId);
421
        txnquery->SQL->Text = sql_statement;
422
        txnquery->Open();
423
 
424
        if( !txnquery->Eof )
425
        {
426
            stats.completed  = true;
427
            stats.startTime = txnquery->FieldByName("ADDED_TIME")->AsDateTime;
428
            stats.processedFiles = txnquery->FieldByName("NUMBER_FILES")->AsInteger;
429
            stats.processedBytes = txnquery->FieldByName("NUMBER_BYTES")->AsInteger;
430
 
431
            // End time may not be populated in times of program crashes. Ignore the
432
            // problem here and handle it when the statistics get used.
433
            try
434
            {
435
                stats.endTime = txnquery->FieldByName("END_TIME")->AsDateTime;
436
            }
437
            catch( EDatabaseError & e ) { }
438
 
439
            AnsiString batches = txnquery->FieldByName("BATCH_HISTORY")->AsString;
440
            if( !batches.IsEmpty() &&
441
                (batches != "(null)") )
442
            {
443
                // Tokenise our batch history string to our list
444
 
445
                TStringList * list = new TStringList;
446
                try {
447
                    if( list != NULL )
448
                    {
449
                        try {
450
                            list->CommaText = batches;
451
                            for( int i = 0; i < list->Count; i++ )
452
                            {
453
                                stats.batches.push_back( list->Strings[i].ToInt() );
454
                            }
455
                        }
456
                        catch( EConvertError & e ) {} // Ignore
457
                    }
458
                }
459
                __finally
460
                {
461
                    delete list;
462
                }
463
            }
464
            found = true;
465
        }
466
        delete txnquery;
467
    }
468
 
469
    return found;
470
}
471
//---------------------------------------------------------------------------
472
 
473
void UdTransferManager::UpdateTaskStatistics( const int & taskId,
474
                                              const UdTransferStatistics & stats )
475
{
476
    // Format the batches list into a comma delimited string
477
 
478
    AnsiString batches;
479
    BatchSizeItem batch = (int *)stats.batches.begin();
480
    for( ; batch != stats.batches.end(); batch++ )
481
    {
482
        if( batch != stats.batches.begin() ) batches += ",";
483
        batches += IntToStr( *batch );
484
    }
485
 
486
    TADOQuery * txnquery = new TADOQuery(NULL);
487
    if( txnquery == NULL ) return;
488
 
489
    txnquery->Connection = Data_Module->IntegrationDBConnection;
490
 
491
    AnsiString sql_statement;
492
    sql_statement.sprintf("update TRANSFER_HISTORY set "
493
                          "       NUMBER_FILES = %d, "
494
                          "       NUMBER_BYTES = %d, "
495
                          "       BATCH_HISTORY = '%s' "
496
                          "where  TRANSFER_NO = %d",
497
                          stats.processedFiles,
498
                          stats.processedBytes,
499
                          batches,
500
                          taskId);
501
    txnquery->SQL->Text = sql_statement;
502
    if( txnquery->ExecSQL() != 1 )
503
    {
504
        MERROR( "Failed to persist transfer statistics to database for task " << taskId );
505
    }
506
    txnquery->Close();
507
    delete txnquery;
508
 
509
    UdTransferHistoryForm->RefreshHistory();
510
}
511
//---------------------------------------------------------------------------
512
 
513
bool UdTransferManager::IsTaskRunning()
514
{
515
    bool running = false;
516
 
517
    UdTransferThreadItem thread = m_threads.begin();
518
    for( ; thread != m_threads.end(); thread++ )
519
    {
520
        if( ((*thread).second != NULL) &&
521
            (*thread).second->IsRunning() )
522
        {
523
            running = true;
524
            break;
525
        }
526
    }
527
 
528
    return running;
529
}