comparison src/c/urweb.c @ 683:9a2c18dab11d

Expunging non-nullable rows
author Adam Chlipala <adamc@hcoop.net>
date Sun, 29 Mar 2009 13:30:01 -0400
parents 5bbb542243e8
children f0224c7f12bb
comparison
equal deleted inserted replaced
682:5bbb542243e8 683:9a2c18dab11d
206 206
207 pthread_mutex_unlock(&c->lock); 207 pthread_mutex_unlock(&c->lock);
208 } 208 }
209 209
210 static void free_client(client *c) { 210 static void free_client(client *c) {
211 printf("Freeing client %d\n", c->id); 211 printf("Freeing client %u\n", c->id);
212 212
213 c->mode = UNUSED; 213 c->mode = UNUSED;
214 c->pass = -1; 214 c->pass = -1;
215 215
216 c->next = clients_free; 216 c->next = clients_free;
217 clients_free = c; 217 clients_free = c;
218 }
219
220 extern int uw_timeout;
221
222 void uw_prune_clients() {
223 client *c, *next, *prev = NULL;
224 time_t cutoff;
225
226 cutoff = time(NULL) - uw_timeout;
227
228 pthread_mutex_lock(&clients_mutex);
229
230 for (c = clients_used; c; c = next) {
231 next = c->next;
232 pthread_mutex_lock(&c->lock);
233 if (c->last_contact < cutoff) {
234 if (prev)
235 prev->next = next;
236 else
237 clients_used = next;
238 free_client(c);
239 }
240 else
241 prev = c;
242 pthread_mutex_unlock(&c->lock);
243 }
244
245 pthread_mutex_unlock(&clients_mutex);
246 } 218 }
247 219
248 static uw_Basis_channel new_channel(client *c) { 220 static uw_Basis_channel new_channel(client *c) {
249 uw_Basis_channel ch = {c->id, c->n_channels++}; 221 uw_Basis_channel ch = {c->id, c->n_channels++};
250 return ch; 222 return ch;
320 client *client; 292 client *client;
321 293
322 char error_message[ERROR_BUF_LEN]; 294 char error_message[ERROR_BUF_LEN];
323 }; 295 };
324 296
325 extern int uw_inputs_len; 297 extern int uw_inputs_len, uw_timeout;
326 298
327 uw_context uw_init(size_t outHeaders_len, size_t script_len, size_t page_len, size_t heap_len) { 299 uw_context uw_init(size_t outHeaders_len, size_t script_len, size_t page_len, size_t heap_len) {
328 uw_context ctx = malloc(sizeof(struct uw_context)); 300 uw_context ctx = malloc(sizeof(struct uw_context));
329 301
330 ctx->headers = ctx->headers_end = NULL; 302 ctx->headers = ctx->headers_end = NULL;
1886 if (ctx->client) 1858 if (ctx->client)
1887 pthread_mutex_unlock(&ctx->client->lock); 1859 pthread_mutex_unlock(&ctx->client->lock);
1888 1860
1889 return uw_db_rollback(ctx); 1861 return uw_db_rollback(ctx);
1890 } 1862 }
1863
1864
1865 // "Garbage collection"
1866
1867 void uw_expunger(uw_context ctx, uw_Basis_client cli);
1868
1869 static failure_kind uw_expunge(uw_context ctx, uw_Basis_client cli) {
1870 int r = setjmp(ctx->jmp_buf);
1871
1872 if (r == 0)
1873 uw_expunger(ctx, cli);
1874
1875 return r;
1876 }
1877
1878 void uw_prune_clients(uw_context ctx) {
1879 client *c, *next, *prev = NULL;
1880 time_t cutoff;
1881
1882 cutoff = time(NULL) - uw_timeout;
1883
1884 pthread_mutex_lock(&clients_mutex);
1885
1886 for (c = clients_used; c; c = next) {
1887 next = c->next;
1888 pthread_mutex_lock(&c->lock);
1889 if (c->last_contact < cutoff) {
1890 failure_kind fk = UNLIMITED_RETRY;
1891 if (prev)
1892 prev->next = next;
1893 else
1894 clients_used = next;
1895 while (fk == UNLIMITED_RETRY) {
1896 uw_reset(ctx);
1897 fk = uw_expunge(ctx, c->id);
1898 if (fk == SUCCESS) {
1899 free_client(c);
1900 break;
1901 }
1902 }
1903 if (fk != SUCCESS)
1904 printf("Expunge blocked by error: %s\n", uw_error_message(ctx));
1905 }
1906 else
1907 prev = c;
1908 pthread_mutex_unlock(&c->lock);
1909 }
1910
1911 pthread_mutex_unlock(&clients_mutex);
1912 }