int main (int argc, char *argv[]) { payguide::time_start=time(NULL); int Ppid=CheckIfPayguideAlreadyUp(); if (Ppid==0) { if (MakeLockFile()!=0) { std::cout << "Error while creating lock file. Can't write /tmp/payguide.lock" << std::endl; LogWrite(LOGMSG_CRITICAL, "Error while creating lock file. Can't write /tmp/payguide.lock"); } } else { char msg[512]; snprintf(msg, 511,"Error: payguide already running as process %i. Balling out.", Ppid); std::cout << msg << std::endl; LogWrite(LOGMSG_CRITICAL, msg); exit(0); } PayguideInit(); WorkInit(); bool work_init_already=true; bonbon::BonbonInit(); PerlInit(argv[0], payguide::perl_module.c_str()); payguide::data_conventor.Init(); for (EVER) { std::cout << "Running xml paycheck..." << std::endl; const char *main_config_file="/etc/payguide.cfg"; paycheck::CPaycheckCore paycheck_core; paycheck_core.LoadConfig(main_config_file); paycheck::CServer server_code; bonbon::CJobManager in_manager; std::vector <paycheck::CSocket *> connections_store; paycheck::CPaycheckThreadParam params(&in_manager, &connections_store, &paycheck_core); bonbon::CThread xml_server1(server_code, params); payguide::xml_paycheck_core=&paycheck_core; payguide::quit=false; if (!work_init_already) WorkInit(); int sleep_count=0; timespec req; req.tv_sec=0; req.tv_nsec=50000000; payguide::working=true; LogWrite(LOGMSG_SYSTEM, "Payguide server started sucessful and ready for a work"); /* Ok, lets rock */ SPay *new_pay=NULL; sem_wait(&payguide::shutdown_lock); bool working_state=payguide::working; sem_post(&payguide::shutdown_lock); printf("TESTING printf(): if you see that in log - world gone mad\n"); std::cout << "TESTING std::cout: if you see that in log - world gone mad" << std::endl; while (working_state) { sem_wait(&payguide::shutdown_lock); working_state=payguide::working; sem_post(&payguide::shutdown_lock); /* Get next pay from DB */ if (new_pay==NULL) { new_pay=paycheck_core.XMLGetNextPay(); if (new_pay==NULL) { new_pay=PCGetNextPay(); if (new_pay==NULL) { //printf("get new pay from DB\n"); if (sleep_count==1) new_pay=DBGetNextPay(); } else if (new_pay->test==NO_TEST) { LogWrite(LOGMSG_CRITICAL, "Payguide received from BIN PAYCHECK (payd) must be marked as testing. Shutdown."); char tmp[1024]; snprintf(tmp, 1024, "Pay params: id/session=[%lli] terminal=[%lli] operator=%i", new_pay->id, new_pay->terminal_id, new_pay->provider_id); LogWrite(LOGMSG_CRITICAL, tmp); exit(-1); } } else if (new_pay->test==NO_TEST) { LogWrite(LOGMSG_CRITICAL, "Payguide received from XML PAYCHECK must be marked as testing. Shutdown."); char tmp[1024]; snprintf(tmp, 1024, "Pay params: id/session=[%lli] terminal=[%lli] operator=%i", new_pay->id, new_pay->terminal_id, new_pay->provider_id); LogWrite(LOGMSG_CRITICAL, tmp); exit(-1); } } if (new_pay!=NULL) { // char logmsg[101]; snprintf(logmsg, 100,"Working on pay %lli", new_pay->id); SendLogMessages(0, logmsg); sem_wait(&payguide::free_workers_lock); //printf("lock catched\n"); /* If were is no free worker - find one or create new. */ if (payguide::free_worker==NULL) SetFreeWorker(NULL); /* If it's ok - init free worker with a new pay */ if (payguide::free_worker!=NULL) { LaunchNewPay(new_pay); new_pay=NULL; sem_post(&payguide::free_workers_lock); } /* We can't create a new worker - threads limit hit. */ else { //LogWrite(LOGMSG_WARNING, "Threads limit hit. Payguide server is overloaded."); sem_post(&payguide::free_workers_lock); if (sleep_count==20) { ReloadConfigIfImportant(); ManagerEx(); sleep_count=0; } nanosleep(&req, NULL);sleep_count++; StatisticTick(0.2); } } /* No new pays, sleep (nojobs_sleep_time) sec*/ else { /* Manage inactive workers */ if (sleep_count==20) { ReloadConfigIfImportant(); ManagerEx(); sleep_count=0; } // sleep(SLEEP_TIME); sleep_count=20; nanosleep(&req, NULL);sleep_count++; StatisticTick(0.2); } } /* Waiting for all workers, or even cancel all pays if force_quit is 1 ... */ LogWrite(LOGMSG_SYSTEM, "Waiting for all active pays to end - for safe exit - you had to specify right timeouts in your modules."); WaitForAllPaysToFinish(force_quit); /* If it's not reboot - exit */ sem_wait(&payguide::shutdown_lock); bool quit_state=payguide::quit; sem_post(&payguide::shutdown_lock); if (quit_state) { LogWrite(LOGMSG_SYSTEM, "Payguide server shutdown normally."); LogWrite(LOGMSG_SYSTEM, "Bye-bye!"); /* Stop connection with MySQL database */ DBShutdown(); /* Stop control server. */ //CtlServerStop(); mysql_library_end(); if (ossl_lock!=NULL) delete [] ossl_lock; if (pc_init_result==0) PCShutdown(); /* CleanUp will be automatically called by atexit() function */ if (RemoveLockFile()!=0) { std::cout << "Can't remove /tmp/payguide.lock. File doesn't exist or maybe you should delete it manually." << std::endl; LogWrite(LOGMSG_CRITICAL, "Can't remove /tmp/payguide.lock. File doesn't exist or maybe you should delete it manually."); } OperatorsShutdown(); EVP_cleanup(); payguide::data_conventor.Clean(); PerlShutdown(); printf("destroying queue\n"); in_manager.Destroy(); printf("done\n"); exit (0); } /* Stop connection with MySQL database */ DBShutdown(); printf("destroying queue\n"); in_manager.Destroy(); printf("done\n"); server_code.Kill(); LogWrite(LOGMSG_SYSTEM, "Rebooting..."); work_init_already=false; CleanUp(); } return 0; }
/*! Thread worker - fill the fifo with socket data */ void Stream::Work() { int waittime = 0; // lower thread priority { struct sched_param parm; int policy; if(pthread_getschedparam(pthread_self(),&policy,&parm) >= 0) { int minprio = sched_get_priority_min(policy); if(debug) post("priority was %i (min = %i)",parm.sched_priority,minprio); parm.sched_priority += THRPRIOR; if(parm.sched_priority < minprio) parm.sched_priority = minprio; pthread_setschedparam(pthread_self(),policy,&parm); } if(pthread_getschedparam(pthread_self(),&policy,&parm) >= 0) { if(debug) post("priority set to %i",parm.sched_priority); } } while(!exit) { pthread_mutex_lock(&mutex); bool wait = true; if(!hostname.length() || !mountpt.length() || port < 0) {} else if(state == ST_INIT || state == ST_RECONNECT) { // initialize! bool ok = true; try { file = Connect( hostname.c_str(),mountpt.c_str(),port); } catch(char *str) { if(state != ST_RECONNECT) post(str); ok = false; } catch(...) { post("Unknown error while connecting"); ok = false; } // initialize decoder if(ok) ok = WorkInit(); // try to fill buffer if(ok) { int i,lim = (int)(encoded.Size()*encthresh); for(i = MAXINITTRIES; i > 0 && encoded.Have() < lim; ) { int n = ReadChunk(encoded.Free(),true); if(!n) --i; } if(!i) ok = false; } if(!ok) { Reset(); if(state == ST_INIT) state = ST_IDLE; // if reconnecting keep on doing that... } else { state = ST_PROCESS; waittime = 0; } } else if(isOk()) { SOCKET fd = file; int chunk = encoded.Free(); if(chunk > encchunk) chunk = encchunk; if(chunk) { int n = ReadChunk(chunk,true); if(n == 0) { if(debug) post("error receiving data"); state = ST_WAIT; } else // reset error state state = ST_PROCESS; } if(encoded.Have() < encoded.Size()*encthresh) // immediately get the next chunk wait = false; } if(debug && encoded.Free()) { post("fifo: sz/fill = %5i/%3.0f%%",encoded.Size(),(float)encoded.Have()/encoded.Size()*100); } if(state == ST_WAIT) { if(debug) post("Wait for data"); Sleep(waitgrain); waittime += waitgrain; if(waittime > waitreconnect) { if(debug) post("do reconnect"); state = ST_RECONNECT; } wait = false; } else if(state == ST_RECONNECT) { if(debug) post("Reconnecting again"); Sleep(waitgrain); wait = false; } if(wait) pthread_cond_wait(&cond,&mutex); pthread_mutex_unlock(&mutex); } state = ST_FINISHED; }