Skip to content

Commit

Permalink
new IP assignment, random init, fifo reuse of IP
Browse files Browse the repository at this point in the history
Initialized the free IP pool with a random order and time stamp to
build a queue in the ets table. Released IPs are appended to the end
of the free queue (through the timestamp).
  • Loading branch information
RoadRunnr committed Jun 11, 2021
1 parent 468a306 commit 5ac3842
Show file tree
Hide file tree
Showing 5 changed files with 338 additions and 23 deletions.
74 changes: 74 additions & 0 deletions apps/ergw_core/c_src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Based on c_src.mk from erlang.mk by Loic Hoguin <essen@ninenines.eu>

CURDIR := $(shell pwd)
BASEDIR := $(abspath $(CURDIR)/..)

PROJECT ?= $(notdir $(BASEDIR))
PROJECT := $(strip $(PROJECT))

ERTS_INCLUDE_DIR ?= $(shell erl -noshell -eval "io:format(\"~ts/erts-~ts/include/\", [code:root_dir(), erlang:system_info(version)])." -s init stop)
ERL_INTERFACE_INCLUDE_DIR ?= $(shell erl -noshell -eval "io:format(\"~ts\", [code:lib_dir(erl_interface, include)])." -s init stop)
ERL_INTERFACE_LIB_DIR ?= $(shell erl -noshell -eval "io:format(\"~ts\", [code:lib_dir(erl_interface, lib)])." -s init stop)

C_SRC_DIR = $(CURDIR)
C_SRC_OUTPUT ?= $(CURDIR)/../priv/$(PROJECT).so

# System type and C compiler/flags.

UNAME_SYS := $(shell uname -s)
ifeq ($(UNAME_SYS), Darwin)
CC ?= cc
CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall
LDFLAGS ?= -arch x86_64 -flat_namespace -undefined suppress
else ifeq ($(UNAME_SYS), FreeBSD)
CC ?= cc
CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS ?= -O3 -finline-functions -Wall
else ifeq ($(UNAME_SYS), Linux)
CC ?= gcc
CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS ?= -O3 -finline-functions -Wall
endif

CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)

LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lei
LDFLAGS += -shared

# Verbosity.

c_verbose_0 = @echo " C " $(?F);
c_verbose = $(c_verbose_$(V))

cpp_verbose_0 = @echo " CPP " $(?F);
cpp_verbose = $(cpp_verbose_$(V))

link_verbose_0 = @echo " LD " $(@F);
link_verbose = $(link_verbose_$(V))

SOURCES := $(shell find $(C_SRC_DIR) -type f \( -name "*.c" -o -name "*.C" -o -name "*.cc" -o -name "*.cpp" \))
OBJECTS = $(addsuffix .o, $(basename $(SOURCES)))

COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c
COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c

$(C_SRC_OUTPUT): $(OBJECTS)
@mkdir -p $(BASEDIR)/priv/
$(link_verbose) $(CC) $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $(C_SRC_OUTPUT)

%.o: %.c
$(COMPILE_C) $(OUTPUT_OPTION) $<

%.o: %.cc
$(COMPILE_CPP) $(OUTPUT_OPTION) $<

%.o: %.C
$(COMPILE_CPP) $(OUTPUT_OPTION) $<

%.o: %.cpp
$(COMPILE_CPP) $(OUTPUT_OPTION) $<

clean:
@rm -f $(C_SRC_OUTPUT) $(OBJECTS)
202 changes: 202 additions & 0 deletions apps/ergw_core/c_src/uint32_fy_shuffle.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
/* Copyright 2021, Travelping GmbH <info@travelping.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/

/* Generate a sequence of at most 2^32 unsigned 32bit integers using the
* Fisher-Yates shuffle */

#include <erl_nif.h>
#include <stdint.h>
#include <time.h>

#define STEPCNT (4*1024)

#define min(x,y) ( \
{ __auto_type __x = (x); __auto_type __y = (y); \
__x < __y ? __x : __y; })

static ERL_NIF_TERM
mk_atom(ErlNifEnv* env, const char* atom)
{
ERL_NIF_TERM ret;

if(!enif_make_existing_atom(env, atom, &ret, ERL_NIF_LATIN1))
{
return enif_make_atom(env, atom);
}

return ret;
}

static void swap (unsigned int *a, unsigned int *b)
{
unsigned int temp = *a;
*a = *b;
*b = temp;
}

static ERL_NIF_TERM shuffle_ret(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM new_argv[4];
ERL_NIF_TERM head, tail;
unsigned int i, n, end;
unsigned int *arr;
ErlNifBinary bin;

if (argc != 4 ||
!enif_get_uint(env, argv[0], &n) || n <= 0 ||
!enif_get_uint(env, argv[1], &i) || i > n ||
!enif_inspect_binary(env, argv[2], &bin) ||
!enif_is_list(env, argv[3]))
return enif_make_badarg(env);

/* printf("ret i: %u\n\r", i); */
/* printf("ret n: %u\n\r", n); */

tail = argv[3];
end = min(n, i + STEPCNT);
arr = (unsigned int *)bin.data;

for (; i < end; i++) {
head = enif_make_tuple1(env,
enif_make_tuple2(env,
enif_make_int64(env, INT64_MIN + i),
enif_make_uint(env, arr[i])));
tail = enif_make_list_cell(env, head, tail);
}

if (i >= n) {
enif_release_binary(&bin);
return tail;
} else {
new_argv[0] = argv[0];
new_argv[1] = enif_make_uint(env, i);
new_argv[2] = argv[2];
new_argv[3] = tail;
return enif_schedule_nif(env, "shuffle_ret", 0, shuffle_ret, 4, new_argv);
}
}

static ERL_NIF_TERM shuffle_randomize(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM new_argv[4];
unsigned int i, n, end;
unsigned int *arr;
ErlNifBinary bin;

if (argc != 3 ||
!enif_get_uint(env, argv[0], &n) || n <= 0 ||
!enif_get_uint(env, argv[1], &i) || i > n ||
!enif_inspect_binary(env, argv[2], &bin))
return enif_make_badarg(env);

if (i == n - 1)
srand(time(NULL));

end = (i > STEPCNT) ? i - STEPCNT : 0;
arr = (unsigned int *)bin.data;

for (; i > end; i--) {
unsigned int j = rand() % (i+1);
swap(&arr[i], &arr[j]);
}

new_argv[0] = argv[0];
new_argv[2] = argv[2];

if (i == 0) {
new_argv[1] = enif_make_uint(env, 0);
new_argv[3] = enif_make_list(env, 0);
return enif_schedule_nif(env, "shuffle_ret", 0, shuffle_ret, 4, new_argv);
} else {
new_argv[1] = enif_make_uint(env, i);
return enif_schedule_nif(env, "shuffle_randomize", 0, shuffle_randomize, 3, new_argv);
}
}

static ERL_NIF_TERM shuffle_fill(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM new_argv[3];
unsigned int i, n, end;
unsigned int *arr;
ErlNifBinary bin;

if (argc != 3 ||
!enif_get_uint(env, argv[0], &n) || n <= 0 ||
!enif_get_uint(env, argv[1], &i) || i > n ||
!enif_inspect_binary(env, argv[2], &bin))
return enif_make_badarg(env);

/* printf("fill i: %u\r\n", i); */
/* printf("fill n: %u\r\n", n); */

end = min(n, i + STEPCNT);
arr = (unsigned int *)bin.data;

for (; i < end; i++)
arr[i] = i;

new_argv[0] = argv[0];
new_argv[2] = argv[2];

if (i == n) {
new_argv[1] = enif_make_uint(env, n - 1);
return enif_schedule_nif(env, "shuffle_randomize", 0, shuffle_randomize, 3, new_argv);
} else {
new_argv[1] = enif_make_uint(env, i);
return enif_schedule_nif(env, "shuffle_fill", 0, shuffle_fill, 3, new_argv);
}
}

static ERL_NIF_TERM shuffle(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM new_argv[3];
unsigned int n;

if (!enif_get_uint(env, argv[0], &n) || n <= 0)
return enif_make_badarg(env);

if (!(enif_make_new_binary(env, n * sizeof(unsigned int), &new_argv[2])))
return enif_raise_exception(env, mk_atom(env, "out_of_memory"));

new_argv[0] = argv[0];
new_argv[1] = enif_make_uint(env, 0);
return enif_schedule_nif(env, "shuffle_fill", 0, shuffle_fill, 3, new_argv);
}

#if 0
static ERL_NIF_TERM shuffle(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM head, tail;
unsigned int *arr;
unsigned int i, n;

if (!enif_get_uint(env, argv[0], &n) || n <= 0)
return enif_make_badarg(env);

if (!(arr = enif_alloc(n * sizeof(arr[0]))))
return enif_raise_exception(env, mk_atom(env, "out_of_memory"));

for (i = 0; i < n; i++)
arr[i] = i;
//randomize(arr, n);

tail = enif_make_list(env, 0);
for (i = 0; i < n; i++) {
head = enif_make_uint(env, arr[i]);
tail = enif_make_list_cell(env, head, tail);
}
return tail;
}
#endif

static ErlNifFunc nif_funcs[] =
{
{"shuffle", 1, shuffle}
};

ERL_NIF_INIT(uint32_fy_shuffle, nif_funcs, NULL, NULL, NULL, NULL)
9 changes: 9 additions & 0 deletions apps/ergw_core/rebar.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{erl_opts, [debug_info]}.
{deps, []}.

{pre_hooks,
[{"(linux|darwin|solaris)", compile, "make -C c_src"},
{"(freebsd)", compile, "gmake -C c_src"}]}.
{post_hooks,
[{"(linux|darwin|solaris)", clean, "make -C c_src clean"},
{"(freebsd)", clean, "gmake -C c_src clean"}]}.
Loading

0 comments on commit 5ac3842

Please sign in to comment.