UltraScan III
us_data_process.cpp
Go to the documentation of this file.
1 
3 #include "us_data_process.h"
4 #include "us_data_model.h"
5 #include "us_sync_exper.h"
6 #include "us_util.h"
7 #include "us_settings.h"
8 #include "us_datafiles.h"
9 
10 // class to process operatations on data: upload/download/remove
11 US_DataProcess::US_DataProcess( US_DataModel* dmodel, QWidget* parent /*=0*/ )
12 {
13  parentw = parent;
14  da_model = dmodel;
15  db = da_model->dbase();
17 
18  syncExper = new US_SyncExperiment( db, parent );
19 }
20 
21 // perform a record upload to the database from local disk
23 {
24 DbgLv(1) << "REC_ULD: row" << row+1;
25  int stat = 0;
26 
27  cdesc = da_model->row_datadesc( row );
28 
29  if ( ! raw_ancestor_ok( row ) )
30  { // Cannot upload if ancestor Raw is not in both DB and Local
31  errMsg = tr( "Cannot upload records whose ancestor"
32  " Raw record is not both DB and Local.\n"
33  "Use us_convert (Utilities->Convert Legacy Data)"
34  " to create or modify the ancestor Raw." );
35  stat = 3061;
36  return stat;
37  }
38 
39  QDateTime dtime = QDateTime::fromString( cdesc.lastmodDate );
40  QDateTime ftime = QDateTime::fromString( cdesc.filemodDate );
41 
42  if ( ( cdesc.recState & US_DataModel::REC_DB ) != 0 &&
43  ftime < dtime )
44  { // Cannot replace DB record with older Local record
45  errMsg = tr( "The Local file record is older than the DB record." );
46  stat = 3061;
47  return stat;
48  }
49 
50  QStringList query;
51  QString filepath = cdesc.filename;
52  QString pathdir = filepath.section( "/", 0, -2 );
53  QString filename = filepath.section( "/", -1, -1 );
54  int idData = cdesc.recordID;
55 
56  //if ( cdesc.recType == 1 )
57  if ( cdesc.recType == 1 && cdesc.recType != 1 ) // never upload raw
58  { // upload a Raw record
59  QString runID = filename.section( ".", 0, 0 );
60  QString tripl = filename.section( ".", -4, -2 )
61  .replace( ".", " / " );
62 DbgLv(1) << "REC_ULD:RAW: runID" << runID << " tripl" << tripl;
63 
64  //stat = syncExper->synchronize( cdesc );
65 DbgLv(1) << "REC_ULD:RAW: parentGUID" << cdesc.parentGUID;
66  QString expGUID = cdesc.parentGUID;
67 
68  if ( stat == 0 )
69  {
70  idData = cdesc.recordID;
71  stat = db->writeBlobToDB( filepath,
72  QString( "upload_aucData" ),
73  idData );
74  errMsg = tr( "Raw upload writeBlobToDB() status %1" ).arg( stat );
75  stat = ( stat == 0 ) ? 0 : 3041;
76  }
77  }
78 
79  else if ( cdesc.recType == 2 )
80  { // upload an EditedData record
81  QString runID = filename.section( ".", 0, 0 );
82  QString label = filename.section( ".", 0, 1 );
83  QString editGUID = cdesc.dataGUID;
84  QString rawGUID = cdesc.parentGUID;
85  QString editID = QString::number( idData );
86 
87  query.clear();
88  query << "get_rawDataID_from_GUID" << rawGUID;
89  db->query( query );
90 
91  if ( ( stat = db->lastErrno() ) != US_DB2::OK )
92  {
93  errMsg = tr( "Raw DB record for Edit could not be accessed: %1" )
94  .arg( stat );
95  stat = 3052;
96  }
97 
98  else
99  {
100  db->next();
101  DbgLv(1) << "editUpld: rawGUID" << rawGUID;
102 
103  QString rawDataID = db->value( 0 ).toString();
104 
105  DbgLv(1) << "editUpld: rawDataID" << rawDataID;
106 
107  if ( idData < 0 )
108  {
109  query.clear();
110  query << "new_editedData" << rawDataID << editGUID << runID
111  << filename << cdesc.description;
112  db->query( query );
113  idData = db->lastInsertID();
114  editID = QString::number( idData );
115  DbgLv(1) << "editUpld: NEW idData" << idData << editID;
116  }
117 
118  query.clear();
119  query << "update_editedData" << editID << rawDataID << editGUID
120  << label << filename << cdesc.description;
121  db->query( query );
122  DbgLv(1) << "editUpld: label" << label;
123 
124  stat = db->writeBlobToDB( filepath,
125  QString( "upload_editData" ),
126  idData );
127  errMsg = tr( "writeBlob Edited stat %1, idData %2" )
128  .arg( stat ).arg( idData );
129  stat = ( stat == 0 ) ? 0 : 3042;
130  cdesc.recordID = idData;
131  }
132  }
133 
134  else if ( cdesc.recType == 3 )
135  { // upload a Model record
136  US_Model model;
137  filepath = get_model_filename( cdesc.dataGUID );
138 
139  model.load( filepath ); // load model from local disk
140  model.update_coefficients(); // fill in any missing coefficients
141  stat = model.write( db ); // store model to database
142  errMsg = tr( "model write to DB stat %1" ).arg( stat );
143  stat = ( stat == 0 ) ? 0 : 3043;
145 DbgLv(1) << errMsg;
146  }
147 
148  else if ( cdesc.recType == 4 )
149  { // upload a Noise record
150  US_Noise noise;
151 DbgLv(2) << "NOISE: (1) filepath" << filepath;
152  filepath = get_noise_filename( cdesc.dataGUID );
153 DbgLv(2) << "NOISE: (2) filepath" << filepath;
154 
155  noise.load( filepath );
156  stat = noise.write( db );
157  errMsg = tr( "noise write to DB stat %1" ).arg( stat );
158  stat = ( stat == 0 ) ? 0 : 3044;
160  }
161 
162  else
163  { // *ERROR*: invalid type
164  errMsg = tr( "upload attempt with type=%1" ).arg( cdesc.recType );
165  stat = 3045;
166  }
167 
168  if ( stat == 0 )
169  {
170  da_model->change_datadesc( cdesc, row );
171  }
172 
173  return stat;
174 }
175 
176 // perform a record download from the database to local disk
178 {
179  int stat = 0;
180  QStringList query;
181 
182  cdesc = da_model->row_datadesc( row );
183 
184  if ( ! raw_ancestor_ok( row ) )
185  { // Cannot download if ancestor Raw is not in both DB and Local
186  errMsg = tr( "Cannot download records whose ancestor"
187  " Raw record is not both DB and Local.\n"
188  "Use us_convert (Utilities->Convert Legacy Data)"
189  " to create or modify the ancestor Raw." );
190  stat = 3061;
191  return stat;
192  }
193 
194  int idData = cdesc.recordID;
195  QString dataID = QString::number( idData );
196  QString filepath = cdesc.filename;
197  QString dataGUID = cdesc.dataGUID;
198  QString filename = filepath.section( "/", -1, -1 );
199  QString runID = filename.section( ".", 0, 0 );
200 
201  filepath = ( filepath == filename ) ?
202  US_Settings::resultDir() + "/" + runID + "/" + filename :
203  filepath;
204 
205  QDir dirp;
206  QString filedir = filepath.section( "/", 0, -2 );
207 
208  if ( ! dirp.exists( filedir ) )
209  {
210  if ( ! dirp.mkpath( filedir ) )
211  {
212  stat = 3091;
213  errMsg = tr( "Unable to create download directory\n" )
214  + filedir;
215  return stat;
216  }
217  }
218 
219  //if ( cdesc.recType == 1 )
220  if ( cdesc.recType == 1 && cdesc.recType != 1 ) // never download raw
221  { // download a Raw record
222  stat = db->readBlobFromDB( filepath, "download_aucData", idData );
223  if ( stat != 0 )
224  errMsg = tr( "Raw download status %1" ).arg( stat )
225  + "\n " + filepath;
226  }
227 
228  else if ( cdesc.recType == 2 )
229  { // download an EditedData record
230  stat = db->readBlobFromDB( filepath, "download_editData", idData );
231  if ( stat != 0 )
232  errMsg = tr( "Edited download status %1" ).arg( stat )
233  + "\n " + filepath;
234  }
235 
236  else if ( cdesc.recType == 3 )
237  { // download a Model record
238 //QTime timer3;
239 //timer3.start();
240  filepath = get_model_filename( &cdesc );
241 //qDebug() << "DwnLd: model time1" << timer3.elapsed();
242  QStringList query;
243  query << "get_model_info" << dataID;
244  db->query( query );
245  stat = db->lastErrno();
246  if ( stat == US_DB2::OK )
247  {
248  db->next();
249 //qDebug() << "DwnLd: model time2" << timer3.elapsed();
250  QString contents = db->value( 2 ).toString();
251  QFile fileo( filepath );
252  if ( fileo.open( QIODevice::WriteOnly | QIODevice::Text ) )
253  {
254  QTextStream tso( &fileo );
255  tso << contents;
256  fileo.close();
257 //qDebug() << "DwnLd: model time3" << timer3.elapsed();
258  }
259  }
260 
261  else
262  {
263  errMsg = tr( "Model load for download, status %1" ).arg( stat );
264  stat = 3033; // download read error
265  }
266  }
267 
268  else if ( cdesc.recType == 4 )
269  { // download a Noise record
270  US_Noise noise;
271 
272  filepath = get_noise_filename( &cdesc );
273  stat = noise.load( dataID, db );
274 
275  if ( stat == US_DB2::OK )
276  {
277  stat = noise.write( filepath );
278 
279  if ( stat != US_DB2::OK )
280  {
281  errMsg = tr( "Noise write for download, status %1" ).arg( stat );
282  stat = 3024; // download write error
283  }
284 
285  else
286  cdesc.filename = filepath;
287  }
288 
289  else
290  {
291  errMsg = tr( "Noise load for download, status %1" ).arg( stat );
292  stat = 3034; // download read error
293  }
294  }
295 
296  else
297  { // *ERROR*: invalid type
298  errMsg = tr( "download attempt with type=%1" ).arg( cdesc.recType );
299  stat = 3015;
300  }
301 
302  if ( stat == 0 )
303  { // Change the record state to include "in-DB"
305  da_model->change_datadesc( cdesc, row );
306  }
307 
308  return stat;
309 }
310 // perform a record remove from the database
312 {
313  int stat = 0;
314  QStringList query;
315 
316  cdesc = da_model->row_datadesc( row );
317  int irecID = cdesc.recordID;
318  QString dataID = QString::number( irecID );
319 
320  if ( cdesc.recType == 1 )
321  { // remove a Raw record
322 query.clear();
323 query << "get_rawDataID_from_GUID" << cdesc.dataGUID;
324 db->query( query );
325 db->next();
326 DbgLv(1) << "REC_RMV: rawGUID rawID expID" << cdesc.dataGUID
327  << db->value( 0 ).toString() << db->value( 1 ).toString();
328  query.clear();
329  query << "delete_rawData" << QString::number( cdesc.parentID );
330 DbgLv(1) << "REC_RMV: exp ID" << cdesc.parentID;
331 
332  if ( ( stat = db->statusQuery( query ) ) != 0 )
333  {
334  errMsg = tr( "delete_rawData status=%1" ).arg( stat );
335  stat = 2011;
336  }
337  else
338  irecID = -1;
339  }
340 
341  else if ( cdesc.recType == 2 )
342  { // remove an EditedData record
343  query.clear();
344  query << "delete_editedData" << dataID;
345 DbgLv(1) << "EDT_RMV:" << query;
346 
347  if ( ( stat = db->statusQuery( query ) ) != 0 )
348  {
349  errMsg = tr( "delete_editedData status=%1" ).arg( stat );
350 DbgLv(1) << "EDT_RMV: stat" << stat << db->lastError() << db->lastErrno();
351 DbgLv(1) << "EDT_RMV: dataID" << dataID << "errMsg:" << errMsg;
352  stat = 2012;
353  }
354  else
355  irecID = -1;
356 DbgLv(1) << "EDT_RMV: stat" << stat;
357  }
358 
359  else if ( cdesc.recType == 3 )
360  { // remove a Model record
361  query.clear();
362  query << "delete_model" << dataID;
363 
364  if ( ( stat = db->statusQuery( query ) ) != 0 )
365  {
366  errMsg = tr( "delete_model status=%1" ).arg( stat );
367 DbgLv(1) << "MOD_RMV: dataID" << dataID << "errMsg:" << errMsg;
368 DbgLv(1) << "MOD_RMV: lastErr" << db->lastError() << db->lastErrno();
369  stat = 2013;
370  }
371  else
372  irecID = -1;
373  }
374 
375  else if ( cdesc.recType == 4 )
376  { // remove a Noise record
377  query.clear();
378  query << "delete_noise" << dataID;
379 
380  if ( ( stat = db->statusQuery( query ) ) != 0 )
381  {
382  errMsg = tr( "delete_noise status=%1" ).arg( stat );
383 DbgLv(1) << "NOI_RMV: dataID" << dataID << "errMsg:" << errMsg;
384 DbgLv(1) << "NOI_RMV: lastErr" << db->lastError() << db->lastErrno();
385  stat = 2014;
386  }
387  else
388  irecID = -1;
389  }
390 
391  else
392  { // *ERROR*: invalid type
393  errMsg = tr( "DB remove attempt for type=%1" ).arg( cdesc.recType );
394  stat = 2015;
395  }
396 
397  if ( stat == 0 )
398  {
399  cdesc.recordID = irecID;
400  da_model->change_datadesc( cdesc, row );
401  }
402 
403  return stat;
404 }
405 
406 // perform a record remove from local disk
408 {
409  int stat = 0;
410  cdesc = da_model->row_datadesc( row );
411 
412  QString filepath = cdesc.filename;
413  QString filename = filepath.section( "/", -1, -1 );
414  QFile file( filepath );
415 
416  if ( file.exists() )
417  { // the file to remove does exist
418 
419  if ( file.remove() )
420  { // the remove was successful
421 
422  if ( ( cdesc.recState & US_DataModel::REC_DB ) == 0 )
423  { // it was local-only, so now it's a dummy
425  }
426 
427  else
428  { // it was on both, so now it's db-only
429  cdesc.recState &= ~US_DataModel::REC_LO;
430  }
431  }
432 
433  else
434  { // an error occurred in removing
435  errMsg = tr( "File remove error,\n" ) + filepath;
436  stat = 1000;
437  }
438  }
439 
440  else
441  { // file did not exist
442  errMsg = tr( "*ERROR* attempt to remove non-existent file\n" ) + filepath;
443  stat = 2000;
444  }
445 
446  if ( stat == 0 )
447  {
448  da_model->change_datadesc( cdesc, row );
449  }
450 
451  return stat;
452 }
453 
454 // Get next model file name
456 {
457  QString path = ddesc->filename;
458 
459  if ( !path.isEmpty() && QFile( path ).exists() )
460  return path;
461 
462  if ( ( ddesc->recState & US_DataModel::REC_LO ) == 0 )
463  return get_model_filename( "" );
464  else
465  return get_model_filename( ddesc->dataGUID );
466 }
467 
468 // Get next model file name
469 QString US_DataProcess::get_model_filename( QString guid )
470 {
471  QString path;
472 
473  if ( ! US_Model::model_path( path ) )
474  return "";
475 
476  return US_DataFiles::get_filename( path, guid, "M", "model", "modelGUID" );
477 }
478 
479 
480 // Get next noise file name
482 {
483  QString path = ddesc->filename;
484 
485  if ( !path.isEmpty() && QFile( path ).exists() )
486  return path;
487 
488  if ( ( ddesc->recState & US_DataModel::REC_LO ) == 0 )
489  return get_noise_filename( "" );
490  else
491  return get_noise_filename( ddesc->dataGUID );
492 }
493 
494 // Get next noise file name
495 QString US_DataProcess::get_noise_filename( QString guid )
496 {
497  QString path = US_Settings::dataDir() + "/noises";
498  QDir dir;
499 
500  if ( ! dir.exists( path ) )
501  {
502  if ( ! dir.mkpath( path ) )
503  return "";
504  }
505 
506  return US_DataFiles::get_filename( path, guid, "N", "noise", "noiseGUID" );
507 }
508 
509 // Return the last error message
511 {
512  return errMsg;
513 }
514 
515 // Append to last error message a notice of errors on some actions
516 void US_DataProcess::partialError( int nacterrs, int nactions )
517 {
518  errMsg += tr( "\n\n%1 error(s) on %2 attempted actions.\n" )
519  .arg( nacterrs ).arg( nactions );
520 }
521 
522 // Append a string to the last error message
523 void US_DataProcess::appendError( QString aperrMsg )
524 {
525  errMsg += aperrMsg;
526 }
527 
528 // Test for ancestor Raw record in both DB and local
530 {
531  bool isOK = false;
532  int jrow = row;
534 
535  while ( --jrow >= 0 )
536  { // walk up tree until a Raw record is encountered.
538 
539  if ( ddesc.recType == 1 )
540  { // This is the Raw ancestor of the given record
541  if ( ( ddesc.recState & bSrc ) == bSrc )
542  { // If both DB and Local, mark as OK for upload/download
543  isOK = true;
544  }
545  break;
546  }
547  }
548 
549  return isOK;
550 }
551