/* * Buxton * * Copyright (C) 2016 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include "log.h" #include "cache.h" #include "buxton_error.h" #define CACHE_COUNT_MAX 2000 #define CACHE_SIZE_MAX (1024 * 1024) /* 1MB per cache (MAX) */ #define DEFAULT_DROP_CACHE_SIZE 50 #undef LOG_TAG #define LOG_TAG "BXT_CACHE" typedef struct _cache { GHashTable *hash_table; enum layer_attribute_type layer_type; int count; int size; } bxt_cache; typedef struct _cache_data { enum layer_attribute_type layer_type; int len; /* data size */ void *data; /* raw data */ } cache_data; static bxt_cache *g_base_db_cache; static bxt_cache *g_normal_db_cache; static bxt_cache *get_cache(enum layer_attribute_type layer_type) { return (layer_type == LAYER_ATTRIBUTE_RW) ? g_normal_db_cache : g_base_db_cache; } static void destroy_key(gpointer key) { if (key) free(key); } static void destroy_data(gpointer data) { cache_data *cdata = (cache_data *) data; bxt_cache *cache = NULL; if (!cdata) return; cache = get_cache(cdata->layer_type); if (!cache) return; if (cdata->data) { if (cache) { cache->size -= cdata->len; cache->count--; } free(cdata->data); } free(data); } void cache_init(void) { g_base_db_cache = (bxt_cache *)malloc(sizeof(bxt_cache)); if (!g_base_db_cache) return; g_normal_db_cache = (bxt_cache *)malloc(sizeof(bxt_cache)); if (!g_normal_db_cache) { free(g_base_db_cache); g_base_db_cache = NULL; return; } g_base_db_cache->hash_table = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)destroy_key, (GDestroyNotify)destroy_data); g_base_db_cache->size = 0; g_base_db_cache->count = 0; g_normal_db_cache->hash_table = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)destroy_key, (GDestroyNotify)destroy_data); g_normal_db_cache->size = 0; g_normal_db_cache->count = 0; } void cache_remove(enum layer_attribute_type layer_type, const char *key) { GHashTable *hash_table = NULL; bxt_cache *cache = get_cache(layer_type); if (!cache) return; hash_table = cache->hash_table; if (!hash_table) return; if (g_hash_table_remove(hash_table, key)) { bxt_dbg("[%s cache] removed (%s)/count(%d)/total size(%d)", (layer_type == LAYER_ATTRIBUTE_RW) ? "NORMAL" : "BASE", key, cache->count, cache->size); } } void cache_update_data(enum layer_attribute_type layer_type, const char *key, uint8_t *data, int len) { GHashTable *hash_table = NULL; gpointer raw_data; cache_data *cdata; bxt_cache *cache = get_cache(layer_type); if (!cache) return; hash_table = cache->hash_table; raw_data = g_hash_table_lookup(hash_table, key); if (!raw_data) { cache_insert(layer_type, key, data, len); return; } cdata = (cache_data *)raw_data; if (cdata->data) free(cdata->data); cdata->data = malloc(len); if (!cdata->data) return; memcpy(cdata->data, data, len); cdata->len = len; } static void cache_drop(enum layer_attribute_type layer_type, int size) { GHashTableIter iter; gpointer key; gpointer value; int remain = size; GHashTable *hash_table = NULL; bxt_cache *cache = get_cache(layer_type); if (!cache) return; hash_table = cache->hash_table; g_hash_table_iter_init(&iter, hash_table); while (g_hash_table_iter_next(&iter, &key, &value)) { if (remain > 0) { bxt_dbg("[%s cache][%d] removed (%s)", (layer_type == LAYER_ATTRIBUTE_RW) ? "NORMAL" : "BASE", remain, (char *)key); g_hash_table_iter_remove(&iter); remain--; } } } void cache_insert(enum layer_attribute_type layer_type, const char *key, uint8_t *data, int len) { GHashTable *hash_table = NULL; char *key_name; bxt_cache *cache = get_cache(layer_type); cache_data *raw_data; if (!cache) return; hash_table = cache->hash_table; if (g_hash_table_contains(hash_table, key)) return; if ((g_hash_table_size(hash_table) >= CACHE_COUNT_MAX) || (cache->size >= CACHE_SIZE_MAX)) cache_drop(layer_type, DEFAULT_DROP_CACHE_SIZE); key_name = (char *)strdup(key); if (!key_name) return; raw_data = (cache_data *)malloc(sizeof(cache_data)); if (!raw_data) { free(key_name); return; } raw_data->data = malloc(len); if (!raw_data->data) { free(key_name); free(raw_data); return; } memcpy(raw_data->data, data, len); raw_data->len = len; raw_data->layer_type = layer_type; g_hash_table_insert(hash_table, key_name, (gpointer) raw_data); cache->count++; cache->size += len; bxt_dbg("[%s cache] inserted (%s)/size(%d)/count(%d)/total size(%d)", (layer_type == LAYER_ATTRIBUTE_RW) ? "NORMAL" : "BASE", key, len, cache->count, cache->size); } int cache_get(enum layer_attribute_type layer_type, const char *key, void **data, int *data_len) { GHashTable *hash_table = NULL; gpointer raw_data; cache_data *cdata; bxt_cache *cache = get_cache(layer_type); if (!cache) return BUXTON_ERROR_INVALID_PARAMETER; hash_table = cache->hash_table; raw_data = g_hash_table_lookup(hash_table, key); if (!raw_data) return BUXTON_ERROR_NOT_EXIST; cdata = (cache_data *)raw_data; *data = malloc(cdata->len); if (!*data) return BUXTON_ERROR_OUT_OF_MEMORY; memcpy(*data, cdata->data, cdata->len); *data_len = cdata->len; bxt_dbg("[%s cache] get (%s)/size(%d)", (layer_type == LAYER_ATTRIBUTE_RW) ? "NORMAL" : "BASE", key, cdata->len); return BUXTON_ERROR_NONE; } void cache_clear(enum layer_attribute_type layer_type) { bxt_cache *cache = get_cache(layer_type); if (!cache) return; g_hash_table_remove_all(cache->hash_table); }