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 }