1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 
3 #include "proxy.h"
4 
5 typedef struct {
6     struct proxy_hash_caller phc; // passed back to proxy API
7     unsigned int buckets;
8 } mcplib_jump_hash_t;
9 
mcplib_dist_jump_hash_get_server(uint64_t hash,void * ctx)10 static uint32_t mcplib_dist_jump_hash_get_server(uint64_t hash, void *ctx) {
11     mcplib_jump_hash_t *jh = ctx;
12 
13     int64_t b = -1, j = 0;
14     while (j < jh->buckets) {
15         b = j;
16         hash = hash * 2862933555777941757ULL + 1;
17         j = (b + 1) * ((double)(1LL << 31) / (double)((hash >> 33) + 1));
18     }
19     return b;
20 }
21 
22 // stack = [pool, option]
mcplib_dist_jump_hash_new(lua_State * L)23 static int mcplib_dist_jump_hash_new(lua_State *L) {
24     luaL_checktype(L, 1, LUA_TTABLE);
25     lua_Unsigned buckets = lua_rawlen(L, 1);
26 
27     mcplib_jump_hash_t *jh = lua_newuserdatauv(L, sizeof(mcplib_jump_hash_t), 0);
28 
29     // don't need to loop through the table at all, just need its length.
30     // could optimize startup time by adding hints to the module for how to
31     // format pool (ie; just a total count or the full table)
32     jh->buckets = buckets;
33     jh->phc.ctx = jh;
34     jh->phc.selector_func = mcplib_dist_jump_hash_get_server;
35 
36     lua_pushlightuserdata(L, &jh->phc);
37 
38     // - return [UD, lightuserdata]
39     return 2;
40 }
41 
mcplib_open_dist_jump_hash(lua_State * L)42 int mcplib_open_dist_jump_hash(lua_State *L) {
43     const struct luaL_Reg jump_f[] = {
44         {"new", mcplib_dist_jump_hash_new},
45         {NULL, NULL},
46     };
47 
48     luaL_newlib(L, jump_f);
49 
50     return 1;
51 }
52