From 01ff056a55b198b91ef327d7ca223bab9452034c Mon Sep 17 00:00:00 2001 From: Detlev Casanova Date: Thu, 15 Jul 2010 12:09:26 +0200 Subject: Get to work with the changes in layman. Fix most of the memory leaks --- src/config.c | 34 ++++++++++++++++-- src/config.h | 3 +- src/dbbase.c | 10 ++++++ src/dbbase.h | 1 + src/laymanapi.c | 105 ++++++++++++++++++++++++++++++++++++------------------- src/laymanapi.h | 29 +++++---------- src/message.c | 10 ++++++ src/message.h | 5 +-- src/stringlist.c | 57 +++++++++++++++++++++++------- src/stringlist.h | 13 ++++--- src/tester.c | 36 ++++++++++++++----- 11 files changed, 214 insertions(+), 89 deletions(-) diff --git a/src/config.c b/src/config.c index 624f1ab..47d4437 100644 --- a/src/config.c +++ b/src/config.c @@ -57,16 +57,44 @@ const char* bareConfigGetDefaultValue(BareConfig* cfg, const char* opt) return NULL; if (PyDict_Contains(obj, PyBytes_FromString(opt))) - return PyBytes_AsString(PyDict_GetItem(obj, PyBytes_FromString(opt))); + { + PyObject *pyopt = PyBytes_FromString(opt); + char *tmp = PyBytes_AsString(PyDict_GetItem(obj, pyopt)); + Py_DECREF(pyopt); + + char *ret = malloc(sizeof(char) * strlen(tmp)); + strcpy(ret, tmp); + Py_DECREF(obj); + + return ret; + } else return ""; } +const char* bareConfigGetOptionValue(BareConfig* cfg, const char* opt) +{ + PyObject *obj = PyObject_CallMethod(cfg->object, "get_option", "(z)", opt); + char *tmp = PyBytes_AsString(obj); + char *ret = malloc(sizeof(char) * (strlen(tmp) + 1)); + + strcpy(ret, tmp); + + Py_DECREF(obj); + + return ret; +} + int bareConfigSetOptionValue(BareConfig* cfg, const char* opt, const char* val) { PyObject *obj = PyObject_CallMethod(cfg->object, "set_option", "(zz)", opt, val); + int ret; if (obj) - return 1; + ret = 1; else - return 0; + ret = 0; + + Py_DECREF(obj); + + return ret; } diff --git a/src/config.h b/src/config.h index 33bfd1e..a89883b 100644 --- a/src/config.h +++ b/src/config.h @@ -15,10 +15,9 @@ BareConfig* bareConfigCreate(Message* m, FILE* outFd, FILE* inFd, FILE* errFd); */ const char* bareConfigGetDefaultValue(BareConfig* cfg, const char*); +const char* bareConfigGetOptionValue(BareConfig* cfg, const char* opt); int bareConfigSetOptionValue(BareConfig* cfg, const char*, const char*); - PyObject* _bareConfigObject(BareConfig*); - void bareConfigFree(BareConfig*); #endif diff --git a/src/dbbase.c b/src/dbbase.c index dbff007..fdefac4 100644 --- a/src/dbbase.c +++ b/src/dbbase.c @@ -29,3 +29,13 @@ DbBase* createDbBase(const char *paths[], unsigned int pathCount, Dict *dict, in return ret; } + +void dbBaseFree(DbBase* db) +{ + if (db && db->object) + { + Py_DECREF(db->object); + } + if (db) + free(db); +} diff --git a/src/dbbase.h b/src/dbbase.h index 56f9270..bd3786c 100644 --- a/src/dbbase.h +++ b/src/dbbase.h @@ -7,5 +7,6 @@ typedef struct DbBase DbBase; DbBase* createDbBase(const char *paths[], unsigned int path_count, Dict *c, int ignore, int quiet, int ignore_init_read_errors); +void dbBaseFree(DbBase*); #endif diff --git a/src/laymanapi.c b/src/laymanapi.c index 328a572..4509511 100644 --- a/src/laymanapi.c +++ b/src/laymanapi.c @@ -19,7 +19,7 @@ OverlayInfo strToInfo(const char* str) LaymanAPI* laymanAPICreate(BareConfig* config, int report_error, int output) { - PyObject *obj = executeFunction("layman.api", "LaymanAPI", "OII", _bareConfigObject(config), report_error, output); + PyObject *obj = executeFunction("layman.api", "LaymanAPI", "Oii", _bareConfigObject(config), report_error, output); if (!obj) return NULL; @@ -29,92 +29,127 @@ LaymanAPI* laymanAPICreate(BareConfig* config, int report_error, int output) return ret; } -StringList* laymanAPIGetAvailable(LaymanAPI* l) +StringList* laymanAPIGetAvailable(LaymanAPI* l, int reload) { if (!l || !l->object) return NULL; - PyObject *obj = PyObject_CallMethod(l->object, "get_available", NULL); - StringList* ret = listToCList(obj); + PyObject *obj = PyObject_CallMethod(l->object, "get_available", "(i)", reload); + StringList *ret = listToCList(obj); Py_DECREF(obj); return ret; } -StringList* laymanAPIGetInstalled(LaymanAPI* l) +/*StringList* laymanAPIGetInstalled(LaymanAPI* l) +{ + return laymanAPIGetInstalled(l, 0); +}*/ + +StringList* laymanAPIGetInstalled(LaymanAPI* l, int reload) { if (!l || !l->object) return NULL; - PyObject *obj = PyObject_CallMethod(l->object, "get_installed", NULL); + PyObject *obj = PyObject_CallMethod(l->object, "get_installed", "(i)", reload); StringList* ret = listToCList(obj); Py_DECREF(obj); return ret; } -int laymanAPISync(LaymanAPI* l, const char* overlay) +int laymanAPISync(LaymanAPI* l, const char* overlay, int verbose) { if (!l || !l->object) - return EXIT_FAILURE; - - PyObject *list = PyList_New(1); - PyList_Insert(list, 0, PyBytes_FromString(overlay)); - - PyObject *obj = PyObject_CallMethod(l->object, "sync", "O", list); - Py_DECREF(list); + return 0; + PyObject *obj = PyObject_CallMethod(l->object, "sync", "(si)", overlay, verbose); if (!obj) - return EXIT_FAILURE; + return 0; - PyObject *success = PyList_GetItem(obj, 1); - if (success == Py_None) - return EXIT_FAILURE; + int ret; + if (PyObject_IsTrue(obj)) + ret = 1; + else + ret = 0; + + Py_DECREF(obj); - return EXIT_SUCCESS; + return ret; } int laymanAPIFetchRemoteList(LaymanAPI* l) { if (!l || !l->object) - return EXIT_FAILURE; + return 0; PyObject *obj = PyObject_CallMethod(l->object, "fetch_remote_list", NULL); int ret; - if (PyObject_IsTrue(obj)) - ret = EXIT_SUCCESS; + if (!PyObject_IsTrue(obj)) //FIXME : does this work ? It seems to return 1 when false and 0 when true + ret = 1; else - ret = EXIT_FAILURE; + ret = 0; Py_DECREF(obj); return ret; } -const char* laymanAPIGetInfo(LaymanAPI* l, const char* overlay) +OverlayInfo *laymanAPIGetInfo(LaymanAPI* l, const char* overlay) { - if (!l || !l->object) + if (!l || !l->object || !overlay) return NULL; PyObject *list = PyList_New(1); - PyList_Insert(list, 0, PyBytes_FromString(overlay)); + PyList_SetItem(list, 0, PyBytes_FromString(overlay)); - PyObject *obj = PyObject_CallMethod(l->object, "get_info", "O", list); + PyObject *obj = PyObject_CallMethod(l->object, "get_info", "(O)", list); Py_DECREF(list); - if (!obj) + if (!obj || !PyDict_Check(obj)) + { + if (obj) + { + Py_DECREF(obj); + } return NULL; + } - PyObject *result = PyList_GetItem(obj, 0); - char* tmp = PyBytes_AsString(result); - char* ret = malloc((strlen(tmp) + 1) * sizeof(char)); - strcpy(ret, tmp); - Py_DECREF(result); + PyObject *tuple = PyDict_GetItemString(obj, overlay); - return ret; - //TODO:also return 'official' an 'supported' (see laymanapi.h) + if (!tuple || !PyTuple_Check(tuple)) + { + if (tuple) + { + Py_DECREF(tuple); + } + Py_DECREF(obj); + + return NULL; + } + + PyObject *text = PyTuple_GetItem(tuple, 0); + PyObject *official = PyTuple_GetItem(tuple, 1); + PyObject *supported = PyTuple_GetItem(tuple, 2); + + OverlayInfo *oi = malloc(sizeof(OverlayInfo)); + + char* tmp = PyBytes_AsString(text); + oi->text = malloc((strlen(tmp) + 1) * sizeof(char)); + strcpy(oi->text, tmp); + + oi->official = PyObject_IsTrue(official); + oi->supported = PyObject_IsTrue(supported); + + Py_DECREF(obj); + Py_DECREF(tuple); + Py_DECREF(text); + Py_DECREF(official); + Py_DECREF(supported); + + return oi; } void laymanAPIFree(LaymanAPI* l) diff --git a/src/laymanapi.h b/src/laymanapi.h index c89d3a4..0a38169 100644 --- a/src/laymanapi.h +++ b/src/laymanapi.h @@ -10,7 +10,8 @@ typedef enum OverlayType {Svn = 0, Git, Bzr} OverlayType; typedef enum OverlayQuality {Experimental = 0, Stable, Testing} OverlayQuality; typedef struct OverlayInfo { - char *name; + char *text; + /*char *name; char *source; char *contact; OverlayType type; @@ -18,32 +19,18 @@ typedef struct OverlayInfo OverlayQuality quality; char *description; char *link; - char *feed; + char *feed;*/ int official; int supported; } OverlayInfo; LaymanAPI* laymanAPICreate(BareConfig*, int, int); -StringList* laymanAPIGetAvailable(LaymanAPI*); -StringList* laymanAPIGetInstalled(LaymanAPI*); - -/* - * The Python API returns a list of warnings/sucesses/errors - * In here, a boolean value is returned. - * Warnings can be retreived with - * laymanAPIWarnings() - * laymanAPIErrors() - * As there's only one argument here, there's need to have success results. - * - * The reason it's done this way is that the Python way of doing things is not the same as the Python way. - * - * FIXME:is it a good idea to have different APIs for different languages ? - */ -int laymanAPISync(LaymanAPI*, const char*); +StringList* laymanAPIGetAvailable(LaymanAPI*, int reload); +StringList* laymanAPIGetInstalled(LaymanAPI*, int reload); +int laymanAPISync(LaymanAPI* l, const char* overlay, int verbose); int laymanAPIFetchRemoteList(LaymanAPI*); -const char* laymanAPIGetInfo(LaymanAPI*, const char*); - -void laymanAPIFree(LaymanAPI*); +OverlayInfo *laymanAPIGetInfo(LaymanAPI* l, const char* overlay); +void laymanAPIFree(LaymanAPI*); #endif diff --git a/src/message.c b/src/message.c index 85a1717..14b211c 100644 --- a/src/message.c +++ b/src/message.c @@ -69,6 +69,16 @@ Message *messageCreate(const char* module, return ret; } +void messageFree(Message *m) +{ + if (m && m->object) + { + Py_DECREF(m->object); + } + if (m) + free(m); +} + PyObject *_messageObject(Message* m) { if (m && m->object) diff --git a/src/message.h b/src/message.h index 15f3e15..33399f6 100644 --- a/src/message.h +++ b/src/message.h @@ -9,7 +9,8 @@ typedef struct Message Message; /* * arguments : module (String), stdout (fd), stderr (fd), stderr (fd), debug_level, debug_verbosity, info_level, warn_level, ?, ?, ?, ? */ -Message *messageCreate(const char*, FILE*, FILE*, FILE*, int, int, int, int, int, StringList*, StringList*, StringList*); -PyObject *_messageObject(Message* m); +Message* messageCreate(const char*, FILE*, FILE*, FILE*, int, int, int, int, int, StringList*, StringList*, StringList*); +PyObject* _messageObject(Message* m); +void messageFree(Message *m); #endif diff --git a/src/stringlist.c b/src/stringlist.c index 22d6ef6..7944564 100644 --- a/src/stringlist.c +++ b/src/stringlist.c @@ -3,12 +3,41 @@ struct StringList { char **list; - int count; + unsigned int count; }; -StringList* stringListCreate(size_t count) +StringList* stringListCreate(size_t len) { - return NULL; + StringList *ret = malloc(sizeof(StringList)); + ret->count = len; + ret->list = malloc(sizeof(char*) * len); + + return ret; +} + +int stringListInsertAt(StringList *l, unsigned int pos, char *str) +{ + if(!l || !l->list || l->count < pos) + return 0; + + l->list[pos] = str; + + return 1; +} + +unsigned int stringListCount(StringList *l) +{ + if (!l) + return 0; + return l->count; +} + +char* stringListGetAt(StringList *l, unsigned int pos) +{ + if (!l || !l->list || pos >= l->count) + return NULL; + + return l->list[pos]; } StringList* listToCList(PyObject* list) @@ -16,12 +45,12 @@ StringList* listToCList(PyObject* list) if (!list || !PyList_Check(list)) return NULL; - int len = PyList_Size(list); + unsigned int len = PyList_Size(list); StringList *ret = malloc(sizeof(StringList)); ret->count = len; ret->list = malloc(sizeof(char*) * len); - for (int i = 0; i < len; i++) + for (unsigned int i = 0; i < len; i++) { PyObject *elem = PyList_GetItem(list, i); ret->list[i] = malloc(sizeof(char) * (PyBytes_Size(elem) + 1)); @@ -37,7 +66,7 @@ PyObject* cListToPyList(StringList* list) Py_RETURN_NONE; PyObject *ret = PyList_New(list->count); - for(int i = 0; i < list->count; i++) + for(unsigned int i = 0; i < list->count; i++) { PyList_Append(ret, PyBytes_FromString(list->list[i])); } @@ -50,14 +79,12 @@ void stringListPrint(StringList* list) if (!list) return; - for(int i = 0; i < list->count; i++) + for(unsigned int i = 0; i < list->count; i++) { printf("\"%s\"", list->list[i]); if (i < list->count - 1) printf(", "); } - - free(list); } void stringListFree(StringList* list) @@ -65,11 +92,17 @@ void stringListFree(StringList* list) if (!list) return; - for(int i = 0; i < list->count; i++) + if (list && list->list) { - free(list->list[i]); + for(unsigned int i = 0; i < list->count; i++) + { + free(list->list[i]); + } + + free(list->list); } - free(list); + if (list) + free(list); } diff --git a/src/stringlist.h b/src/stringlist.h index 46151a4..00b4e76 100644 --- a/src/stringlist.h +++ b/src/stringlist.h @@ -5,10 +5,13 @@ typedef struct StringList StringList; -StringList* stringListCreate(size_t); -StringList* listToCList(PyObject* list); -PyObject* cListToPyList(StringList*); -void stringListPrint(StringList*); -void stringListFree(StringList*); +StringList* stringListCreate(size_t); +unsigned int stringListCount(StringList*); +int stringListInsertAt(StringList*, unsigned int, char*); +char* stringListGetAt(StringList*, unsigned int); +StringList* listToCList(PyObject* list); +PyObject* cListToPyList(StringList*); +void stringListPrint(StringList*); +void stringListFree(StringList*); #endif diff --git a/src/tester.c b/src/tester.c index 7fc40f9..1d31407 100644 --- a/src/tester.c +++ b/src/tester.c @@ -13,27 +13,45 @@ int main(int argc, char *argv[]) Message *msg = messageCreate("layman", 0, 0, 0, 4, 2, 4, 4, 1, NULL, NULL, NULL); BareConfig *cfg = bareConfigCreate(msg, 0, 0, 0); - if (!bareConfigSetOptionValue(cfg, "local_list", "/home/detlev/srg/gsoc2010/layman/layman/tests/testfiles/global-overlays.xml")) + /*if (!bareConfigSetOptionValue(cfg, "local_list", "/home/detlev/src/gsoc2010/layman/layman/tests/testfiles/global-overlays.xml")) printf("Error setting config option.\n"); - //printf("config: %s\n", bareConfigGetDefaultValue(cfg, "config")); - //printf("storage: %s\n", bareConfigGetDefaultValue(cfg, "storage")); - //printf("local_list: %s\n", bareConfigGetDefaultValue(cfg, "local_list")); - + if (!bareConfigSetOptionValue(cfg, "storage", "/home/detlev/gsoc2010/layman-test")) + printf("Error setting config option.\n"); + printf("config: %s\n", bareConfigGetOptionValue(cfg, "config")); + printf("storage: %s\n", bareConfigGetOptionValue(cfg, "storage")); + printf("local_list: %s\n", bareConfigGetOptionValue(cfg, "local_list"));*/ + LaymanAPI *l = laymanAPICreate(cfg, 0, 0); - if (!laymanAPIFetchRemoteList(l)) + /*if (0 == laymanAPIFetchRemoteList(l)) { printf("Unable to fetch the remote list.\n"); ret = -1; goto finish; - } - - StringList *strs = laymanAPIGetAvailable(l); + }*/ + StringList *strs = laymanAPIGetAvailable(l, 0); + printf("list:\n"); stringListPrint(strs); + + printf("\n"); + + unsigned int len = stringListCount(strs); + for (unsigned int i = 0; i < len; i++) + { + OverlayInfo *info = laymanAPIGetInfo(l, stringListGetAt(strs, i)); + if (!info) + continue; + printf("%s\n", info->text); + free(info->text); + free(info); + } + + printf("\n"); finish: bareConfigFree(cfg); laymanAPIFree(l); + stringListFree(strs); interpreterFinalize(); -- cgit v1.2.3-1-g7c22