Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2265 kivins 1
//---------------------------------------------------------------------------
2
 
3
#include <vcl.h>
4
#pragma hdrstop
5
 
6
#include "UdTransferHistory.h"
7
#include "UdTransfer.h"
8
#include "DataModule.h"
9
#include <dateutils.hpp>
10
//---------------------------------------------------------------------------
11
#pragma package(smart_init)
12
#pragma link "Grids_ts"
13
#pragma link "TSDBGrid"
14
#pragma link "TSGrid"
15
//#pragma link "PERFGRAP"
16
#pragma link "AdvPageControl"
17
#pragma link "AdvGrid"
18
#pragma link "BaseGrid"
19
#pragma link "DBAdvGrd"
20
#pragma link "AdvGrid"
21
#pragma link "BaseGrid"
22
#pragma resource "*.dfm"
23
TUdTransferHistoryForm *UdTransferHistoryForm;
24
 
25
namespace
26
{
27
    AnsiString GetDurationString( const TDateTime & now, const TDateTime & then )
28
    {
29
        AnsiString duration;
30
        AnsiString text;
31
 
32
        // Longest duration should be in days
33
 
34
        int days        = DaysBetween( now, then );
35
        __int64 hours   = HoursBetween( now, then );
36
        __int64 mins    = MinutesBetween( now, then );
37
        __int64 secs    = SecondsBetween( now, then );
38
 
39
        if( days > 0 )
40
        {
41
            text.sprintf( "%d day(s), ", days );
42
            duration = text;
43
            hours = hours % 24;
44
            mins = mins % 60;
45
            secs = secs % 60;
46
        }
47
        else if( hours > 0 )
48
        {
49
            mins = mins % 60;
50
            secs = secs % 60;
51
        }
52
        else if( mins > 0 )
53
        {
54
            secs = secs % 60;
55
        }
56
 
57
        text.sprintf( "%02Ld:%02Ld:%02Ld", hours, mins, secs );
58
        duration += text;
59
 
60
        return duration;
61
    }
62
 
63
    AnsiString GetDurationString( const int & duration )
64
    {
65
        TDateTime then = 0;
66
        TDateTime now  = (double)duration/(24*60*60);
67
        return GetDurationString( now, then );
68
    }
69
 
70
    AnsiString FormatNumeric( long double number, int precision = 0 )
71
    {
72
        return AnsiString::FloatToStrF((long double)number, AnsiString::sffNumber, 18, precision);
73
    }
74
 
75
    typedef enum
76
    {
77
        COL_ATTRIB      = 1,
78
        COL_VALUE       = 2
79
 
80
    } TransferDetailsColumns;
81
 
82
    typedef enum
83
    {
84
        ROW_SOURCE_PATH = 1,
85
        ROW_DESTINATION = 2,
86
        ROW_BATCH_SIZE  = 3,
87
        ROW_END_TIME    = 4,
88
        ROW_COMMENTS    = 5,
89
        ROW_RAMP_TYPE   = 6,
90
        ROW_RAMP_TIME   = 7,
91
        ROW_DURATION    = 8,
92
        ROW_FREQUENCY   = 9,
93
        ROW_GRADIENT    = 10,
94
        ROW_RECURRING   = 11
95
 
96
    } TransferDetailsRows;
97
}
98
 
99
//---------------------------------------------------------------------------
100
__fastcall TUdTransferHistoryForm::TUdTransferHistoryForm(TComponent* Owner)
101
    : TForm(Owner), m_manager( NULL )
102
{
103
}
104
//---------------------------------------------------------------------------
105
 
106
void __fastcall TUdTransferHistoryForm::btAddClick(TObject *Sender)
107
{
108
    if( UdTransferForm->ShowForm( m_manager ) == mrOk )
109
    {
110
        RefreshHistory();
111
    }
112
}
113
//---------------------------------------------------------------------------
114
 
115
void __fastcall TUdTransferHistoryForm::btnAbortClick(TObject *Sender)
116
{
117
    if( MessageDlg("Are you sure you want to abort this transfer task?",
118
            mtConfirmation, TMsgDlgButtons() << mbNo << mbYes, 0 ) == mrYes )
119
    {
120
        UdTransferTask task;
121
        task.id = m_curTransferNum;
122
 
123
        if( m_manager->GetTaskDetails( task ) )
124
        {
125
            AnsiString comment;
126
            int status = gridHistory->DataSource->DataSet->FieldByName("status")->AsInteger;
127
 
128
            task.state = UdTransferAborted;
129
            if( status == UdTransferPending )
130
            {
131
                comment = "Transfer aborted before processing started.";
132
            }
133
            else if( status == UdTransferInProgress )
134
            {
135
                if( !task.recurring )
136
                {
137
                    comment = "Transfer aborted during processing.";
138
                }
139
                else
140
                {
141
                    // Stopping a recurring task is not really an error
142
 
143
                    comment = "User stopped recurring transfers during processing.";
144
                    task.state = UdTransferCompleted;
145
                }
146
            }
147
 
148
            m_manager->UpdateTask( task, comment );
149
        }
150
        else
151
        {
152
            // Only way this could happen is if we are aborting a task set as
153
            // in progress after which the program crashed. Simply update the status flag.
154
 
155
            TADOQuery * txnquery = new TADOQuery(NULL);
156
            if( txnquery == NULL ) return;
157
 
158
            txnquery->Connection = Data_Module->IntegrationDBConnection;
159
 
160
            AnsiString sql_statement;
161
            sql_statement.sprintf("update TRANSFER_HISTORY set "
162
                                  "       STATUS = %d, "
163
                                  "       END_TIME = sysdate "
164
                                  "where  TRANSFER_NO = %d",
165
                                  (int)UdTransferAborted,
166
                                  m_curTransferNum);
167
            txnquery->SQL->Text = sql_statement;
168
            txnquery->ExecSQL();
169
            txnquery->Close();
170
            delete txnquery;
171
 
172
            RefreshHistory();
173
        }
174
    }
175
}
176
//---------------------------------------------------------------------------
177
 
178
void __fastcall TUdTransferHistoryForm::gridHistoryCellLoaded(
179
      TObject *Sender, int DataCol, Variant &DataRow, Variant &Value)
180
{
181
    // Format some of the loaded grid data
182
 
183
    if( DataCol == 5 ) // Status
184
    {
185
        switch( gridHistory->DataSource->DataSet->FieldByName("status")->AsInteger )
186
        {
187
        case UdTransferCompleted:   Value = "Completed";        break;
188
        case UdTransferFailed:      Value = "Failed";           break;
189
        case UdTransferAborted:     Value = "Aborted";          break;
190
        case UdTransferInProgress:  Value = "In Progress";      break;
191
        case UdTransferPending:     Value = "Pending";          break;
192
        };
193
    }
194
}
195
 
196
//---------------------------------------------------------------------------
197
 
198
void __fastcall TUdTransferHistoryForm::gridHistoryRowChanged(
199
      TObject *Sender, Variant &OldRow, Variant &NewRow)
200
{
201
    m_curTransferNum = gridHistory->DataSource->DataSet->FieldByName("transfer_no")->AsInteger;
202
 
203
    LoadTransferDetails();
204
    LoadTransferStatistics();
205
 
206
    try {
207
        bool isOwner = (gridHistory->DataSource->DataSet
208
            ->FieldByName("username")->AsString == m_manager->GetUsername());
209
 
210
        switch( gridHistory->DataSource->DataSet->FieldByName("status")->AsInteger )
211
        {
212
        case UdTransferCompleted:
213
        case UdTransferFailed:
214
        case UdTransferAborted:
215
            btnAbort->Enabled = false;
216
            break;
217
 
218
        case UdTransferInProgress:
219
        case UdTransferPending:
220
            btnAbort->Enabled = isOwner;
221
            break;
222
        };
223
    }
224
    catch( EDatabaseError & e )
225
    {
226
        btnAbort->Enabled = false;
227
    }
228
}
229
//---------------------------------------------------------------------------
230
 
231
void __fastcall TUdTransferHistoryForm::ShowForm(TObject *Sender)
232
{
233
    btnAbort->Enabled = false;
234
    m_curTransferNum = 0;
235
 
236
    gridDetails->Cells[COL_ATTRIB][ROW_SOURCE_PATH] = "Source Path";
237
    gridDetails->Cells[COL_ATTRIB][ROW_DESTINATION] = "Destination";
238
    gridDetails->Cells[COL_ATTRIB][ROW_BATCH_SIZE]  = "Batch Size";
239
    gridDetails->Cells[COL_ATTRIB][ROW_END_TIME]    = "End Time";
240
    gridDetails->Cells[COL_ATTRIB][ROW_COMMENTS]    = "Comments";
241
    gridDetails->Cells[COL_ATTRIB][ROW_RAMP_TYPE]   = "Ramp Type";
242
    gridDetails->Cells[COL_ATTRIB][ROW_RAMP_TIME]   = "Ramp Time";
243
    gridDetails->Cells[COL_ATTRIB][ROW_DURATION]    = "Duration";
244
    gridDetails->Cells[COL_ATTRIB][ROW_FREQUENCY]   = "Frequency";
245
    gridDetails->Cells[COL_ATTRIB][ROW_GRADIENT]    = "Ramp Gradient";
246
    gridDetails->Cells[COL_ATTRIB][ROW_RECURRING]   = "Recurring Test";
247
 
248
    qryTransferHistory->Active = true;
249
    gridHistory->DataSource = dsTransferHistory;
250
}
251
//---------------------------------------------------------------------------
252
 
253
void __fastcall TUdTransferHistoryForm::LoadTransferDetails()
254
{
255
    // Get the data and load the new entries
256
 
257
    TADOQuery * txnquery = new TADOQuery(NULL);
258
    if( txnquery == NULL ) return;
259
 
260
    txnquery->Connection = Data_Module->IntegrationDBConnection;
261
 
262
    AnsiString sql_statement;
263
    sql_statement.sprintf("select SOURCE_PATH, DESTINATION, BATCH_SIZE, END_TIME, COMMENTS, "
264
                          "       RAMP_TYPE, RAMP_TIME, DURATION, FREQUENCY, RAMP_GRADIENT, RECURRING "
265
                          "from   TRANSFER_HISTORY "
266
                          "where  TRANSFER_NO = %d",
267
                          m_curTransferNum);
268
    txnquery->SQL->Text = sql_statement;
269
    txnquery->Open();
270
 
271
    if( !txnquery->Eof )
272
    {
273
        UdTransferTask task;
274
        AnsiString comments;
275
        TDateTime endTime;
276
 
277
        task.sourcePath     = txnquery->FieldByName("SOURCE_PATH")->AsString;
278
        task.destination    = txnquery->FieldByName("DESTINATION")->AsString;
279
        task.batchSize      = txnquery->FieldByName("BATCH_SIZE")->AsInteger;
280
        endTime             = txnquery->FieldByName("END_TIME")->AsDateTime;
281
        comments            = txnquery->FieldByName("COMMENTS")->AsString;
282
        task.rampType       = (RampTestType)txnquery->FieldByName("RAMP_TYPE")->AsInteger;
283
        task.rampTime       = txnquery->FieldByName("RAMP_TIME")->AsDateTime;
284
        task.duration       = txnquery->FieldByName("DURATION")->AsInteger;
285
        task.frequency      = txnquery->FieldByName("FREQUENCY")->AsInteger;
286
        task.gradient       = txnquery->FieldByName("RAMP_GRADIENT")->AsFloat;
287
        task.recurring      = (txnquery->FieldByName("RECURRING")->AsInteger > 0);
288
 
289
        SetTransferDetails( task, endTime, comments );
290
    }
291
 
292
    delete txnquery;
293
}
294
//---------------------------------------------------------------------------
295
 
296
void __fastcall TUdTransferHistoryForm::ResetTransferDetails()
297
{
298
    gridDetails->ClearCols( 3, 1 );
299
}
300
//---------------------------------------------------------------------------
301
 
302
void __fastcall TUdTransferHistoryForm::ResetTransferStatistics()
303
{
304
    bool isTransferRunning = false;
305
 
306
    if( (m_curTransferNum != 0) &&
307
         gridHistory->DataSource->DataSet->Active )
308
    {
309
        int status = gridHistory->DataSource->DataSet->FieldByName("status")->AsInteger;
310
        isTransferRunning = ((status == UdTransferInProgress) ||
311
                             (status == UdTransferPending));
312
    }
313
 
314
    lblNumFiles->Caption    = "N/A";
315
    lblBytes->Caption       = "N/A";
316
    lblTransferTime->Caption= "N/A";
317
    lblFilesPerSec->Caption = "N/A";
318
    lblBytesPerSec->Caption = "N/A";
319
 
320
    lblPercent->Caption     = "0%";
321
    pbCompleted->Position   = 0;
322
 
323
    lblPercent->Visible     = isTransferRunning;
324
    pbCompleted->Visible    = isTransferRunning;
325
    lblProgress->Visible    = isTransferRunning;
326
 
327
    seriesBatches->Clear();
328
    chartBatchSize->LeftAxis->Automatic = false;
329
    chartBatchSize->BottomAxis->Automatic = false;
330
    chartBatchSize->LeftAxis->SetMinMax( 0, 10 );
331
    chartBatchSize->BottomAxis->SetMinMax( 1, 10 );
332
}
333
//---------------------------------------------------------------------------
334
 
335
void __fastcall TUdTransferHistoryForm::SetTransferDetails( const UdTransferTask & task,
336
                                                            const TDateTime & endTime,
337
                                                            const AnsiString & comments )
338
{
339
    ResetTransferDetails();
340
 
341
    gridDetails->Cells[COL_VALUE][ROW_SOURCE_PATH]  = task.sourcePath;
342
    gridDetails->Cells[COL_VALUE][ROW_DESTINATION]  = task.destination;
343
    gridDetails->Cells[COL_VALUE][ROW_BATCH_SIZE]   = task.batchSize;
344
    gridDetails->Cells[COL_VALUE][ROW_COMMENTS]     = comments;
345
    gridDetails->Cells[COL_VALUE][ROW_DURATION]     = GetDurationString( task.duration );
346
    gridDetails->Cells[COL_VALUE][ROW_FREQUENCY]    = GetDurationString( task.frequency );
347
 
348
    gridDetails->Cells[COL_VALUE][ROW_END_TIME] =
349
        ((int)endTime == 0) ? "Not Finished" : endTime.DateTimeString().c_str();
350
 
351
    gridDetails->Cells[COL_VALUE][ROW_RAMP_TIME] =
352
        (task.rampType == RampTestDisabled) ? "Not Applicable" : task.rampTime.DateTimeString().c_str();
353
 
354
    gridDetails->Cells[COL_VALUE][ROW_GRADIENT] =
355
        (task.rampType == RampTestByDemand) ? FloatToStr(task.gradient).c_str() : "Not Applicable";
356
 
357
    gridDetails->Cells[COL_VALUE][ROW_RECURRING] =
358
        (task.recurring ? "True" : "False");
359
 
360
    AnsiString rampType = "Unknown";
361
 
362
    switch( task.rampType )
363
    {
364
    case RampTestDisabled:  rampType = "Batch Transfer";   break;
365
    case RampTestByDemand:  rampType = "Ramp by Demand";   break;
366
    case RampTestByRatio:   rampType = "Ramp by Ratio";    break;
367
    }
368
    gridDetails->Cells[COL_VALUE][ROW_RAMP_TYPE] = rampType;
369
 
370
}
371
//---------------------------------------------------------------------------
372
 
373
void __fastcall TUdTransferHistoryForm::LoadTransferStatistics()
374
{
375
    ResetTransferStatistics();
376
    UpdateTransferStatistics();
377
}
378
//---------------------------------------------------------------------------
379
 
380
void __fastcall TUdTransferHistoryForm::UpdateTransferStatistics()
381
{
382
    UdTransferStatistics stats;
383
    if( m_manager->GetTaskStatistics( m_curTransferNum, stats ) )
384
    {
385
        int percentDone = 0;
386
        bool displayDurations = true;
387
 
388
        // If the task is pending, duration statistics are not valid yet
389
 
390
        try
391
        {
392
            int status = gridHistory->DataSource->DataSet->FieldByName("status")->AsInteger;
393
            if( status == UdTransferPending )
394
            {
395
                lblTransferTime->Caption = "Pending ...";
396
                displayDurations = false;
397
            }
398
        }
399
        catch( EDatabaseError & e )
400
        {
401
            displayDurations = false;
402
        }
403
 
404
        // Set processed/total files stats
405
 
406
        if( stats.completed )
407
        {
408
            lblNumFiles->Caption = FormatNumeric( stats.processedFiles );
409
            lblBytes->Caption = FormatNumeric( stats.processedBytes );
410
 
411
            displayDurations = (stats.processedFiles > 0);
412
        }
413
        else if( stats.totalFiles > 0 )
414
        {
415
            // Stats provided in realtime (non-complete) have more info to display
416
 
417
            lblBytes->Caption = FormatNumeric( stats.processedBytes );
418
            lblNumFiles->Caption = FormatNumeric( stats.processedFiles % stats.totalFiles )
419
                + " / " + FormatNumeric( stats.totalFiles );
420
 
421
            if( stats.processedFiles > stats.totalFiles )
422
            {
423
                AnsiString recurses = lblNumFiles->Caption;
424
                recurses += " (x" + IntToStr( stats.processedFiles / stats.totalFiles ) + ")";
425
                lblNumFiles->Caption = recurses;
426
            }
427
 
428
            if( gridDetails->Cells[COL_VALUE][ROW_RECURRING] != "True" )
429
            {
430
                percentDone = (((stats.processedFiles % stats.totalFiles)*100) / stats.totalFiles);
431
            }
432
        }
433
 
434
        // Fill in the chart details
435
 
436
        if( !stats.batches.empty() )
437
        {
438
            seriesBatches->Clear();
439
            chartBatchSize->LeftAxis->Automatic = true;
440
            chartBatchSize->BottomAxis->Automatic = true;
441
 
442
            BatchSizeItem batch = stats.batches.begin();
443
            for( int count = 1; batch != stats.batches.end(); batch++, count++ )
444
            {
445
                seriesBatches->AddXY( count, (double)(*batch)/1024, "", clBlue );
446
            }
447
        }
448
 
449
        // Dont display durations for transfers with no files sent
450
 
451
        if( displayDurations )
452
        {
453
            try {
454
                TDateTime startTime = stats.startTime;
455
                TDateTime endTime = TDateTime::CurrentDateTime();
456
                if( stats.completed ) endTime = gridDetails->Cells[COL_VALUE][ROW_END_TIME];
457
 
458
                lblTransferTime->Caption = GetDurationString( endTime, startTime );
459
                __int64 duration = SecondsBetween( endTime, startTime );
460
 
461
                if( duration > 0 )
462
                {
463
                    lblFilesPerSec->Caption = FormatNumeric( (double)stats.processedFiles / duration, 3 );
464
                    lblBytesPerSec->Caption = FormatNumeric( (double)stats.processedBytes / duration, 3 );
465
                }
466
                else
467
                {
468
                    lblFilesPerSec->Caption = FormatNumeric( (double)stats.processedFiles, 3 );
469
                    lblBytesPerSec->Caption = FormatNumeric( (double)stats.processedBytes, 3 );
470
                }
471
 
472
                if( !stats.completed )
473
                {
474
                    __int64 completion = SecondsBetween( stats.endTime, startTime );
475
                    if( completion > 0 )
476
                    {
477
                        if( duration > completion )
478
                        {
479
                            percentDone = 100;
480
                        }
481
                        else
482
                        {
483
                            int timePercent = (((duration % completion)*100) / completion);
484
                            if( timePercent > percentDone )
485
                            {
486
                                percentDone = timePercent;
487
                            }
488
                        }
489
                    }
490
                }
491
            }
492
            catch( EConvertError & e )
493
            {
494
                // If we're here, it means we have a case where we are accessing
495
                // an in-progress task after a program crash (end time will fail to convert
496
                // as it is just text). We wont know the end time in anycase, so just
497
                // ignore it and display "N/A"s.
498
            }
499
            catch( EDatabaseError & e ) {} // Ignore
500
        }
501
 
502
        // Set the progress bar if required. Take the max between files remaining
503
        // (if not recurring task), and the time remaining till completion.
504
 
505
        if( !stats.completed )
506
        {
507
            if( percentDone > 100 ) percentDone = 100;
508
 
509
            lblPercent->Caption = IntToStr( percentDone ) + "%";
510
            pbCompleted->Position = percentDone;
511
        }
512
    }
513
}
514
//---------------------------------------------------------------------------
515
 
516
void __fastcall TUdTransferHistoryForm::gridRowResized(
517
      TObject *Sender, int RowColnr)
518
{
519
    // Ensure row height is not less than the font size
520
 
521
    int minHistoryRowSize = (gridHistory->Font->Size + 5);
522
    if( gridHistory->DefaultRowHeight < minHistoryRowSize )
523
    {
524
        gridHistory->DefaultRowHeight = minHistoryRowSize;
525
    }
526
 
527
    int minDetailsRowSize = (gridDetails->Font->Size +5);
528
    if( gridDetails->DefaultRowHeight < minDetailsRowSize )
529
    {
530
        gridDetails->DefaultRowHeight = minDetailsRowSize;
531
    }
532
}
533
//---------------------------------------------------------------------------
534
 
535
void __fastcall TUdTransferHistoryForm::btnCloseClick(TObject *Sender)
536
{
537
    Visible = false;
538
}
539
//---------------------------------------------------------------------------
540
 
541
void __fastcall TUdTransferHistoryForm::btnRefreshClick(TObject *Sender)
542
{
543
    RefreshHistory();
544
}
545
//---------------------------------------------------------------------------
546
 
547
void __fastcall TUdTransferHistoryForm::TimerTick(TObject *Sender)
548
{
549
    if( (tabDetails->ActivePageIndex == 1) &&
550
        qryTransferHistory->Active )
551
    {
552
        int status = gridHistory->DataSource->DataSet->FieldByName("status")->AsInteger;
553
        if( (status == UdTransferPending || status == UdTransferInProgress) )
554
        {
555
            UpdateTransferStatistics();
556
        }
557
    }
558
}
559
//---------------------------------------------------------------------------
560
 
561
void __fastcall TUdTransferHistoryForm::RefreshHistory()
562
{
563
    qryTransferHistory->Active = false;
564
    qryTransferHistory->Active = true;
565
/*
566
    if( gridHistory-> )
567
    {
568
        gridHistory->CurrentCell->MoveTo( 1, 1 );
569
    }
570
 
571
    LoadTransferDetails();
572
    LoadTransferStatistics();
573
*/
574
}
575