mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
dmubus: improve chache handling
- use less memory - decrease lookup time - make read only variables const - remove unused variables / macros Signed-off-by: Daniel Danzberger <daniel@dd-wrt.com>
This commit is contained in:
parent
588db7e54f
commit
7779fc6928
3 changed files with 107 additions and 150 deletions
|
|
@ -73,8 +73,6 @@ static int dm_ctx_init_custom(struct dmctx *ctx, unsigned int dm_type, unsigned
|
|||
UPNP_SUPPORTED_DM *tUPNPSupportedDM = NULL;
|
||||
#endif
|
||||
if (custom == CTX_INIT_ALL) {
|
||||
memset(&dmubus_ctx, 0, sizeof(struct dmubus_ctx));
|
||||
INIT_LIST_HEAD(&dmubus_ctx.obj_head);
|
||||
uci_ctx = uci_alloc_context();
|
||||
uci_varstate_ctx = uci_alloc_context();
|
||||
DMUCI_INIT(bbfdm);
|
||||
|
|
@ -124,7 +122,7 @@ static int dm_ctx_clean_custom(struct dmctx *ctx, int custom)
|
|||
if (uci_varstate_ctx) uci_free_context(uci_varstate_ctx);
|
||||
uci_varstate_ctx = NULL;
|
||||
DMUCI_EXIT(bbfdm);
|
||||
dmubus_ctx_free(&dmubus_ctx);
|
||||
dmubus_free();
|
||||
dmcleanmem();
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -16,30 +16,26 @@
|
|||
#include "dmmem.h"
|
||||
#include "dmcommon.h"
|
||||
|
||||
#define UBUS_BUFFEER_SIZE 1024 * 8
|
||||
static LIST_HEAD(dmubus_cache);
|
||||
|
||||
struct dmubus_ctx dmubus_ctx;
|
||||
struct dm_ubus_cache_entry {
|
||||
struct list_head list;
|
||||
json_object *data;
|
||||
unsigned hash;
|
||||
};
|
||||
|
||||
struct dm_ubus_req {
|
||||
const char *obj;
|
||||
const char *method;
|
||||
struct ubus_arg *args;
|
||||
unsigned n_args;
|
||||
};
|
||||
|
||||
#if DM_USE_LIBUBUS
|
||||
static struct blob_buf b;
|
||||
static struct ubus_context *ubus_ctx;
|
||||
static int timeout = 1000;
|
||||
static json_object *json_res = NULL;
|
||||
#endif
|
||||
|
||||
static inline int ubus_arg_cmp(struct ubus_arg *src_args, int src_size, struct ubus_arg dst_args[], int dst_size)
|
||||
{
|
||||
if (src_size != dst_size)
|
||||
return -1;
|
||||
int i;
|
||||
for (i = 0; i < src_size; i++) {
|
||||
if (strcmp( src_args[i].key, dst_args[i].key) != 0 || strcmp( src_args[i].val, dst_args[i].val) != 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if DM_USE_LIBUBUS
|
||||
|
||||
static void dm_libubus_free()
|
||||
{
|
||||
|
|
@ -97,7 +93,8 @@ static int __dm_ubus_call(const char *obj, const char *method, const struct ubus
|
|||
blobmsg_add_string(&b, u_args[i].key, u_args[i].val);
|
||||
|
||||
if (!ubus_lookup_id(ubus_ctx, obj, &id))
|
||||
rc = ubus_invoke(ubus_ctx, id, method, b.head, receive_call_result_data, NULL, timeout);
|
||||
rc = ubus_invoke(ubus_ctx, id, method, b.head,
|
||||
receive_call_result_data, NULL, timeout);
|
||||
else
|
||||
rc = -1;
|
||||
|
||||
|
|
@ -198,105 +195,95 @@ static inline json_object *ubus_call_req(char *obj, char *method, struct ubus_ar
|
|||
#endif
|
||||
}
|
||||
|
||||
int dmubus_call(char *obj, char *method, struct ubus_arg u_args[], int u_args_size, json_object **req_res)
|
||||
/* Based on an efficient hash function published by D. J. Bernstein
|
||||
*/
|
||||
static unsigned int djbhash(unsigned hash, const char *data, unsigned len)
|
||||
{
|
||||
struct ubus_obj *i = NULL;
|
||||
struct ubus_meth *j = NULL;
|
||||
struct ubus_msg *k = NULL;
|
||||
json_object **jr;
|
||||
bool found = false;
|
||||
unsigned i;
|
||||
|
||||
*req_res = NULL;
|
||||
list_for_each_entry(i, &dmubus_ctx.obj_head, list) {
|
||||
if (strcmp(obj, i->name) == 0) {
|
||||
found = true;
|
||||
for (i = 0; i < len; i++)
|
||||
hash = ((hash << 5) + hash) + data[i];
|
||||
|
||||
return (hash & 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
static unsigned dm_ubus_req_hash(const struct dm_ubus_req *req)
|
||||
{
|
||||
unsigned hash = 5381;
|
||||
unsigned i;
|
||||
|
||||
hash = djbhash(hash, req->obj, strlen(req->obj));
|
||||
hash = djbhash(hash, req->method, strlen(req->method));
|
||||
|
||||
for (i = 0; i < req->n_args; i++) {
|
||||
hash = djbhash(hash, req->args[i].key, strlen(req->args[i].key));
|
||||
hash = djbhash(hash, req->args[i].val, strlen(req->args[i].val));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
static const struct dm_ubus_cache_entry * dm_ubus_cache_lookup(unsigned hash)
|
||||
{
|
||||
const struct dm_ubus_cache_entry *entry;
|
||||
const struct dm_ubus_cache_entry *entry_match = NULL;
|
||||
|
||||
list_for_each_entry(entry, &dmubus_cache, list) {
|
||||
if (entry->hash == hash) {
|
||||
entry_match = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
i = dmcalloc(1, sizeof(struct ubus_obj));
|
||||
//init method head
|
||||
INIT_LIST_HEAD(&i->method_head);
|
||||
i->name = dmstrdup(obj);
|
||||
list_add(&i->list, &dmubus_ctx.obj_head);
|
||||
return entry_match;
|
||||
}
|
||||
|
||||
static void dm_ubus_cache_entry_new(unsigned hash, json_object *data)
|
||||
{
|
||||
struct dm_ubus_cache_entry *entry = malloc(sizeof(*entry));
|
||||
|
||||
if (entry) {
|
||||
entry->data = data;
|
||||
entry->hash = hash;
|
||||
list_add_tail(&entry->list, &dmubus_cache);
|
||||
}
|
||||
found = false;
|
||||
list_for_each_entry(j, &i->method_head, list) {
|
||||
if (strcmp(method, j->name) == 0) {
|
||||
*req_res = j->res;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
j = dmcalloc(1, sizeof(struct ubus_meth));
|
||||
//init message head
|
||||
INIT_LIST_HEAD(&j->msg_head);
|
||||
j->name = dmstrdup(method);
|
||||
list_add(&j->list, &i->method_head);
|
||||
jr = &j->res;
|
||||
}
|
||||
// Arguments
|
||||
if (u_args_size != 0) {
|
||||
found = false;
|
||||
list_for_each_entry(k, &j->msg_head, list) {
|
||||
if (ubus_arg_cmp(k->ug, k->ug_size, u_args, u_args_size) == 0) {
|
||||
*req_res = k->res;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
k = dmcalloc(1, sizeof(struct ubus_msg));
|
||||
list_add(&k->list, &j->msg_head);
|
||||
k->ug = dmcalloc(u_args_size, sizeof(struct ubus_arg));
|
||||
k->ug_size = u_args_size;
|
||||
jr = &k->res;
|
||||
int c;
|
||||
for (c = 0; c < u_args_size; c++) {
|
||||
k->ug[c].key = dmstrdup(u_args[c].key);
|
||||
k->ug[c].val = dmstrdup(u_args[c].val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
*jr = ubus_call_req(obj, method, u_args, u_args_size);
|
||||
*req_res = *jr;
|
||||
}
|
||||
|
||||
static void dm_ubus_cache_entry_free(struct dm_ubus_cache_entry *entry)
|
||||
{
|
||||
list_del(&entry->list);
|
||||
json_object_put(entry->data);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
int dmubus_call(char *obj, char *method, struct ubus_arg u_args[],
|
||||
int u_args_size, json_object **req_res)
|
||||
{
|
||||
const struct dm_ubus_req req = {
|
||||
.obj = obj,
|
||||
.method = method,
|
||||
.args = u_args,
|
||||
.n_args = u_args_size
|
||||
};
|
||||
const unsigned hash = dm_ubus_req_hash(&req);
|
||||
const struct dm_ubus_cache_entry *entry = dm_ubus_cache_lookup(hash);
|
||||
json_object *res;
|
||||
|
||||
if (entry) {
|
||||
res = entry->data;
|
||||
} else {
|
||||
res = ubus_call_req(obj, method, u_args, u_args_size);
|
||||
dm_ubus_cache_entry_new(hash, res);
|
||||
}
|
||||
|
||||
*req_res = res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dmubus_ctx_free(struct dmubus_ctx *ctx)
|
||||
void dmubus_free()
|
||||
{
|
||||
struct ubus_obj *i, *_i;
|
||||
struct ubus_meth *j, *_j;
|
||||
struct ubus_msg *k, *_k;
|
||||
struct dm_ubus_cache_entry *entry, *tmp;
|
||||
|
||||
list_for_each_entry_safe(entry, tmp, &dmubus_cache, list)
|
||||
dm_ubus_cache_entry_free(entry);
|
||||
|
||||
list_for_each_entry_safe(i, _i, &ctx->obj_head, list) {
|
||||
list_for_each_entry_safe(j, _j, &i->method_head, list) {
|
||||
list_for_each_entry_safe(k, _k, &j->msg_head, list) {
|
||||
if (k->ug_size != 0) {
|
||||
int c;
|
||||
for (c = 0; c < k->ug_size; c++) {
|
||||
dmfree(k->ug[c].key);
|
||||
dmfree(k->ug[c].val);
|
||||
}
|
||||
dmfree(k->ug);
|
||||
}
|
||||
list_del(&k->list);
|
||||
if (k->res)
|
||||
json_object_put(k->res);
|
||||
dmfree(k);
|
||||
}
|
||||
list_del(&j->list);
|
||||
if (j->res)
|
||||
json_object_put(j->res);
|
||||
dmfree(j->name);
|
||||
dmfree(j);
|
||||
}
|
||||
list_del(&i->list);
|
||||
dmfree(i->name);
|
||||
dmfree(i);
|
||||
}
|
||||
dm_libubus_free();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,58 +11,30 @@
|
|||
* Author: Anis Ellouze <anis.ellouze@pivasoftware.com>
|
||||
*/
|
||||
|
||||
#ifndef __UBUS_H
|
||||
#define __UBUS_H
|
||||
#ifndef __DMUBUS_H
|
||||
#define __DMUBUS_H
|
||||
|
||||
#include <libubox/list.h>
|
||||
#include <libubox/blobmsg_json.h>
|
||||
#include <json-c/json.h>
|
||||
|
||||
#define UBUS_ARGS (struct ubus_arg[])
|
||||
#define SIMPLE_OUTPUT -1
|
||||
#define INDENT_OUTPUT 0
|
||||
#define JSON_OUTPUT SIMPLE_OUTPUT
|
||||
|
||||
struct dmubus_ctx {
|
||||
struct list_head obj_head;
|
||||
};
|
||||
|
||||
struct ubus_obj {
|
||||
struct list_head list;
|
||||
struct list_head method_head;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct ubus_meth {
|
||||
struct list_head list;
|
||||
struct list_head msg_head;
|
||||
char *name;
|
||||
json_object *res;
|
||||
};
|
||||
|
||||
struct ubus_msg {
|
||||
struct list_head list;
|
||||
struct ubus_arg *ug; // ubus method param
|
||||
int ug_size;
|
||||
json_object *res;
|
||||
};
|
||||
|
||||
struct ubus_arg{
|
||||
char *key;
|
||||
char *val;
|
||||
int type;
|
||||
};
|
||||
|
||||
enum ubus_args_enum {
|
||||
enum ubus_arg_type {
|
||||
String,
|
||||
Integer,
|
||||
};
|
||||
|
||||
extern struct dmubus_ctx dmubus_ctx;
|
||||
struct ubus_arg {
|
||||
const char *key;
|
||||
const char *val;
|
||||
enum ubus_arg_type type;
|
||||
};
|
||||
|
||||
#define dm_ubus_get_value(jobj,ARGC,args...) \
|
||||
dmjson_get_value(jobj, ARGC, ##args)
|
||||
int dmubus_call(char *obj, char *method, struct ubus_arg u_args[], int u_args_size, json_object **req_res);
|
||||
|
||||
int dmubus_call(char *obj, char *method, struct ubus_arg u_args[],
|
||||
int u_args_size, json_object **req_res);
|
||||
int dmubus_call_set(char *obj, char *method, struct ubus_arg u_args[], int u_args_size);
|
||||
void dmubus_ctx_free(struct dmubus_ctx *ctx);
|
||||
void dmubus_free();
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue