Skip to content

Commit 7f106a3

Browse files
committed
change fstat to not reuse request object
When fstat is called it now uses the handle to get the opened request, pulls the filepath from that and creates a new request for the fstat call. This eliminates the need to change the Method on the request object and furthers the goal of eliminating post-creation mutation of the request object to open up the possibility to eliminate or at least reduce the use of the global request lock.
1 parent c71cbb1 commit 7f106a3

File tree

3 files changed

+18
-31
lines changed

3 files changed

+18
-31
lines changed

request-server.go

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -60,33 +60,19 @@ func (rs *RequestServer) nextRequest(r *Request) string {
6060
return handle
6161
}
6262

63-
// Returns Request from openRequests, bool is false if it is missing
64-
// If the method is different, save/return a new Request w/ that Method.
63+
// Returns Request from openRequests, bool is false if it is missing.
6564
//
6665
// The Requests in openRequests work essentially as open file descriptors that
6766
// you can do different things with. What you are doing with it are denoted by
68-
// the first packet of that type (read/write/etc). We create a new Request when
69-
// it changes to set the request.Method attribute in a thread safe way.
70-
func (rs *RequestServer) getRequest(handle, method string) (*Request, bool) {
67+
// the first packet of that type (read/write/etc).
68+
func (rs *RequestServer) getRequest(handle string) (*Request, bool) {
7169
rs.openRequestLock.RLock()
70+
defer rs.openRequestLock.RUnlock()
7271
r, ok := rs.openRequests[handle]
73-
rs.openRequestLock.RUnlock()
74-
if !ok || r.Method == method {
75-
return r, ok
76-
}
77-
// if we make it here we need to replace the request
78-
rs.openRequestLock.Lock()
79-
defer rs.openRequestLock.Unlock()
80-
r, ok = rs.openRequests[handle]
81-
if !ok || r.Method == method { // re-check needed b/c lock race
82-
return r, ok
83-
}
84-
r = r.copy()
85-
r.Method = method
86-
rs.openRequests[handle] = r
8772
return r, ok
8873
}
8974

75+
// Close the Request and clear from openRequests map
9076
func (rs *RequestServer) closeRequest(handle string) error {
9177
rs.openRequestLock.Lock()
9278
defer rs.openRequestLock.Unlock()
@@ -179,9 +165,18 @@ func (rs *RequestServer) packetWorker(
179165
request := requestFromPacket(ctx, pkt)
180166
rs.nextRequest(request)
181167
rpkt = request.open(rs.Handlers, pkt)
168+
case *sshFxpFstatPacket:
169+
handle := pkt.getHandle()
170+
request, ok := rs.getRequest(handle)
171+
if !ok {
172+
rpkt = statusFromError(pkt, syscall.EBADF)
173+
} else {
174+
request = NewRequest("Stat", request.Filepath)
175+
rpkt = request.call(rs.Handlers, pkt)
176+
}
182177
case hasHandle:
183178
handle := pkt.getHandle()
184-
request, ok := rs.getRequest(handle, requestMethod(pkt))
179+
request, ok := rs.getRequest(handle)
185180
if !ok {
186181
rpkt = statusFromError(pkt, syscall.EBADF)
187182
} else {
@@ -201,12 +196,6 @@ func (rs *RequestServer) packetWorker(
201196
return nil
202197
}
203198

204-
// True is responsePacket is an OK status packet
205-
func statusOk(rpkt responsePacket) bool {
206-
p, ok := rpkt.(sshFxpStatusPacket)
207-
return ok && p.StatusError.Code == ssh_FX_OK
208-
}
209-
210199
// clean and return name packet for file
211200
func cleanPacketPath(pkt *sshFxpRealpathPacket) responsePacket {
212201
path := cleanPath(pkt.getPath())

request-server_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func TestRequestCache(t *testing.T) {
8484
fh := p.svr.nextRequest(foo)
8585
bh := p.svr.nextRequest(bar)
8686
assert.Len(t, p.svr.openRequests, 2)
87-
_foo, ok := p.svr.getRequest(fh, "")
87+
_foo, ok := p.svr.getRequest(fh)
8888
assert.Equal(t, foo.Method, _foo.Method)
8989
assert.Equal(t, foo.Filepath, _foo.Filepath)
9090
assert.Equal(t, foo.Target, _foo.Target)
@@ -94,7 +94,7 @@ func TestRequestCache(t *testing.T) {
9494
assert.NotNil(t, _foo.ctx)
9595
assert.Equal(t, _foo.Context().Err(), nil, "context is still valid")
9696
assert.True(t, ok)
97-
_, ok = p.svr.getRequest("zed", "")
97+
_, ok = p.svr.getRequest("zed")
9898
assert.False(t, ok)
9999
p.svr.closeRequest(fh)
100100
assert.Equal(t, _foo.Context().Err(), context.Canceled, "context is now canceled")

request.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,6 @@ func (r *Request) opendir(h Handlers, pkt requestPacket) responsePacket {
206206
// wrap FileReader handler
207207
func fileget(h FileReader, r *Request, pkt requestPacket) responsePacket {
208208
//fmt.Println("fileget", r)
209-
var err error
210209
r.state.RLock()
211210
reader := r.state.readerAt
212211
r.state.RUnlock()
@@ -231,7 +230,6 @@ func fileget(h FileReader, r *Request, pkt requestPacket) responsePacket {
231230
// wrap FileWriter handler
232231
func fileput(h FileWriter, r *Request, pkt requestPacket) responsePacket {
233232
//fmt.Println("fileput", r)
234-
var err error
235233
r.state.RLock()
236234
writer := r.state.writerAt
237235
r.state.RUnlock()
@@ -240,7 +238,7 @@ func fileput(h FileWriter, r *Request, pkt requestPacket) responsePacket {
240238
}
241239

242240
data, offset, _ := packetData(pkt)
243-
_, err = writer.WriteAt(data, offset)
241+
_, err := writer.WriteAt(data, offset)
244242
return statusFromError(pkt, err)
245243
}
246244

0 commit comments

Comments
 (0)