00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00053
00054
00055
00056
00058
00059 #include <stdio.h>
00060 #include <stdlib.h>
00061 #include <string.h>
00062 #include "Stiostream.h"
00063 #include "Stsstream.h"
00064 #include "mysql.h"
00065 #include "mysql_com.h"
00066 #include "DbEndian.h"
00067 #include "StMessMgr.h"
00068 #include "StDbBroker.h"
00069
00070 extern "C" void * DbUse(uint *nRows,
00071 uint *datetime,
00072 const char * tableName,
00073 const char * structName,
00074 uint nVar,
00075 uint sizeOfStruct,
00076 StDbBroker::oldDescriptor *d)
00077 {
00078 enum EColumnType {kNAN, kFloat, kInt, kLong, kShort, kDouble, kUInt
00079 ,kULong, kUShort, kUChar, kChar };
00080
00081
00082
00083
00084
00085 uint j;
00086 uint count;
00087
00088 MYSQL mysql;
00089 MYSQL_RES *result;
00090 MYSQL_ROW row;
00091
00092 unsigned int num_fields;
00093 unsigned int num_rows;
00094
00095
00096
00097 ostrstream Query;
00098 char temps[128];
00099
00100 char validFrom[20];
00101 char currentDateTime[20];
00102 char time[7];
00103
00104 sprintf(currentDateTime,"%.8d",datetime[0]);
00105 sprintf(time,"%.6d",datetime[1]);
00106 strcat(currentDateTime,time);
00107
00108 currentDateTime[19]='\0';
00109 currentDateTime[18]=currentDateTime[13];
00110 currentDateTime[17]=currentDateTime[12];
00111 currentDateTime[16]=':';
00112 currentDateTime[15]=currentDateTime[11];
00113 currentDateTime[14]=currentDateTime[10];
00114 currentDateTime[13]=':';
00115 currentDateTime[12]=currentDateTime[9];
00116 currentDateTime[11]=currentDateTime[8];
00117 currentDateTime[10]=' ';
00118 currentDateTime[9]=currentDateTime[7];
00119 currentDateTime[8]=currentDateTime[6];
00120 currentDateTime[7]='-';
00121 currentDateTime[6]=currentDateTime[5];
00122 currentDateTime[5]=currentDateTime[4];
00123 currentDateTime[4]='-';
00124
00125 mysql_init(&mysql);
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 char *dbName=new char[strlen("params")+1]; strcpy(dbName,"params");
00138
00139 char *dbHost=new char[strlen("db1.star.bnl.gov")+1];strcpy(dbHost,"db1.star.bnl.gov");
00140
00141
00142
00143
00144
00145
00146 if (!mysql_real_connect(&mysql,dbHost,"","",dbName,0,NULL,0))
00147 {
00148 LOG_ERROR << "Failed to connect to database: Error: "
00149 << mysql_error(&mysql) << endm;
00150 *nRows=0;
00151 return NULL;
00152 }
00153
00154
00155
00156 Query.seekp(0);
00157 if(strlen(tableName)>0)
00158 {
00159
00160 Query << "SELECT DISTINCT MAX(instances.validFrom) FROM instances, structures WHERE instances.strID=structures.ID AND instances.name=\"" << tableName << "\" AND structures.name=\"" << structName << "\" AND instances.validFrom<\""<<currentDateTime<<"\" GROUP BY instances.name"<< ends;
00161
00162 }
00163 else
00164 {
00165 LOG_ERROR<<"ERROR: Zero length for Table Name is not allowed"<<endm;
00166 return NULL;
00167 }
00168
00169 uint num_latest;
00170 int latestDirDate;
00171 int latestDirTime;
00172
00173 if (mysql_real_query(&mysql,Query.str(),Query.pcount()-1))
00174 {
00175 LOG_ERROR << "Failed to query: Error: " << mysql_error(&mysql) << endm;
00176 mysql_close(&mysql);
00177 return NULL;
00178 }
00179 else
00180 {
00181 result = mysql_store_result(&mysql);
00182 if (result)
00183 {
00184 num_fields = mysql_num_fields(result);
00185 if (num_fields!=1) LOG_ERROR << "ERROR: wrong size of LATEST query"<<endm;
00186
00187 num_latest = mysql_num_rows(result);
00188
00189 if (num_latest==0)
00190 {
00191 LOG_ERROR << "INFO: db " << dbName << " on host "<< dbHost
00192 << " has no struct+table pair "<<structName<<"+"<< tableName
00193 << " valid for "<<currentDateTime <<endm;
00194 mysql_close(&mysql);
00195 return NULL;
00196 }
00197 else
00198 {
00199 if (num_latest>1) LOG_ERROR << "ERROR: found more than one latest date"
00200 << tableName << endm;
00201
00202
00203 row = mysql_fetch_row(result);
00204
00205 strncpy(validFrom,row[0],19);validFrom[19]='\0';
00206
00207 int ic=10;
00208 for(int i3=0;i3<3;i3++,++ic) {
00209 for(int i2=0;i2<2;i2++,++ic) {
00210 temps[ic]=row[0][ic];
00211 }
00212 }
00213 temps[6]='\0';
00214 latestDirTime = atoi(temps);
00215
00216
00217
00218 strncpy(temps,validFrom,10);
00219 temps[4]=temps[5];
00220 temps[5]=temps[6];
00221 temps[6]=temps[8];
00222 temps[7]=temps[9];
00223 temps[8]='\0';
00224
00225 latestDirDate = atoi(temps);
00226 }
00227 mysql_free_result(result);
00228 }
00229 else
00230 {
00231 LOG_ERROR << "no result: Error: " << mysql_error(&mysql) << endm;
00232 mysql_close(&mysql);
00233 return NULL;
00234 }
00235 }
00236
00237
00238 Query.seekp(0);
00239 Query << "SELECT DISTINCT instances.ID, instances.nRows, instances.strID, structures.sizeOfStruct, structures.nElements FROM instances, structures WHERE instances.strID=structures.ID AND instances.name=\"" << tableName << "\" AND structures.name=\"" << structName << "\" AND instances.validFrom=\""<<validFrom<<"\" ORDER BY instances.entered"<< ends;
00240
00241
00242
00243 uint num_instances=99999;
00244 int latestDirID=99999;
00245 int latestStrID=99999;
00246 uint sizeOfDbStruct=99999;
00247 uint nDbVar=99999;
00248
00249 if (mysql_real_query(&mysql,Query.str(),Query.pcount()-1))
00250 {
00251 LOG_ERROR << "Failed to query: Error: " << mysql_error(&mysql) << endm;
00252 mysql_close(&mysql);
00253 return NULL;
00254 }
00255 else
00256 {
00257 result = mysql_store_result(&mysql);
00258 if (result)
00259 {
00260 num_fields = mysql_num_fields(result);
00261 if (num_fields!=5) LOG_ERROR << "ERROR: wrong size of latest entries query"<<endm;
00262
00263 num_instances = mysql_num_rows(result);
00264
00265 if (num_instances==0)
00266 {
00267 LOG_ERROR << "ERROR: db " << dbName << " has lost the struct+table pair "
00268 <<structName<<"+"<< tableName << endm;
00269 mysql_close(&mysql);
00270 return NULL;
00271 }
00272 else
00273 {
00274 if (num_instances>1)
00275 {
00276 LOG_ERROR << "INFO: db " << dbName << " has more then one struct+table pair "
00277 <<structName<<"+"<< tableName
00278 << " valid for "<<currentDateTime
00279 <<", the LAST INSERTED is used"<<endl;
00280 LOG_ERROR << "database query: " << Query.str() << endm;
00281 }
00282 for (uint id=0;id<num_instances;id++)
00283 {
00284 row = mysql_fetch_row(result);
00285 latestDirID = atoi(row[0]);
00286 *nRows = (uint) atoi(row[1]);
00287 latestStrID = atoi(row[2]);
00288 sizeOfDbStruct = (uint)atoi(row[3]);
00289 nDbVar = (uint)atoi(row[4]);
00290 }
00291 }
00292 mysql_free_result(result);
00293 }
00294 else
00295 {
00296 LOG_ERROR << "no result: Error: " << mysql_error(&mysql) << endm;
00297 mysql_close(&mysql);
00298 return NULL;
00299 }
00300 }
00301
00302 Query.seekp(0);
00303
00304 if(sizeOfDbStruct!=sizeOfStruct)
00305 {
00306 LOG_ERROR<<"ERROR: DB struct byteSize is "<<sizeOfDbStruct<<endm;
00307 LOG_ERROR<<" user struct byteSize is "<<sizeOfStruct<<endm;
00308 LOG_ERROR << "structure: "<<structName<<endm;
00309 *nRows=0;
00310 return NULL;
00311 }
00312
00313 if(nVar!=nDbVar)
00314 {
00315 LOG_ERROR << "ERROR: DB struct nVariables is "<<nDbVar<<endm;
00316 LOG_ERROR << " user struct nVariables is "<<nVar<<endm;
00317 LOG_ERROR << "structure: "<<structName<<endm;
00318 *nRows = 0;
00319 return NULL;
00320 }
00321
00322
00323 char **types =0;
00324 char **names =0;
00325 int *offset=0;
00326 int *nDims=0;
00327 int *firstDim=0;
00328
00329
00330 Query.seekp(0);
00331 Query<<"SELECT name, type, offset, nDims, firstDim FROM headers WHERE strID="
00332 << latestStrID << " ORDER BY offset" << ends;
00333
00334
00335 if (mysql_real_query(&mysql,Query.str(),Query.pcount()-1))
00336 {
00337 LOG_ERROR << "Failed to query: Error: " << mysql_error(&mysql) << endm;
00338 mysql_close(&mysql);
00339 return NULL;
00340 }
00341 else
00342 {
00343 result = mysql_store_result(&mysql);
00344 if (result)
00345 {
00346 num_fields = mysql_num_fields(result);
00347 if (num_fields!=5) LOG_ERROR<<"ERROR: wrong size of headers query"<<endm;
00348
00349 num_rows = mysql_num_rows(result);
00350
00351
00352 if (num_rows!=nVar)
00353 {
00354 cout<<"WARNING: database structure is of "<< num_rows
00355 <<" variables, this structure is "<< nVar <<endl;
00356 }
00357
00358 types = new char*[num_rows];
00359 names = new char*[num_rows];
00360 offset = new int[num_rows];
00361 nDims = new int[num_rows];
00362 firstDim = new int[num_rows];
00363
00364 for (j=0;j<num_rows;j++)
00365 {
00366 row = mysql_fetch_row(result);
00367
00368 names[j] = strdup(row[0]);
00369 types[j] = strdup(row[1]);
00370 offset[j] = atoi(row[2]);
00371 nDims[j] = atoi(row[3]);
00372 firstDim[j] = atoi(row[4]);
00373
00374
00375
00376
00377
00378
00379 }
00380 mysql_free_result(result);
00381 }
00382 }
00383
00384
00385
00386
00387 count = 0;
00388
00389 for (j=0;j<nVar;j++)
00390 {
00391 if (strcmp(d[j].fColumnName,names[j]))
00392 break;
00393
00394
00395 if ( d[j].fOffset!=(unsigned int)offset[j] )
00396 break;
00397
00398
00399
00400 if ( d[j].fDimensions!=(unsigned int)nDims[j] )
00401 break;
00402
00403
00404
00405 if ( d[j].fIndexArray[0]!=(unsigned int)firstDim[j] )
00406 break;
00407
00408
00409 count++;
00410 }
00411
00412 if (count!=nVar)
00413 {
00414 LOG_ERROR<<"structure " << structName
00415 <<" is not compatible with database instance ID "<<latestDirID<<endm;
00416 LOG_ERROR <<"nVar "<<nVar<<", count "<<count<<endm;
00417
00418 for (j=0;j<nVar;j++)
00419 {
00420 LOG_ERROR<<"names: \""<<d[j].fColumnName<<"\" \""<<names[j]<<"\""<<endm;
00421 if (strcmp(d[j].fColumnName,names[j]))
00422 break;
00423
00424 LOG_ERROR<<"offset: "<<d[j].fOffset<<" "<<offset[j]<<endm;
00425 if ( d[j].fOffset!=(unsigned int)offset[j] )
00426 break;
00427
00428 LOG_ERROR<<"nDims: "<<d[j].fDimensions<<" "<<nDims[j]<<endm;
00429 if ( d[j].fDimensions!=(unsigned int)nDims[j] )
00430 break;
00431
00432 LOG_ERROR<<"firstDim: "<<d[j].fIndexArray[0]<<" "<<firstDim[j]<<endm;
00433 if ( d[j].fIndexArray[0]!=(unsigned int)firstDim[j] )
00434 break;
00435 }
00436
00437 *nRows=0;
00438 return NULL;
00439 }
00440
00441
00442
00443
00444
00445
00446 void* pDbData = calloc((size_t) *nRows, (size_t) sizeOfDbStruct);
00447
00448 if (pDbData==NULL){
00449 LOG_ERROR<<"DbUse: failed to allocate memory nedeed for the array of "
00450 << *nRows <<" structs " <<structName <<" each of "
00451 <<sizeOfStruct <<" bytes"<<endm;
00452 *nRows=0;
00453 return NULL;
00454 }
00455
00456 char* pCurrent = (char*) pDbData;
00457
00458 uint num_blobs;
00459 unsigned long *lengths;
00460
00461 Query.seekp(0);
00462 Query << "SELECT bytes FROM bytes WHERE instanceID="<<latestDirID<< ends;
00463
00464
00465
00466 if (mysql_real_query(&mysql,Query.str(),Query.pcount()-1))
00467 {
00468 LOG_ERROR << "Failed to query: Error: " << mysql_error(&mysql) << endm;
00469 LOG_ERROR << "database query: " << Query.str() << endm;
00470 mysql_close(&mysql);
00471 return NULL;
00472 }
00473 else
00474 {
00475 result = mysql_store_result(&mysql);
00476 if (!result)
00477 {
00478 LOG_ERROR << "no result: Error: " << mysql_error(&mysql) << endm;
00479 mysql_close(&mysql);
00480 return NULL;
00481 }
00482 else
00483 {
00484 num_fields = mysql_num_fields(result);
00485 if (num_fields!=1) LOG_ERROR << "ERROR: wrong size of blob query"<<endm;
00486
00487 num_blobs = mysql_num_rows(result);
00488
00489 if (num_blobs==0)
00490 {
00491 LOG_ERROR << "ERROR: db " << dbName << " has lost BLOB for struct+table pair "
00492 <<structName<<"+"<< tableName
00493 << " valid for "<<currentDateTime <<endm;
00494 mysql_close(&mysql);
00495 return NULL;
00496 }
00497 else
00498 {
00499 if (num_blobs>1) LOG_ERROR << "ERROR: found more than one BLOB for "
00500 <<tableName<<endm;
00501
00502 row = mysql_fetch_row(result);
00503
00504 if (row)
00505 {
00506 lengths = mysql_fetch_lengths(result);
00507
00508
00509 if (lengths[0]!=(*nRows)*sizeOfDbStruct)
00510 {
00511 LOG_ERROR << "ERROR: wrong blob size "
00512 <<tableName<<endm;
00513 LOG_ERROR <<"lengths[0] "<<lengths[0]
00514 <<", nRows "<<(*nRows)
00515 <<", sizeOfDbStruct "<<sizeOfDbStruct
00516 <<", nRows*sizeOfDbStruct "<<(*nRows)*sizeOfDbStruct
00517 <<endm;
00518 mysql_close(&mysql);
00519 *nRows=0;
00520 return NULL;
00521 }
00522
00523 #ifndef BIG_ENDIAN
00524 memcpy(pCurrent,row[0],(size_t) (*nRows)*sizeOfDbStruct);
00525 #else // do byte swapping
00526
00527 uint i, k, nTimes, firstByte, firstDbByte;
00528
00529
00530 for (i=0;i<*nRows;i++)
00531 {
00532 for (j=0;j<nVar;j++)
00533 {
00534
00535 switch(d[j].fDimensions)
00536 {
00537 case 0:
00538 nTimes=1;
00539 break;
00540 case 1:
00541 nTimes=d[j].fIndexArray[0];
00542 break;
00543 case 2:
00544 LOG_ERROR<<"two-dims not handled yet"<<endm;
00545 nTimes=0;
00546
00547 break;
00548 default:
00549 LOG_ERROR << "ERROR: more that one dimension "<<endm;
00550 nTimes=0;
00551 break;
00552 }
00553
00554
00555 firstByte=i*sizeOfStruct+d[j].fOffset;
00556 firstDbByte=i*sizeOfDbStruct+offset[j];
00557
00558 for (k=0;k<nTimes;k++) {
00559
00560
00561 switch((StDbBroker::EColumnType)d[j].fType)
00562 {
00563 case kUChar:
00564 case kChar:
00565 pCurrent[firstByte+k]=row[0][firstDbByte+k];
00566 break;
00567
00568 case kShort:
00569 case kUShort:
00570 pCurrent[firstByte+2*k+1]=row[0][+2*k ];
00571 pCurrent[firstByte+2*k ]=row[0][firstDbByte+2*k+1];
00572 break;
00573
00574 case kInt:
00575 case kUInt:
00576
00577 case kULong:
00578 case kLong:
00579
00580 case kFloat:
00581
00582 pCurrent[firstByte+4*k+3]=row[0][firstDbByte+4*k ];
00583 pCurrent[firstByte+4*k+2]=row[0][firstDbByte+4*k+1];
00584 pCurrent[firstByte+4*k+1]=row[0][firstDbByte+4*k+2];
00585 pCurrent[firstByte+4*k ]=row[0][firstDbByte+4*k+3];
00586 break;
00587
00588 case kDouble:
00589
00590 pCurrent[firstByte+8*k+7]=row[0][firstDbByte+8*k ];
00591 pCurrent[firstByte+8*k+6]=row[0][firstDbByte+8*k+1];
00592 pCurrent[firstByte+8*k+5]=row[0][firstDbByte+8*k+2];
00593 pCurrent[firstByte+8*k+4]=row[0][firstDbByte+8*k+3];
00594 pCurrent[firstByte+8*k+3]=row[0][firstDbByte+8*k+4];
00595 pCurrent[firstByte+8*k+2]=row[0][firstDbByte+8*k+5];
00596 pCurrent[firstByte+8*k+1]=row[0][firstDbByte+8*k+6];
00597 pCurrent[firstByte+8*k ]=row[0][firstDbByte+8*k+7];
00598 break;
00599
00600 case kNAN:
00601 default:
00602 LOG_ERROR << "ERROR: unknown type!"<<endm;
00603 break;
00604 }
00605 }
00606 }
00607 }
00608 #endif
00609 }
00610 }
00611 mysql_free_result(result);
00612 }
00613 }
00614
00615
00616 Query.seekp(0);
00617
00618 Query << "SELECT DISTINCT MIN(instances.validFrom) FROM instances, structures WHERE instances.strID=structures.ID AND instances.name=\"" << tableName << "\" AND structures.name=\"" << structName << "\" AND instances.validFrom>\""<<currentDateTime<<"\" GROUP BY instances.name"<<ends;
00619
00620
00621
00622 uint num_next;
00623 int nextDirDate;
00624 int nextDirTime;
00625
00626 if (mysql_real_query(&mysql,Query.str(),Query.pcount()-1))
00627 {
00628 LOG_ERROR << "Failed to query: Error: " << mysql_error(&mysql) << endm;
00629 mysql_close(&mysql);
00630 return NULL;
00631 }
00632 else
00633 {
00634 result = mysql_store_result(&mysql);
00635 if (result)
00636 {
00637 num_fields = mysql_num_fields(result);
00638 if (num_fields!=1) LOG_ERROR << "ERROR: wrong size of next date query"<<endm;
00639
00640 num_next = mysql_num_rows(result);
00641
00642 if (num_next==0)
00643 {
00644
00645
00646
00647 nextDirDate=20380101;
00648 nextDirTime=0;
00649 }
00650 else
00651 {
00652 if (num_next>1) LOG_ERROR << "ERROR: found more than one next date"
00653 <<tableName<<endm;
00654
00655
00656 row = mysql_fetch_row(result);
00657
00658
00659
00660 strncpy(validFrom,row[0],19);validFrom[19]='\0';
00661
00662 int ic=10;
00663 for(int i3=0;i3<3;i3++,++ic) {
00664 for(int i2=0;i2<2;i2++,++ic) {
00665 temps[ic]=row[0][ic];
00666 }
00667 }
00668 temps[6]='\0';
00669 nextDirTime = atoi(temps);
00670
00671
00672 strncpy(temps,validFrom,10);
00673 temps[4]=temps[5];
00674 temps[5]=temps[6];
00675 temps[6]=temps[8];
00676 temps[7]=temps[9];
00677 temps[8]='\0';
00678
00679 nextDirDate = atoi(temps);
00680 }
00681 mysql_free_result(result);
00682 }
00683 else
00684 {
00685 LOG_ERROR << "no result: Error: " << mysql_error(&mysql) << endm;
00686 mysql_close(&mysql);
00687 return NULL;
00688 }
00689 }
00690
00691
00692
00693 mysql_close(&mysql);
00694
00695 delete [] types;
00696 delete [] names;
00697 delete [] offset;
00698 delete [] nDims;
00699 delete [] firstDim;
00700
00701
00702
00703 datetime[0] = latestDirDate;
00704 datetime[1] = latestDirTime;
00705 datetime[2] = nextDirDate;
00706 datetime[3] = nextDirTime;
00707
00708
00709
00710
00711
00712 return pDbData;
00713
00714 }
00715
00716