liquid_feedback_core
annotate lf_update.c @ 423:73c2ab2d068f
Work on configuration of complexity of counting of the votes (extent of tie-breaking):
- added configuration field in "policy" table
- calculation of secondary criterion for the defeat strength (tie-breaking of the links) based on initiative id's
- added configuration field in "policy" table
- calculation of secondary criterion for the defeat strength (tie-breaking of the links) based on initiative id's
author | jbe |
---|---|
date | Thu Apr 10 00:20:03 2014 +0200 (2014-04-10) |
parents | 3f7a89ad996d |
children | 5855ff9e5c8f |
rev | line source |
---|---|
jbe@0 | 1 #include <stdlib.h> |
jbe@0 | 2 #include <stdio.h> |
jbe@0 | 3 #include <string.h> |
jbe@0 | 4 #include <libpq-fe.h> |
jbe@0 | 5 |
jbe@345 | 6 static char *escapeLiteral(PGconn *conn, const char *str, size_t len) { |
jbe@345 | 7 // provides compatibility for PostgreSQL versions prior 9.0 |
jbe@345 | 8 // in future: return PQescapeLiteral(conn, str, len); |
jbe@345 | 9 char *res; |
jbe@345 | 10 size_t res_len; |
jbe@345 | 11 res = malloc(2*len+3); |
jbe@357 | 12 if (!res) return NULL; |
jbe@345 | 13 res[0] = '\''; |
jbe@345 | 14 res_len = PQescapeStringConn(conn, res+1, str, len, NULL); |
jbe@345 | 15 res[res_len+1] = '\''; |
jbe@345 | 16 res[res_len+2] = 0; |
jbe@345 | 17 return res; |
jbe@345 | 18 } |
jbe@345 | 19 |
jbe@345 | 20 static void freemem(void *ptr) { |
jbe@345 | 21 // to be used for "escapeLiteral" function |
jbe@345 | 22 // provides compatibility for PostgreSQL versions prior 9.0 |
jbe@345 | 23 // in future: PQfreemem(ptr); |
jbe@345 | 24 free(ptr); |
jbe@345 | 25 } |
jbe@345 | 26 |
jbe@0 | 27 int main(int argc, char **argv) { |
jbe@1 | 28 |
jbe@1 | 29 // variable declarations: |
jbe@65 | 30 int err = 0; |
jbe@0 | 31 int i, count; |
jbe@0 | 32 char *conninfo; |
jbe@0 | 33 PGconn *db; |
jbe@334 | 34 PGresult *res; |
jbe@1 | 35 |
jbe@1 | 36 // parse command line: |
jbe@0 | 37 if (argc == 0) return 1; |
jbe@0 | 38 if (argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { |
jbe@0 | 39 FILE *out; |
jbe@0 | 40 out = argc == 1 ? stderr : stdout; |
jbe@362 | 41 fprintf(out, "\n"); |
jbe@362 | 42 fprintf(out, "Usage: %s <conninfo>\n", argv[0]); |
jbe@362 | 43 fprintf(out, "\n"); |
jbe@362 | 44 fprintf(out, "<conninfo> is specified by PostgreSQL's libpq,\n"); |
jbe@362 | 45 fprintf(out, "see http://www.postgresql.org/docs/9.1/static/libpq-connect.html\n"); |
jbe@362 | 46 fprintf(out, "\n"); |
jbe@362 | 47 fprintf(out, "Example: %s dbname=liquid_feedback\n", argv[0]); |
jbe@362 | 48 fprintf(out, "\n"); |
jbe@0 | 49 return argc == 1 ? 1 : 0; |
jbe@0 | 50 } |
jbe@0 | 51 { |
jbe@0 | 52 size_t len = 0; |
jbe@0 | 53 for (i=1; i<argc; i++) len += strlen(argv[i]) + 1; |
jbe@0 | 54 conninfo = malloc(len * sizeof(char)); |
jbe@0 | 55 if (!conninfo) { |
jbe@0 | 56 fprintf(stderr, "Error: Could not allocate memory for conninfo string\n"); |
jbe@0 | 57 return 1; |
jbe@0 | 58 } |
jbe@0 | 59 conninfo[0] = 0; |
jbe@0 | 60 for (i=1; i<argc; i++) { |
jbe@0 | 61 if (i>1) strcat(conninfo, " "); |
jbe@0 | 62 strcat(conninfo, argv[i]); |
jbe@0 | 63 } |
jbe@0 | 64 } |
jbe@1 | 65 |
jbe@1 | 66 // connect to database: |
jbe@0 | 67 db = PQconnectdb(conninfo); |
jbe@0 | 68 if (!db) { |
jbe@0 | 69 fprintf(stderr, "Error: Could not create database handle\n"); |
jbe@0 | 70 return 1; |
jbe@0 | 71 } |
jbe@0 | 72 if (PQstatus(db) != CONNECTION_OK) { |
jbe@0 | 73 fprintf(stderr, "Could not open connection:\n%s", PQerrorMessage(db)); |
jbe@0 | 74 return 1; |
jbe@0 | 75 } |
jbe@1 | 76 |
jbe@235 | 77 // delete expired sessions: |
jbe@334 | 78 res = PQexec(db, "DELETE FROM \"expired_session\""); |
jbe@334 | 79 if (!res) { |
jbe@235 | 80 fprintf(stderr, "Error in pqlib while sending SQL command deleting expired sessions\n"); |
jbe@235 | 81 err = 1; |
jbe@235 | 82 } else if ( |
jbe@334 | 83 PQresultStatus(res) != PGRES_COMMAND_OK && |
jbe@334 | 84 PQresultStatus(res) != PGRES_TUPLES_OK |
jbe@235 | 85 ) { |
jbe@334 | 86 fprintf(stderr, "Error while executing SQL command deleting expired sessions:\n%s", PQresultErrorMessage(res)); |
jbe@235 | 87 err = 1; |
jbe@334 | 88 PQclear(res); |
jbe@235 | 89 } else { |
jbe@334 | 90 PQclear(res); |
jbe@235 | 91 } |
jbe@235 | 92 |
jbe@184 | 93 // check member activity: |
jbe@334 | 94 res = PQexec(db, "SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SELECT \"check_activity\"()"); |
jbe@334 | 95 if (!res) { |
jbe@184 | 96 fprintf(stderr, "Error in pqlib while sending SQL command checking member activity\n"); |
jbe@103 | 97 err = 1; |
jbe@103 | 98 } else if ( |
jbe@334 | 99 PQresultStatus(res) != PGRES_COMMAND_OK && |
jbe@334 | 100 PQresultStatus(res) != PGRES_TUPLES_OK |
jbe@103 | 101 ) { |
jbe@334 | 102 fprintf(stderr, "Error while executing SQL command checking member activity:\n%s", PQresultErrorMessage(res)); |
jbe@103 | 103 err = 1; |
jbe@334 | 104 PQclear(res); |
jbe@103 | 105 } else { |
jbe@334 | 106 PQclear(res); |
jbe@103 | 107 } |
jbe@103 | 108 |
jbe@4 | 109 // calculate member counts: |
jbe@334 | 110 res = PQexec(db, "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SELECT \"calculate_member_counts\"()"); |
jbe@334 | 111 if (!res) { |
jbe@4 | 112 fprintf(stderr, "Error in pqlib while sending SQL command calculating member counts\n"); |
jbe@65 | 113 err = 1; |
jbe@65 | 114 } else if ( |
jbe@334 | 115 PQresultStatus(res) != PGRES_COMMAND_OK && |
jbe@334 | 116 PQresultStatus(res) != PGRES_TUPLES_OK |
jbe@4 | 117 ) { |
jbe@334 | 118 fprintf(stderr, "Error while executing SQL command calculating member counts:\n%s", PQresultErrorMessage(res)); |
jbe@65 | 119 err = 1; |
jbe@334 | 120 PQclear(res); |
jbe@65 | 121 } else { |
jbe@334 | 122 PQclear(res); |
jbe@4 | 123 } |
jbe@4 | 124 |
jbe@1 | 125 // update open issues: |
jbe@334 | 126 res = PQexec(db, "SELECT \"id\" FROM \"open_issue\""); |
jbe@334 | 127 if (!res) { |
jbe@0 | 128 fprintf(stderr, "Error in pqlib while sending SQL command selecting open issues\n"); |
jbe@65 | 129 err = 1; |
jbe@334 | 130 } else if (PQresultStatus(res) != PGRES_TUPLES_OK) { |
jbe@334 | 131 fprintf(stderr, "Error while executing SQL command selecting open issues:\n%s", PQresultErrorMessage(res)); |
jbe@65 | 132 err = 1; |
jbe@334 | 133 PQclear(res); |
jbe@65 | 134 } else { |
jbe@334 | 135 count = PQntuples(res); |
jbe@65 | 136 for (i=0; i<count; i++) { |
jbe@334 | 137 char *issue_id, *escaped_issue_id; |
jbe@334 | 138 PGresult *res2, *old_res2; |
jbe@334 | 139 int j; |
jbe@334 | 140 issue_id = PQgetvalue(res, i, 0); |
jbe@345 | 141 escaped_issue_id = escapeLiteral(db, issue_id, strlen(issue_id)); |
jbe@357 | 142 if (!escaped_issue_id) { |
jbe@357 | 143 fprintf(stderr, "Could not escape literal in memory.\n"); |
jbe@357 | 144 err = 1; |
jbe@357 | 145 break; |
jbe@357 | 146 } |
jbe@334 | 147 old_res2 = NULL; |
jbe@334 | 148 for (j=0; ; j++) { |
jbe@334 | 149 if (j >= 20) { // safety to avoid endless loops |
jbe@334 | 150 fprintf(stderr, "Function \"check_issue\"(...) returned non-null value too often.\n"); |
jbe@334 | 151 err = 1; |
jbe@334 | 152 if (j > 0) PQclear(old_res2); |
jbe@334 | 153 break; |
jbe@334 | 154 } |
jbe@334 | 155 if (j == 0) { |
jbe@334 | 156 char *cmd; |
jbe@334 | 157 if (asprintf(&cmd, "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SELECT \"check_issue\"(%s, NULL)", escaped_issue_id) < 0) { |
jbe@334 | 158 fprintf(stderr, "Could not prepare query string in memory.\n"); |
jbe@334 | 159 err = 1; |
jbe@334 | 160 break; |
jbe@334 | 161 } |
jbe@334 | 162 res2 = PQexec(db, cmd); |
jbe@334 | 163 free(cmd); |
jbe@334 | 164 } else { |
jbe@334 | 165 char *persist, *escaped_persist, *cmd; |
jbe@334 | 166 persist = PQgetvalue(old_res2, 0, 0); |
jbe@345 | 167 escaped_persist = escapeLiteral(db, persist, strlen(persist)); |
jbe@357 | 168 if (!escaped_persist) { |
jbe@357 | 169 fprintf(stderr, "Could not escape literal in memory.\n"); |
jbe@357 | 170 err = 1; |
jbe@357 | 171 PQclear(old_res2); |
jbe@357 | 172 break; |
jbe@357 | 173 } |
jbe@334 | 174 if (asprintf(&cmd, "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SELECT \"check_issue\"(%s, %s::\"check_issue_persistence\")", escaped_issue_id, escaped_persist) < 0) { |
jbe@345 | 175 freemem(escaped_persist); |
jbe@334 | 176 fprintf(stderr, "Could not prepare query string in memory.\n"); |
jbe@334 | 177 err = 1; |
jbe@334 | 178 PQclear(old_res2); |
jbe@334 | 179 break; |
jbe@334 | 180 } |
jbe@345 | 181 freemem(escaped_persist); |
jbe@334 | 182 res2 = PQexec(db, cmd); |
jbe@334 | 183 free(cmd); |
jbe@334 | 184 PQclear(old_res2); |
jbe@334 | 185 } |
jbe@334 | 186 if (!res2) { |
jbe@334 | 187 fprintf(stderr, "Error in pqlib while sending SQL command to call function \"check_issue\"(...):\n"); |
jbe@334 | 188 err = 1; |
jbe@334 | 189 break; |
jbe@334 | 190 } else if ( |
jbe@334 | 191 PQresultStatus(res2) != PGRES_COMMAND_OK && |
jbe@334 | 192 PQresultStatus(res2) != PGRES_TUPLES_OK |
jbe@334 | 193 ) { |
jbe@334 | 194 fprintf(stderr, "Error while calling SQL function \"check_issue\"(...):\n%s", PQresultErrorMessage(res2)); |
jbe@334 | 195 err = 1; |
jbe@334 | 196 PQclear(res2); |
jbe@334 | 197 break; |
jbe@334 | 198 } else { |
jbe@334 | 199 if (PQntuples(res2) >= 1 && !PQgetisnull(res2, 0, 0)) { |
jbe@334 | 200 old_res2 = res2; |
jbe@334 | 201 } else { |
jbe@334 | 202 PQclear(res2); |
jbe@334 | 203 break; |
jbe@334 | 204 } |
jbe@334 | 205 } |
jbe@65 | 206 } |
jbe@345 | 207 freemem(escaped_issue_id); |
jbe@65 | 208 } |
jbe@334 | 209 PQclear(res); |
jbe@0 | 210 } |
jbe@1 | 211 |
jbe@375 | 212 // cleanup and exit: |
jbe@0 | 213 PQfinish(db); |
jbe@65 | 214 return err; |
jbe@1 | 215 |
jbe@0 | 216 } |