#if defined (__MINGW32__) || defined (__MSVCRT__) #include #endif #include // for assert #include // for cerr #include // for unlink, write #include // for strdup #include "ant.h" // for BasenameOf and GetUserName and GetTempDirectory and GetEnv #include "libCfg.h" #include "libdb.h" #ifdef SQLITE_DB #include "sqlite3.h" #include "libdbSQLite.h" #endif #ifdef MYSQL_DB #include "mysql.h" #include "libdbMySQL.h" #include "MirrorDatabase.h" #endif #ifdef SwRI_DB #include "dbf.h" #include "libserver.h" // key_to_fields #endif #ifdef ALL_DB #include "dbf.h" #include "mysql.h" #include "sqlite3.h" #include "libserverWrap.h" #include "MirrorDatabase.h" #endif #include "Entry.h" #include "CServer.h" #include "cTime.h" #include "Promote.h" // private functions in separate file int _StartPromoStatus (); int _Process (char *arg0, ...); #if defined (__MINGW32__) || defined (__MSVCRT__) SOCKET _PipeFD; #else int _PipeFD; #endif Promote::Promote (const char *app_name, SDDAS_BOOL forcePromote) { _XStatus = ON; if (app_name != NULL) _app_name = strdup (app_name); else _app_name = strdup ("UNKNOWN"); _forcePromote = forcePromote; _mirror = NULL; _haveMeta = DB_GOOD; #ifndef MYSQL_DB assert (Projects != NULL); #endif _PipeFD = 0; memset (_error_msg, 0, sizeof (_error_msg)); #ifdef SwRI_DB _autoPromoteMeta = sFalse; #else _autoPromoteMeta = sTrue; #endif _btime = new TimeObj (); _etime = new TimeObj (); _data_sources.clear(); } Promote::~Promote () { unsigned int i; for (i = 0; i < _Server.size (); i++) { delete _Server [i]; } _Server.clear (); for (i = 0; i < _entryList.size (); i++) { delete _entryList [i]; } _entryList.clear (); _ServerUsed.clear (); delete _btime; delete _etime; if (_app_name != NULL) free (_app_name); } void Promote::SetBTime (SDDAS_INT year, SDDAS_INT day, SDDAS_LONG msec) { _btime->SetTime (year, day, msec); } void Promote::SetBTime (SDDAS_INT year, SDDAS_INT day, SDDAS_INT hour, SDDAS_INT min, SDDAS_INT sec, SDDAS_LONG msec) { SDDAS_LONG converted = msec + (sec * 1000) + (min * 60000) + (hour * 3600000); _btime->SetTime (year, day, converted); } void Promote::SetETime (SDDAS_INT year, SDDAS_INT day, SDDAS_LONG msec) // year, day, msec { _etime->SetTime (year, day, msec); } void Promote::SetETime (SDDAS_INT year, SDDAS_INT day, SDDAS_INT hour, SDDAS_INT min, SDDAS_INT sec, SDDAS_LONG msec) { SDDAS_LONG converted = msec + (sec * 1000) + (min * 60000) + (hour * 3600000); _etime->SetTime (year, day, converted); } void Promote::AddSource (SDDAS_ULONG data_key) { if (data_key == 0) return; // no NULL data keys! for (unsigned int i = 0; i < _data_sources.size (); i++) { if (data_key == _data_sources [i]) return; // no duplicates! } _data_sources.push_back (data_key); SetupDefaultServers (_data_sources.size () - 1); // The servers are all 1 to 1 with the data sources } void Promote::AddSource (char *P, char *M, char *E, char *I, char *V) { SDDAS_ULONG data_key; char str [512]; int result; data_key = dbGetDataKey (P, M, E, I, V); if (data_key == 0) { sprintf (str, "INSERT INTO hierarchy VALUES (NULL, '%s', '%s', '%s', '%s', '%s');", P, M, E, I, V); if ((result = dbQueryExec (str)) == 0) { snprintf (_error_msg, 256, "failed to insert %s, %s, %s, %s, %s\nPromote::AddSource - error: %s\n", P, M, E, I, V, dbErrorMsg()); std::cerr << _error_msg << std::endl; } data_key = dbGetDataKey(P, M, E, I, V); } AddSource (data_key); } void Promote::SetXStatus (XFileStatusType status) { _XStatus = status; } void Promote::SetAutoPromoteMeta (SDDAS_BOOL do_it_or_not) { _autoPromoteMeta = do_it_or_not; } SDDAS_BOOL Promote::PromoteMeta () { SDDAS_BOOL ret_code = sTrue; if (_data_sources.size () > 0) { SDDAS_BOOL real_ret_code = sTrue; unsigned int src_num = 0; // Having the "&& (ret_code == sTrue)" makes this loop stop after the first failure // We can take this out since a failure on one does not necessarily mean the next // one will fail while (src_num < _data_sources.size ()) { // && (ret_code == sTrue)) { _src_in_use = src_num; ret_code = PromoteMetaForSource (_data_sources [src_num], src_num); if (ret_code == sFalse) real_ret_code = sFalse; src_num++; } ret_code = real_ret_code; } else ret_code = sFalse; return (ret_code); } SDDAS_BOOL Promote::PromoteList () { InitializePromoStatus (_entryList.size ()); SDDAS_BOOL ret_code = sTrue; unsigned int i = 0; // Having the "&& (ret_code == sTrue)" makes this loop stop after the first failure while ((i < _entryList.size ()) && (ret_code == sTrue)) { Entry *E = _entryList [i]; ret_code = PromoteSingleEntry (i, E, _ServerUsed [i]); i++; } ClosePromoStatus (); return (ret_code); } SDDAS_BOOL Promote::DemoteAllData (SDDAS_BOOL deleteRegardless) { int ret_code = 0; unsigned int i = 0; while ((i < _entryList.size ()) && (ret_code != -1)) { Entry *E = _entryList [i]; if ((E->GetOldStatus () == OFFLINE) || (deleteRegardless == sTrue)) if (E->GetIDFSType () == _I_FILE_) { E->CheckVIDFEntry (); } ret_code = unlink (E->GetFName ()); i++; } if (ret_code == 0) return sTrue; else return sFalse; } ///////////////////////////////////////////////////////////////////////////// // // private routines // ///////////////////////////////////////////////////////////////////////////// void Promote::SetupDefaultServers (unsigned int which_server) { char *netid; int i = 0; // reset all the servers CServer *server = new CServer (); while ((netid = dbCfgItem (_data_sources [which_server], "NetID", i++)) != NULL) server->AddServer (netid); _Server.push_back (server); } #ifdef SwRI_DB #include "SwRI_DB_inc.C" #endif #ifdef ALL_DB #include "ALL_DB_inc.C" #include "SwRI_DB_inc.C" #endif #if defined(MYSQL_DB) || defined(SQLITE_DB) #include "ALL_DB_inc.C" #endif #ifdef MYSQL_DB #include "SQL_DB_inc.C" #endif #ifdef SQLITE_DB #include "SQLite_DB_inc.C" #endif SDDAS_INT Promote::BuildDBList (int IDFSType, FileStatusType status, int max_number) { // Check that we have valid sources if (_data_sources.size () == 0) { std::cerr << "libPromote/BuildDBList: Invalid source!" << std::endl; snprintf (_error_msg, 256, "The data sources are not valid!"); return -1; } #ifdef ALL_DB if(dbIsSwRI()) return SwRI_BuildDBList(IDFSType, status, max_number); else return SQL_BuildDBList(IDFSType, status, max_number); #endif #ifdef SwRI_DB return SwRI_BuildDBList(IDFSType, status, max_number); #endif #if defined(MYSQL_DB) || defined(SQLITE_DB) return SQL_BuildDBList(IDFSType, status, max_number); #endif } SDDAS_BOOL Promote::AutoGetMeta (SDDAS_ULONG data_key) { if (_autoPromoteMeta == sTrue) return (PromoteMetaForSource (data_key, 0)); else return sFalse; } SDDAS_BOOL Promote::PromoteMetaForSource_EXTERNAL (char *which_server, SDDAS_ULONG data_key) { char *exe; char *btime, *etime; char proj [MAX_IDFS_NAME], miss [MAX_IDFS_NAME], exp [MAX_IDFS_NAME], inst [MAX_IDFS_NAME], vinst [MAX_IDFS_VIRT_NAME]; if (dbKeyToStrings (data_key, proj, miss, exp, inst, vinst) != sTrue) return sFalse; if ((exe = CfgGetItem ("MetaPromote", 0, proj, miss, exp, inst, vinst, NULL)) == NULL) { return sFalse; } btime = strdup (_btime->GetTimeStr (COLON_SEP)); etime = strdup (_etime->GetTimeStr (COLON_SEP)); int ret; ret = _Process (exe, BasenameOf (exe), which_server, btime, etime, proj, miss, exp, inst, vinst, NULL); free (btime); free (etime); if (ret == 0) return sTrue; else return sFalse; } SDDAS_BOOL Promote::PromoteHDI (Entry *E, char *which_server) { char *exe; char byr[10], bday[10], bmsec[10], type[5], post[5], pre[5], promote_char[2]; char proj [MAX_IDFS_NAME], miss [MAX_IDFS_NAME], exp [MAX_IDFS_NAME], inst [MAX_IDFS_NAME], vinst [MAX_IDFS_VIRT_NAME]; if (dbKeyToStrings (E->GetSource (), proj, miss, exp, inst, vinst) != sTrue) return sFalse; if ((exe = CfgGetItem ("DataPromote", 0, proj, miss, exp, inst, vinst, NULL)) == NULL) { return sFalse; } memset (type, 0, sizeof (type)); memset (post, 0, sizeof (post)); memset (pre, 0, sizeof (pre)); switch (E->GetIDFSType ()) { case _H_FILE_ : type[0] = 'H'; break; // do the header first! case _D_FILE_ : type[0] = 'D'; break; case _I_FILE_ : type[0] = 'V'; break; case _V3_FILE_ : strcpy (type, "V.v3"); break; case _P_FILE_ : type[0] = 'P'; break; case _S_FILE_ : type[0] = 'S'; break; default : std::cerr << "no type for " << E->GetIDFSType () << std::endl; } // switch sprintf (byr, "%d", (int) E->GetBegTime ()->GetYear ()); sprintf (bday, "%d", (int) E->GetBegTime ()->GetDay ()); sprintf (bmsec, "%ld", (long) E->GetBegTime ()->GetMSec ()); pre [0] = E->GetPreProc (); post [0] = E->GetPostProc (); if (_forcePromote == sTrue) promote_char [0] = '1'; else promote_char [0] = '0'; promote_char [1] = '\0'; int ret; // One final check in case something else has promoted it! if (E->FileExists () == false) { ret = _Process (exe, BasenameOf (exe), which_server, type, proj, miss, exp, inst, vinst, byr, bday, bmsec, pre, post, "xxx", _app_name, promote_char, NULL); if (ret == 0) return sTrue; else return sFalse; } else return sTrue; } void Promote::InitializePromoStatus (int num_entries) { // If the X window is up, lets us initialize it before the promotion if (_XStatus == ON) { _PipeFD = _StartPromoStatus (); char msg [25]; sprintf (msg, "PercentSetup %3d\n", num_entries); WritePipeMessage (msg); } } void Promote::ClosePromoStatus () { if (_XStatus == ON) close (_PipeFD); } void Promote::WritePipeMessage (char *msg) { if (_PipeFD != 0) { write (_PipeFD, msg, strlen (msg)); } } SDDAS_BOOL Promote::PromoteSingleEntry (int cnt, Entry *E, int server_to_use) { char msg [256]; char *which_server; SERVER_ID serverUsed = _Server [server_to_use]->GetCurrentServer (); if (serverUsed == -1) snprintf (_error_msg, 256, "Config files do not have a server defined for %s!", E->GetVInst ()); // while the promote has not succeeded, try new servers SDDAS_BOOL success = sFalse; while ((success == sFalse) && (serverUsed != -1)) { // get our server which_server = _Server [server_to_use]->GetServerIPFromID (serverUsed); // Send a message to our pipe saying we are trying to promote memset (msg, 0, sizeof (msg)); sprintf (msg, "List + %8ld %3d P - %s from %s\n", (long) getpid (), cnt, BasenameOf (E->GetFName ()), which_server); WritePipeMessage (msg); // putting a message to the screen // Because we have interesting issues on Mac with redirection, // we only do the print if we do not have an promotion status window if (_XStatus == OFF) std::cout << "Promoting " << BasenameOf (E->GetFName ()) << " from " << which_server << "..." << std::endl; // do the actual promotion success = PromoteHDI (E, which_server); // if it didn't work, use next server if (!success) { snprintf (_error_msg, 256, "Could not promote %s from %s", BasenameOf (E->GetFName ()), which_server); _Server [server_to_use]->ServerFailure (serverUsed); serverUsed = _Server [server_to_use]->GetNextServer (serverUsed); } // let the user know what happened msg [5] = '-'; // change the + to a - if (success) { msg [20] = 'C'; // change the P to a C } else { msg [20] = 'E'; // change the P to a E } WritePipeMessage (msg); } memset (msg, 0, sizeof (msg)); strcat (msg, "PercentDec\n"); WritePipeMessage (msg); return (success); } SDDAS_BOOL Promote::PromoteMetaForSource (SDDAS_ULONG data_key, int server_to_use) { char *which_server; SERVER_ID serverUsed = _Server [server_to_use]->GetCurrentServer (); // while the promote has not succeeded, try new servers SDDAS_BOOL success = sFalse; #ifndef SwRI_DB DBPromoteStatus dbPromo = Promote::DB_ERROR; #endif char *btime = strdup (_btime->GetTimeStr (NICE_FMT)); char *etime = strdup (_etime->GetTimeStr (NICE_FMT)); while ((success == sFalse) && (serverUsed != -1)) { // get our server which_server = _Server [server_to_use]->GetServerIPFromID (serverUsed); #ifndef SwRI_DB // do the actual promotion, try for a SQL database first // Check to see if we have already tried connecting to a SQL database #ifdef ALL_DB if (dbGetDatabaseType () != SwRI) { #endif #ifndef SQLITE_DB if (_Server [server_to_use]->IsSQL (serverUsed) != CServer::OLD) { success = sTrue; dbPromo = PromoteMetaForSource_MYSQL (which_server, data_key); } #endif #ifdef ALL_DB } #endif if (dbPromo == Promote::DB_ERROR) #endif success = PromoteMetaForSource_EXTERNAL (which_server, data_key); // if it didn't work, use next server if (!success) { _Server [server_to_use]->ServerFailure (serverUsed); serverUsed = _Server [server_to_use]->GetNextServer (serverUsed); } } // free strings free (btime); free (etime); return (success); } Entry * Promote::GetEntry (unsigned int whichEntry) { assert (whichEntry < _entryList.size ()); return (_entryList [whichEntry]); }