anchor.diff:              end;
           _ -> error
       end.
  -
  -geoman() ->
  -    ok.
  
positive.code: %% Geographic IP Informatin Server
  %%================================
  
  %% TODO: erlang:decode_packet
  %% TODO: inet:parse_ipv4strict_address
  
  -module(geoip).
  -author('wuhualiang@meituan.com').
  
  -mode(compile).
  
  -export([start/2]).
  
  -define(DEV, _).
  -ifdef(DEV).
  -export([http_response/2]).
  -export([special_ip/1]).
  -export([multicast_ip/1]).
  -endif.
  
  -define(IPS_FILE, "ips.dump").
  -define(GEO_FILE, "geo.meta").
  -define(IPS_TABLE, mt_ips).
  -define(GEO_TABLE, mt_geo).
  -define(GEO_MANAGER, geoman).
  -define(HIGH_WATER_MARK, 1000).
  -define(SNAPSHOT_INTV, 86400*1000).
  -define(WRITEBACK_THR, 100000).
  
  start(Port, Threads) ->
      inets:start(),
      % ets:new(?IPS_TABLE, [set, public, named_table])
      % ets:new(?GEO_TABLE, [set, public, named_table])
      {ok, ?IPS_TABLE} = ets:file2tab(?IPS_FILE),
      {ok, ?GEO_TABLE} = ets:file2tab(?GEO_FILE),
      GeoMan = spawn(geoman),
      register(?GEO_MANAGER, GeoMan),
      lists:map(fun worker_init/1, [0, Threads-1]),
      {ok, LSock} = gen_tcp:listen(Port, []),
      listen(Port).
  
  %% ======== Internal Functions ======== %%
  
  listen(Port) ->
     ok. 
  
  snapshot() ->
      timer:sleep(?SNAPSHOT_INTV),
  
negative.code:     ets:tab2file(?IPS_TABLE, ?IPS_FILE ++ Suffix),
      ets:tab2file(?GEO_TABLE, ?GEO_FILE ++ Suffix),
      snapshot().
  
  lookup(IP) when is_list(IP) ->
      case inet:parse_ipv4strict_address(IP) of
  