diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/sledjchisl/sledjchisl.c | 144 |
1 files changed, 61 insertions, 83 deletions
diff --git a/src/sledjchisl/sledjchisl.c b/src/sledjchisl/sledjchisl.c index 5a06fa2..ddb041d 100644 --- a/src/sledjchisl/sledjchisl.c +++ b/src/sledjchisl/sledjchisl.c | |||
@@ -979,7 +979,13 @@ static boolean dbCheckError(MYSQL *db, char *error, char *sql) | |||
979 | return FALSE; | 979 | return FALSE; |
980 | } | 980 | } |
981 | 981 | ||
982 | typedef struct _dbField dbField; | 982 | typedef struct _dbFields dbFields; |
983 | struct _dbFields | ||
984 | { | ||
985 | qlisttbl_t *flds; | ||
986 | int count; | ||
987 | }; | ||
988 | typedef struct _dbField dbField; | ||
983 | struct _dbField | 989 | struct _dbField |
984 | { | 990 | { |
985 | char *name; | 991 | char *name; |
@@ -989,11 +995,11 @@ struct _dbField | |||
989 | unsigned int decimals; | 995 | unsigned int decimals; |
990 | }; | 996 | }; |
991 | 997 | ||
992 | qlisttbl_t *dbGetFields(MYSQL *db, char *table) | 998 | dbFields *dbGetFields(MYSQL *db, char *table) |
993 | { | 999 | { |
994 | static qhashtbl_t *tables = NULL; | 1000 | static qhashtbl_t *tables = NULL; |
995 | if (NULL == tables) tables = qhashtbl(0, 0); | 1001 | if (NULL == tables) tables = qhashtbl(0, 0); |
996 | qlisttbl_t *ret = tables->get(tables, table, NULL, false); | 1002 | dbFields *ret = tables->get(tables, table, NULL, false); |
997 | 1003 | ||
998 | if (NULL == ret) | 1004 | if (NULL == ret) |
999 | { | 1005 | { |
@@ -1028,7 +1034,9 @@ d("Getting field metadata for %s", table); | |||
1028 | { | 1034 | { |
1029 | unsigned int i, num_fields = mysql_num_fields(res); | 1035 | unsigned int i, num_fields = mysql_num_fields(res); |
1030 | 1036 | ||
1031 | ret = qlisttbl(QLISTTBL_UNIQUE | QLISTTBL_LOOKUPFORWARD); | 1037 | ret = xmalloc(sizeof(dbFields)); |
1038 | ret->flds = qlisttbl(QLISTTBL_UNIQUE | QLISTTBL_LOOKUPFORWARD); | ||
1039 | ret->count = 1; | ||
1032 | for (i = 0; i < num_fields; i++) | 1040 | for (i = 0; i < num_fields; i++) |
1033 | { | 1041 | { |
1034 | dbField *fld = xmalloc(sizeof(dbField)); | 1042 | dbField *fld = xmalloc(sizeof(dbField)); |
@@ -1037,7 +1045,7 @@ d("Getting field metadata for %s", table); | |||
1037 | fld->length = fields[i].length; | 1045 | fld->length = fields[i].length; |
1038 | fld->flags = fields[i].flags; | 1046 | fld->flags = fields[i].flags; |
1039 | fld->decimals = fields[i].decimals; | 1047 | fld->decimals = fields[i].decimals; |
1040 | ret->put(ret, fld->name, fld, sizeof(*fld)); | 1048 | ret->flds->put(ret->flds, fld->name, fld, sizeof(*fld)); |
1041 | free(fld); | 1049 | free(fld); |
1042 | } | 1050 | } |
1043 | tables->put(tables, table, ret, sizeof(*ret)); | 1051 | tables->put(tables, table, ret, sizeof(*ret)); |
@@ -1047,24 +1055,30 @@ d("Getting field metadata for %s", table); | |||
1047 | } | 1055 | } |
1048 | free(sql); | 1056 | free(sql); |
1049 | } | 1057 | } |
1058 | else // Reference count these, coz some tables are used more than once. | ||
1059 | ret->count++; | ||
1050 | 1060 | ||
1051 | return ret; | 1061 | return ret; |
1052 | } | 1062 | } |
1053 | 1063 | ||
1054 | void dbFreeFields(qlisttbl_t *flds) | 1064 | void dbFreeFields(dbFields *flds) |
1055 | { | 1065 | { |
1056 | qlisttbl_obj_t obj; | 1066 | flds->count--; |
1057 | memset((void *) &obj, 0, sizeof(obj)); | 1067 | if (0 >= flds->count) |
1058 | flds->lock(flds); | ||
1059 | d("Freeing fields."); | ||
1060 | while(flds->getnext(flds, &obj, NULL, false) == true) | ||
1061 | { | 1068 | { |
1062 | dbField *fld = (dbField *) obj.data; | 1069 | qlisttbl_obj_t obj; |
1063 | d("Freeing field %s", fld->name); | 1070 | |
1064 | free(fld->name); | 1071 | memset((void *) &obj, 0, sizeof(obj)); |
1072 | flds->flds->lock(flds->flds); | ||
1073 | while(flds->flds->getnext(flds->flds, &obj, NULL, false) == true) | ||
1074 | { | ||
1075 | dbField *fld = (dbField *) obj.data; | ||
1076 | free(fld->name); | ||
1077 | } | ||
1078 | flds->flds->unlock(flds->flds); | ||
1079 | flds->flds->free(flds->flds); | ||
1080 | free(flds); | ||
1065 | } | 1081 | } |
1066 | flds->unlock(flds); | ||
1067 | flds->free(flds); | ||
1068 | } | 1082 | } |
1069 | 1083 | ||
1070 | enum dbCommandType | 1084 | enum dbCommandType |
@@ -1080,7 +1094,8 @@ struct _dbRequest | |||
1080 | { | 1094 | { |
1081 | MYSQL *db; | 1095 | MYSQL *db; |
1082 | char *table, *join, *where, *order, *sql; | 1096 | char *table, *join, *where, *order, *sql; |
1083 | MYSQL_STMT *prep, *prep0; // NOTE - executing it stores state in this. | 1097 | MYSQL_STMT *prep; // NOTE - executing it stores state in this. |
1098 | dbFields *fields; | ||
1084 | qlisttbl_t *flds; | 1099 | qlisttbl_t *flds; |
1085 | int inCount, outCount, rowCount; | 1100 | int inCount, outCount, rowCount; |
1086 | char **inParams, **outParams; | 1101 | char **inParams, **outParams; |
@@ -1111,13 +1126,14 @@ int dbDoSomething(dbRequest *req, boolean count, ...) | |||
1111 | if (0 == req->type) | 1126 | if (0 == req->type) |
1112 | req->type = CT_SELECT; | 1127 | req->type = CT_SELECT; |
1113 | 1128 | ||
1114 | req->flds = dbGetFields(req->db, req->table); | 1129 | req->fields = dbGetFields(req->db, req->table); |
1115 | if (NULL == req->flds) | 1130 | if (NULL == req->fields) |
1116 | { | 1131 | { |
1117 | E("Unknown fields for table %s.", req->table); | 1132 | E("Unknown fields for table %s.", req->table); |
1118 | ret++; | 1133 | ret++; |
1119 | goto end; | 1134 | goto end; |
1120 | } | 1135 | } |
1136 | req->flds = req->fields->flds; | ||
1121 | 1137 | ||
1122 | switch (req->type) | 1138 | switch (req->type) |
1123 | { | 1139 | { |
@@ -1200,8 +1216,6 @@ int dbDoSomething(dbRequest *req, boolean count, ...) | |||
1200 | d("New SQL statement - %s", req->sql); | 1216 | d("New SQL statement - %s", req->sql); |
1201 | // prepare statement with the other fields | 1217 | // prepare statement with the other fields |
1202 | req->prep = mysql_stmt_init(req->db); | 1218 | req->prep = mysql_stmt_init(req->db); |
1203 | // Save the pointer before something mysteriously clobbers it, so we can close it later. | ||
1204 | req->prep0 = req->prep; | ||
1205 | if (NULL == req->prep) | 1219 | if (NULL == req->prep) |
1206 | { | 1220 | { |
1207 | E("Statement prepare init failed: %s\n", mysql_stmt_error(req->prep)); | 1221 | E("Statement prepare init failed: %s\n", mysql_stmt_error(req->prep)); |
@@ -1820,17 +1834,6 @@ end: | |||
1820 | double n = (now.tv_sec * 1000000000.0) + now.tv_nsec; | 1834 | double n = (now.tv_sec * 1000000000.0) + now.tv_nsec; |
1821 | double t = (then.tv_sec * 1000000000.0) + then.tv_nsec; | 1835 | double t = (then.tv_sec * 1000000000.0) + then.tv_nsec; |
1822 | T("dbDoSomething(%s) took %lf seconds", req->sql, (n - t) / 1000000000.0); | 1836 | T("dbDoSomething(%s) took %lf seconds", req->sql, (n - t) / 1000000000.0); |
1823 | /* | ||
1824 | if (NULL != req->prep) | ||
1825 | I("The prepared statement itself is NOT NULL."); | ||
1826 | else | ||
1827 | W("The prepared statement itself is NULL!"); | ||
1828 | |||
1829 | if (NULL != req->prep0) | ||
1830 | I("The prepared0 statement itself is NOT NULL."); | ||
1831 | else | ||
1832 | W("The prepared0 statement itself is NULL!"); | ||
1833 | */ | ||
1834 | 1837 | ||
1835 | return ret; | 1838 | return ret; |
1836 | } | 1839 | } |
@@ -1863,30 +1866,20 @@ void dbFreeRequest(dbRequest *req) | |||
1863 | { | 1866 | { |
1864 | int i; | 1867 | int i; |
1865 | 1868 | ||
1866 | // TODO - this leaks for some bizare reason. Not even req->sql survives. | ||
1867 | D("Cleaning up prepared database request %s - %s %d %d", req->table, req->where, req->outCount, req->inCount); | 1869 | D("Cleaning up prepared database request %s - %s %d %d", req->table, req->where, req->outCount, req->inCount); |
1868 | 1870 | ||
1869 | if (NULL != req->prep) | 1871 | if (NULL != req->fields) |
1870 | I("The prepared statement itself is NOT NULL."); | 1872 | { |
1871 | else | 1873 | dbFreeFields(req->fields); |
1872 | W("The prepared statement itself is NULL!"); | 1874 | req->fields = NULL; |
1873 | 1875 | } | |
1874 | if (NULL != req->prep0) | ||
1875 | I("The prepared0 statement itself is NOT NULL."); | ||
1876 | else | ||
1877 | W("The prepared0 statement itself is NULL!"); | ||
1878 | |||
1879 | if (NULL != req->flds) | ||
1880 | dbFreeFields(req->flds); | ||
1881 | else | 1876 | else |
1882 | D("No fields to clean up for %s - %s.", req->table, req->where); | 1877 | D(" No fields to clean up for %s - %s.", req->table, req->where); |
1883 | 1878 | ||
1884 | if (NULL != req->outBind) | 1879 | if (NULL != req->outBind) |
1885 | { | 1880 | { |
1886 | d("Free outBind"); | ||
1887 | for (i = 0; i < req->outCount; i++) | 1881 | for (i = 0; i < req->outCount; i++) |
1888 | { | 1882 | { |
1889 | d("Free outBind %d %s", i, req->sql); | ||
1890 | if (NULL != req->outBind[i].buffer) free(req->outBind[i].buffer); | 1883 | if (NULL != req->outBind[i].buffer) free(req->outBind[i].buffer); |
1891 | if (NULL != req->outBind[i].length) free(req->outBind[i].length); | 1884 | if (NULL != req->outBind[i].length) free(req->outBind[i].length); |
1892 | if (NULL != req->outBind[i].error) free(req->outBind[i].error); | 1885 | if (NULL != req->outBind[i].error) free(req->outBind[i].error); |
@@ -1895,13 +1888,11 @@ d("Free outBind %d %s", i, req->sql); | |||
1895 | free(req->outBind); | 1888 | free(req->outBind); |
1896 | } | 1889 | } |
1897 | else | 1890 | else |
1898 | D("No out binds to clean up for %s - %s.", req->table, req->where); | 1891 | D(" No out binds to clean up for %s - %s.", req->table, req->where); |
1899 | if (NULL != req->inBind) | 1892 | if (NULL != req->inBind) |
1900 | { | 1893 | { |
1901 | d("Free inBind"); | ||
1902 | for (i = 0; i < req->inCount; i++) | 1894 | for (i = 0; i < req->inCount; i++) |
1903 | { | 1895 | { |
1904 | d("Free inBind %d %s", i, req->sql); | ||
1905 | if (NULL != req->inBind[i].buffer) free(req->inBind[i].buffer); | 1896 | if (NULL != req->inBind[i].buffer) free(req->inBind[i].buffer); |
1906 | if (NULL != req->inBind[i].length) free(req->inBind[i].length); | 1897 | if (NULL != req->inBind[i].length) free(req->inBind[i].length); |
1907 | if (NULL != req->inBind[i].error) free(req->inBind[i].error); | 1898 | if (NULL != req->inBind[i].error) free(req->inBind[i].error); |
@@ -1910,24 +1901,20 @@ d("Free inBind %d %s", i, req->sql); | |||
1910 | free(req->inBind); | 1901 | free(req->inBind); |
1911 | } | 1902 | } |
1912 | else | 1903 | else |
1913 | D("No in binds to clean up for %s - %s.", req->table, req->where); | 1904 | D(" No in binds to clean up for %s - %s.", req->table, req->where); |
1914 | 1905 | ||
1915 | if (req->freeOutParams) free(req->outParams); | 1906 | if (req->freeOutParams) free(req->outParams); |
1916 | else | 1907 | else |
1917 | D("No out params to clean up for %s - %s.", req->table, req->where); | 1908 | D(" No out params to clean up for %s - %s.", req->table, req->where); |
1918 | if (NULL != req->sql) free(req->sql); | 1909 | if (NULL != req->sql) free(req->sql); |
1919 | else | 1910 | else |
1920 | D("No SQL to clean up for %s - %s.", req->table, req->where); | 1911 | D(" No SQL to clean up for %s - %s.", req->table, req->where); |
1921 | if (NULL != req->prep0) | 1912 | if (NULL != req->prep) |
1922 | { | 1913 | { |
1923 | // TODO - this leaks for some bizare reason. | 1914 | if (0 != mysql_stmt_close(req->prep)) |
1924 | D(" Cleaning up the prepared statement."); | ||
1925 | if (0 != mysql_stmt_close(req->prep0)) | ||
1926 | C(" Unable to close the prepared statement!"); | 1915 | C(" Unable to close the prepared statement!"); |
1927 | free(req->prep0); | 1916 | req->prep = NULL; |
1928 | } | 1917 | } |
1929 | else | ||
1930 | W(" The prepared statement itself is NULL!"); | ||
1931 | } | 1918 | } |
1932 | 1919 | ||
1933 | my_ulonglong dbCount(MYSQL *db, char *table, char *where) | 1920 | my_ulonglong dbCount(MYSQL *db, char *table, char *where) |
@@ -2194,7 +2181,7 @@ gridStats *getStats(MYSQL *db, gridStats *stats) | |||
2194 | rgnSizes->inParams = szi; | 2181 | rgnSizes->inParams = szi; |
2195 | rgnSizes->outParams = szo; | 2182 | rgnSizes->outParams = szo; |
2196 | rgnSizes->where = "sizeX != 0"; | 2183 | rgnSizes->where = "sizeX != 0"; |
2197 | dbRequests->addfirst(dbRequests, rgnSizes, sizeof(*rgnSizes)); | 2184 | dbRequests->addfirst(dbRequests, &rgnSizes, sizeof(dbRequest *)); |
2198 | } | 2185 | } |
2199 | dbDoSomething(rgnSizes, FALSE); | 2186 | dbDoSomething(rgnSizes, FALSE); |
2200 | rowData *rows = rgnSizes->rows; | 2187 | rowData *rows = rgnSizes->rows; |
@@ -3876,7 +3863,7 @@ notWritten: | |||
3876 | acntsI->outParams = szo; | 3863 | acntsI->outParams = szo; |
3877 | acntsI->where = ""; | 3864 | acntsI->where = ""; |
3878 | acntsI->type = CT_CREATE; | 3865 | acntsI->type = CT_CREATE; |
3879 | dbRequests->addfirst(dbRequests, acntsI, sizeof(*acntsI)); | 3866 | dbRequests->addfirst(dbRequests, &acntsI, sizeof(dbRequest *)); |
3880 | } | 3867 | } |
3881 | static dbRequest *authI = NULL; | 3868 | static dbRequest *authI = NULL; |
3882 | if (NULL == authI) | 3869 | if (NULL == authI) |
@@ -3890,7 +3877,7 @@ notWritten: | |||
3890 | authI->outParams = szo; | 3877 | authI->outParams = szo; |
3891 | authI->where = ""; | 3878 | authI->where = ""; |
3892 | authI->type = CT_CREATE; | 3879 | authI->type = CT_CREATE; |
3893 | dbRequests->addfirst(dbRequests, authI, sizeof(*authI)); | 3880 | dbRequests->addfirst(dbRequests, &authI, sizeof(dbRequest *)); |
3894 | } | 3881 | } |
3895 | static dbRequest *invFolderI = NULL; | 3882 | static dbRequest *invFolderI = NULL; |
3896 | if (NULL == invFolderI) | 3883 | if (NULL == invFolderI) |
@@ -3913,7 +3900,7 @@ notWritten: | |||
3913 | invFolderI->outParams = szo; | 3900 | invFolderI->outParams = szo; |
3914 | invFolderI->where = ""; | 3901 | invFolderI->where = ""; |
3915 | invFolderI->type = CT_CREATE; | 3902 | invFolderI->type = CT_CREATE; |
3916 | dbRequests->addfirst(dbRequests, invFolderI, sizeof(*invFolderI)); | 3903 | dbRequests->addfirst(dbRequests, &invFolderI, sizeof(dbRequest *)); |
3917 | } | 3904 | } |
3918 | static dbRequest *gUserI = NULL; | 3905 | static dbRequest *gUserI = NULL; |
3919 | if (NULL == gUserI) | 3906 | if (NULL == gUserI) |
@@ -3928,7 +3915,7 @@ notWritten: | |||
3928 | gUserI->outParams = szo; | 3915 | gUserI->outParams = szo; |
3929 | gUserI->where = ""; | 3916 | gUserI->where = ""; |
3930 | gUserI->type = CT_CREATE; | 3917 | gUserI->type = CT_CREATE; |
3931 | dbRequests->addfirst(dbRequests, gUserI, sizeof(*gUserI)); | 3918 | dbRequests->addfirst(dbRequests, &gUserI, sizeof(dbRequest *)); |
3932 | } | 3919 | } |
3933 | 3920 | ||
3934 | I("Creating database user %s %s.", uuid, getStrH(Rd->stuff, "name")); | 3921 | I("Creating database user %s %s.", uuid, getStrH(Rd->stuff, "name")); |
@@ -5116,7 +5103,7 @@ static int accountRead(reqData *Rd, char *uuid, char *firstName, char *lastName) | |||
5116 | uuids->inParams = szi; | 5103 | uuids->inParams = szi; |
5117 | uuids->outParams = szo; | 5104 | uuids->outParams = szo; |
5118 | uuids->where = "PrincipalID=?"; | 5105 | uuids->where = "PrincipalID=?"; |
5119 | dbRequests->addfirst(dbRequests, uuids, sizeof(*uuids)); | 5106 | dbRequests->addfirst(dbRequests, &uuids, sizeof(dbRequest *)); |
5120 | } | 5107 | } |
5121 | static dbRequest *acnts = NULL; | 5108 | static dbRequest *acnts = NULL; |
5122 | if (NULL == acnts) | 5109 | if (NULL == acnts) |
@@ -5129,7 +5116,7 @@ static int accountRead(reqData *Rd, char *uuid, char *firstName, char *lastName) | |||
5129 | acnts->inParams = szi; | 5116 | acnts->inParams = szi; |
5130 | acnts->outParams = szo; | 5117 | acnts->outParams = szo; |
5131 | acnts->where = "FirstName=? and LastName=?"; | 5118 | acnts->where = "FirstName=? and LastName=?"; |
5132 | dbRequests->addfirst(dbRequests, acnts, sizeof(*acnts)); | 5119 | dbRequests->addfirst(dbRequests, &acnts, sizeof(dbRequest *)); |
5133 | } | 5120 | } |
5134 | static dbRequest *auth = NULL; | 5121 | static dbRequest *auth = NULL; |
5135 | if (NULL == auth) | 5122 | if (NULL == auth) |
@@ -5142,7 +5129,7 @@ static int accountRead(reqData *Rd, char *uuid, char *firstName, char *lastName) | |||
5142 | auth->inParams = szi; | 5129 | auth->inParams = szi; |
5143 | auth->outParams = szo; | 5130 | auth->outParams = szo; |
5144 | auth->where = "UUID=?"; | 5131 | auth->where = "UUID=?"; |
5145 | dbRequests->addfirst(dbRequests, auth, sizeof(*auth)); | 5132 | dbRequests->addfirst(dbRequests, &auth, sizeof(dbRequest *)); |
5146 | } | 5133 | } |
5147 | 5134 | ||
5148 | Rd->fromDb = FALSE; | 5135 | Rd->fromDb = FALSE; |
@@ -6328,23 +6315,14 @@ void account_html(char *file, reqData *Rd, HTMLfile *thisFile) | |||
6328 | 6315 | ||
6329 | static void cleanup(void) | 6316 | static void cleanup(void) |
6330 | { | 6317 | { |
6331 | // TODO - not sure why, but this gets called twice on quitting. | 6318 | // TODO - not sure why, but this gets called twice on quitting sometimes. |
6332 | C("Caught signal, or quitting, cleaning up."); | 6319 | C("Caught signal, or quitting, cleaning up."); |
6333 | dbRequest *req = NULL; | 6320 | dbRequest **rq; |
6334 | 6321 | ||
6335 | while (NULL != (req = (dbRequest *) dbRequests->getat(dbRequests, 0, NULL, false))) | 6322 | while (NULL != (rq = (dbRequest **) dbRequests->popfirst(dbRequests, NULL))) |
6336 | { | 6323 | { |
6337 | if (NULL != req->prep) | 6324 | dbFreeRequest(*rq); |
6338 | I("The prepared statement itself is NOT NULL."); | 6325 | free(rq); |
6339 | else | ||
6340 | W("The prepared statement itself is NULL!"); | ||
6341 | |||
6342 | if (NULL != req->prep0) | ||
6343 | I("The prepared0 statement itself is NOT NULL."); | ||
6344 | else | ||
6345 | W("The prepared0 statement itself is NULL!"); | ||
6346 | dbFreeRequest(req); | ||
6347 | dbRequests->removefirst(dbRequests); | ||
6348 | } | 6326 | } |
6349 | 6327 | ||
6350 | if (accountPages) | 6328 | if (accountPages) |