static void np_conn_destroy(Npconn *conn) { int n; NP_ASSERT(conn != NULL); NP_ASSERT(conn->refcount == 0); /* issue 83: remove from srv->conns before destroying fidpool */ np_srv_remove_conn (conn->srv, conn); if (conn->fidpool) { if ((n = np_fidpool_destroy(conn->fidpool)) > 0) { np_logmsg (conn->srv, "%s: connection closed with " "%d unclunked fids", np_conn_get_client_id (conn), n); } conn->fidpool = NULL; } if (conn->trans) { np_trans_destroy (conn->trans); conn->trans = NULL; } pthread_mutex_destroy(&conn->lock); pthread_mutex_destroy(&conn->wlock); pthread_cond_destroy(&conn->refcond); free(conn); }
void np_conn_decref(Npconn *conn) { Npfcall *fc, *fc1; pthread_mutex_lock(&conn->lock); assert(conn->refcount > 0); conn->refcount--; if (conn->refcount) { pthread_mutex_unlock(&conn->lock); return; } if (conn->fidpool) { np_fidpool_destroy(conn->fidpool); conn->fidpool = NULL; } fc = conn->freerclist; conn->freerclist = NULL; while (fc != NULL) { fc1 = fc->next; free(fc); fc = fc1; } pthread_mutex_unlock(&conn->lock); pthread_mutex_destroy(&conn->lock); free(conn); }
Npconn* np_conn_create(Npsrv *srv, Nptrans *trans, char *client_id) { Npconn *conn; int err; if (!(conn = malloc(sizeof(*conn)))) { errno = ENOMEM; return NULL; } pthread_mutex_init(&conn->lock, NULL); pthread_mutex_init(&conn->wlock, NULL); pthread_cond_init(&conn->resetcond, NULL); conn->refcount = 0; conn->resetting = 0; conn->srv = srv; conn->msize = srv->msize; conn->shutdown = 0; conn->reqs_in = 0; conn->reqs_out = 0; if (!(conn->fidpool = np_fidpool_create())) { free (conn); errno = ENOMEM; return NULL; } snprintf(conn->client_id, sizeof(conn->client_id), "%s", client_id); conn->authuser = P9_NONUNAME; conn->trans = trans; conn->aux = NULL; np_srv_add_conn(srv, conn); err = pthread_create(&conn->rthread, NULL, np_conn_read_proc, conn); if (err != 0) { np_srv_remove_conn (srv, conn); np_fidpool_destroy(conn->fidpool); free (conn); errno = err; return NULL; } return conn; }
/* Clear all state associated with conn out of the srv. * No more I/O is possible; we have disassociated the trans from the conn. */ static void np_conn_reset(Npconn *conn) { int reqslen; Npsrv *srv; Npreq *preqs, **reqs; xpthread_mutex_lock(&conn->lock); conn->resetting = 1; xpthread_mutex_unlock(&conn->lock); xpthread_mutex_lock(&conn->srv->lock); srv = conn->srv; preqs = _get_waiting_reqs (conn); if (_get_working_reqs (conn, &reqs, &reqslen) < 0) { xpthread_mutex_unlock(&conn->srv->lock); goto error; } xpthread_mutex_unlock(&conn->srv->lock); _flush_waiting_reqs (preqs); _flush_working_reqs (reqs, reqslen); xpthread_mutex_lock(&srv->lock); while (_count_working_reqs (conn, 1) > 0) xpthread_cond_wait(&conn->resetcond, &srv->lock); xpthread_mutex_unlock(&srv->lock); xpthread_mutex_lock(&conn->lock); if (conn->fidpool) { np_fidpool_destroy(conn->fidpool); conn->fidpool = NULL; } conn->resetting = 0; xpthread_mutex_unlock(&conn->lock); _free_working_reqs (reqs, reqslen); return; error: return; }
void np_conn_decref(Npconn *conn) { xpthread_mutex_lock(&conn->lock); assert(conn->refcount > 0); conn->refcount--; if (conn->refcount) { xpthread_mutex_unlock(&conn->lock); return; } if (conn->fidpool) { np_fidpool_destroy(conn->fidpool); conn->fidpool = NULL; } xpthread_mutex_unlock(&conn->lock); pthread_mutex_destroy(&conn->lock); pthread_cond_destroy(&conn->resetcond); free(conn); }
void np_conn_reset(Npconn *conn, u32 msize, int dotu) { int i, n; Npsrv *srv; Npreq *req, *req1, *preqs, **reqs; Npfcall *fc, *fc1; pthread_mutex_lock(&conn->lock); conn->resetting = 1; pthread_mutex_unlock(&conn->lock); pthread_mutex_lock(&conn->srv->lock); srv = conn->srv; // first flush all outstanding requests preqs = NULL; req = srv->reqs_first; while (req != NULL) { req1 = req->next; if (req->conn == conn) { np_srv_remove_req(srv, req); req->next = preqs; preqs = req; } req = req1; } // then flush all working requests n = 0; req = conn->srv->workreqs; while (req != NULL) { if (req->conn == conn && (msize==0 || req->tcall->type != Tversion)) n++; req = req->next; } reqs = malloc(n * sizeof(Npreq *)); n = 0; req = conn->srv->workreqs; while (req != NULL) { if (req->conn == conn && (msize==0 || req->tcall->type != Tversion)) reqs[n++] = np_req_ref(req); req = req->next; } pthread_mutex_unlock(&conn->srv->lock); req = preqs; while (req != NULL) { req1 = req->next; np_conn_respond(req); np_req_unref(req); req = req1; } for(i = 0; i < n; i++) { req = reqs[i]; if (req->conn->srv->flush) (*req->conn->srv->flush)(req); } /* wait until all working requests finish */ /* pthread_mutex_lock(&conn->lock); while (1) { for(i = 0; i < n; i++) if (!reqs[i]->responded) break; if (i >= n) break; pthread_cond_wait(&conn->resetcond, &conn->lock); } */ pthread_mutex_lock(&srv->lock); while (1) { for(req = srv->workreqs; req != NULL; req = req->next) if (req->conn == conn && (msize==0 || req->tcall->type != Tversion)) break; if (req == NULL) break; while(conn->resetting) pthread_cond_wait(&conn->resetcond, &srv->lock); } pthread_mutex_unlock(&srv->lock); /* free old pool of fcalls */ fc = conn->freerclist; conn->freerclist = NULL; while (fc != NULL) { fc1 = fc->next; free(fc); fc = fc1; } if (conn->fidpool) { np_fidpool_destroy(conn->fidpool); conn->fidpool = NULL; } if (msize) { conn->dotu = dotu; conn->resetting = 0; conn->fidpool = np_fidpool_create(); pthread_cond_broadcast(&conn->resetdonecond); } conn->resetting = 0; pthread_mutex_unlock(&conn->lock); /* free the working requests */ for(i = 0; i < n; i++) np_req_unref(reqs[i]); free(reqs); }