file_system_session: add modification time

* add modification_time member
* add WRITE_TIMESTAMP packet
This commit is contained in:
Josef Söntgen 2019-03-20 11:46:34 +01:00 committed by Christian Helmuth
parent ab5187d673
commit 2ec3aaf639
6 changed files with 84 additions and 12 deletions

View File

@ -71,6 +71,26 @@ namespace File_system {
typedef Genode::uint64_t seek_off_t;
typedef Genode::uint64_t file_size_t;
struct Timestamp
{
/*
* The INVALID value is used whenever the underlying file system
* session does not support modification timestamps. The value is
* chosen such that it is unlikely to occur, instead of simply '0',
* which would correspond to plausible time (see comment below).
* This allows for handling this case explicitly. In any case, an
* invalid timestamp should not be used for doing any calculations.
*/
static constexpr Genode::int64_t INVALID = 0x7fffffffffffffffLL;
/*
* The 'value' member contains the modification timestamp in seconds.
* Value '0' is defined as 1970-01-01T00:00:00Z, where a positive value
* covers all seconds after this date and a negative one all before.
*/
Genode::int64_t value;
};
typedef Genode::Out_of_ram Out_of_ram;
typedef Genode::Out_of_caps Out_of_caps;
@ -127,6 +147,7 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor
enum Opcode {
READ,
WRITE,
WRITE_TIMESTAMP,
CONTENT_CHANGED,
READ_READY,
@ -143,9 +164,16 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor
Node_handle _handle { 0 }; /* node handle */
Opcode _op; /* requested operation */
seek_off_t _position; /* file seek offset in bytes */
size_t _length; /* transaction length in bytes */
bool _success; /* indicates success of operation */
union
{
struct
{
seek_off_t _position; /* file seek offset in bytes */
size_t _length; /* transaction length in bytes */
};
Timestamp _modification_time; /* seconds since the Unix epoch */
};
public:
@ -156,7 +184,7 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor
Genode::size_t buf_size = 0)
:
Genode::Packet_descriptor(buf_offset, buf_size),
_op(READ), _position(0), _length(0), _success(false) { }
_op(READ), _success(false), _position(0), _length(0) { }
/**
* Constructor
@ -172,8 +200,8 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor
seek_off_t position = SEEK_TAIL)
:
Genode::Packet_descriptor(p.offset(), p.size()),
_handle(handle), _op(op),
_position(position), _length(length), _success(false)
_handle(handle), _op(op), _success(false),
_position(position), _length(length)
{ }
/**
@ -185,16 +213,33 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor
Packet_descriptor(Node_handle handle, Opcode op)
:
Genode::Packet_descriptor(0, 0),
_handle(handle), _op(op),
_position(0), _length(0), _success(true)
_handle(handle), _op(op), _success(true),
_position(0), _length(0)
{ }
/**
* Constructor
*/
Packet_descriptor(Packet_descriptor p, Node_handle handle, Opcode op, Timestamp const &mtime)
:
Genode::Packet_descriptor(p.offset(), p.size()),
_handle(handle), _op(op), _success(false),
_modification_time(mtime)
{ }
Node_handle handle() const { return _handle; }
Opcode operation() const { return _op; }
seek_off_t position() const { return _position; }
size_t length() const { return _length; }
seek_off_t position() const { return _op != Opcode::WRITE_TIMESTAMP ? _position : 0; }
size_t length() const { return _op != Opcode::WRITE_TIMESTAMP ? _length : 0; }
bool succeeded() const { return _success; }
template <typename FN>
void with_timestamp(FN const &fn) const
{
if (_op == Opcode::WRITE_TIMESTAMP)
fn(_modification_time);
}
/*
* Accessors called at the server side
*/
@ -212,13 +257,13 @@ struct File_system::Status
};
/*
* XXX add access time
* XXX add executable bit
*/
file_size_t size;
unsigned mode;
unsigned long inode;
Timestamp modification_time;
/**
* Return true if node is a directory

View File

@ -228,6 +228,7 @@ class Ram_fs::Directory : public Node
s.inode = inode();
s.size = _num_entries * sizeof(File_system::Directory_entry);
s.mode = File_system::Status::MODE_DIRECTORY;
s.modification_time = modification_time();
return s;
}
};

View File

@ -112,10 +112,11 @@ class Ram_fs::File : public Node
Status status() override
{
Status s;
Status s { };
s.inode = inode();
s.size = _length;
s.mode = File_system::Status::MODE_FILE;
s.modification_time = modification_time();
return s;
}

View File

@ -108,6 +108,18 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
open_node.mark_as_written();
break;
case Packet_descriptor::WRITE_TIMESTAMP: {
Locked_ptr<Node> node { open_node.node() };
if (!node.valid())
break;
packet.with_timestamp([&] (File_system::Timestamp const time) {
node->update_modification_time(time);
succeeded = true;
});
break;
}
case Packet_descriptor::CONTENT_CHANGED:
Genode::error("CONTENT_CHANGED packets from clients have no effect");
return;

View File

@ -23,6 +23,7 @@ namespace Ram_fs {
using namespace Genode;
using File_system::seek_off_t;
using File_system::Status;
using File_system::Timestamp;
class Node;
class File;
class Symlink;
@ -48,6 +49,7 @@ class Ram_fs::Node : public File_system::Node_base,
int _ref_count;
Name _name;
unsigned long const _inode;
Timestamp _modification_time { };
/**
* Generate unique inode number
@ -62,7 +64,10 @@ class Ram_fs::Node : public File_system::Node_base,
Node()
: _ref_count(0), _inode(_unique_inode())
{ _name[0] = 0; }
{
_name[0] = 0;
_modification_time.value = File_system::Timestamp::INVALID;
}
virtual ~Node() { lock_for_destruction(); }
@ -74,6 +79,13 @@ class Ram_fs::Node : public File_system::Node_base,
*/
void name(char const *name) { strncpy(_name, name, sizeof(_name)); }
void update_modification_time(Timestamp const time)
{
_modification_time = time;
}
Timestamp modification_time() const { return _modification_time; }
virtual size_t read(char *dst, size_t len, seek_off_t) = 0;
virtual size_t write(char const *src, size_t len, seek_off_t) = 0;

View File

@ -71,6 +71,7 @@ class Ram_fs::Symlink : public Node
s.inode = inode();
s.size = _len;
s.mode = File_system::Status::MODE_SYMLINK;
s.modification_time = modification_time();
return s;
}
};