1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
/*
* Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
/** \file stdout.c Functions that deal with writing to stdout. */
#include <dirent.h> /* readdir() */
#include <assert.h>
#include "para.h"
#include "string.h"
#include "list.h"
#include "sched.h"
#include "fd.h"
#include "error.h"
#include "stdout.h"
/**
* The pre_select function of the stdout task.
*
* \param s The scheduler this task was registered to.
* \param t The task structure of the stdout task.
*
* This function is always successful. If there is data available in the input
* buffer, it adds \p STDOUT_FILENO to the write fd set of \a s.
*/
static void stdout_pre_select(struct sched *s, struct task *t)
{
struct stdout_task *sot = container_of(t, struct stdout_task, task);
t->error = 0;
sot->check_fd = 0;
if (!*sot->loaded) {
if (*sot->input_error < 0) {
t->error = *sot->input_error;
s->timeout.tv_sec = 0;
s->timeout.tv_usec = 1;
}
return;
}
sot->check_fd = 1;
para_fd_set(STDOUT_FILENO, &s->wfds, &s->max_fileno);
}
/**
* The post select function of the stdout task.
*
* \param s The scheduler this task was registered to.
* \param t The task structure of the stdout task.
*
* This function checks if \p STDOUT_FILENO was included by in the write fd set
* of \a s during the previous pre_select call. If yes, and \p STDOUT_FILENO
* appeears to be writable, the data loaded in the input buffer is written to
* stdout.
*/
static void stdout_post_select(struct sched *s, struct task *t)
{
struct stdout_task *sot = container_of(t, struct stdout_task, task);
ssize_t ret;
t->error = 0;
if (!sot->check_fd) {
if (!*sot->loaded && *sot->input_error < 0)
t->error = *sot->input_error;
return;
}
if (!FD_ISSET(STDOUT_FILENO, &s->wfds))
return;
ret = write(STDOUT_FILENO, *sot->bufp, *sot->loaded);
if (ret < 0) {
t->error = -ERRNO_TO_PARA_ERROR(errno);
return;
}
*sot->loaded -= ret;
if (*sot->loaded)
memmove(*sot->bufp, *sot->bufp + ret, *sot->loaded);
}
/**
* Initialize a stdout task structure with default values.
*
* \param sot The stdout task structure.
*
* This fills in the pre/post select function poinzters of the task structure
* given by \a sot.
*/
void stdout_set_defaults(struct stdout_task *sot)
{
int ret;
sot->task.pre_select = stdout_pre_select;
sot->task.post_select = stdout_post_select;
sprintf(sot->task.status, "stdout writer");
ret = mark_fd_nonblocking(STDOUT_FILENO);
if (ret >= 0)
return;
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
exit(EXIT_FAILURE);
}
|