anchor.diff:      lists:flatten(io_lib:format("~s/projection",  [DataDir]));
   make_projection_filename(DataDir, File) ->
       lists:flatten(io_lib:format("~s/projection/~s",  [DataDir, File])).
  +
  +%% @doc Given a filename, return true if it is a valid machi filename,
  +%% false otherwise.
  +-spec is_valid_filename( Filename :: string() ) -> true | false.
  +is_valid_filename(Filename) ->
  +    case parse_filename(Filename) of
  +        [] -> false;
  +        _ -> true
  +    end.
  +
  +%% @doc Given a machi filename, return a set of components in a list.
  +%% The components will be:
  +%% <ul>
  +%%      <li>Prefix</li>
  +%%      <li>UUID</li>
  +%%      <li>Sequence number</li>
  +%% </ul>
  +%%
  +%% Invalid filenames will return an empty list.
  +-spec parse_filename( Filename :: string() ) -> [ string() ].
  +parse_filename(Filename) ->
  +    case string:tokens(Filename, "^") of
  +        [_Prefix, _UUID, _SeqNo] = L -> L;
  +        _ -> []
  +    end.
  +
   
   %% @doc Read the file size of a config file, which is used as the
   %% basis for a minimum sequence number.
  
positive.code:          make_config_filename/2,
           make_checksum_filename/4, make_checksum_filename/2,
           make_data_filename/4, make_data_filename/2,
           make_projection_filename/2,
           read_max_filenum/2, increment_max_filenum/2,
           info_msg/2, verb/1, verb/2,
           mbytes/1,
           pretty_time/0, pretty_time/2,
           %% TCP protocol helpers
           connect/2, connect/3,
  
negative.code:          combinations/1, ordered_combinations/1,
           mk_order/2
          ]).
  
  %% TODO: Leave this in place?
  -compile(export_all).
  
  -include("machi.hrl").
  