source: box/trunk/lib/common/RateLimitingStream.cpp @ 2862

Revision 2862, 2.9 KB checked in by chris, 15 months ago (diff)

Hopefully fix divide by zero error on rate limiting stream.

  • Property svn:eol-style set to native
Line 
1// --------------------------------------------------------------------------
2//
3// File
4//              Name:    RateLimitingStream.cpp
5//              Purpose: Rate-limiting write-only wrapper around IOStreams
6//              Created: 2011/01/11
7//
8// --------------------------------------------------------------------------
9
10#include "Box.h"
11#include "RateLimitingStream.h"
12#include "CommonException.h"
13
14#include <string.h>
15
16#include "MemLeakFindOn.h"
17
18// --------------------------------------------------------------------------
19//
20// Function
21//              Name:    RateLimitingStream::RateLimitingStream(const char *, int, int)
22//              Purpose: Constructor, set up buffer
23//              Created: 2011/01/11
24//
25// --------------------------------------------------------------------------
26RateLimitingStream::RateLimitingStream(IOStream& rSink, size_t targetBytesPerSecond)
27: mrSink(rSink), mStartTime(GetCurrentBoxTime()), mTotalBytesRead(0),
28  mTargetBytesPerSecond(targetBytesPerSecond)
29{ }
30
31// --------------------------------------------------------------------------
32//
33// Function
34//              Name:    RateLimitingStream::Read(void *pBuffer, int NBytes,
35//                       int Timeout)
36//              Purpose: Reads bytes to the underlying stream at no more than
37//                       a fixed rate
38//              Created: 2011/01/11
39//
40// --------------------------------------------------------------------------
41int RateLimitingStream::Read(void *pBuffer, int NBytes, int Timeout)
42{
43        if(NBytes > 0 && (size_t)NBytes > mTargetBytesPerSecond)
44        {
45                // Limit to one second's worth of data for performance
46                BOX_TRACE("Reducing read size from " << NBytes << " to " <<
47                        mTargetBytesPerSecond << " to smooth upload rate");
48                NBytes = mTargetBytesPerSecond;
49        }
50
51        int bytesReadThisTime = mrSink.Read(pBuffer, NBytes, Timeout);
52
53        // How many bytes we will have written after this write finishes?
54        mTotalBytesRead += bytesReadThisTime;
55
56        // When should it be completed by?
57        box_time_t desiredFinishTime = mStartTime +
58                SecondsToBoxTime(mTotalBytesRead / mTargetBytesPerSecond);
59
60        // How long do we have to wait?
61        box_time_t currentTime = GetCurrentBoxTime();
62        int64_t waitTime = desiredFinishTime - currentTime;
63
64        // How are we doing so far? (for logging only)
65        box_time_t currentDuration = currentTime - mStartTime;
66
67        // in case our timer is not very accurate, don't divide by zero on first pass
68        if(currentDuration == 0)
69        {
70                BOX_TRACE("Current rate not yet known, sending immediately");
71                return bytesReadThisTime;
72        }
73               
74        uint64_t effectiveRateSoFar = (mTotalBytesRead * MICRO_SEC_IN_SEC_LL)
75                / currentDuration;
76
77        if(waitTime > 0)
78        {
79                BOX_TRACE("Current rate " << effectiveRateSoFar <<
80                        " higher than desired rate " << mTargetBytesPerSecond <<
81                        ", sleeping for " << BoxTimeToMilliSeconds(waitTime) <<
82                        " ms");
83                ShortSleep(waitTime, false);
84        }
85        else
86        {
87                BOX_TRACE("Current rate " << effectiveRateSoFar <<
88                        " lower than desired rate " << mTargetBytesPerSecond <<
89                        ", sending immediately (would have sent " <<
90                        (BoxTimeToMilliSeconds(-waitTime)) << " ms ago)");
91        }
92
93        return bytesReadThisTime;
94}
95
Note: See TracBrowser for help on using the repository browser.