forked from filebench/filebench
-
Notifications
You must be signed in to change notification settings - Fork 0
/
buffer.c
188 lines (155 loc) · 4.35 KB
/
buffer.c
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#include "filebench.h"
#include "utils.h"
/* Parses buffer segments from file. Sets relevant fields of buffer structure */
static int
parse_segments(char *segments_path, struct buffer *buf)
{
int ret = FILEBENCH_ERROR;
char *fcontents = read_entire_file(segments_path);
if (!fcontents) {
return FILEBENCH_ERROR;
}
uint64_t lines = 0;
for (uint64_t i = 0; fcontents[i] != 0; i++) {
if (fcontents[i] == '\n')
lines++;
}
struct buf_segment *segments = ipc_buf_segments_alloc(lines);
if (!segments) {
filebench_log(LOG_ERROR, "Allocation failed for buffer segments");
goto free_contents;
}
uint64_t max_seg_end = 0;
char *str = fcontents;
for (uint64_t i = 0; i < lines; i++) {
char *line_right = strsep(&str, "\n");
char *line_left = strsep(&line_right, ":");
if (line_right == NULL) {
filebench_log(LOG_ERROR, "Failed to parse segments file");
goto free_contents;
}
char *endptr;
uint64_t seg_start = strtoull(line_left, &endptr, 10);
if (*endptr != '\0') {
filebench_log(LOG_ERROR, "Failed to parse segment's starting byte");
goto free_contents;
}
uint64_t seg_end = strtoull(line_right, &endptr, 10);
if (*endptr != '\0') {
filebench_log(LOG_ERROR, "Failed to parse segment's ending byte");
goto free_contents;
}
if (seg_start > seg_end) {
filebench_log(LOG_ERROR, "Invalid segment %llu:%llu", seg_start,
seg_end);
goto free_contents;
}
if (seg_end > max_seg_end)
max_seg_end = seg_end;
segments[i] = (struct buf_segment){.start = seg_start,
.size = seg_end - seg_start + 1};
}
buf->segments = segments;
buf->segments_amount = lines;
buf->segment_head = 0;
buf->size = max_seg_end;
ret = FILEBENCH_OK;
free_contents:
free(fcontents);
return ret;
}
/*
* This routine implements the 'define buffer' calls found in a .f
* workload, such as in the following example:
* define buffer name=mybuffer,path=/opt/data/buf.txt,size=10000
*/
struct buffer *
buffer_define(char *name, char *data_path, char *segments_path)
{
struct buffer *buf = ipc_malloc(FILEBENCH_BUFFER);
if (!buf) {
filebench_log(LOG_ERROR, "Can't allocate buffer %s", name);
return NULL;
}
filebench_log(LOG_DEBUG_IMPL, "Defining buffer %s", name);
buf->name = name;
buf->data_path = data_path;
if (parse_segments(segments_path, buf)) {
return NULL;
}
/* Add buffer to global list */
(void)ipc_mutex_lock(&filebench_shm->shm_buffer_lock);
if (filebench_shm->shm_bufferlist == NULL) {
filebench_shm->shm_bufferlist = buf;
buf->next = NULL;
} else {
buf->next = filebench_shm->shm_bufferlist;
filebench_shm->shm_bufferlist = buf;
}
(void)ipc_mutex_unlock(&filebench_shm->shm_buffer_lock);
// increase amount of required ISM
// as buffer's data will be allocted there
filebench_shm->ism_required += buf->size;
return buf;
}
static int
buffer_allocate(struct buffer *buf)
{
filebench_log(LOG_INFO, "Allocating buffer %s", buf->name);
ssize_t ism_offset = ipc_ismmalloc(buf->size);
if (ism_offset == -1) {
filebench_log(LOG_ERROR, "Can't allocate data for buffer %s",
buf->name);
return FILEBENCH_ERROR;
}
buf->ism_offset = ism_offset;
FILE *file = fopen(buf->data_path, "rb");
if (!file) {
filebench_log(LOG_ERROR, "Failed to open file %s to allocate buffer %s",
buf->data_path, buf->name);
return FILEBENCH_ERROR;
}
if (fread(filebench_ism + ism_offset, 1, buf->size, file) != buf->size) {
(void)fclose(file);
filebench_log(LOG_ERROR,
"Failed to read %d bytes from file %s to buffer %s",
buf->size, buf->data_path, buf->name);
return FILEBENCH_ERROR;
}
(void)fclose(file);
return FILEBENCH_OK;
}
/*
* Allocates memory for all buffers
* and reads data files into them.
*/
int
buffer_allocate_all()
{
int ret;
(void)ipc_mutex_lock(&filebench_shm->shm_buffer_lock);
struct buffer *buf = filebench_shm->shm_bufferlist;
while (buf) {
if ((ret = buffer_allocate(buf))) {
return ret;
}
buf = buf->next;
}
(void)ipc_mutex_unlock(&filebench_shm->shm_buffer_lock);
return FILEBENCH_OK;
}
/* Finds buffer with specified name in global list */
struct buffer *
buffer_find_by_name(char *name)
{
(void)ipc_mutex_lock(&filebench_shm->shm_buffer_lock);
struct buffer *buf = filebench_shm->shm_bufferlist;
while (buf) {
if (!strcmp(name, buf->name)) {
break;
}
buf = buf->next;
}
(void)ipc_mutex_unlock(&filebench_shm->shm_buffer_lock);
return buf;
}