-
Notifications
You must be signed in to change notification settings - Fork 144
/
libflow.h
121 lines (102 loc) · 3.01 KB
/
libflow.h
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
#ifndef HEADER_LIBFLOW_H
#define HEADER_LIBFLOW_H
#include <stdint.h>
#include <stdbool.h>
struct flow;
typedef int (*flow_func_flush_chunk_t)(const struct flow *fw, int fd);
struct flow {
/* Total number of bytes to be processed. */
uint64_t total_size;
/* Total number of bytes already processed. */
uint64_t total_processed;
/* If true, show progress. */
int progress;
/* Block size in bytes. */
int block_size;
/* Delay intended between measurements in milliseconds. */
unsigned int delay_ms;
/* Increment to apply to @blocks_per_delay. */
int64_t step;
/* Blocks to process before measurement. */
int64_t blocks_per_delay;
/* Maximum processing rate in bytes per second. */
double max_process_rate;
/* Number of measured blocks. */
uint64_t measured_blocks;
/* Measured time. */
uint64_t measured_time_ms;
/* State. */
enum {FW_INC, FW_DEC, FW_SEARCH, FW_STEADY} state;
/* Number of characters to erase before printing out progress. */
int erase;
/*
* Methods
*/
flow_func_flush_chunk_t func_flush_chunk;
/*
* Initialized while measuring
*/
/* Number of blocks processed since last measurement. */
int64_t processed_blocks;
/*
* Accumulated delay before @processed_blocks reaches @blocks_per_delay
* in microseconds.
*/
uint64_t acc_delay_us;
/* Range of blocks_per_delay while in FW_SEARCH state. */
int64_t bpd1, bpd2;
/* Time measurements. */
struct timeval t1;
};
/* If @max_process_rate <= 0, the maximum processing rate is infinity.
* The unit of @max_process_rate is KB per second.
*/
void init_flow(struct flow *fw, uint64_t total_size,
long max_process_rate, int progress,
flow_func_flush_chunk_t func_flush_chunk);
void start_measurement(struct flow *fw);
int measure(int fd, struct flow *fw, long processed);
int end_measurement(int fd, struct flow *fw);
static inline int has_enough_measurements(const struct flow *fw)
{
return fw->measured_time_ms > fw->delay_ms;
}
static inline double get_avg_speed_given_time(struct flow *fw,
uint64_t total_time_ms)
{
return (double)(fw->measured_blocks * fw->block_size * 1000) /
total_time_ms;
}
/* Average writing speed in byte/s. */
static inline double get_avg_speed(struct flow *fw)
{
return get_avg_speed_given_time(fw, fw->measured_time_ms);
}
static inline uint64_t get_rem_chunk_size(struct flow *fw)
{
assert(fw->blocks_per_delay > fw->processed_blocks);
return (fw->blocks_per_delay - fw->processed_blocks) * fw->block_size;
}
struct dynamic_buffer {
char *buf;
size_t len;
bool max_buf;
char backup_buf[1 << 21]; /* 2MB */
};
static inline void dbuf_init(struct dynamic_buffer *dbuf)
{
dbuf->buf = dbuf->backup_buf;
dbuf->len = sizeof(dbuf->backup_buf);
dbuf->max_buf = false;
}
void dbuf_free(struct dynamic_buffer *dbuf);
/*
* Although the returned buffer may be smaller than @size,
* this function never returns NULL.
*/
char *dbuf_get_buf(struct dynamic_buffer *dbuf, size_t size);
static inline size_t dbuf_get_len(const struct dynamic_buffer *dbuf)
{
return dbuf->len;
}
#endif /* HEADER_LIBFLOW_H */