00001
00002
00003
00004
00005
00006
00007 #include <iostream>
00008 #include <string>
00009 #include <unistd.h>
00010 #include <vector>
00011 #include <math.h>
00012 #include "SMTPConnectionPool.h"
00013
00014 using namespace std;
00015
00016 namespace SmtpThread
00017 {
00018
00019
00020
00021
00022 SMTPConnectionPool::SMTPConnectionPool()
00023 {
00024 init();
00025 }
00026
00027
00028
00029
00030
00031
00032 SMTPConnectionPool::~SMTPConnectionPool()
00033 {
00034 if( _optimzePoolSize )
00035 {
00036 cout << "last pool-size: " << pool.size() << endl;
00037 cout << "avg. number of parallel connections: " << _avgNumOfTries << " +-" << _rms << endl;;
00038 }
00039 close();
00040 }
00041
00042
00043
00044
00045
00046
00047
00048 void SMTPConnectionPool::init()
00049 {
00050
00051 _minPoolSize = 1;
00052 _maxPoolSize = 100;
00053 _optimzePoolSize = true;
00054
00055 _statsTotalMails = 0;
00056 _statsTotalErrors = 0;
00057 _statsMailsAfterOpt = 0;
00058 _avgNumOfTries = 0;
00059 _rms = 0;
00060
00061 _myHostname = "localhost";
00062 _smtpHost = "127.0.0.1";
00063 _smtpPort = 25;
00064
00065 setPoolSize( 1 );
00066
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076 void SMTPConnectionPool::close()
00077 {
00078
00079 for( unsigned long idx = 0; idx < pool.size(); idx++ )
00080 {
00081
00082 pool[ idx ]->Stop();
00083 }
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 int SMTPConnectionPool::sendMail( string& from, string& to, string& msg )
00096 {
00097
00098 bool found = false;
00099
00100
00101 unsigned long conNumber = 0;
00102
00103
00104 int numCheck = 0;
00105
00106
00107 int maxTries = 100;
00108
00109
00110 ThreadedSMTPConnection *smtp;
00111
00112
00113 _statsTotalMails ++;
00114 _statsMailsAfterOpt ++;
00115
00116
00117 while( ! found )
00118 {
00119
00120
00121
00122 smtp = pool[ conNumber++ ];
00123
00124
00125 if( smtp->isReady() )
00126 {
00127
00128
00129 found = true;
00130
00131
00132 smtp->sendMail( from, to, msg );
00133
00134
00135
00136
00137 if( _optimzePoolSize )
00138 {
00139
00140
00141 double d = _avgNumOfTries - 1.0 * ( numCheck +1 ) * ( conNumber );
00142 double dSquare = d * d;
00143 double curremtRMS = sqrt( dSquare );
00144
00145
00146 if( (_statsTotalMails - _statsTotalErrors) > 0 )
00147 {
00148
00149
00150
00151
00152 _avgNumOfTries = (
00153 ( 1.0 * (
00154 ( _statsTotalMails - _statsTotalErrors -1 ) * _avgNumOfTries
00155 +
00156 ( numCheck +1 ) * ( conNumber ) )
00157 )
00158 /
00159 (
00160 1.0 * ( _statsTotalMails - _statsTotalErrors )
00161 )
00162 );
00163
00164
00165
00166 _rms = (
00167 ( 1.0 * (
00168 ( _statsTotalMails - _statsTotalErrors -1 ) * _rms
00169 +
00170 curremtRMS )
00171 )
00172 /
00173 (
00174 1.0 * ( _statsTotalMails - _statsTotalErrors )
00175 )
00176 );
00177
00178
00179 }
00180
00181
00182
00183
00184 if( _statsMailsAfterOpt > pool.size() )
00185 {
00186
00187 unsigned long optPoolSize = (unsigned long) ceil( _avgNumOfTries + 2.0 * _rms );
00188
00189
00190 if( ( pool.size() < optPoolSize ) || ( pool.size() > optPoolSize +1 ) )
00191 {
00192
00193 if( ( optPoolSize < _maxPoolSize ) && ( optPoolSize > _minPoolSize ) )
00194 {
00195
00196 setPoolSize( optPoolSize );
00197
00198
00199 _statsMailsAfterOpt = 0;
00200 }
00201 }
00202 }
00203 }
00204
00205
00206 return 0;
00207 }
00208
00209
00210
00211 if( conNumber >= pool.size() )
00212 {;
00213
00214
00215 conNumber = 0;
00216
00217
00218 numCheck++;
00219
00220
00221
00222
00223
00224 usleep( 250000 );
00225
00226
00227 if( numCheck > maxTries )
00228 {
00229
00230
00231 _statsTotalErrors ++;
00232
00233
00234 return -1;
00235
00236 }
00237 }
00238 }
00239
00240 return -1;
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 void SMTPConnectionPool::setPoolSize( unsigned long poolSize )
00256 {
00257
00258 cout << "adjusting pool-size to " << poolSize << endl;
00259
00260
00261 unsigned long pSize = pool.size();
00262
00263
00264 if( poolSize > pSize )
00265 {
00266
00267
00268 while( pool.size() < poolSize )
00269 {
00270
00271 ThreadedSMTPConnection* con = new ThreadedSMTPConnection();
00272
00273
00274 con->setSMTPHost( _smtpHost );
00275 con->setSMTPPort( _smtpPort );
00276 con->setMyHostname( _myHostname );
00277
00278
00279
00280
00281
00282 con->Start( (void*) 0 );
00283
00284
00285 pool.push_back( con );
00286 }
00287 }
00288
00289
00290 if( poolSize < pSize )
00291 {
00292
00293
00294 while( pool.size() > poolSize )
00295 {
00296
00297
00298
00299
00300
00301
00302 pool.pop_back();
00303
00304 }
00305 }
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315 unsigned long SMTPConnectionPool::getPoolSize()
00316 {
00317
00318 return pool.size();
00319 }
00320
00321
00322
00323 void SMTPConnectionPool::setSMTPHost( string host )
00324 {
00325 _smtpHost = host;
00326
00327 ThreadedSMTPConnection* smtp;
00328 for( unsigned long idx = 0; idx < pool.size(); idx++ )
00329 {
00330 smtp = pool[ idx ];
00331 smtp->setSMTPHost( host );
00332 }
00333 }
00334
00335
00336
00337 void SMTPConnectionPool::setSMTPPort( int port )
00338 {
00339 _smtpPort = port;
00340
00341 ThreadedSMTPConnection* smtp;
00342 for( unsigned long idx = 0; idx < pool.size(); idx++ )
00343 {
00344 smtp = pool[ idx ];
00345 smtp->setSMTPPort( port );
00346 }
00347 }
00348
00349
00350
00351 void SMTPConnectionPool::setMyHostname( string myname )
00352 {
00353 _myHostname = myname;
00354
00355 ThreadedSMTPConnection* smtp;
00356 for( unsigned long idx = 0; idx < pool.size(); idx++ )
00357 {
00358 smtp = pool[ idx ];
00359 smtp->setMyHostname( myname );
00360 }
00361 }
00362
00363
00364
00365 void SMTPConnectionPool::setOptimizePool( bool opt )
00366 {
00367 _optimzePoolSize = opt;
00368 }
00369
00370
00371
00372 void SMTPConnectionPool::setMinPoolSize( long minimum )
00373 {
00374 _minPoolSize = minimum;
00375
00376
00377 if( pool.size() < _minPoolSize )
00378 {
00379 setPoolSize( _minPoolSize );
00380 }
00381 }
00382
00383
00384
00385 void SMTPConnectionPool::setMaxPoolSize( long maximum )
00386 {
00387 _maxPoolSize = maximum;
00388
00389
00390 if( pool.size() > _maxPoolSize )
00391 {
00392 setPoolSize( _maxPoolSize );
00393 }
00394 }
00395
00396 }