blob.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #include "blob.h"
  2. #include "addstorage.h"
  3. #include <util/system/yassert.h>
  4. #include <util/system/filemap.h>
  5. #include <util/system/mlock.h>
  6. #include <util/stream/buffer.h>
  7. #include <util/generic/ptr.h>
  8. #include <util/generic/string.h>
  9. #include <util/generic/buffer.h>
  10. #include <util/generic/ylimits.h>
  11. #include <util/generic/singleton.h>
  12. #include <util/generic/yexception.h>
  13. template <class TCounter>
  14. class TDynamicBlobBase: public TBlob::TBase,
  15. public TRefCounted<TDynamicBlobBase<TCounter>, TCounter>,
  16. public TAdditionalStorage<TDynamicBlobBase<TCounter>> {
  17. using TRefBase = TRefCounted<TDynamicBlobBase, TCounter>;
  18. public:
  19. inline TDynamicBlobBase() = default;
  20. ~TDynamicBlobBase() override = default;
  21. void Ref() noexcept override {
  22. TRefBase::Ref();
  23. }
  24. void UnRef() noexcept override {
  25. TRefBase::UnRef();
  26. }
  27. inline void* Data() const noexcept {
  28. return this->AdditionalData();
  29. }
  30. inline size_t Length() const noexcept {
  31. return this->AdditionalDataLength();
  32. }
  33. };
  34. template <class TCounter>
  35. class TBufferBlobBase: public TBlob::TBase, public TRefCounted<TBufferBlobBase<TCounter>, TCounter> {
  36. using TRefBase = TRefCounted<TBufferBlobBase, TCounter>;
  37. public:
  38. inline TBufferBlobBase(TBuffer& buf) {
  39. Buf_.Swap(buf);
  40. }
  41. ~TBufferBlobBase() override = default;
  42. void Ref() noexcept override {
  43. TRefBase::Ref();
  44. }
  45. void UnRef() noexcept override {
  46. TRefBase::UnRef();
  47. }
  48. inline const TBuffer& Buffer() const noexcept {
  49. return Buf_;
  50. }
  51. private:
  52. TBuffer Buf_;
  53. };
  54. template <class TCounter>
  55. class TStringBlobBase: public TBlob::TBase, public TRefCounted<TStringBlobBase<TCounter>, TCounter> {
  56. using TRefBase = TRefCounted<TStringBlobBase, TCounter>;
  57. public:
  58. inline TStringBlobBase(const TString& s)
  59. : S_(s)
  60. {
  61. }
  62. TStringBlobBase(TString&& s) noexcept
  63. : S_(std::move(s))
  64. {
  65. }
  66. ~TStringBlobBase() override = default;
  67. void Ref() noexcept override {
  68. TRefBase::Ref();
  69. }
  70. void UnRef() noexcept override {
  71. TRefBase::UnRef();
  72. }
  73. inline const TString& String() const noexcept {
  74. return S_;
  75. }
  76. private:
  77. const TString S_;
  78. };
  79. template <class TCounter>
  80. class TMappedBlobBase: public TBlob::TBase, public TRefCounted<TMappedBlobBase<TCounter>, TCounter> {
  81. using TRefBase = TRefCounted<TMappedBlobBase<TCounter>, TCounter>;
  82. public:
  83. inline TMappedBlobBase(const TMemoryMap& map, ui64 offset, size_t len, EMappingMode mode)
  84. : Map_(map)
  85. , Mode_(mode)
  86. {
  87. Y_ENSURE(Map_.IsOpen(), TStringBuf("memory map not open"));
  88. Map_.Map(offset, len);
  89. if (len && !Map_.Ptr()) { // Ptr is 0 for blob of size 0
  90. ythrow yexception() << "can not map(" << offset << ", " << len << ")";
  91. }
  92. if (Mode_ == EMappingMode::Locked) {
  93. LockMemory(Data(), Length());
  94. }
  95. }
  96. ~TMappedBlobBase() override {
  97. if (Mode_ == EMappingMode::Locked && Length()) {
  98. UnlockMemory(Data(), Length());
  99. }
  100. }
  101. void Ref() noexcept override {
  102. TRefBase::Ref();
  103. }
  104. void UnRef() noexcept override {
  105. TRefBase::UnRef();
  106. }
  107. inline const void* Data() const noexcept {
  108. return Map_.Ptr();
  109. }
  110. inline size_t Length() const noexcept {
  111. return Map_.MappedSize();
  112. }
  113. private:
  114. TFileMap Map_;
  115. EMappingMode Mode_;
  116. };
  117. TBlob TBlob::SubBlob(size_t len) const {
  118. /*
  119. * may be slightly optimized
  120. */
  121. return SubBlob(0, len);
  122. }
  123. TBlob TBlob::SubBlob(size_t begin, size_t end) const {
  124. if (begin > Length() || end > Length() || begin > end) {
  125. ythrow yexception() << "incorrect subblob (" << begin << ", " << end << ", outer length = " << Length() << ")";
  126. }
  127. return TBlob(Begin() + begin, end - begin, S_.Base);
  128. }
  129. TBlob TBlob::DeepCopy() const {
  130. return TBlob::Copy(Data(), Length());
  131. }
  132. template <class TCounter>
  133. static inline TBlob CopyConstruct(const void* data, size_t len) {
  134. using Base = TDynamicBlobBase<TCounter>;
  135. THolder<Base> base(new (len) Base);
  136. Y_ASSERT(base->Length() == len);
  137. memcpy(base->Data(), data, len);
  138. TBlob ret(base->Data(), len, base.Get());
  139. Y_UNUSED(base.Release());
  140. return ret;
  141. }
  142. TBlob TBlob::CopySingleThreaded(const void* data, size_t length) {
  143. return CopyConstruct<TSimpleCounter>(data, length);
  144. }
  145. TBlob TBlob::Copy(const void* data, size_t length) {
  146. return CopyConstruct<TAtomicCounter>(data, length);
  147. }
  148. TBlob TBlob::NoCopy(const void* data, size_t length) {
  149. return TBlob(data, length, nullptr);
  150. }
  151. template <class TCounter>
  152. static inline TBlob ConstructFromMap(const TMemoryMap& map, ui64 offset, size_t length, EMappingMode mode) {
  153. using TBase = TMappedBlobBase<TCounter>;
  154. THolder<TBase> base(new TBase(map, offset, length, mode));
  155. TBlob ret(base->Data(), base->Length(), base.Get());
  156. Y_UNUSED(base.Release());
  157. return ret;
  158. }
  159. template <class TCounter, class T>
  160. static inline TBlob ConstructAsMap(const T& t, EMappingMode mode) {
  161. TMemoryMap::EOpenMode openMode = (mode == EMappingMode::Precharged) ? (TMemoryMap::oRdOnly | TMemoryMap::oPrecharge) : TMemoryMap::oRdOnly;
  162. TMemoryMap map(t, openMode);
  163. const ui64 toMap = map.Length();
  164. if (toMap > Max<size_t>()) {
  165. ythrow yexception() << "can not map whole file(length = " << toMap << ")";
  166. }
  167. return ConstructFromMap<TCounter>(map, 0, static_cast<size_t>(toMap), mode);
  168. }
  169. TBlob TBlob::FromFileSingleThreaded(const TString& path, EMappingMode mode) {
  170. return ConstructAsMap<TSimpleCounter>(path, mode);
  171. }
  172. TBlob TBlob::FromFile(const TString& path, EMappingMode mode) {
  173. return ConstructAsMap<TAtomicCounter>(path, mode);
  174. }
  175. TBlob TBlob::FromFileSingleThreaded(const TFile& file, EMappingMode mode) {
  176. return ConstructAsMap<TSimpleCounter>(file, mode);
  177. }
  178. TBlob TBlob::FromFile(const TFile& file, EMappingMode mode) {
  179. return ConstructAsMap<TAtomicCounter>(file, mode);
  180. }
  181. TBlob TBlob::FromFileSingleThreaded(const TString& path) {
  182. return ConstructAsMap<TSimpleCounter>(path, EMappingMode::Standard);
  183. }
  184. TBlob TBlob::FromFile(const TString& path) {
  185. return ConstructAsMap<TAtomicCounter>(path, EMappingMode::Standard);
  186. }
  187. TBlob TBlob::FromFileSingleThreaded(const TFile& file) {
  188. return ConstructAsMap<TSimpleCounter>(file, EMappingMode::Standard);
  189. }
  190. TBlob TBlob::FromFile(const TFile& file) {
  191. return ConstructAsMap<TAtomicCounter>(file, EMappingMode::Standard);
  192. }
  193. TBlob TBlob::PrechargedFromFileSingleThreaded(const TString& path) {
  194. return ConstructAsMap<TSimpleCounter>(path, EMappingMode::Precharged);
  195. }
  196. TBlob TBlob::PrechargedFromFile(const TString& path) {
  197. return ConstructAsMap<TAtomicCounter>(path, EMappingMode::Precharged);
  198. }
  199. TBlob TBlob::PrechargedFromFileSingleThreaded(const TFile& file) {
  200. return ConstructAsMap<TSimpleCounter>(file, EMappingMode::Precharged);
  201. }
  202. TBlob TBlob::PrechargedFromFile(const TFile& file) {
  203. return ConstructAsMap<TAtomicCounter>(file, EMappingMode::Precharged);
  204. }
  205. TBlob TBlob::LockedFromFileSingleThreaded(const TString& path) {
  206. return ConstructAsMap<TSimpleCounter>(path, EMappingMode::Locked);
  207. }
  208. TBlob TBlob::LockedFromFile(const TString& path) {
  209. return ConstructAsMap<TAtomicCounter>(path, EMappingMode::Locked);
  210. }
  211. TBlob TBlob::LockedFromFileSingleThreaded(const TFile& file) {
  212. return ConstructAsMap<TSimpleCounter>(file, EMappingMode::Locked);
  213. }
  214. TBlob TBlob::LockedFromFile(const TFile& file) {
  215. return ConstructAsMap<TAtomicCounter>(file, EMappingMode::Locked);
  216. }
  217. TBlob TBlob::LockedFromMemoryMapSingleThreaded(const TMemoryMap& map, ui64 offset, size_t length) {
  218. return ConstructFromMap<TSimpleCounter>(map, offset, length, EMappingMode::Locked);
  219. }
  220. TBlob TBlob::LockedFromMemoryMap(const TMemoryMap& map, ui64 offset, size_t length) {
  221. return ConstructFromMap<TAtomicCounter>(map, offset, length, EMappingMode::Locked);
  222. }
  223. TBlob TBlob::FromMemoryMapSingleThreaded(const TMemoryMap& map, ui64 offset, size_t length) {
  224. return ConstructFromMap<TSimpleCounter>(map, offset, length, EMappingMode::Standard);
  225. }
  226. TBlob TBlob::FromMemoryMap(const TMemoryMap& map, ui64 offset, size_t length) {
  227. return ConstructFromMap<TAtomicCounter>(map, offset, length, EMappingMode::Standard);
  228. }
  229. template <class TCounter>
  230. static inline TBlob ReadFromFile(const TFile& file, ui64 offset, size_t length) {
  231. using TBase = TDynamicBlobBase<TCounter>;
  232. THolder<TBase> base(new (length) TBase);
  233. Y_ASSERT(base->Length() == length);
  234. file.Pload(base->Data(), length, offset);
  235. TBlob ret(base->Data(), length, base.Get());
  236. Y_UNUSED(base.Release());
  237. return ret;
  238. }
  239. template <class TCounter>
  240. static inline TBlob ConstructFromFileContent(const TFile& file, ui64 offset, ui64 length) {
  241. if (length > Max<size_t>()) {
  242. ythrow yexception() << "can not read whole file(length = " << length << ")";
  243. }
  244. return ReadFromFile<TCounter>(file, offset, static_cast<size_t>(length));
  245. }
  246. TBlob TBlob::FromFileContentSingleThreaded(const TString& path) {
  247. TFile file(path, RdOnly);
  248. return ConstructFromFileContent<TSimpleCounter>(file, 0, file.GetLength());
  249. }
  250. TBlob TBlob::FromFileContent(const TString& path) {
  251. TFile file(path, RdOnly);
  252. return ConstructFromFileContent<TAtomicCounter>(file, 0, file.GetLength());
  253. }
  254. TBlob TBlob::FromFileContentSingleThreaded(const TFile& file) {
  255. return ConstructFromFileContent<TSimpleCounter>(file, 0, file.GetLength());
  256. }
  257. TBlob TBlob::FromFileContent(const TFile& file) {
  258. return ConstructFromFileContent<TAtomicCounter>(file, 0, file.GetLength());
  259. }
  260. TBlob TBlob::FromFileContentSingleThreaded(const TFile& file, ui64 offset, size_t length) {
  261. return ConstructFromFileContent<TSimpleCounter>(file, offset, length);
  262. }
  263. TBlob TBlob::FromFileContent(const TFile& file, ui64 offset, size_t length) {
  264. return ConstructFromFileContent<TAtomicCounter>(file, offset, length);
  265. }
  266. template <class TCounter>
  267. static inline TBlob ConstructFromBuffer(TBuffer& in) {
  268. using TBase = TBufferBlobBase<TCounter>;
  269. THolder<TBase> base(new TBase(in));
  270. TBlob ret(base->Buffer().Data(), base->Buffer().Size(), base.Get());
  271. Y_UNUSED(base.Release());
  272. return ret;
  273. }
  274. template <class TCounter>
  275. static inline TBlob ConstructFromStream(IInputStream& in) {
  276. TBuffer buf;
  277. {
  278. TBufferOutput out(buf);
  279. TransferData(&in, &out);
  280. }
  281. return ConstructFromBuffer<TCounter>(buf);
  282. }
  283. TBlob TBlob::FromStreamSingleThreaded(IInputStream& in) {
  284. return ConstructFromStream<TSimpleCounter>(in);
  285. }
  286. TBlob TBlob::FromStream(IInputStream& in) {
  287. return ConstructFromStream<TAtomicCounter>(in);
  288. }
  289. TBlob TBlob::FromBufferSingleThreaded(TBuffer& in) {
  290. return ConstructFromBuffer<TSimpleCounter>(in);
  291. }
  292. TBlob TBlob::FromBuffer(TBuffer& in) {
  293. return ConstructFromBuffer<TAtomicCounter>(in);
  294. }
  295. template <class TCounter, class S>
  296. TBlob ConstructFromString(S&& s) {
  297. using TBase = TStringBlobBase<TCounter>;
  298. auto base = MakeHolder<TBase>(std::forward<S>(s));
  299. TBlob ret(base->String().data(), base->String().size(), base.Get());
  300. Y_UNUSED(base.Release());
  301. return ret;
  302. }
  303. TBlob TBlob::FromStringSingleThreaded(const TString& s) {
  304. return ConstructFromString<TSimpleCounter>(s);
  305. }
  306. TBlob TBlob::FromStringSingleThreaded(TString&& s) {
  307. return ConstructFromString<TSimpleCounter>(std::move(s));
  308. }
  309. TBlob TBlob::FromString(const TString& s) {
  310. return ConstructFromString<TAtomicCounter>(s);
  311. }
  312. TBlob TBlob::FromString(TString&& s) {
  313. return ConstructFromString<TAtomicCounter>(std::move(s));
  314. }