00001 #include "util/stream/io.hh"
00002
00003 #include "util/file.hh"
00004 #include "util/stream/chain.hh"
00005
00006 #include <cstddef>
00007
00008 namespace util {
00009 namespace stream {
00010
00011 ReadSizeException::ReadSizeException() throw() {}
00012 ReadSizeException::~ReadSizeException() throw() {}
00013
00014 void Read::Run(const ChainPosition &position) {
00015 const std::size_t block_size = position.GetChain().BlockSize();
00016 const std::size_t entry_size = position.GetChain().EntrySize();
00017 for (Link link(position); link; ++link) {
00018 std::size_t got = util::ReadOrEOF(file_, link->Get(), block_size);
00019 UTIL_THROW_IF(got % entry_size, ReadSizeException, "File ended with " << got << " bytes, not a multiple of " << entry_size << ".");
00020 if (got == 0) {
00021 link.Poison();
00022 return;
00023 } else {
00024 link->SetValidSize(got);
00025 }
00026 }
00027 }
00028
00029 void PRead::Run(const ChainPosition &position) {
00030 scoped_fd owner;
00031 if (own_) owner.reset(file_);
00032 const uint64_t size = SizeOrThrow(file_);
00033 UTIL_THROW_IF(size % static_cast<uint64_t>(position.GetChain().EntrySize()), ReadSizeException, "File size " << file_ << " size is " << size << " not a multiple of " << position.GetChain().EntrySize());
00034 const std::size_t block_size = position.GetChain().BlockSize();
00035 const uint64_t block_size64 = static_cast<uint64_t>(block_size);
00036 Link link(position);
00037 uint64_t offset = 0;
00038 for (; offset + block_size64 < size; offset += block_size64, ++link) {
00039 ErsatzPRead(file_, link->Get(), block_size, offset);
00040 link->SetValidSize(block_size);
00041 }
00042
00043 if (size - offset) {
00044 ErsatzPRead(file_, link->Get(), size - offset, offset);
00045 link->SetValidSize(size - offset);
00046 ++link;
00047 }
00048 link.Poison();
00049 }
00050
00051 void Write::Run(const ChainPosition &position) {
00052 for (Link link(position); link; ++link) {
00053 WriteOrThrow(file_, link->Get(), link->ValidSize());
00054 }
00055 }
00056
00057 void WriteAndRecycle::Run(const ChainPosition &position) {
00058 const std::size_t block_size = position.GetChain().BlockSize();
00059 for (Link link(position); link; ++link) {
00060 WriteOrThrow(file_, link->Get(), link->ValidSize());
00061 link->SetValidSize(block_size);
00062 }
00063 }
00064
00065 void PWriteAndRecycle::Run(const ChainPosition &position) {
00066 const std::size_t block_size = position.GetChain().BlockSize();
00067 uint64_t offset = 0;
00068 for (Link link(position); link; ++link) {
00069 ErsatzPWrite(file_, link->Get(), link->ValidSize(), offset);
00070 offset += link->ValidSize();
00071 link->SetValidSize(block_size);
00072 }
00073
00074 util::ResizeOrThrow(file_, offset);
00075 }
00076
00077 }
00078 }