Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
cmsc818fall2023projects
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Peter Keleher
cmsc818fall2023projects
Commits
dc8a1d43
Commit
dc8a1d43
authored
1 year ago
by
Peter J. Keleher
Browse files
Options
Downloads
Patches
Plain Diff
auto
parent
a2180a2a
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
p2.md
+86
-44
86 additions, 44 deletions
p2.md
with
86 additions
and
44 deletions
p2.md
+
86
−
44
View file @
dc8a1d43
# Project 2: Remote Procedure Calls and Remote Servers
**Due: Sept 24, 2023, 11:59:59 pm, v1**
## Big Picture
This project requires you to use gRPC to split your code from Project
1 into a command-line interface and a
*blobserver*
. You will also
build a discrete
*lockserver*
that responds to gRPC lock and unlock requests.
the system.
## gRPC
...
...
@@ -22,7 +25,7 @@ Download starter files from [here](http://triffid.cs.umd.edu/818/projects/p2.tgz
For example, on a mac:
```
brew install protobuf
brew install protobuf
`
protoc --version # at least 24.3
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
...
...
@@ -74,14 +77,76 @@ Each of these locks should be implemented with `sync.RWMutex`, and acquire reque
paths already locked with incompatible modes would result in the gRPC request being blocked
until the situation changes.
## Details
## Details: gRPC protocol definition
`pb/comm.proto`
will define the object services that your servers will respond
to. I gave you the service definition, and the "message" definitions
for the
`BlobPutRequest`
. Define the others similarly.
Then, compile the protocol w/ the
`protoc`
command in the comment.
This will create files
`comm.pb.go`
and
`comm_grpc.pb.go`
. The latter
defines the routines that use object
*reflection*
to generate
communication stubs that call the functions you write in your server.
The service definition is:
```
service Blob {
rpc Put (BlobPutRequest) returns (BlobPutReply) {}
rpc Get (BlobGetRequest) returns (BlobGetReply) {}
rpc List (BlobListRequest) returns (BlobListReply) {}
rpc Lock (LockRequest) returns (LockReply) {}
rpc Unlock (UnlockRequest) returns (UnlockReply) {}
}
```
You will need to define server routines corresponding to each of the
above. For example, the
`put`
command function will look like:
```
func (s *GRPCserver) Put(ctx context.Context, in *pb.BlobPutRequest) (*pb.BlobPutReply, error) {
....
return &pb.BlobPutReply{Sig: sig, ErrorString: ""}, nil
}
```
-
`pbc/comm.proto`
defines the object services that your servers will respond
to. The starter files contain files
`tool/main.go`
for talking to the
blobserver, and
`app.go`
to exercise your lock server and show how an application could
use the interface.
Most of this stuff works seamlessly. One oddity is that when you start
up your server (in
`server.go`
), the actual startup is here:
```
lis, err := net.Listen("tcp", ServerAddress)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterBlobServer(s, &GRPCserver{})
-
The lock gRPC calls are made directly from the application level (see
`app.go`
)
```
The
`GRPCserver`
is a placeholder structure that does not need to
define any properties or methods, except the
`UnimplementedBlobServer`
method. From
`blobstore/grpcServe.go`
```
type GRPCserver struct {
pb.UnimplementedBlobServer
}
```
## Details: Locks
Implement the locks using
`Sync.RWMutex`
from the standard
library. The
`path`
used to choose which lock to lock/unlock is an
arbitrary string, and
*each path must have a distinct lock*
.
This means you need to create
`RWMutex`
's at runtime. You can store them
in a map for easy lookup. Though I won't be testing high-speed
concurrent locks, your implementation should work w/ even when
multiple clients are trying to lock a path at the same time, and:
-
the path hasn't been accessed before, so no lock is pre-existing
-
you must ensure that only one
`RWMutex`
is create per lock (no
overwriting!).
This is complicated by the fact that gRPC is multi-threaded; each incoming
request is given it's own server go-thread and runs concurrently with
all other requests
## Setup
...
...
@@ -90,22 +155,21 @@ Download the starter files for this project [here](https://sedna.cs.umd.edu/818/
## Command-line parameters
The server:
```
go run cli.go [-d|-s <host:port>] (desc <sig>|get <sig> <destination>|put <source>|list|lock <path>|unlock <path>)
go run store.go [-d|-s <host:port>]
go run server.go [-d] [-s <host:port>]
```
## Testing
There are several moving parts here, though you won't be writing all that much code.
*
Test
parts separately
*
when possible:
-
`blobget.go`
will use the same gRPC definitions to interact with your blobserver as
your main fuse program. Use it list the contents of the database and to debug your gRPC
code.
The clients:
```
go run blob.go [-d] [-s <host:port>] (desc <sig>|get <sig> <destination>|put <source>|list|lock <path>|unlock <path>)
go run lock.go [-d] [-s <host:port>] (lock <path>|rlock <path>|unlock <path>|runlock <path>)
```
-
`app.go`
will use the same gRPC definitions as your lock server. I will be using it to
test your lockserver; you should too.
## Testing
The testscript from before is a good place to start, but you also need
locking behavior identical as shown in the video.
## Notes
-
Use the
`context`
to set RPC timeouts to 60 seconds.
...
...
@@ -113,34 +177,12 @@ test your lockserver; you should too.
## Grading
I will assign grades vaguely as follow:
-
50 pts - blobserver
-
`redis`
test
-
examine contents of leveldb and server workings w/
`blobget.go`
-
50 pts - lockserver
-
I'll pass it various paths and verify that the correct locks are acquired, that gRPCs
are blocked until conditions are appropriate, and releases are correct. A release from
replica
*i*
should not unblock a lock held only by repica
*j*
.
## Files
This repository
contains the following files:
-
`main.go`
- Scaffolding for P3, which references files in subdirs
`dfs`
,
`pbc`
, and
`pbl`
.
-
`blobget.go`
- retrieves data corresponding to specific signature, name (such as
'head'), or pathname from your blobserver. Can also be used to print out all keys in the object store.
-
`app.go`
tester for your lockserver.
-
`blob/pbc.proto`
- definition of protobuf formats and services for blobserver
-
`lock/pbl.proto`
- definition of protobuf formats and services for lockserver
## Submit
-
70 pts - distributing the blobserver
-
30 pts - lockserver
Submit as follows (substituting your
*real*
directoryid for
`<your dirid>`
):
```
cd ~/go/src/818fall18/
tar cvfz p3.tgz p3
```
and upload to
[
myelms
](
https://myelms.umd.edu/courses/1247011/assignments/4738791
)
.
## Submit
Submit by copying into your distro and pushing to gitlab.
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment