00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "RioError.h"
00020 #include "RioServersFile.h"
00021
00022
00023 #include <http_log.h>
00024 #include <ap_compat.h>
00025
00026
00027 #include <time.h>
00028
00029
00030
00031 CRioServersFile::CRioServersFile( request_rec *Request, unsigned int LineSize )
00032 {
00033
00034 m_Request = Request;
00035 m_LineSize = LineSize;
00036 m_ServersInfo = NULL;
00037 m_TotalServers = 0;
00038 m_Initialized = false;
00039 m_BestMaxSessions = -1;
00040 m_BestMaxAverage = -1;
00041
00042
00043 srandom( time( NULL ) );
00044 }
00045
00046
00047 CRioServersFile::~CRioServersFile()
00048 {
00049
00050 DeleteServersInfo();
00051 }
00052
00053
00054 void CRioServersFile::DeleteServersInfo()
00055 {
00056 unsigned int i;
00057
00058 if( m_ServersInfo != NULL )
00059 {
00060 for( i = 0; i < m_TotalServers; i++ )
00061 {
00062
00063 if( m_ServersInfo[ i ].ServerName != NULL )
00064 free( m_ServersInfo[ i ].ServerName );
00065
00066
00067 if( m_ServersInfo[ i ].RIOServerName != NULL )
00068 free( m_ServersInfo[ i ].RIOServerName );
00069 }
00070 free( m_ServersInfo );
00071 }
00072 m_ServersInfo = NULL;
00073 m_TotalServers = 0;
00074 }
00075
00076
00077 void CRioServersFile::RemoveSpaces( char **Line )
00078 {
00079 char *End;
00080
00081 #ifdef RIO_DEBUG2
00082 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00083 "Before removing spaces: %s", *Line );
00084 #endif
00085
00086
00087 while( ( strlen( *Line ) > 1 ) &&
00088 ( ( **Line == ' ' ) || ( **Line == '\t' ) ) )
00089 ( *Line )++;
00090
00091
00092 End = &( *Line )[ strlen( *Line ) - 1 ];
00093 while( ( strlen( *Line ) > 1 ) &&
00094 ( ( *End == ' ' ) || ( *End == '\t' ) ) )
00095 {
00096 *End = 0;
00097 End--;
00098 }
00099
00100 #ifdef RIO_DEBUG2
00101 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00102 "After removing spaces: %s", *Line );
00103 #endif
00104 }
00105
00106
00107
00108 bool CRioServersFile::ProcessLine( char *FileName, char *Line,
00109 unsigned int LineNumber,
00110 RioServerInfo *ServerInfo )
00111 {
00112
00113
00114
00115
00116
00117
00118 enum ParamType
00119 {
00120 SERVERNAME,
00121 RIOSERVERNAME,
00122 MAXSESSIONS,
00123 MAXAVERAGE,
00124 NOTUSED
00125 };
00126
00127
00128 ParamType Param;
00129
00130 unsigned int LinePos;
00131
00132 unsigned int ParamPos;
00133
00134 unsigned int LineSize;
00135
00136
00137 Param = SERVERNAME;
00138 ServerInfo->ServerName = NULL;
00139 ServerInfo->RIOServerName = NULL;
00140 ServerInfo->MaxSessions = 0;
00141 ServerInfo->MaxAverage = 0;
00142 LinePos = 0;
00143 LineSize = strlen( Line );
00144
00145
00146 while( LinePos < LineSize )
00147 {
00148
00149 while( ( LinePos < LineSize ) &&
00150 ( ( Line[ LinePos ] == ' ' ) || ( Line[ LinePos ] == '\t' ) ||
00151 ( Line[ LinePos ] == '\n' ) ) )
00152 LinePos++;
00153 ParamPos = LinePos;
00154
00155 while( ( LinePos < LineSize ) && ( Line[ LinePos ] != ' ' ) &&
00156 ( Line[ LinePos ] != '\n' ) && ( Line[ LinePos ] != '\t' ) )
00157 LinePos++;
00158
00159 if( ParamPos < LineSize )
00160 {
00161
00162 Line[ LinePos ] = 0;
00163
00164
00165 LinePos++;
00166
00167 #ifdef RIO_DEBUG2
00168 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00169 "File %s(%u:%u): processing parameter %s",
00170 FileName, LineNumber, ParamPos + 1, &Line[ ParamPos ]
00171 );
00172 #endif
00173
00174
00175 switch( Param )
00176 {
00177 case SERVERNAME:
00178 ServerInfo->ServerName = strdup( &Line[ ParamPos ] );
00179 if( ServerInfo->ServerName == NULL )
00180 {
00181 m_SystemStatus = ENOMEM;
00182
00183 #ifdef RIO_DEBUG2
00184 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00185 "File %s(%u:%u): error %u (%s) "
00186 "allocating ServerName", FileName,
00187 LineNumber, ParamPos + 1, m_SystemStatus,
00188 strerror( m_SystemStatus ) );
00189 #endif
00190
00191 return false;
00192 }
00193 Param = RIOSERVERNAME;
00194 break;
00195
00196
00197 case RIOSERVERNAME:
00198 ServerInfo->RIOServerName = strdup( &Line[ ParamPos ] );
00199 if( ServerInfo->RIOServerName == NULL )
00200 {
00201 m_SystemStatus = ENOMEM;
00202
00203 #ifdef RIO_DEBUG2
00204 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00205 "File %s(%u:%u): error %u (%s) "
00206 "allocating RIOServerName", FileName,
00207 LineNumber, ParamPos + 1, m_SystemStatus,
00208 strerror( m_SystemStatus ) );
00209 #endif
00210
00211 return false;
00212 }
00213 Param = MAXSESSIONS;
00214 break;
00215 case MAXSESSIONS:
00216 errno = 0;
00217 ServerInfo->MaxSessions = strtod( &Line[ ParamPos ], NULL );
00218 if( errno != 0 )
00219 {
00220 m_SystemStatus = errno;
00221
00222 #ifdef RIO_DEBUG2
00223 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00224 "File %s(%u:%u): error %u (%s) "
00225 "converting MaxSessions", FileName,
00226 LineNumber, ParamPos + 1, m_SystemStatus,
00227 strerror( m_SystemStatus ) );
00228 #endif
00229
00230 return false;
00231 }
00232 Param = MAXAVERAGE;
00233 break;
00234 case MAXAVERAGE:
00235 errno = 0;
00236 ServerInfo->MaxAverage = strtod( &Line[ ParamPos ], NULL );
00237 if( errno != 0 )
00238 {
00239 m_SystemStatus = errno;
00240
00241 #ifdef RIO_DEBUG2
00242 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00243 "File %s(%u:%u): error %u (%s) "
00244 "converting MaxAverage", FileName,
00245 LineNumber, ParamPos + 1, m_SystemStatus,
00246 strerror( m_SystemStatus ) );
00247 #endif
00248
00249 return false;
00250 }
00251 Param = NOTUSED;
00252 break;
00253 default:
00254 #ifdef RIO_DEBUG2
00255 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00256 "File %s(%u:%u): discarded additional "
00257 "parameter %s", FileName, LineNumber,
00258 ParamPos + 1, &Line[ ParamPos ] );
00259 #endif
00260 break;
00261 }
00262 }
00263 }
00264
00265
00266 if( Param != NOTUSED )
00267 {
00268 m_RioStatus = ERROR_RIOMODULE + ERROR_INVALID_PARAM;
00269
00270 #ifdef RIO_DEBUG2
00271 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00272 "File %s(%u) not enoungh params: error %u (%s) ",
00273 FileName, LineNumber, m_RioStatus,
00274 GetErrorDescription( m_RioStatus ).c_str() );
00275 #endif
00276
00277
00278
00279 if( ServerInfo->ServerName != NULL );
00280 free( ServerInfo->ServerName );
00281
00282
00283 if( ServerInfo->RIOServerName != NULL );
00284 free( ServerInfo->RIOServerName );
00285
00286
00287 ServerInfo->ServerName = NULL;
00288 ServerInfo->RIOServerName = NULL;
00289 ServerInfo->MaxSessions = 0;
00290 ServerInfo->MaxAverage = 0;
00291
00292 return false;
00293 }
00294 else
00295 return true;
00296 }
00297
00298
00299
00300 bool CRioServersFile::Open( char *FileName )
00301 {
00302
00303 apr_file_t *fp = NULL;
00304
00305 apr_status_t rv;
00306
00307 char *Line;
00308
00309
00310 unsigned int LineNumber;
00311
00312 RioServerInfo *NewServersInfo;
00313
00314
00315 DeleteServersInfo();
00316
00317
00318 m_Initialized = false;
00319
00320
00321 Line = ( char * ) malloc( sizeof( char ) * ( m_LineSize + 1 ) );
00322 if( Line == NULL )
00323 {
00324 m_SystemStatus = ENOMEM;
00325
00326 #ifdef RIO_DEBUG2
00327 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00328 "Error %u (%s) allocating Line buffer for file %s",
00329 m_SystemStatus, strerror( m_SystemStatus ), FileName );
00330 #endif
00331
00332 return false;
00333 }
00334
00335
00336 rv = apr_file_open( &fp, FileName, APR_READ, APR_OS_DEFAULT,
00337 m_Request->pool );
00338 if( rv != APR_SUCCESS )
00339 {
00340 m_ApacheStatus = rv;
00341
00342 #ifdef RIO_DEBUG2
00343 ap_log_rerror( APLOG_MARK, APLOG_ERR, m_ApacheStatus, m_Request,
00344 "Unable to open module servers file %s", FileName );
00345 #endif
00346
00347 return false;
00348 }
00349
00350
00351 m_ServersInfo = NULL;
00352 m_TotalServers = 0;
00353 LineNumber = 1;
00354 m_BestMaxSessions = -1;
00355 m_BestMaxAverage = -1;
00356
00357
00358 while( ( rv = apr_file_gets( Line, m_LineSize, fp ) ) != APR_EOF )
00359 {
00360
00361 if( rv != APR_SUCCESS )
00362 {
00363 m_ApacheStatus = rv;
00364
00365 rv = apr_file_close( fp );
00366 if( rv != APR_SUCCESS )
00367 m_ApacheStatus = rv;
00368
00369 #ifdef RIO_DEBUG2
00370 ap_log_rerror( APLOG_MARK, APLOG_ERR, m_ApacheStatus, m_Request,
00371 "Unable to read module servers file %s", FileName );
00372 #endif
00373
00374 return rv;
00375 }
00376
00377
00378 RemoveSpaces( &Line );
00379
00380
00381
00382 if( ( strlen( Line ) > 0 ) && ( Line[ 0 ] != '#' ) )
00383 {
00384
00385 NewServersInfo = ( RioServerInfo * ) realloc( m_ServersInfo,
00386 sizeof( RioServerInfo )
00387 * ( m_TotalServers + 1 ) );
00388 if( NewServersInfo == NULL )
00389 {
00390 m_ApacheStatus = apr_file_close( fp );
00391 m_SystemStatus = ENOMEM;
00392
00393 #ifdef RIO_DEBUG2
00394 ap_log_rerror( APLOG_MARK, APLOG_ERR, m_ApacheStatus, m_Request,
00395 "Error %u (%s) processing line %s of file %s",
00396 m_SystemStatus, strerror( m_SystemStatus ),
00397 Line, FileName );
00398 #endif
00399
00400 return false;
00401 }
00402 m_ServersInfo = NewServersInfo;
00403
00404 m_TotalServers++;
00405
00406
00407 if( !ProcessLine( FileName, Line, LineNumber,
00408 &m_ServersInfo[ m_TotalServers - 1 ] ) )
00409 {
00410 m_ApacheStatus = apr_file_close( fp );
00411
00412 #ifdef RIO_DEBUG2
00413 ap_log_rerror( APLOG_MARK, APLOG_ERR, m_ApacheStatus, m_Request,
00414 "Error processing line %s of file %s", Line,
00415 FileName );
00416 #endif
00417
00418 return false;
00419 }
00420
00421 #ifdef RIO_DEBUG2
00422 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00423 "Line info: ServerName = %s, RIOServerName = %s "
00424 "MaxSessions = %f, MaxAverage = %f",
00425 m_ServersInfo[ m_TotalServers - 1 ].ServerName,
00426 m_ServersInfo[ m_TotalServers - 1 ].RIOServerName,
00427 m_ServersInfo[ m_TotalServers - 1 ].MaxSessions,
00428 m_ServersInfo[ m_TotalServers - 1 ].MaxAverage );
00429
00430 #endif
00431
00432 if( ( m_BestMaxSessions == -1 ) ||
00433 ( ( m_ServersInfo[ m_TotalServers - 1 ].MaxSessions <
00434 m_ServersInfo[ m_BestMaxSessions ].MaxSessions ) ) )
00435 m_BestMaxSessions = m_TotalServers - 1;
00436
00437
00438 if( ( m_BestMaxAverage == -1 ) ||
00439 ( ( m_ServersInfo[ m_TotalServers - 1 ].MaxAverage <
00440 m_ServersInfo[ m_BestMaxAverage ].MaxAverage ) ) )
00441 m_BestMaxAverage = m_TotalServers - 1;
00442 }
00443
00444 LineNumber++;
00445 }
00446
00447
00448 rv = apr_file_close( fp );
00449 if( rv )
00450 {
00451 m_ApacheStatus = rv;
00452
00453 #ifdef RIO_DEBUG2
00454 ap_log_rerror( APLOG_MARK, APLOG_ERR, m_ApacheStatus, m_Request,
00455 "Unable to close module servers file %s", FileName );
00456 #endif
00457
00458 return false;
00459 }
00460
00461
00462 if( m_TotalServers == 0 )
00463 {
00464 m_RioStatus = ERROR_RIOMODULE + ERROR_SERVER_NOT_DEFINED;
00465
00466 #ifdef RIO_DEBUG2
00467 ap_log_rerror( APLOG_MARK, APLOG_ERR, m_ApacheStatus, m_Request,
00468 "Unable to close module servers file %s", FileName );
00469 #endif
00470
00471 return false;
00472 }
00473 else
00474 {
00475
00476 m_Initialized = true;
00477
00478 return true;
00479 }
00480 }
00481
00482
00483
00484 bool CRioServersFile::ChooseServer( ServerSelectionType SelectionType,
00485 RioServerInfo *ServerInfo )
00486 {
00487
00488 unsigned int ChoosenServer;
00489
00490
00491
00492 ServerInfo->ServerName = NULL;
00493 ServerInfo->RIOServerName = NULL;
00494 ServerInfo->MaxSessions = 0;
00495 ServerInfo->MaxAverage = 0;
00496
00497
00498 if( !m_Initialized )
00499 {
00500 m_RioStatus = ERROR_RIOMODULE + ERROR_NOT_INITIALIZED;
00501 #ifdef RIO_DEBUG2
00502 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00503 "Error %u (%s): no file was opened", m_RioStatus,
00504 GetErrorDescription( m_RioStatus ).c_str() );
00505 #endif
00506
00507 return false;
00508 }
00509
00510
00511
00512 switch( SelectionType )
00513 {
00514 case RIO_SELECTION_RANDOM:
00515
00516 ChoosenServer = random() % m_TotalServers;
00517 break;
00518
00519 case RIO_SELECTION_L_LOAD:
00520 ChoosenServer = m_BestMaxSessions;
00521 break;
00522
00523 case RIO_SELECTION_MV_AVG:
00524 ChoosenServer = m_BestMaxAverage;
00525 break;
00526 case RIO_SELECTION_FIRST:
00527 ChoosenServer = 0;
00528 break;
00529
00530 default:
00531 m_RioStatus = ERROR_RIOMODULE + ERROR_INVALID_PARAM;
00532
00533 #ifdef RIO_DEBUG2
00534 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, m_Request,
00535 "Error %u (%s): invalid selection type %u",
00536 m_RioStatus,
00537 GetErrorDescription( m_RioStatus ).c_str(),
00538 SelectionType );
00539 #endif
00540
00541 return false;
00542 break;
00543 }
00544
00545
00546 ServerInfo->ServerName = m_ServersInfo[ ChoosenServer ].ServerName;
00547 ServerInfo->RIOServerName = m_ServersInfo[ ChoosenServer ].RIOServerName;
00548 ServerInfo->MaxSessions = m_ServersInfo[ ChoosenServer ].MaxSessions;
00549 ServerInfo->MaxAverage = m_ServersInfo[ ChoosenServer ].MaxAverage;
00550
00551 return true;
00552 }
00553
00554
00555
00556 void CRioServersFile::GetErrors( apr_status_t *ApacheStatus, int *SystemStatus,
00557 RioResult *RioStatus )
00558 {
00559 *ApacheStatus = m_ApacheStatus;
00560 *SystemStatus = m_SystemStatus;
00561 *RioStatus = m_RioStatus;
00562 }
00563
00564