@@ -119,6 +119,88 @@ static int error_message(request_rec *r, const char *format, ...)
119119 return OK ;
120120}
121121
122+ static apr_pool_t * create_buffer_pool (request_rec * r )
123+ {
124+ apr_allocator_t * allocator ;
125+ apr_pool_t * pool ;
126+
127+ if (apr_allocator_create (& allocator ) != APR_SUCCESS ) {
128+ ap_log_rerror (APLOG_MARK , APLOG_WARNING , 0 , r ,
129+ "Failed to create buffer allocator" );
130+ }
131+
132+ apr_allocator_max_free_set (allocator , 1 );
133+
134+ if (apr_pool_create_ex (& pool , NULL , NULL , allocator ) != APR_SUCCESS ) {
135+ ap_log_rerror (APLOG_MARK , APLOG_WARNING , 0 , r ,
136+ "Failed to create buffer pool" );
137+ apr_allocator_destroy (allocator );
138+ }
139+
140+ apr_allocator_owner_set (allocator , pool );
141+
142+ return pool ;
143+ }
144+
145+ static void destroy_buffer_pool (apr_pool_t * pool )
146+ {
147+ apr_pool_destroy (pool );
148+ }
149+
150+ static int get_global_lock (request_rec * r , apr_global_mutex_t * mutex )
151+ {
152+ apr_status_t rs ;
153+ int camped ;
154+
155+ for (camped = 0 ; camped < MAXCAMP ; camped ++ ) {
156+ rs = apr_global_mutex_trylock (mutex );
157+
158+ if (APR_STATUS_IS_EBUSY (rs )) {
159+ apr_sleep (CAMPOUT );
160+ } else if (rs == APR_SUCCESS ) {
161+ return 1 ;
162+ } else if (APR_STATUS_IS_ENOTIMPL (rs )) {
163+ /* If it's not implemented, just hang in the mutex. */
164+ rs = apr_global_mutex_lock (mutex );
165+
166+ if (rs == APR_SUCCESS ) {
167+ return 1 ;
168+ } else {
169+ ap_log_rerror (APLOG_MARK , APLOG_WARNING , 0 , r , "Could not get hardlock" );
170+ return 0 ;
171+ }
172+ } else {
173+ ap_log_rerror (APLOG_MARK , APLOG_NOTICE , 0 , r , "Unknown return status from trylock" );
174+ return 0 ;
175+ }
176+ }
177+
178+ ap_log_rerror (APLOG_MARK , APLOG_DEBUG , 0 , r , "Timedout trylock" );
179+ return 0 ;
180+ }
181+
182+ static int get_stats_copy (request_rec * r , tile_server_conf * scfg , stats_data * * stats_copy )
183+ {
184+ stats_data * stats ;
185+ unsigned long sizeof_config_elements ;
186+
187+ if (get_global_lock (r , stats_mutex ) != 0 ) {
188+ // Copy over the global counter variable into
189+ // local variables, that we can immediately
190+ // release the lock again
191+ sizeof_config_elements = sizeof (apr_uint64_t ) * scfg -> configs -> nelts ;
192+ stats = (stats_data * )apr_shm_baseaddr_get (stats_shm );
193+ * stats_copy = (stats_data * )apr_pmemdup (r -> pool , stats , sizeof (stats_data ));
194+ (* stats_copy )-> noResp200Layer = (apr_uint64_t * )apr_pmemdup (r -> pool , stats -> noResp200Layer , sizeof_config_elements );
195+ (* stats_copy )-> noResp404Layer = (apr_uint64_t * )apr_pmemdup (r -> pool , stats -> noResp404Layer , sizeof_config_elements );
196+ apr_global_mutex_unlock (stats_mutex );
197+ } else {
198+ return error_message (r , "Failed to acquire lock, can't copy stats" );
199+ }
200+
201+ return OK ;
202+ }
203+
122204static int socket_init (request_rec * r )
123205{
124206 struct addrinfo hints ;
@@ -556,38 +638,6 @@ static void add_expiry(request_rec *r, struct protocol *cmd)
556638 apr_table_setn (t , "Expires" , timestr );
557639}
558640
559- static int get_global_lock (request_rec * r , apr_global_mutex_t * mutex )
560- {
561- apr_status_t rs ;
562- int camped ;
563-
564- for (camped = 0 ; camped < MAXCAMP ; camped ++ ) {
565- rs = apr_global_mutex_trylock (mutex );
566-
567- if (APR_STATUS_IS_EBUSY (rs )) {
568- apr_sleep (CAMPOUT );
569- } else if (rs == APR_SUCCESS ) {
570- return 1 ;
571- } else if (APR_STATUS_IS_ENOTIMPL (rs )) {
572- /* If it's not implemented, just hang in the mutex. */
573- rs = apr_global_mutex_lock (mutex );
574-
575- if (rs == APR_SUCCESS ) {
576- return 1 ;
577- } else {
578- ap_log_rerror (APLOG_MARK , APLOG_WARNING , 0 , r , "Could not get hardlock" );
579- return 0 ;
580- }
581- } else {
582- ap_log_rerror (APLOG_MARK , APLOG_NOTICE , 0 , r , "Unknown return status from trylock" );
583- return 0 ;
584- }
585- }
586-
587- ap_log_rerror (APLOG_MARK , APLOG_DEBUG , 0 , r , "Timedout trylock" );
588- return 0 ;
589- }
590-
591641static int incRespCounter (int resp , request_rec * r , struct protocol * cmd , int layerNumber )
592642{
593643 stats_data * stats ;
@@ -1301,7 +1351,8 @@ static int tile_handler_json(request_rec *r)
13011351 }
13021352 }
13031353
1304- buf = (char * )apr_pcalloc (r -> pool , 8 * 1024 );
1354+ apr_pool_t * pool = create_buffer_pool (r );
1355+ buf = (char * )apr_pcalloc (pool , 8 * 1024 );
13051356
13061357 snprintf (buf , 8 * 1024 ,
13071358 "{\n"
@@ -1347,28 +1398,7 @@ static int tile_handler_json(request_rec *r)
13471398 apr_rfc822_date (timestr , (apr_time_from_sec (maxAge ) + r -> request_time ));
13481399 apr_table_setn (t , "Expires" , timestr );
13491400 ap_rwrite (buf , len , r );
1350-
1351- return OK ;
1352- }
1353-
1354- static int _get_stats_copy (request_rec * r , tile_server_conf * scfg , stats_data * * stats_copy )
1355- {
1356- stats_data * stats ;
1357- unsigned long sizeof_config_elements ;
1358-
1359- if (get_global_lock (r , stats_mutex ) != 0 ) {
1360- // Copy over the global counter variable into
1361- // local variables, that we can immediately
1362- // release the lock again
1363- sizeof_config_elements = sizeof (apr_uint64_t ) * scfg -> configs -> nelts ;
1364- stats = (stats_data * )apr_shm_baseaddr_get (stats_shm );
1365- * stats_copy = (stats_data * )apr_pmemdup (r -> pool , stats , sizeof (stats_data ));
1366- (* stats_copy )-> noResp200Layer = (apr_uint64_t * )apr_pmemdup (r -> pool , stats -> noResp200Layer , sizeof_config_elements );
1367- (* stats_copy )-> noResp404Layer = (apr_uint64_t * )apr_pmemdup (r -> pool , stats -> noResp404Layer , sizeof_config_elements );
1368- apr_global_mutex_unlock (stats_mutex );
1369- } else {
1370- return error_message (r , "Failed to acquire lock, can't copy stats" );
1371- }
1401+ destroy_buffer_pool (pool );
13721402
13731403 return OK ;
13741404}
@@ -1391,7 +1421,7 @@ static int tile_handler_mod_stats(request_rec *r)
13911421 return error_message (r , "Stats are not enabled for this server" );
13921422 }
13931423
1394- _get_stats_copy (r , scfg , & local_stats );
1424+ get_stats_copy (r , scfg , & local_stats );
13951425
13961426 if (!local_stats ) {
13971427 return OK ;
@@ -1449,7 +1479,7 @@ static int tile_handler_metrics(request_rec *r)
14491479 return error_message (r , "Stats are not enabled for this server" );
14501480 }
14511481
1452- _get_stats_copy (r , scfg , & local_stats );
1482+ get_stats_copy (r , scfg , & local_stats );
14531483
14541484 if (!local_stats ) {
14551485 return OK ;
@@ -1556,7 +1586,8 @@ static int tile_handler_serve(request_rec *r)
15561586 gettimeofday (& start , NULL );
15571587
15581588 // FIXME: It is a waste to do the malloc + read if we are fulfilling a HEAD or returning a 304.
1559- buf = (char * )apr_pcalloc (r -> pool , tile_max );
1589+ apr_pool_t * pool = create_buffer_pool (r );
1590+ buf = (char * )apr_pcalloc (pool , tile_max );
15601591
15611592 if (!buf ) {
15621593 if (!incRespCounter (HTTP_INTERNAL_SERVER_ERROR , r , cmd , rdata -> layerNumber )) {
@@ -1607,6 +1638,8 @@ static int tile_handler_serve(request_rec *r)
16071638 incTimingCounter ((end .tv_sec * 1000000 + end .tv_usec ) - (start .tv_sec * 1000000 + start .tv_usec ), cmd -> z , r );
16081639
16091640 if ((errstatus = ap_meets_conditions (r )) != OK ) {
1641+ destroy_buffer_pool (pool );
1642+
16101643 if (!incRespCounter (errstatus , r , cmd , rdata -> layerNumber )) {
16111644 ap_log_rerror (APLOG_MARK , APLOG_WARNING , 0 , r ,
16121645 "Failed to increase response stats counter" );
@@ -1615,6 +1648,7 @@ static int tile_handler_serve(request_rec *r)
16151648 return errstatus ;
16161649 } else {
16171650 ap_rwrite (buf , len , r );
1651+ destroy_buffer_pool (pool );
16181652
16191653 if (!incRespCounter (errstatus , r , cmd , rdata -> layerNumber )) {
16201654 ap_log_rerror (APLOG_MARK , APLOG_WARNING , 0 , r ,
@@ -1625,6 +1659,7 @@ static int tile_handler_serve(request_rec *r)
16251659 }
16261660 }
16271661
1662+ destroy_buffer_pool (pool );
16281663 ap_log_rerror (APLOG_MARK , APLOG_WARNING , 0 , r , "Failed to read tile from disk: %s" , err_msg );
16291664
16301665 if (!incRespCounter (HTTP_NOT_FOUND , r , cmd , rdata -> layerNumber )) {
0 commit comments