static int file_read_cached(const char *file_name, uint8_t **mem, uint32_t beg, uint32_t len, uint32_t socket, struct hash_set *hs) { if (len == 0) { *mem = 0; return 0; } uint8_t *data_mem; /* Since the configuration can reference the same file from multiple places, use prox_shared infrastructure to detect this and return previously loaded data. */ char name[256]; snprintf(name, sizeof(name), "%u-%u:%s", beg, len, file_name); *mem = prox_sh_find_socket(socket, name); if (*mem) return 0; /* check if the file has been loaded on the other socket. */ if (socket == 1 && (data_mem = prox_sh_find_socket(0, name))) { uint8_t *data_find = hash_set_find(hs, data_mem, len); if (!data_find) { data_find = prox_zmalloc(len, socket); PROX_PANIC(data_find == NULL, "Failed to allocate memory (%u bytes) to hold header for peer\n", len); rte_memcpy(data_find, data_mem, len); hash_set_add(hs, data_find, len); } *mem = data_find; prox_sh_add_socket(socket, name, *mem); return 0; } /* It is possible that a file with a different name contains the same data. In that case, search all loaded files and compare the data to reduce memory utilization.*/ data_mem = malloc(len); PROX_PANIC(data_mem == NULL, "Failed to allocate temporary memory to hold data\n"); if (file_read_content(file_name, data_mem, beg, len)) { plog_err("%s\n", file_get_error()); return -1; } uint8_t *data_find = hash_set_find(hs, data_mem, len); if (!data_find) { data_find = prox_zmalloc(len, socket); PROX_PANIC(data_find == NULL, "Failed to allocate memory (%u bytes) to hold header for peer\n", len); rte_memcpy(data_find, data_mem, len); hash_set_add(hs, data_find, len); } free(data_mem); *mem = data_find; prox_sh_add_socket(socket, name, *mem); return 0; }
// {{{ file_error() /// Returns 1 if the error message is not empty int file_error(file_t *o) { if(strlen(file_get_error(o))>0) return 1; return 0; }
static int lua_to_peer_data(struct lua_State *L, enum lua_place from, const char *name, uint32_t socket, struct peer_data *peer_data, size_t *cl, struct hash_set *hs) { uint32_t hdr_len, hdr_beg, content_len, content_beg; char hdr_file[256], content_file[256]; int pop; if ((pop = lua_getfrom(L, from, name)) < 0) return -1; if (!lua_istable(L, -1)) return -1; if (lua_getfrom(L, TABLE, "header") < 0) return -1; if (lua_to_int(L, TABLE, "len", &hdr_len) < 0) return -1; if (lua_to_int(L, TABLE, "beg", &hdr_beg) < 0) return -1; if (lua_to_string(L, TABLE, "file_name", hdr_file, sizeof(hdr_file)) < 0) return -1; lua_pop(L, 1); if (lua_getfrom(L, TABLE, "content") < 0) return -1; if (lua_to_int(L, TABLE, "len", &content_len) < 0) return -1; if (lua_to_int(L, TABLE, "beg", &content_beg) < 0) return -1; if (lua_to_string(L, TABLE, "file_name", content_file, sizeof(content_file)) < 0) return -1; lua_pop(L, 1); if (hdr_len == UINT32_MAX) { long ret = file_get_size(hdr_file); if (ret < 0) { plog_err("%s", file_get_error()); return -1; } hdr_len = ret - hdr_beg; } if (content_len == UINT32_MAX) { long ret = file_get_size(content_file); if (ret < 0) { plog_err("%s", file_get_error()); return -1; } content_len = ret - content_beg; } *cl = content_len; peer_data->hdr_len = hdr_len; if (file_read_cached(hdr_file, &peer_data->hdr, hdr_beg, hdr_len, socket, hs)) return -1; if (file_read_cached(content_file, &peer_data->content, content_beg, content_len, socket, hs)) return -1; lua_pop(L, pop); return 0; }