PageRenderTime 33ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/mordor/streams/http.h

http://github.com/mozy/mordor
C Header | 119 lines | 68 code | 16 blank | 35 comment | 0 complexity | b40c1892cab230724ba78b683f80db9e MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #ifndef __MORDOR_HTTP_STREAM__
  2. #define __MORDOR_HTTP_STREAM__
  3. // Copyright (c) 2009 - Mozy, Inc.
  4. #include "filter.h"
  5. #include "mordor/exception.h"
  6. #include "mordor/future.h"
  7. #include "mordor/http/broker.h"
  8. namespace Mordor {
  9. struct EntityChangedException : virtual Exception {};
  10. /// @note When using HTTPStream for PUTs, automatic retry is not supported
  11. /// (since HTTPStream does not see the entire request body in a single call,
  12. /// the retry must be handled at a higher level).
  13. class HTTPStream : public FilterStream
  14. {
  15. public:
  16. typedef boost::shared_ptr<HTTPStream> ptr;
  17. public:
  18. HTTPStream(const URI &uri, HTTP::RequestBroker::ptr requestBroker,
  19. boost::function<bool (size_t)> delayDg = NULL);
  20. HTTPStream(const HTTP::Request &requestHeaders,
  21. HTTP::RequestBroker::ptr requestBroker,
  22. boost::function<bool (size_t)> delayDg = NULL);
  23. ~HTTPStream();
  24. void sharedRetryCounter(size_t *retries) { mp_retries = retries; }
  25. void eTag(const HTTP::ETag &eTag) { m_eTag = eTag; }
  26. HTTP::ETag eTag();
  27. /// Force the transfer to begin (i.e. so a call to size() won't try to
  28. /// do an extra HEAD)
  29. ///
  30. /// @note If the current read advice is zero, this will be forced to do an
  31. /// HTTP request for the entire entity
  32. void start();
  33. /// This will abandon any current transfer in progress. If it returns
  34. /// true, the transfer will have already begun at the current position
  35. bool checkModified();
  36. /// @note In WRITE mode, HTTP response is not available until stream close.
  37. /// It will cause write abortion if this interface is invoked before stream close
  38. const HTTP::Response &response();
  39. bool supportsRead() { return true; }
  40. bool supportsWrite() { return true; }
  41. bool supportsSeek() { return true; }
  42. bool supportsSize();
  43. bool supportsTruncate() { return true; }
  44. bool supportsTell() { return true; }
  45. void close(CloseType type = BOTH);
  46. using FilterStream::read;
  47. size_t read(Buffer &buffer, size_t length);
  48. using FilterStream::write;
  49. size_t write(const Buffer &buffer, size_t length);
  50. long long seek(long long offset, Anchor anchor = BEGIN);
  51. long long size();
  52. /// @note Truncate is accomplished by doing a PUT with
  53. /// Content-Range: */<size>.
  54. void truncate(long long size);
  55. void flush(bool flushParent = true);
  56. /// Advise about subsequent read calls, so that more efficient HTTP
  57. /// requests can be used.
  58. ///
  59. /// Sets the minimum number of bytes per HTTP request. The default is
  60. /// ~0ull, which means only one HTTP request will be needed. Setting to 0
  61. /// would mean each call to read will generate a new HTTP request.
  62. void adviseRead(unsigned long long advice) { m_readAdvice = advice; }
  63. /// Advise about subsequent write calls, so that more efficient HTTP
  64. /// requests can be used.
  65. ///
  66. /// Sets the minimum number of bytes per HTTP request. The default is
  67. /// ~0ull, which means only one HTTP request will be needed. Setting to 0
  68. /// would mean each call to write will generate a new HTTP request.
  69. /// @warning If you write beyond the initial advice, you will invoke
  70. /// non-standardized HTTP behavior that most servers will not support.
  71. /// See http://code.google.com/p/gears/wiki/ContentRangePostProposal
  72. /// and http://www.hpl.hp.com/personal/ange/archives/archives-97/http-wg-archive/2530.html
  73. void adviseWrite(unsigned long long advice) { m_writeAdvice = advice; }
  74. /// Advise about the eventual size of the stream, so that a more efficient
  75. /// HTTP request can be used.
  76. ///
  77. /// Setting this will avoid using chunked encoding.
  78. void adviseSize(long long advice) { m_sizeAdvice = advice; }
  79. private:
  80. void start(size_t length);
  81. void stat();
  82. void doWrite(boost::shared_ptr<HTTP::ClientRequest> request);
  83. void startWrite();
  84. void clearParent(bool error = false);
  85. private:
  86. HTTP::Request m_requestHeaders;
  87. HTTP::Response m_response;
  88. bool m_hasResponse;
  89. HTTP::RequestBroker::ptr m_requestBroker;
  90. HTTP::ETag m_eTag;
  91. long long m_pos, m_size, m_sizeAdvice;
  92. unsigned long long m_readAdvice, m_writeAdvice,
  93. m_readRequested, m_writeRequested;
  94. boost::function<bool (size_t)> m_delayDg;
  95. size_t *mp_retries;
  96. bool m_writeInProgress, m_abortWrite;
  97. Future<> m_writeFuture, m_writeFuture2;
  98. boost::shared_ptr<HTTP::ClientRequest> m_writeRequest;
  99. boost::shared_ptr<HTTP::ClientRequest> m_readRequest;
  100. boost::exception_ptr m_writeException;
  101. };
  102. }
  103. #endif