1515typedef  struct  {
1616    MMDB_s                    mmdb ;
1717    MMDB_lookup_result_s      result ;
18+     time_t                    last_check ;
19+     time_t                    last_change ;
20+     time_t                    check_interval ;
1821#if  (NGX_HAVE_INET6 )
1922    uint8_t                   address [16 ];
2023#else 
@@ -41,6 +44,8 @@ typedef struct {
4144} ngx_http_geoip2_metadata_t ;
4245
4346
47+ static  ngx_int_t  ngx_http_geoip2_reload (ngx_http_geoip2_db_t  * database ,
48+     ngx_log_t  * log );
4449static  ngx_int_t  ngx_http_geoip2_variable (ngx_http_request_t  * r ,
4550    ngx_http_variable_value_t  * v , uintptr_t  data );
4651static  ngx_int_t  ngx_http_geoip2_metadata (ngx_http_request_t  * r ,
@@ -49,6 +54,8 @@ static void *ngx_http_geoip2_create_conf(ngx_conf_t *cf);
4954static  char  * ngx_http_geoip2_init_conf (ngx_conf_t  * cf , void  * conf );
5055static  char  * ngx_http_geoip2 (ngx_conf_t  * cf , ngx_command_t  * cmd ,
5156    void  * conf );
57+ static  char  * ngx_http_geoip2_parse_config (ngx_conf_t  * cf , ngx_command_t  * dummy ,
58+     void  * conf );
5259static  char  * ngx_http_geoip2_add_variable (ngx_conf_t  * cf , ngx_command_t  * dummy ,
5360    void  * conf );
5461static  char  * ngx_http_geoip2_add_variable_geodata (ngx_conf_t  * cf ,
@@ -129,6 +136,41 @@ ngx_module_t  ngx_http_geoip2_module = {
129136};
130137
131138
139+ static  ngx_int_t 
140+ ngx_http_geoip2_reload (ngx_http_geoip2_db_t  * database , ngx_log_t  * log )
141+ {
142+     struct  stat   attr ;
143+     MMDB_s        tmpdb ;
144+     int           status ;
145+ 
146+     if  (database -> check_interval  >  0 
147+             &&  database -> last_check  +  database -> check_interval  <= ngx_time ()) {
148+         database -> last_check  =  ngx_time ();
149+         stat (database -> mmdb .filename , & attr );
150+ 
151+         if  (attr .st_mtime  >  database -> last_change ) {
152+             status  =  MMDB_open (database -> mmdb .filename , MMDB_MODE_MMAP , & tmpdb );
153+ 
154+             if  (status  !=  MMDB_SUCCESS ) {
155+                 ngx_log_error (NGX_LOG_ERR , log , 0 ,
156+                                 "MMDB_open(\"%s\") failed to reload - %s" ,
157+                                 database -> mmdb .filename , MMDB_strerror (status ));
158+                 return  NGX_ERROR ;
159+             }
160+ 
161+             database -> last_change  =  attr .st_mtime ;
162+             MMDB_close (& database -> mmdb );
163+             database -> mmdb  =  tmpdb ;
164+ 
165+             ngx_log_error (NGX_LOG_INFO , log , 0 , "Reload MMDB \"%s\"" ,
166+                                 tmpdb .filename );
167+         }
168+     }
169+ 
170+     return  NGX_OK ;
171+ }
172+ 
173+ 
132174static  ngx_int_t 
133175ngx_http_geoip2_variable (ngx_http_request_t  * r , ngx_http_variable_value_t  * v ,
134176    uintptr_t  data )
@@ -149,6 +191,8 @@ ngx_http_geoip2_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
149191    unsigned long  address ;
150192#endif 
151193
194+     ngx_http_geoip2_reload (database , r -> connection -> log );
195+ 
152196    if  (geoip2 -> source .value .len  >  0 ) {
153197         if  (ngx_http_complex_value (r , & geoip2 -> source , & val ) !=  NGX_OK ) {
154198             goto not_found ;
@@ -294,8 +338,14 @@ ngx_http_geoip2_metadata(ngx_http_request_t *r, ngx_http_variable_value_t *v,
294338    ngx_http_geoip2_db_t         * database  =  metadata -> database ;
295339    u_char                       * p ;
296340
341+     ngx_http_geoip2_reload (database , r -> connection -> log );
342+ 
297343    if  (ngx_strncmp (metadata -> metavalue .data , "build_epoch" , 11 ) ==  0 ) {
298344        FORMAT ("%uL" , database -> mmdb .metadata .build_epoch );
345+     } else  if  (ngx_strncmp (metadata -> metavalue .data , "last_check" , 10 ) ==  0 ) {
346+         FORMAT ("%T" , database -> last_check );
347+     } else  if  (ngx_strncmp (metadata -> metavalue .data , "last_change" , 11 ) ==  0 ) {
348+         FORMAT ("%T" , database -> last_change );
299349    } else  {
300350        v -> not_found  =  1 ;
301351        return  NGX_OK ;
@@ -376,6 +426,8 @@ ngx_http_geoip2(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
376426        return  NGX_CONF_ERROR ;
377427    }
378428
429+     database -> last_check  =  database -> last_change  =  ngx_time ();
430+ 
379431    status  =  MMDB_open ((char  * ) value [1 ].data , MMDB_MODE_MMAP , & database -> mmdb );
380432
381433    if  (status  !=  MMDB_SUCCESS ) {
@@ -392,7 +444,7 @@ ngx_http_geoip2(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
392444#endif 
393445
394446    save  =  * cf ;
395-     cf -> handler  =  ngx_http_geoip2_add_variable ;
447+     cf -> handler  =  ngx_http_geoip2_parse_config ;
396448    cf -> handler_conf  =  (void  * ) database ;
397449
398450    rv  =  ngx_conf_parse (cf , NULL );
@@ -401,6 +453,48 @@ ngx_http_geoip2(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
401453}
402454
403455
456+ static  char  * 
457+ ngx_http_geoip2_parse_config (ngx_conf_t  * cf , ngx_command_t  * dummy , void  * conf )
458+ {
459+     ngx_http_geoip2_db_t   * database ;
460+     ngx_str_t              * value ;
461+     time_t                 interval ;
462+ 
463+     value  =  cf -> args -> elts ;
464+ 
465+     if  (value [0 ].data [0 ] ==  '$' ) {
466+         return  ngx_http_geoip2_add_variable (cf , dummy , conf );
467+     }
468+ 
469+     if  (value [0 ].len  ==  11 
470+             &&  ngx_strncmp (value [0 ].data , "auto_reload" , 11 ) ==  0 ) {
471+         if  ((int ) cf -> args -> nelts  !=  2 ) {
472+             ngx_conf_log_error (NGX_LOG_EMERG , cf , 0 ,
473+                                "invalid number of arguments for auto_reload" );
474+             return  NGX_CONF_ERROR ;
475+         }
476+ 
477+         interval  =  ngx_parse_time (& value [1 ], true);
478+ 
479+         if  (interval  ==  (time_t ) NGX_ERROR ) {
480+             ngx_conf_log_error (NGX_LOG_EMERG , cf , 0 ,
481+                                "invalid interval for auto_reload \"%V\"" ,
482+                                value [1 ]);
483+             return  NGX_CONF_ERROR ;
484+         }
485+ 
486+ 
487+         database  =  (ngx_http_geoip2_db_t  * ) conf ;
488+         database -> check_interval  =  interval ;
489+         return  NGX_CONF_OK ;
490+     }
491+ 
492+     ngx_conf_log_error (NGX_LOG_EMERG , cf , 0 ,
493+                        "invalid setting \"%V\"" , & value [0 ]);
494+     return  NGX_CONF_ERROR ;
495+ }
496+ 
497+ 
404498static  char  * 
405499ngx_http_geoip2_add_variable (ngx_conf_t  * cf , ngx_command_t  * dummy , void  * conf )
406500{
0 commit comments