Skip to content
Permalink
1139b72d5e
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
134 lines (98 sloc) 5.2 KB
# todo: latex this
#
# 18 July 2003
#
# rob latham and team pvfs2
#
Adding a new server operation is currently rather involved. I'm going to try
to lay out what i did to add a flush operation to pvfs2
CLIENT-SIDE
Add a prototype for your function to pvfs2-sysint.h. If your function
just needs to know if it suceeded or failed, you are done. If not, you
must also define a server response structure.
We are moving to using state machines for both client and server
operations, so if you are adding a new operation, make it a state
machine. Define your operation-specific state machine structure in
client-state-machine.h and add it to the PINT_client_sm structure. Add
your operation to the switch statement in
PINT_client_state_machine_post()
there is an unnamed enum in client-state-machine.h with some other
operations (PVFS_SYS_REMOVE, PVFS_SYS_IO, etc). Add your operation to
that enum.
also in client-state-machine.h, declare your state machine 'extern'
with the other operation state machine declarations.
add the .c file for your operation to src/client/sysint/module.mk.in
A client-side state machine can take advantage of several nested state
machines. The client state machines tend to have a certain pattern to
them: check_parameters, then for each time they talk to the server
there is a 'setup/xfer/failure' triplet of states to send a msgpair (or
a bunch of msgpairs in one msgpairarray). lastly, 'cleanup'. As with
the server, the best documentation is other state machines.
SERVER-SIDE
It's probably a good idea to start implementing your new operation
at the trove layer, then adding support for it at the job interface.
Once the job interface is in place, then you can implement the state
machine. Doing things this way means you can always compile the tree
to catch errors.
Trove:
If you need to extend trove functionality to implement your new
operation, start by adding a prototype to trove-proto.h. This will
autogenerate the code that links the trove api to the underlying
storage implementation (currently dbpf).
Define a new member of the TROVE_bstream_ops, TROVE_keyval_ops, and/or
TROVE_dspace_ops structure. Add the dbpf implementation: check out
trove-dbpf/dbpf-bstream.c and trove-dbpf/dbpf-keyval. At the bottom
of those files is a structure of function pointers. Add your new
function.
If your new function is nonblocking, add it to the dbpf_op_type enum.
Job:
You can follow the example of the other job functions to get error
handling/reporting, mutex locking, and calling down to trove correct.
Add a prototype for your function to job.h
State Machine:
Write a state machine to deal with the server-side of your operation.
The 'prelude' and 'final_response' states take care of some common
tasks. look at the other server state machines to see how things
should go: that's the best documetnation so far.
Declare this new state machine in pvfs2-server.h with the other server
operation state machines.
Everything Else:
define a PINT_server_xxx_op with the information specific to your new
operation, and add it to the union in PINT_server_op.
Add a new enum to PVFS_server_op, just before the sentinel
PVFS_SERV_NUM_OPS. Define a server request structure
(PVFS_servreq_xxx) and optionally (but encouraged) a
PINT_SERVREQ_xxx_FILL macro. If your operation needs information back
from the server (beyond 'success' or 'fail'), define a
PVFS_servresp_xxx structure for the server response. Add these new
structures to the union in the declaration of the PVFS_server_req and
PVFS_server_resp (if necessary).
For many operations, -TROVE_ENOENT is ok (e.g. operations on datafiles
[because we do not store attributes with datafiles], flushing a keyval
when the keyval space has not been created on disk, or setting
attributes on a file that didn't have atributes previously). If your
operation is like that, modifly prelude_perm_check and add it to the
list of operations for which TROVE_ENOENT is ok. If you haven't
figured out what it means to 'check permissions' for your operation,
add it towards the bottom of the function with the other oddball
operations.
Help out the debugging helper functions by adding a text
representation of your operation to PINT_map_server_op_to_string()
The server will not know how to handle the new operation until you've
addded it along with the other operations in
server_state_table_initialize().
If your operation needs data from the request structure (and most of
them do), modify PINT_req_sched_target_handle to make the apropriate
copies.
PROTOCOL
the encode and decode system needs to know how to handle your new
operation. If it is a self-contained structure -- that is, it has no
pointers -- then it can be added with the other self-contained
structures in do_decode_req(), do_encode_req(), do_decode_resp(), and
do_encode_resp(). Otherwise, you'll have to perform more steps like
those done in PVFS_SERV_IO and PVFS_SERV_MKDIR and others.
TESTING
no new operation should go in without a testcase exercising that
operation. add it to the other tests in tests/client/sysint and add
it to the list of targets to build in module.mk.in
# vim: tw=72