Now we'll discuss the primitives provided by the
lab of virtual memory for the app developer. Recall
what I said earlier and that is we
do not want the in memory data structures when
modified to immediately start writing to the corresponding
on disk version in the external data segments, because
that would result in a lot of random
rights. And therefore we suggested that what we want
to do is use a log segment aggregate changes that we're making to the portions
of the virtual address space so that the
log segment can then be committed to the
disk to record the changes that we're making to the virtual memory and so the
first set of primitives that RVM provides is initialization.
And in particular, this initialize primitive identifies
the log segment to be used by the
server process for recording changes to the persistent
data structures of this process. And every process
can declare its own log segment data structure
for use in managing its persistence. So if I have a file system, it has it's
own data structures. Because remember that RVM is
not inside the operating system, but RVM is provided
as a run time library in support of
applications that lives on top of the operating
system. So the library provides it's primitives and
so initialize is allowing the process that is
using this library to declare a log segment
data structure, which will be the data structure
into which RVM, in the course of execution
of the process, will aggregate changes that this process
is making to persistent data structures, so
that later on those changes in the log
segment can be committed to the desk. And
even further, those changes can eventually be deflected
in the data segments that those in memory
versions of persistent data structures that present. The
map primitive is the primitive that allows the
application to say, what is the region of
the virtual address space that I want mapped
to an external data segment. I mentioned that there
is a one to one correspondence between an address
range and the virtual address space and the external
data segments. So if I need to map different
portions of the address space of the process to
different data segments. I would execute multiple map calls
to map different regions of my virtual address space
to different external data segments. So this
regional descriptor can contains both the address range
that I want to be mapped as well as it names the external data segment. That
corresponds to this particular address range. In
unmap, thus delivers mainly it decouples the address
range from the external data segment that it
is associated with up. So in the body
of the server code These are calls that an app developer would make. The
begin transaction and the end transaction alerts
the RVM run time that the application is
about to make changes to persistent data
structures between these begin and end transaction
calls to the RVM library. And in fact, signals to the RVM library that the
transaction has committed, meaning that all the
changes that the application made in between begin
and end to data structures that are persistent have to be flushed to the disk.
That is, they have to be made persistent. On the other hand, a begin transaction
could also end in an abort transaction which
essentially signals to the RVM library that all
the changes that the application made bound
between begin transaction and abort transaction. Have to
be thrown away by the RVM library and should not be committed to the disk, that
is they should not be persistent. So the
idea then is, between begin transaction and end
transaction, the application developer is modifying the in-memory
version of the persistent data structures And committing
them to the persistency storage by calling this
n transaction which is saying, commit my changes
to the in memory versions to the persistent
version on the disc. On the other hand, if
the developer calls an abort transaction after a
begin transaction then all the changes that he
or she made to persistent data structures should
be thrown by the RVM library and not persistent
on the disc. The set range call is the very first thing that an app developer
will do inside a begin transaction end transaction
sequence. You can think of this code between begin
transaction and end transaction like a critical section
of the app developer's code base. And the first
thing that happens within that critical section is
a call to set range. What the set range
is saying is even though an address region
may be mapped to an external data segments, in
this particular critical section by begin and end
transaction, I'm going to modify only a portion of that
address range, and that portion of the address
range that I'm going to modify Is specified by
the starting address and the size of that block
that I'm going to modify. That's the purpose of the
set-range call, which says, for this particular
transaction, which I started here, for which RVM
will return a unique transaction ID to me, when i make this call I'm going
to use this transaction ID and tell
RVM that for this particular transaction, I'm going
modify only a block of memory starting
at this address and bound by this address.
That's the purpose of the set change code. So,
it is only this portion of it that you are
going to modify. And we will see how all of
what I said is used by the RVM library in
its implementation in a minute. But from the user's
point of view, from the developer's point of view, this
is all that developer needs to know and use in
order to write his application that has persistent data structures.
As simple as that. All the heavy lifting that is
needed to accomplish the developers intent for persistence that are
enshrined in these primitives is taken care of by the
RVM run time which we will see in a minute.