From a10a8fb335e5a817e1a9add49ee179394eea67c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20Luka=20=C5=A0ijanec?= Date: Sun, 26 Dec 2021 19:52:31 +0100 Subject: fixed parser, fixed leak, O(log n) storage - tsearch(3) - 0.0.17 --- src/structs.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 20 deletions(-) (limited to 'src/structs.c') diff --git a/src/structs.c b/src/structs.c index 83d19b9..650eb88 100644 --- a/src/structs.c +++ b/src/structs.c @@ -4,22 +4,28 @@ #define SC_CRLE(c, name) (pthread_rwlock_rdlock(name) ? (SC_LOG(SC_LOG_ERROR,c,SC_I18N_LOCKING " " #name " " SC_I18N_FAILED)||1) :0) #define SC_CUE(c, name) (pthread_rwlock_unlock(name) ? (SC_LOG(SC_LOG_ERROR,c,SC_I18N_UNLOCKING " " #name " " SC_I18N_FAILED)||1):0) #define SC_REALLOC_K 1.5 /* constant to dynamically realloc large arrays (new size = current size * K) */ -#define SC_ENGINE_GOOGLE (1 << 0) /* _Atomic(size_t) sc_mem_max = 100e6; */ /* the really soft memory limit of the program: 100MB - NOT IMPLEMENTED */ #define SC_LOG(t, c, m, ...) sc_push_log(t, c, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) -#define SC_LOG_ERROR (1 << 0) -#define SC_LOG_WARNING (1 << 1) -#define SC_LOG_INFO (1 << 2) -#define SC_LOG_DEBUG (1 << 3) #define SC_BIGGER_ARRAY(name, type, shallinit) do { \ name = realloc(name, sizeof(name[0])*ceil(name##_sizeof*SC_REALLOC_K)); \ for (size_t i = name##_sizeof; shallinit && (i < ceil(name##_sizeof*SC_REALLOC_K)); i++) \ name[i] = type##_init(); \ name##_sizeof = ceil(name##_sizeof*SC_REALLOC_K); /* ceil je ZELO pomemben, če je chunk 1 recimo */ \ } while (0); -#define SC_OPT_TYPE unsigned char -#define SC_OPT_IMAGE (1 << 0) #define SC_STR(x) #x +enum sc_opt { + SC_ENGINE_GOOGLE = 1 << 0, + SC_LOG_ERROR = 1 << 1, + SC_LOG_WARNING = 1 << 2, + SC_LOG_INFO = 1 << 3, + SC_LOG_DEBUG = 1 << 4, + SC_OPT_IMAGE = 1 << 5 +}; +#define SC_LOG_MASK (SC_LOG_ERROR | SC_LOG_WARNING | SC_LOG_INFO | SC_LOG_DEBUG) +#define SC_OPT_TYPE enum sc_opt +#define SC_OPT_INIT 0 +#define SC_OPT_COMPAR /* mask */ (/* SC_ENGINE_GOOGLE | */ /* any engine is okay */ SC_OPT_IMAGE) +#define SC_COMPAR_CAST (int (*)(const void *, const void *)) #ifdef SC_LOGMEM struct sc_logentry { unsigned char type; /* SC_LOG_ERROR, SC_LOG_WARNING, SC_LOG_INFO, SC_LOG_DEBUG */ @@ -32,6 +38,19 @@ struct sc_logentry { int sc_logentry_free (struct sc_logentry * l); /* defined in log.c */ struct sc_logentry * sc_logentry_init (); /* defined in log.c */ #endif +struct sc_cache { +#ifdef SC_OLD_STORAGE + SC_IN_STRUCT_ARRAY(struct sc_query, queries); /* yesfree */ +#else + void * qrp; /* queries root pointer-tsearch(3) */ +#endif + pthread_rwlock_t * queries_lock; +#ifdef SC_LOGMEM + SC_IN_STRUCT_ARRAY(struct sc_logentry, logentries); /* yesfree */ + pthread_rwlock_t * logentries_lock; +#endif +}; +int sc_push_log (unsigned char t, struct sc_cache * c, const char * ca, char * f, size_t l, unsigned short int isf, char * m, ...); struct sc_result { struct sc_query * query; /* nofree - free from sc_cache */ char * url; /* yesfree - url of referer page when image searching */ @@ -65,8 +84,7 @@ struct sc_query { SC_IN_STRUCT_ARRAY(struct sc_result, results); /* yesfree */ char * string; /* yesfree - query string, stripped of any excess characters that should be excluded from indexing */ time_t lookup_time; /* time of last lookup */ - unsigned char engines; /* with what engine(s) was the query done - bitmask - if there are results from multiple engines */ - SC_OPT_TYPE opt; /* some options */ + SC_OPT_TYPE opt; /* some options including engines */ }; struct sc_query * sc_query_init () { struct sc_query * q = calloc(1, sizeof(struct sc_query)); @@ -77,31 +95,60 @@ struct sc_query * sc_query_init () { q->results[i]->query = q; } q->string = NULL; + q->opt = SC_OPT_INIT; return q; } -int sc_query_free (struct sc_query * q) { +#ifdef SC_OLD_STORAGE +int +#else +void +#endif +sc_query_free ( +#ifdef SC_OLD_STORAGE + struct sc_query +#else + void +#endif + * i) { + struct sc_query * q = +#ifndef SC_OLD_STORAGE + (struct sc_query *) +#endif + i; if (!q) - return -1; + return +#ifdef SC_OLD_STORAGE + -1 +#endif + ; + if (q->cache) + SC_LOG(SC_LOG_DEBUG, q->cache, "sc_query_free: %s", q->string ? q->string : "NULL"); free(q->string); /* if they were not alloced, they are NULL, if they were free'd somewhere else, they are also set to NULL */ for (size_t i = 0; i < q->results_sizeof; i++) sc_result_free(q->results[i]); free(q->results); free(q); - return 1; -} -struct sc_cache { - SC_IN_STRUCT_ARRAY(struct sc_query, queries); /* yesfree */ - pthread_rwlock_t * queries_lock; -#ifdef SC_LOGMEM - SC_IN_STRUCT_ARRAY(struct sc_logentry, logentries); /* yesfree */ - pthread_rwlock_t * logentries_lock; + return +#ifdef SC_OLD_STORAGE + 1 #endif -}; + ; +} +int sc_query_compar (const struct sc_query * a, const struct sc_query * b) { +#define SC_QUERY_COMPAR_OPT ->opt & SC_OPT_COMPAR + int r = (a SC_QUERY_COMPAR_OPT) < (b SC_QUERY_COMPAR_OPT) ? -1 + : (a SC_QUERY_COMPAR_OPT) > (b SC_QUERY_COMPAR_OPT) ? 1 : 0; + if (r) /* first we compare options, because it should be faster than query strings */ + return r; /* yeah, I know, useless optimizations */ + return strcmp(a->string, b->string); +} struct sc_cache * sc_cache_init() { #define SC_CILI(name) do { name##_lock = malloc(sizeof(pthread_rwlock_t)); pthread_rwlock_init(name##_lock, NULL); } while (0) struct sc_cache * c = calloc(1, sizeof(struct sc_cache)); +#ifdef SC_OLD_STORAGE c->queries_sizeof = SC_ALLOC_CHUNK; c->queries = calloc(c->queries_sizeof, sizeof(struct sc_query *)); +#endif #ifdef SC_LOGMEM c->logentries_sizeof = SC_ALLOC_CHUNK; c->logentries = calloc(c->logentries_sizeof, sizeof(struct sc_logentry *)); @@ -116,10 +163,14 @@ int sc_cache_free(struct sc_cache * c) { #define SC_CFLD(name) do { pthread_rwlock_destroy(name##_lock); free(name##_lock); } while(0) if (!c) return -1; +#ifdef SC_OLD_STORAGE fprintf(stderr, "c->queries_sizeof = %zu\n", c->queries_sizeof); for (size_t i = 0; i < c->queries_sizeof; i++) sc_query_free(c->queries[i]); free(c->queries); +#else + tdestroy(c->qrp, sc_query_free); +#endif #ifdef SC_LOGMEM for (size_t i = 0; i < c->logentries_sizeof; i++) sc_logentry_free(c->logentries[i]); -- cgit v1.2.3