-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSendfileIOPump.cpp
179 lines (157 loc) · 5.29 KB
/
SendfileIOPump.cpp
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
/*
* File: SendfileIOPump.cpp
* Author: try
*
* Created on 2011年7月12日, 下午12:27
*/
#include <errno.h>
#include <sys/sendfile.h>
#include <math.h>
#include <stdlib.h>
#include "SendfileIOPump.h"
SendfileIOPump::SendfileIOPump(FD recvfd, FD sendfd, unsigned int speed, size_t maxSendSize):
recefd(recvfd), sendfd(sendfd), speed((unsigned int)(speed*1.3)), maxSendSize(maxSendSize), sendedBytes(0), eagainCount(0),
readEvent(this), writeEvent(this)
{
sendfiletimer.set<SendfileIOPump, &SendfileIOPump::timerCallback> (this);
offset = 0;
dmaxSendSize = maxSendSize + maxSendSize;
setLength(0);
}
SendfileIOPump::~SendfileIOPump() {
//LOG_DEBUG("");
close();
}
void SendfileIOPump::setLength(size_t len){
this->length = len;
if(length > 0){
//根据length计算timeoutInterval, readBytesPerEach, sendBytesPerEach
calculateSpeed(speed, &timeoutInterval, &readBytesPerEach, length>maxSendSize?maxSendSize:length);
// LOG_DEBUG("1 readBytesPerEach:%d, timeoutInterval:%f", readBytesPerEach, timeoutInterval);
sendBytesPerEach = readBytesPerEach;
}else{
calculateSpeed(speed, &timeoutInterval, &readBytesPerEach, maxSendSize);
// LOG_DEBUG("2 readBytesPerEach:%d, timeoutInterval:%f", readBytesPerEach, timeoutInterval);
sendBytesPerEach = readBytesPerEach;
}
dupTimeoutInterval = timeoutInterval;
//maxEagainCount = (int)(1.0/timeoutInterval);
maxEagainCount = 20;
//LOG_DEBUG("maxEagainCount:%f", maxEagainCount);
};
/**
* 启动
*/
bool SendfileIOPump::start(){
if(status == NEW){
status = RUNNING;
sendData();
return true;
}
return false;
}
/**
* 关闭
*/
void SendfileIOPump::close(){
if(status == CLOSED)return;
stopSendfileTimer();
status = CLOSED;
}
/**
* 复位
*/
void SendfileIOPump::reset(){
if(status == CLOSED)return;
status = NEW;
offset = 0;
sendBytesPerEach = readBytesPerEach;
timeoutInterval = dupTimeoutInterval;
if(sendfiletimer.is_active()){
sendfiletimer.stop();
}
}
void SendfileIOPump::startSendfileTimer(){
if(!isRunning()) return;
if(eagainCount > 5){
LOG_DEBUG("eagainCount:%d, timeoutInterval:%f, calInterval:%f", eagainCount, timeoutInterval, (timeoutInterval + eagainCount * eagainCount * timeoutInterval))
}
sendfiletimer.start(eagainCount>0?(timeoutInterval + eagainCount * eagainCount * timeoutInterval):timeoutInterval, 0);
}
void SendfileIOPump::stopSendfileTimer(){
if(sendfiletimer.is_active()){
sendfiletimer.stop();
}
}
void SendfileIOPump::timerCallback(ev::timer &ev, int revents){
sendData();
}
//此方法实现的不满意,待有时间再优化
void SendfileIOPump::sendData(){
if(!isRunning()) return;
// LOG_DEBUG("offset:%d", offset);
ssize_t sendsize = ::sendfile(recefd, sendfd, &offset, sendBytesPerEach);
bool isAgain = ERRNO_IS_AGAIN();
//处理length大于0的情况, 指定了下载数据量
if(length > 0 && sendsize > 0){
sendedBytes += sendsize;
if(sendedBytes >= length){
//已经传输完计划传输量
readEvent.length = sendsize;
writeEvent.length = sendsize;
//触发事件
fireTransportEvent(&readEvent, &writeEvent);
//传输结束
readEvent.length = 0;
writeEvent.length = 0;
//触发事件
fireTransportEvent(&readEvent, &writeEvent);
return;
}
}
if(sendsize >=0 || (sendsize < 0 && !isAgain)){
readEvent.length = sendsize;
writeEvent.length = sendsize;
//触发事件
fireTransportEvent(&readEvent, &writeEvent);
if(!isRunning()) return;
}
//以下代码写的不满意,以后有时间再优化
if(sendsize >= 0 || isAgain){
//重新计算下载数据量和频率
if(length > 0){
//指定下载数据量的情况
if(sendsize > 0){
maxSendSize = (sendsize + sendsize/3);
size_t excessBytes = length - sendedBytes; //还剩下多少数据量没有发送
maxSendSize = maxSendSize < excessBytes?maxSendSize:excessBytes;
calculateSpeed(speed, &timeoutInterval, &sendBytesPerEach, maxSendSize);
if(eagainCount > 0){
eagainCount = eagainCount/2;
}
}else{
sendBytesPerEach = readBytesPerEach; //发送数据量不变
timeoutInterval = dupTimeoutInterval;
if(eagainCount < maxEagainCount){
eagainCount++;
}
}
}else{
//没指定下载数据量的情况
if(sendsize > 0){
calculateSpeed(speed, &timeoutInterval, &sendBytesPerEach, (sendsize + sendsize/3));
if(eagainCount > 0){
eagainCount = eagainCount/2;
}
}else{
timeoutInterval = dupTimeoutInterval;
sendBytesPerEach = readBytesPerEach;
if(eagainCount < maxEagainCount){
eagainCount++;
}
}
}
//继续发
startSendfileTimer();
}
}