Exemplo n.º 1
0
/** Resumes processing the <b>next</b> HTTP request message within this connection.
 *
 * This method may only be invoked when the current/old request has been fully processed,
 * and is though only be invoked from within the finish handler of \p HttpRequest.
 *
 * \see HttpRequest::finish()
 */
void HttpConnection::resume()
{
	TRACE("resume() shouldKeepAlive:%d)", shouldKeepAlive());
	TRACE("-- (status:%s, inputOffset:%ld, inputSize:%ld)", status_str(), inputOffset_, input_.size());

	status_ = KeepAliveRead;
	request_->clear();

	if (socket()->tcpCork())
		socket()->setTcpCork(false);
}
Exemplo n.º 2
0
Arquivo: test.cpp Projeto: mk12/euler
bool test(const int n) {
	const int index = n - 1;
	const auto start_t = std::chrono::high_resolution_clock::now();
	const long result = solvers[index]();
	const auto end_t = std::chrono::high_resolution_clock::now();
	const double elapsed_s =
		std::chrono::duration<double>(end_t - start_t).count();
	const bool success = result == answers[index];
	const char* msg = status_str(success);
	printf("%02d: %12ld ... %4s (%g s)\n", n, result, msg, elapsed_s);
	return success;
}
Exemplo n.º 3
0
Arquivo: mxq_job.c Projeto: mariux/mxq
int mxq_load_jobs_running_on_server(struct mx_mysql *mysql, struct mxq_job **jobs_result, struct mxq_daemon *daemon)
{
    struct mxq_job *jobs_tmp = NULL;
    struct mx_mysql_bind param = {0};
    int idx;
    int res;

    assert(daemon);
    assert(daemon->hostname);
    assert(daemon->daemon_name);
    assert(*daemon->hostname);
    assert(*daemon->daemon_name);

    char *query =
            "SELECT"
                JOB_FIELDS
            " FROM"
                " mxq_job"
            " WHERE job_status IN ("
                            status_str(MXQ_JOB_STATUS_LOADED) ","
                            status_str(MXQ_JOB_STATUS_RUNNING) ")"
              " AND host_hostname = ?"
              " AND server_id     = ?";
    res = mx_mysql_bind_init_param(&param, 2);
    assert(res == 0);

    idx = 0;
    res = 0;
    res += mx_mysql_bind_var(&param, idx++, string, &daemon->hostname);
    res += mx_mysql_bind_var(&param, idx++, string, &daemon->daemon_name);
    assert(res == 0);

    res=do_jobs_statement(mysql, query, &param, &jobs_tmp);
    if (res >= 0)
        *jobs_result = jobs_tmp;

    return res;
}
Exemplo n.º 4
0
bool HttpConnection::onMessageEnd()
{
	TRACE("onMessageEnd() %s (isHandlingRequest:%d)", status_str(), flags_ & IsHandlingRequest);

	// marks the request-content EOS, so that the application knows when the request body
	// has been fully passed to it.
	request_->onRequestContent(BufferRef());

	// If we are currently procesing a request, then stop parsing at the end of this request.
	// The next request, if available, is being processed via resume()
	if (flags_ & IsHandlingRequest)
		return false;

	return true; //shouldKeepAlive();
}
Exemplo n.º 5
0
/**
 * This method gets invoked when there is data in our HttpConnection ready to read.
 *
 * We assume, that we are in request-parsing state.
 */
bool HttpConnection::readSome()
{
	TRACE("readSome()");

	ref();

	if (status() == KeepAliveRead) {
		TRACE("readSome: status was keep-alive-read. resetting to reading-request", request_->outputState_);
		status_ = ReadingRequest;
	}

	ssize_t rv = socket_->read(input_);

	if (rv < 0) { // error
		switch (errno) {
		case EINTR:
		case EAGAIN:
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
		case EWOULDBLOCK:
#endif
			watchInput(worker_->server_.maxReadIdle());
			break;
		default:
			//log(Severity::error, "Connection read error: %s", strerror(errno));
			goto err;
		}
	} else if (rv == 0) {
		// EOF
		TRACE("readSome: (EOF)");
		goto err;
	} else {
		TRACE("readSome: read %ld bytes, status:%s, ros:%d", rv, status_str(), request_->outputState_);
		process();
	}

	unref();
	return true;

err:
	abort();
	unref();
	return false;
}
Exemplo n.º 6
0
void HttpConnection::timeout(Socket *)
{
	TRACE(1, "timedout: status=%s",  status_str());

	switch (status()) {
	case Undefined:
	case ReadingRequest:
	case ProcessingRequest:
		// we do not want further out-timing requests on this conn: just close it.
		abort(HttpStatus::RequestTimeout);
		break;
	case SendingReply:
	case SendingReplyDone:
		abort();
		break;
	case KeepAliveRead:
		close();
		break;
	}
}
Exemplo n.º 7
0
/**
 * Frees up any resources and resets state of this connection.
 *
 * This method is invoked only after the connection has been closed and
 * this resource may now either be physically destructed or put into
 * a list of free connection objects for later use of newly incoming
 * connections (to avoid too many memory allocations).
 */
void HttpConnection::clear()
{
	TRACE(1, "clear(): refCount: %zu, conn.status: %s, parser.state: %s", refCount_, status_str(), state_str());
	//TRACE(1, "Stack Trace:\n%s", StackTrace().c_str());

	HttpMessageProcessor::reset();

	if (request_) {
		request_->clear();
	}

	clearCustomData();

	worker_->server_.onConnectionClose(this);
	delete socket_;
	socket_ = nullptr;
	requestCount_ = 0;

	inputOffset_ = 0;
	input_.clear();
}
Exemplo n.º 8
0
static void dump(void)
{
	struct timeval now;
	struct lk *lk;
	int i;

	gettimeofday(&now, NULL);

	for (i = 0; i < maxn; i++) {
		lk = get_lock(i);
		printf("x %2d lkid %08x gr %2d rq %2d wait_ast %d last op %s  \t%s  %us\n",
			i,
			lk->lksb.sb_lkid,
			lk->grmode,
			lk->rqmode,
			lk->wait_ast,
			op_str(lk->lastop),
			status_str(lk->last_status),
			lk->wait_ast ? (unsigned int)(now.tv_sec - lk->begin.tv_sec) : 0);
	}
}
Exemplo n.º 9
0
Arquivo: mxq_job.c Projeto: mariux/mxq
int mxq_load_job_from_group_assigned_to_daemon(struct mx_mysql *mysql, struct mxq_job **jobs_result, uint64_t group_id, struct mxq_daemon *daemon)
{
    struct mxq_job *jobs_tmp = NULL;
    struct mx_mysql_bind param = {0};
    int res;
    int idx;

    assert(mysql);
    assert(jobs_result);
    assert(!(*jobs_result));
    assert(daemon);
    assert(daemon->daemon_id);

    char *query =
            "SELECT"
                JOB_FIELDS
            " FROM"
                " mxq_job"
            " WHERE job_status = " status_str(MXQ_JOB_STATUS_ASSIGNED)
              " AND group_id  = ?"
              " AND daemon_id = ?"
            " LIMIT 1";

    res = mx_mysql_bind_init_param(&param, 2);
    assert(res == 0);

    idx = 0;
    res = 0;
    res += mx_mysql_bind_var(&param, idx++, uint64, &group_id);
    res += mx_mysql_bind_var(&param, idx++, uint32, &daemon->daemon_id);
    assert(res == 0);

    res = do_jobs_statement(mysql, query, &param, &jobs_tmp);
    if (res >= 0)
        *jobs_result = jobs_tmp;

    return res;
}
Exemplo n.º 10
0
static int s2145_do_cmd(struct shinkos2145_ctx *ctx,
			uint8_t *cmd, int cmdlen,
			int minlen, int *num)
{
	int ret;
	struct s2145_status_hdr *resp = (struct s2145_status_hdr *) rdbuf;

	libusb_device_handle *dev = ctx->dev;
	uint8_t endp_up = ctx->endp_up;
	uint8_t endp_down = ctx->endp_down;

	if ((ret = send_data(dev, endp_down,
			     cmd, cmdlen)))
		return (ret < 0) ? ret : -99;

	ret = read_data(dev, endp_up,
			rdbuf, READBACK_LEN, num);

	if (ret < 0)
		return ret;
	if (*num < minlen) {
		ERROR("Short read! (%d/%d))\n", *num, minlen);
		return -99;
	}

	if (resp->result != RESULT_SUCCESS) {
		INFO("Printer Status:  %02x (%s)\n", resp->status, 
		     status_str(resp->status));
		INFO(" Result: 0x%02x  Error: 0x%02x (0x%02x/0x%02x = %s)\n",
		     resp->result, resp->error, resp->printer_major,
		     resp->printer_minor, error_codes(resp->printer_major, resp->printer_minor));
		return -99;
	}

	return ret;
}
Exemplo n.º 11
0
void HttpConnection::timeout(Socket *)
{
	TRACE("timedout: status=%s",  status_str());

	switch (status()) {
	case StartingUp:
		TRACE("timeout: BUG. we should have never reached here.");
		break;
	case ReadingRequest:
		// we do not want further out-timing requests on this conn: just close it.
		setShouldKeepAlive(false);

		request_->status = HttpError::RequestTimeout;
		status_ = SendingReply;
		request_->finish();
		break;
	case KeepAliveRead:
		close();
		break;
	case SendingReply:
		abort();
		break;
	}
}
Exemplo n.º 12
0
static int shinkos2145_main_loop(void *vctx, int copies) {
	struct shinkos2145_ctx *ctx = vctx;

	int ret, num;
	uint8_t cmdbuf[CMDBUF_LEN];
	uint8_t rdbuf2[READBACK_LEN];

	int i, last_state = -1, state = S_IDLE;

	struct s2145_cmd_hdr *cmd = (struct s2145_cmd_hdr *) cmdbuf;;
	struct s2145_print_cmd *print = (struct s2145_print_cmd *) cmdbuf;
	struct s2145_status_resp *sts = (struct s2145_status_resp *) rdbuf; 
	struct s2145_mediainfo_resp *media = (struct s2145_mediainfo_resp *) rdbuf;

	/* Send Media Query */
	memset(cmdbuf, 0, CMDBUF_LEN);
	cmd->cmd = cpu_to_le16(S2145_CMD_MEDIAINFO);
	cmd->len = cpu_to_le16(0);

	if ((ret = s2145_do_cmd(ctx,
				cmdbuf, sizeof(*cmd),
				sizeof(*media),
				&num)) < 0) {
		ERROR("Failed to execute %s command\n", cmd_names(cmd->cmd));
		return CUPS_BACKEND_FAILED;
	}
	
	if (le16_to_cpu(media->hdr.payload_len) != (sizeof(struct s2145_mediainfo_resp) - sizeof(struct s2145_status_hdr)))
		return CUPS_BACKEND_FAILED;

	/* Validate print sizes */
	for (i = 0; i < media->count ; i++) {
		/* Look for matching media */
		if (le16_to_cpu(media->items[i].columns) == cpu_to_le16(le32_to_cpu(ctx->hdr.columns)) &&
		    le16_to_cpu(media->items[i].rows) == cpu_to_le16(le32_to_cpu(ctx->hdr.rows)) &&
		    media->items[i].print_type == le32_to_cpu(ctx->hdr.method))
			break;
	}
	if (i == media->count) {
		ERROR("Incorrect media loaded for print!\n");
		return CUPS_BACKEND_HOLD;
	}

	// XXX check copies against remaining media!

top:
	if (state != last_state) {
		if (dyesub_debug)
			DEBUG("last_state %d new %d\n", last_state, state);
	}

	/* Send Status Query */
	memset(cmdbuf, 0, CMDBUF_LEN);
	cmd->cmd = cpu_to_le16(S2145_CMD_STATUS);
	cmd->len = cpu_to_le16(0);

	if ((ret = s2145_do_cmd(ctx,
				cmdbuf, sizeof(*cmd),
				sizeof(struct s2145_status_hdr),
				&num)) < 0) {
		ERROR("Failed to execute %s command\n", cmd_names(cmd->cmd));
		return CUPS_BACKEND_FAILED;
	}

	if (memcmp(rdbuf, rdbuf2, READBACK_LEN)) {
		memcpy(rdbuf2, rdbuf, READBACK_LEN);

		INFO("Printer Status: 0x%02x (%s)\n", 
		     sts->hdr.status, status_str(sts->hdr.status));
		if (sts->hdr.result != RESULT_SUCCESS)
			goto printer_error;		
		if (sts->hdr.error == ERROR_PRINTER)
			goto printer_error;
	} else if (state == last_state) {
		sleep(1);
		goto top;
	}
	last_state = state;

	fflush(stderr);       

	switch (state) {
	case S_IDLE:
		INFO("Waiting for printer idle\n");
		/* If either bank is free, continue */
		if (sts->bank1_status == BANK_STATUS_FREE || 
		    sts->bank2_status == BANK_STATUS_FREE) 
			state = S_PRINTER_READY_CMD;

		break;
	case S_PRINTER_READY_CMD:
		INFO("Initiating print job (internal id %d)\n", ctx->jobid);

		memset(cmdbuf, 0, CMDBUF_LEN);
		print->hdr.cmd = cpu_to_le16(S2145_CMD_PRINTJOB);
		print->hdr.len = cpu_to_le16(sizeof (*print) - sizeof(*cmd));

		print->id = ctx->jobid;
		print->count = cpu_to_le16(copies);
		print->columns = cpu_to_le16(le32_to_cpu(ctx->hdr.columns));
		print->rows = cpu_to_le16(le32_to_cpu(ctx->hdr.rows));
		print->media = le32_to_cpu(ctx->hdr.media);
		print->mode = le32_to_cpu(ctx->hdr.mode);
		print->method = le32_to_cpu(ctx->hdr.method);

		if ((ret = s2145_do_cmd(ctx,
					cmdbuf, sizeof(*print),
					sizeof(struct s2145_status_hdr),
					&num)) < 0) {
			ERROR("Failed to execute %s command\n", cmd_names(print->hdr.cmd));
			return ret;
		}

		if (sts->hdr.result != RESULT_SUCCESS) {
			if (sts->hdr.error == ERROR_BUFFER_FULL) {
				INFO("Printer Buffers full, retrying\n");
				break;
			} else if ((sts->hdr.status & 0xf0) == 0x30 || sts->hdr.status == 0x21) {
				INFO("Printer busy (%s), retrying\n", status_str(sts->hdr.status));
				break;
			} else if (sts->hdr.status != ERROR_NONE)
				goto printer_error;
		}

		INFO("Sending image data to printer\n");
		if ((ret = send_data(ctx->dev, ctx->endp_down,
				     ctx->databuf, ctx->datalen)))
			return CUPS_BACKEND_FAILED;

		INFO("Waiting for printer to acknowledge completion\n");
		sleep(1);
		state = S_PRINTER_SENT_DATA;
		break;
	case S_PRINTER_SENT_DATA:
		if (fast_return) {
			INFO("Fast return mode enabled.\n");
			state = S_FINISHED;
		} else if (sts->hdr.status == STATUS_READY ||
			   sts->hdr.status == STATUS_FINISHED) {
			state = S_FINISHED;
		}
		break;
	default:
		break;
	};

	if (state != S_FINISHED)
		goto top;
	
	INFO("Print complete\n");

	return CUPS_BACKEND_OK;

printer_error:
	ERROR("Printer reported error: %#x (%s) status: %#x (%s) -> %#x.%#x (%s)\n",
	      sts->hdr.error, 
	      error_str(sts->hdr.error),
	      sts->hdr.status, 
	      status_str(sts->hdr.status),
	      sts->hdr.printer_major, sts->hdr.printer_minor,
	      error_codes(sts->hdr.printer_major, sts->hdr.printer_minor));
	return CUPS_BACKEND_FAILED;
}
Exemplo n.º 13
0
/** processes a (partial) request from buffer's given \p offset of \p count bytes.
 */
bool HttpConnection::process()
{
	TRACE("process: offset=%ld, size=%ld (before processing)", inputOffset_, input_.size());

	while (state() != MESSAGE_BEGIN || status() == ReadingRequest || status() == KeepAliveRead) {
		BufferRef chunk(input_.ref(inputOffset_));
		if (chunk.empty())
			break;

		// ensure status is up-to-date, in case we came from keep-alive-read
		if (status_ == KeepAliveRead) {
			TRACE("process: status=keep-alive-read, resetting to reading-request");
			status_ = ReadingRequest;
			if (request_->isFinished()) {
				TRACE("process: finalizing request");
				request_->finalize();
			}
		}

		TRACE("process: (size: %ld, isHandlingRequest:%d, state:%s status:%s", chunk.size(), (flags_ & IsHandlingRequest) != 0, state_str(), status_str());
		//TRACE("%s", input_.ref(input_.size() - rv).str().c_str());

		HttpMessageProcessor::process(chunk, &inputOffset_);
		TRACE("process: done process()ing; fd=%d, request=%p state:%s status:%s", socket_->handle(), request_, state_str(), status_str());

		if (isAborted())
			return false;

		if (state() == SYNTAX_ERROR) {
			if (!request_->isFinished()) {
				setShouldKeepAlive(false);
				request_->status = HttpError::BadRequest;
				request_->finish();
			}
			return false;
		}
	}

	TRACE("process: offset=%ld, bs=%ld, state=%s (after processing) io.timer:%d",
			inputOffset_, input_.size(), state_str(), socket_->timerActive());

	return true;
}
Exemplo n.º 14
0
Arquivo: mxq_job.c Projeto: mariux/mxq
int mxq_set_job_status_exited(struct mx_mysql *mysql, struct mxq_job *job)
{
    int res;
    int idx;
    uint16_t newstatus;
    struct mx_mysql_bind param = {0};

    assert(mysql);
    assert(job);
    assert(job->host_pid);

    if (WIFEXITED(job->stats_status)) {
        if (WEXITSTATUS(job->stats_status)) {
            newstatus = MXQ_JOB_STATUS_FAILED;
        } else {
            newstatus = MXQ_JOB_STATUS_FINISHED;
        }
    } else if(WIFSIGNALED(job->stats_status)) {
        newstatus = MXQ_JOB_STATUS_KILLED;
    } else {
        mx_log_err("Status change to status_exit called with unknown stats_status (%d). Aborting Status change.", job->stats_status);
        errno = EINVAL;
        return -1;
    }

    char *query =
            "UPDATE"
                " mxq_job"
            " SET"
                " stats_max_sumrss = ?,"
                " stats_status     = ?,"
                " stats_utime_sec  = ?,"
                " stats_utime_usec = ?,"
                " stats_stime_sec  = ?,"
                " stats_stime_usec = ?,"
                " stats_real_sec   = ?,"
                " stats_real_usec  = ?,"
                " stats_maxrss     = ?,"
                " stats_minflt     = ?,"
                " stats_majflt     = ?,"
                " stats_nswap      = ?,"
                " stats_inblock    = ?,"
                " stats_oublock    = ?,"
                " stats_nvcsw      = ?,"
                " stats_nivcsw     = ?,"
                " job_status       = ?,"
                " date_end         = NULL"
            " WHERE job_status IN ("
                    status_str(MXQ_JOB_STATUS_LOADED)  ","
                    status_str(MXQ_JOB_STATUS_RUNNING) ","
                    status_str(MXQ_JOB_STATUS_KILLING) ")"
              " AND job_id    = ?"
              " AND daemon_id = ?"
              " AND host_pid  = ?";

    res = mx_mysql_bind_init_param(&param, 20);
    assert(res == 0);

    idx = 0;
    res = 0;
    res += mx_mysql_bind_var(&param, idx++, uint64, &(job->stats_max_sumrss));
    res += mx_mysql_bind_var(&param, idx++,  int32, &(job->stats_status));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_utime.tv_sec));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_utime.tv_usec));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_stime.tv_sec));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_stime.tv_usec));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_realtime.tv_sec));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_realtime.tv_usec));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_maxrss));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_minflt));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_majflt));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_nswap));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_inblock));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_oublock));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_nvcsw));
    res += mx_mysql_bind_var(&param, idx++,  int64, &(job->stats_rusage.ru_nivcsw));
    res += mx_mysql_bind_var(&param, idx++, uint16, &(newstatus));
    res += mx_mysql_bind_var(&param, idx++, uint64, &(job->job_id));
    res += mx_mysql_bind_var(&param, idx++, uint32, &(job->daemon_id));
    res += mx_mysql_bind_var(&param, idx++, uint32, &(job->host_pid));
    assert(res == 0);

    res = mx_mysql_do_statement_noresult_retry_on_fail(mysql, query, &param);
    if (res < 0) {
        mx_log_err("mx_mysql_do_statement(): %m");
        return res;
    }

    job->job_status = newstatus;

    return res;
}
Exemplo n.º 15
0
/** processes a (partial) request from buffer's given \p offset of \p count bytes.
 */
bool HttpConnection::process()
{
	TRACE(2, "process: offset=%lu, size=%lu (before processing) %s, %s", inputOffset_, input_.size(), state_str(), status_str());

	while (state() != MESSAGE_BEGIN || status() == ReadingRequest || status() == KeepAliveRead) {
		BufferRef chunk(input_.ref(inputOffset_));
		if (chunk.empty())
			break;

		// ensure status is up-to-date, in case we came from keep-alive-read
		if (status_ == KeepAliveRead) {
			TRACE(1, "process: status=keep-alive-read, resetting to reading-request");
			setStatus(ReadingRequest);
			if (request_->isFinished()) {
				TRACE(1, "process: finalizing request");
				request_->finalize();
			}
		}

		TRACE(1, "process: (size: %lu, isHandlingRequest:%d, state:%s status:%s", chunk.size(), isHandlingRequest(), state_str(), status_str());
		//TRACE(1, "%s", input_.ref(input_.size() - rv).str().c_str());

		size_t rv = HttpMessageProcessor::process(chunk, &inputOffset_);
		TRACE(1, "process: done process()ing; fd=%d, request=%p state:%s status:%s, rv:%d", socket_->handle(), request_, state_str(), status_str(), rv);

		if (isAborted()) {
			TRACE(1, "abort detected");
			return false;
		}

		if (state() == SYNTAX_ERROR) {
			TRACE(1, "syntax error detected");
			if (!request_->isFinished()) {
				abort(HttpStatus::BadRequest);
			}
			TRACE(1, "syntax error detected: leaving process()");
			return false;
		}

		if (rv < chunk.size()) {
			request_->log(Severity::debug1, "parser aborted early.");
			return false;
		}
	}

	TRACE(1, "process: offset=%lu, bs=%lu, state=%s (after processing) io.timer:%d",
			inputOffset_, input_.size(), state_str(), socket_->timerActive());

	return true;
}
Exemplo n.º 16
0
static void astfn(void *arg)
{
	struct lk *lk = arg;
	int i = lk->id;

	if (!lk->wait_ast) {
		printf("     ast: %s %3d\t%x: !wait_ast gr %d rq %d last op %s %s\n",
		       status_str(lk->lksb.sb_status), i, lk->lksb.sb_lkid,
		       lk->grmode, lk->rqmode,
		       op_str(lk->lastop), status_str(lk->last_status));
	}

	log_ast("     ast: %s %3d\t%x\n",
		status_str(lk->lksb.sb_status), i, lk->lksb.sb_lkid);

	lk->last_status = lk->lksb.sb_status;

	if (lk->lksb.sb_status == EUNLOCK) {
		sts_eunlock++;
		memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
		lk->grmode = -1;
		lk->wait_ast = 0;

	} else if (lk->lksb.sb_status == ECANCEL) {
		sts_ecancel++;
		if (lk->grmode == -1) {
			memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
			lk->wait_ast = 0;
		} else {
			if (lk->lastop != Op_unlock && lk->lastop != Op_unlockf)
				lk->wait_ast = 0;
		}

	} else if (lk->lksb.sb_status == ETIMEDOUT) {
		sts_etimedout++;
		if (lk->grmode == -1) {
			memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
			lk->wait_ast = 0;
		} else {
			if (lk->lastop != Op_unlock && lk->lastop != Op_unlockf)
				lk->wait_ast = 0;
		}

	} else if (lk->lksb.sb_status == EDEADLK) {
		sts_edeadlk++;
		if (lk->grmode == -1) {
			memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
			lk->wait_ast = 0;
		} else {
			if (lk->lastop != Op_unlock && lk->lastop != Op_unlockf)
				lk->wait_ast = 0;
		}

	} else if (lk->lksb.sb_status == EAGAIN) {
		sts_eagain++;
		if (lk->grmode == -1) {
			memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
			lk->wait_ast = 0;
		} else {
			if (lk->lastop != Op_unlockf)
				lk->wait_ast = 0;
		}

	} else {
		if (lk->lksb.sb_status != 0) {
			sts_other++;
			printf("BAD  ast: %d %3d\t%x: gr %d rq %d last op %s %s\n",
		       		lk->lksb.sb_status, i, lk->lksb.sb_lkid,
				lk->grmode, lk->rqmode, op_str(lk->lastop),
				status_str(lk->last_status));
			stress_stop = 1;
			return;
		}

		sts_zero++;

		if (lk->lastop != Op_unlockf)
			lk->wait_ast = 0;

		lk->grmode = lk->rqmode;

		if (minhold) {
			gettimeofday(&lk->acquired, NULL);
			lk->minhold = minhold;
		}
	}

	lk->rqmode = -1;
}