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