コード例 #1
0
ファイル: conn.c プロジェクト: EuroCorp/diod
static void
np_conn_flush (Npconn *conn)
{
    Nptpool *tp;
    Npreq *creq, *nextreq;

    xpthread_mutex_lock(&conn->srv->lock);
    for (tp = conn->srv->tpool; tp != NULL; tp = tp->next) {
        for (creq = tp->reqs_first; creq != NULL; creq = nextreq) {
            nextreq = creq->next;
            if (creq->conn != conn)
                continue;
            np_srv_remove_req(tp, creq);
            np_req_unref(creq);
        }
        for (creq = tp->workreqs; creq != NULL; creq = creq->next) {
            if (creq->conn != conn)
                continue;
            creq->state = REQ_NOREPLY;
            if (conn->srv->flags & SRV_FLAGS_FLUSHSIG)
                pthread_kill (creq->wthread->thread, SIGUSR2);
        }
    }
    xpthread_mutex_unlock(&conn->srv->lock);
}
コード例 #2
0
ファイル: conn.c プロジェクト: lowfatcomputing/diod
static void
_free_working_reqs (Npreq **reqs, int len)
{
	int i;

	for(i = 0; i < len; i++) 
		np_req_unref(reqs[i]);
	free(reqs);
}
コード例 #3
0
ファイル: srv.c プロジェクト: lowfatcomputing/diod
static void
np_respond(Nptpool *tp, Npreq *req, Npfcall *rc)
{
	Npreq *freq;

	xpthread_mutex_lock(&req->lock);
	if (req->responded) {
		free(rc);
		xpthread_mutex_unlock(&req->lock);
		np_req_unref(req);
		return;
	}
	req->responded = 1;
	xpthread_mutex_unlock(&req->lock);

	xpthread_mutex_lock(&tp->lock);
	np_srv_remove_workreq(tp, req);
	for(freq = req->flushreq; freq != NULL; freq = freq->flushreq)
		np_srv_remove_workreq(tp, freq);
	xpthread_mutex_unlock(&tp->lock);

	xpthread_mutex_lock(&req->lock);
	req->rcall = rc;
	if (req->rcall) {
		np_set_tag(req->rcall, req->tag);
		if (req->fid != NULL) {
			np_fid_decref(req->fid);
			req->fid = NULL;
		}
		np_conn_respond(req);		
	}

	for(freq = req->flushreq; freq != NULL; freq = freq->flushreq) {
		xpthread_mutex_lock(&freq->lock);
		freq->rcall = np_create_rflush();
		np_set_tag(freq->rcall, freq->tag);
		np_conn_respond(freq);
		xpthread_mutex_unlock(&freq->lock);
		np_req_unref(freq);
	}
	xpthread_mutex_unlock(&req->lock);
	np_req_unref(req);
}
コード例 #4
0
ファイル: conn.c プロジェクト: lowfatcomputing/diod
static void
_flush_waiting_reqs (Npreq *reqs)
{
	Npreq *req = reqs;
	Npreq *req1;

	while (req != NULL) {
		req1 = req->next;
		np_conn_respond(req);
		np_req_unref(req);
		req = req1;
	}
}
コード例 #5
0
ファイル: srv.c プロジェクト: carriercomm/diod
static void
np_respond(Nptpool *tp, Npreq *req, Npfcall *rc)
{
	xpthread_mutex_lock(&tp->srv->lock);
	np_srv_remove_workreq(tp, req);
	xpthread_mutex_unlock(&tp->srv->lock);

	xpthread_mutex_lock(&req->lock);
	req->rcall = rc;
	if (req->rcall) {
		np_set_tag(req->rcall, req->tag);
		if (req->fid != NULL) {
			np_fid_decref(req->fid);
			req->fid = NULL;
		}
		np_conn_respond(req);		
	}

	xpthread_mutex_unlock(&req->lock);
	np_req_unref(req);
}
コード例 #6
0
ファイル: conn.c プロジェクト: EuroCorp/diod
/* Per-connection read thread.
 */
static void *
np_conn_read_proc(void *a)
{
    Npconn *conn = (Npconn *)a;
    Npsrv *srv = conn->srv;
    Npreq *req;
    Npfcall *fc;

    pthread_detach(pthread_self());

    for (;;) {
        if (np_trans_recv(conn->trans, &fc, conn->msize) < 0) {
            np_logerr (srv, "recv error - "
                       "dropping connection to '%s'",
                       conn->client_id);
            break;
        }
        if (!fc) /* EOF */
            break;
        _debug_trace (srv, fc);

        /* Encapsulate fc in a request and hand to srv worker threads.
         * In np_req_alloc, req->fid is looked up/initialized.
         */
        req = np_req_alloc(conn, fc);
        if (!req) {
            np_logmsg (srv, "out of memory in receive path - "
                       "dropping connection to '%s'",
                       conn->client_id);
            free (fc);
            break;
        }

        /* Enqueue request for processing by next available worker
         * thread, except P9_TFLUSH which is handled immediately.
         */
        if (fc->type == P9_TFLUSH) {
            if (np_flush (req, fc)) {
                np_req_respond_flush (req);
                np_req_unref(req);
            }
            xpthread_mutex_lock (&srv->lock);
            srv->tpool->stats.nreqs[P9_TFLUSH]++;
            xpthread_mutex_unlock (&srv->lock);
        } else {
            xpthread_mutex_lock(&srv->lock);
            np_srv_add_req(srv, req);
            xpthread_mutex_unlock(&srv->lock);
        }
    }
    /* Just got EOF on read, or some other fatal error for the
     * connection like out of memory.
     */

    np_conn_flush (conn);

    xpthread_mutex_lock(&conn->lock);
    while (conn->refcount > 0)
        xpthread_cond_wait(&conn->refcond, &conn->lock);
    xpthread_mutex_unlock(&conn->lock);
    np_conn_destroy(conn);

    return NULL;
}
コード例 #7
0
ファイル: conn.c プロジェクト: geekmug/syncfs
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);
}
コード例 #8
0
ファイル: conn.c プロジェクト: geekmug/syncfs
static void *
np_conn_read_proc(void *a)
{
    int i, n, size, msize;
    Npsrv *srv;
    Npconn *conn;
    Nptrans *trans;
    Npreq *req;
    Npfcall *fc, *fc1;

    pthread_detach(pthread_self());
    conn = a;
    np_conn_incref(conn);
    srv = conn->srv;
    msize = conn->msize;
    fc = np_conn_new_incall(conn);
    n = 0;
    while (conn->trans && (i = np_trans_read(conn->trans, fc->pkt + n, msize - n)) > 0) {
        pthread_mutex_lock(&conn->lock);
        if (conn->resetting) {
            while(conn->resetting)
                pthread_cond_wait(&conn->resetdonecond, &conn->lock);
            n = 0;  /* discard all input */
            i = 0;
        }
        pthread_mutex_unlock(&conn->lock);
        n += i;

again:
        if (n < 4)
            continue;

        size = fc->pkt[0] | (fc->pkt[1]<<8) | (fc->pkt[2]<<16) | (fc->pkt[3]<<24);
        if (n < size)
            continue;

        if (!np_deserialize(fc, fc->pkt, conn->dotu))
            break;

        if (conn->srv->debuglevel) {
            fprintf(stderr, "<<< (%p) ", conn);
            np_printfcall(stderr, fc, conn->dotu);
            fprintf(stderr, "\n");
        }

        fc1 = np_conn_new_incall(conn);
        if (n > size)
            memmove(fc1->pkt, fc->pkt + size, n - size);
        n -= size;

        req = np_req_alloc(conn, fc);
        pthread_mutex_lock(&srv->lock);
        if (!conn->resetting)
            np_srv_add_req(srv, req);
        else
            np_req_unref(req);
        pthread_mutex_unlock(&srv->lock);
        fc = fc1;
        if (n > 0)
            goto again;

    }

    pthread_mutex_lock(&conn->lock);
    trans = conn->trans;
    conn->trans = NULL;
    np_conn_free_incall(conn, fc);
    pthread_mutex_unlock(&conn->lock);

    np_srv_remove_conn(conn->srv, conn);
    np_conn_reset(conn, 0, 0);

    if (trans)
        np_trans_destroy(trans);

    np_conn_decref(conn);
    return NULL;
}
コード例 #9
0
ファイル: fcall.c プロジェクト: lowfatcomputing/diod
Npfcall*
np_flush(Npreq *req, Npfcall *tc)
{
	u16 oldtag = tc->u.tflush.oldtag;
	Npreq *creq = NULL;
	Npconn *conn = req->conn;
	Npfcall *ret = NULL;
	Nptpool *tp;

	xpthread_mutex_lock(&conn->srv->lock);
	// check pending requests
	for (tp = conn->srv->tpool; tp != NULL; tp = tp->next) {
		xpthread_mutex_lock(&tp->lock);
		for(creq = tp->reqs_first; creq != NULL; creq = creq->next) {
			if (creq->conn==conn && creq->tag==oldtag) {
				np_srv_remove_req(tp, creq);
				xpthread_mutex_lock(&creq->lock);
				np_conn_respond(creq); /* doesn't send anything */
				xpthread_mutex_unlock(&creq->lock);
				np_req_unref(creq);
				ret = np_create_rflush();
				creq = NULL;
				xpthread_mutex_unlock(&tp->lock);
				goto done;
			}
		}
		xpthread_mutex_unlock(&tp->lock);
	}

	// check working requests
	for (tp = conn->srv->tpool; tp != NULL; tp = tp->next) {
		xpthread_mutex_lock(&tp->lock);
		creq = tp->workreqs;
		while (creq != NULL) {
			if (creq->conn==conn && creq->tag==oldtag) {
				np_req_ref(creq);
				xpthread_mutex_lock(&creq->lock);
				req->flushreq = creq->flushreq;
				creq->flushreq = req;
				xpthread_mutex_unlock(&creq->lock);
				xpthread_mutex_unlock(&tp->lock);
				goto done;
			}
			creq = creq->next;
		}
		xpthread_mutex_unlock(&tp->lock);
	}

	// if not found, return P9_RFLUSH
	if (!creq)
		ret = np_create_rflush();

done:
	xpthread_mutex_unlock(&conn->srv->lock);

	// if working request found, try to flush it
	if (creq && req->conn->srv->flush) {
		(*req->conn->srv->flush)(creq);
		np_req_unref(creq);
	}

	return ret;
}