New upstream version 8.1.0
This commit is contained in:
149
fsck/source/database/DiskList.h
Normal file
149
fsck/source/database/DiskList.h
Normal file
@@ -0,0 +1,149 @@
|
||||
#ifndef DISKLIST_H_
|
||||
#define DISKLIST_H_
|
||||
|
||||
#include <common/threading/Mutex.h>
|
||||
#include <common/toolkit/serialization/Serialization.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct DiskListDoesNotExist : public std::runtime_error
|
||||
{
|
||||
DiskListDoesNotExist(const std::string& file)
|
||||
: runtime_error(file)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename Data>
|
||||
class DiskList;
|
||||
|
||||
template<typename Data>
|
||||
class DiskListCursor
|
||||
{
|
||||
friend class DiskList<Data>;
|
||||
|
||||
public:
|
||||
bool step()
|
||||
{
|
||||
uint64_t itemLen;
|
||||
|
||||
{
|
||||
ssize_t readRes = ::pread(fd, &itemLen, sizeof(itemLen), offset);
|
||||
|
||||
if (readRes == 0)
|
||||
return false;
|
||||
|
||||
if (readRes < (ssize_t) sizeof(itemLen))
|
||||
throw std::runtime_error("could not read from disk list file: " + std::string(strerror(errno)));
|
||||
}
|
||||
|
||||
itemLen = LE_TO_HOST_64(itemLen);
|
||||
|
||||
std::unique_ptr<char[]> itemBuf(new char[itemLen]);
|
||||
|
||||
ssize_t readRes = ::pread(fd, itemBuf.get(), itemLen, offset + sizeof(itemLen));
|
||||
|
||||
if (readRes < (ssize_t) itemLen)
|
||||
throw std::runtime_error("could not read from disk list file: " + std::string(strerror(errno)));
|
||||
|
||||
Deserializer des(itemBuf.get(), itemLen);
|
||||
|
||||
des % item;
|
||||
if (!des.good())
|
||||
throw std::runtime_error("could not read from disk list file: " + std::string(strerror(errno)));
|
||||
|
||||
offset += sizeof(itemLen) + itemLen;
|
||||
return true;
|
||||
}
|
||||
|
||||
Data* get()
|
||||
{
|
||||
return &item;
|
||||
}
|
||||
|
||||
private:
|
||||
int fd;
|
||||
size_t offset;
|
||||
Data item;
|
||||
|
||||
DiskListCursor(int fd):
|
||||
fd(fd), offset(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Data>
|
||||
class DiskList {
|
||||
private:
|
||||
std::string file;
|
||||
int fd;
|
||||
uint64_t itemCount;
|
||||
Mutex mtx;
|
||||
|
||||
DiskList(const DiskList&);
|
||||
DiskList& operator=(const DiskList&);
|
||||
|
||||
public:
|
||||
DiskList(const std::string& file, bool allowCreate = true) :
|
||||
file(file), itemCount(0)
|
||||
{
|
||||
fd = ::open(file.c_str(), O_RDWR | (allowCreate ? O_CREAT : 0), 0660);
|
||||
if(fd < 0)
|
||||
{
|
||||
int eno = errno;
|
||||
if(!allowCreate && errno == ENOENT)
|
||||
throw DiskListDoesNotExist(file);
|
||||
else
|
||||
throw std::runtime_error("could not open disk list file " + file + ": " + strerror(eno));
|
||||
}
|
||||
}
|
||||
|
||||
~DiskList()
|
||||
{
|
||||
if(fd >= 0)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
const std::string filename() const { return file; }
|
||||
|
||||
void append(const Data& data)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(mtx);
|
||||
|
||||
boost::scoped_array<char> buffer;
|
||||
|
||||
ssize_t size = serializeIntoNewBuffer(data, buffer);
|
||||
if (size < 0)
|
||||
throw std::runtime_error("error serializing disk list item");
|
||||
|
||||
uint64_t bufSize = HOST_TO_LE_64(size);
|
||||
if (::write(fd, &bufSize, sizeof(bufSize)) < (ssize_t) sizeof(bufSize))
|
||||
throw std::runtime_error("error writing disk list item: " + std::string(strerror(errno)));
|
||||
|
||||
if (::write(fd, buffer.get(), size) < size)
|
||||
throw std::runtime_error("error writing disk list item: " + std::string(strerror(errno)));
|
||||
}
|
||||
|
||||
DiskListCursor<Data> cursor()
|
||||
{
|
||||
return DiskListCursor<Data>(fd);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (fd >= 0)
|
||||
{
|
||||
if (ftruncate(fd, 0) < 0)
|
||||
throw std::runtime_error("error clearing disk list: " + std::string(strerror(errno)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user