Skip to content
macintux edited this page Dec 23, 2014 · 11 revisions

As of January 2014, Cuttlefish supports the following datatypes:

integer

integer is exactly what it sounds like.

{enum, Enum = [atom()|string()]}

enum is great! You know the fixed set of options for a setting, so use this one. Those fixed options are provided in the second element of the enum tuple.

If you wish to map atoms or strings to some other value, use tuples instead:

{enum, Enum = [{atom()|string(), term()}]}

ip

The ip datatype exists currently as an IP/Port combo. You can specify it as a default as either a string (e.g. "127.0.0.1:8098") or a tuple ({"127.0.0.1", 8098})

string

string is the default datatype. Everything in a .conf file is a string anyway, so we're guaranteed a successful conversion.

atom

it works alot like string, but outputs an erlang atom to your generated app.config.

flag

Flags are pretty cool. We got sick of writing the same boolean translation over and over again. Flags make this easier. They are for variables that have 2 possible values, and can be specified in three formats:

flag The trivial case: "on" in your conf file becomes true in your app.config. "off" becomes false

{flag, On, Off} Say you don't like "on" and "off". You can change those strings to anything you want here.

{flag, {On, OnVal}, {Off, OffVal}} Say the two values you're mapping to aren't true and/or false you can change those with OnVal/OffVal

{duration, BaseUnit = f | w | d | h | m | s | ms }

durations are fixed intervals of time, the largest unit of which will be a one week. Anything larger will have to be expressed in terms of weeks, since larger units (month, year) are of variable duration. durations manifest in .conf files as strings like this: 1w2d.

The following units are supported:

  • f - fortnight
  • w - week
  • d - day
  • h - hour
  • m - minute
  • s - second
  • ms - millisecond

You can use any combination of these. I'm not sure why you'd want to specify 1w13ms, but you can.

Did I mention you can use floats here? 0.5d? no probalo.

duration will convert automatically to BaseUnit in your app.config. If you want it to be seconds instead of milliseconds, just use the datatype {duration, s}. It will round up to the nearest second, so 1ms = 999ms = 1s. Confused? You won't be, after this week's episode of...Soap.

bytesize

In your app.config, these will end up as bytes in integers, so 1KB = 1024.

bytesize will work pretty much like duration but with three differences.

  • The units will are MB, KB, and GB
  • If no unit is specified, it's just bytes
  • You will only be able to use ONE unit. e.g. no 4gb3kb <- that makes no sense!

Note: lowercase units (i.e. gb, mb, and kb) are ok, but mixed case are not. That's to avoid confusion with Megabits

file and directory

file and directory are effectively strings. In the future they could allow for included validators like valid path and exists. Some files may need to exist, some may not. some may need to be writable.

Extended Datatypes

Sometimes you need a composite of two datatypes. Take a look at this example:

%% @doc This option specifies how many of each type of fsm may exist
%% concurrently.  This is for overload protection and is a new
%% mechanism that obsoletes 1.3's health checks. Note that this number
%% represents two potential processes, so erlang.process_limit in
%% vm.args should be at least 3X more. Setting this value to infinite
%% disables fsm overload protection.
{mapping, "max_concurrent_requests", "riak_kv.fsm_limit", [
  {default, 50000},
  {datatype, [integer, {atom, infinite}]},
  {level, advanced}
]}.

{translation, "riak_kv.fsm_limit",
 fun(Conf) ->
  TheLimit = cuttlefish:conf_get("max_concurrent_requests", Conf),
  case TheLimit of
      infinite -> undefined;
      Int when is_integer(Int) -> Int;
      _ ->
          %% This would have been caught earlier in datatype validation
          cuttlefish:invalid("should be an integer")
  end
 end
}.

Look at that datatype! We're saying this can be any integer OR the atom 'infinite'. Under the hood, riak_kv treats 'undefined' as 'infinite', so we take care of that in the translation.

NOTE when providing a default, it must be satisfied by the head of the datatypes list.