Skip to content

Commit c1eb9c6

Browse files
committed
Track the locations of reference sources for the state pool.
1 parent 20b593c commit c1eb9c6

32 files changed

+361
-224
lines changed

api/controller/legacy_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ func (s *legacySuite) TestAPIServerCanShutdownWithOutstandingNext(c *gc.C) {
226226
LogDir: c.MkDir(),
227227
NewObserver: func() observer.Observer { return &fakeobserver.Instance{} },
228228
AutocertURL: "https://0.1.2.3/no-autocert-here",
229+
StatePool: state.NewStatePool(s.State),
229230
})
230231
c.Assert(err, gc.IsNil)
231232

api/pubsub/pubsub_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ func newServerWithHub(c *gc.C, st *state.State, hub *pubsub.StructuredHub) (*api
236236
LogDir: c.MkDir(),
237237
Hub: hub,
238238
NewObserver: func() observer.Observer { return &fakeobserver.Instance{} },
239+
StatePool: state.NewStatePool(st),
239240
})
240241
c.Assert(err, jc.ErrorIsNil)
241242
port := listener.Addr().(*net.TCPAddr).Port

api/watcher/watcher_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,10 @@ type migrationSuite struct {
252252
var _ = gc.Suite(&migrationSuite{})
253253

254254
func (s *migrationSuite) startSync(c *gc.C, st *state.State) {
255-
backingSt, err := s.BackingStatePool.Get(st.ModelUUID())
255+
backingSt, releaser, err := s.BackingStatePool.Get(st.ModelUUID())
256256
c.Assert(err, jc.ErrorIsNil)
257257
backingSt.StartSync()
258+
releaser()
258259
}
259260

260261
func (s *migrationSuite) TestMigrationStatusWatcher(c *gc.C) {

apiserver/admin_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ func (s *loginSuite) TestLoginValidationDuringUpgrade(c *gc.C) {
516516
}
517517

518518
func (s *loginSuite) TestFailedLoginDuringMaintenance(c *gc.C) {
519-
cfg := defaultServerConfig(c)
519+
cfg := defaultServerConfig(c, s.State)
520520
cfg.Validator = func(params.LoginRequest) error {
521521
return errors.New("something")
522522
}
@@ -536,7 +536,7 @@ func (s *loginSuite) TestFailedLoginDuringMaintenance(c *gc.C) {
536536
type validationChecker func(c *gc.C, err error, st api.Connection)
537537

538538
func (s *baseLoginSuite) checkLoginWithValidator(c *gc.C, validator apiserver.LoginValidator, checker validationChecker) {
539-
cfg := defaultServerConfig(c)
539+
cfg := defaultServerConfig(c, s.State)
540540
cfg.Validator = validator
541541
info, srv := newServerWithConfig(c, s.State, cfg)
542542
defer assertStop(c, srv)
@@ -1004,7 +1004,7 @@ func (s *macaroonLoginSuite) TestRemoteUserLoginToModelWithExplicitAccessAndAllo
10041004
}
10051005

10061006
func (s *macaroonLoginSuite) testRemoteUserLoginToModelWithExplicitAccess(c *gc.C, allowModelAccess bool) {
1007-
cfg := defaultServerConfig(c)
1007+
cfg := defaultServerConfig(c, s.State)
10081008
cfg.AllowModelAccess = allowModelAccess
10091009

10101010
info, srv := newServerWithConfig(c, s.State, cfg)

apiserver/apiserver.go

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,14 @@ type ServerConfig struct {
126126
// notified of key events during API requests.
127127
NewObserver observer.ObserverFactory
128128

129+
// StatePool is created by the machine agent and passed in.
130+
StatePool *state.StatePool
131+
129132
// RegisterIntrospectionHandlers is a function that will
130133
// call a function with (path, http.Handler) tuples. This
131134
// is to support registering the handlers underneath the
132135
// "/introspection" prefix.
133136
RegisterIntrospectionHandlers func(func(string, http.Handler))
134-
135-
// StatePool only exists to support testing.
136-
StatePool *state.StatePool
137137
}
138138

139139
func (c *ServerConfig) Validate() error {
@@ -146,6 +146,9 @@ func (c *ServerConfig) Validate() error {
146146
if c.NewObserver == nil {
147147
return errors.NotValidf("missing NewObserver")
148148
}
149+
if c.StatePool == nil {
150+
return errors.NotValidf("missing StatePool")
151+
}
149152

150153
return nil
151154
}
@@ -570,12 +573,9 @@ func (srv *Server) newHandlerArgs(spec apihttp.HandlerConstraints) apihttp.NewHa
570573
controllerModelOnly: spec.ControllerModelOnly,
571574
}
572575
return apihttp.NewHandlerArgs{
573-
Connect: func(req *http.Request) (*state.State, state.Entity, error) {
576+
Connect: func(req *http.Request) (*state.State, func(), state.Entity, error) {
574577
return ctxt.stateForRequestAuthenticatedTag(req, spec.AuthKinds...)
575578
},
576-
Release: func(st *state.State) error {
577-
return ctxt.release(st)
578-
},
579579
}
580580
}
581581

@@ -660,20 +660,16 @@ func (srv *Server) serveConn(wsConn *websocket.Conn, modelUUID string, apiObserv
660660
modelUUID: modelUUID,
661661
})
662662
var (
663-
st *state.State
664-
h *apiHandler
663+
st *state.State
664+
h *apiHandler
665+
releaser func()
665666
)
666667
if err == nil {
667-
st, err = srv.statePool.Get(resolvedModelUUID)
668+
st, releaser, err = srv.statePool.Get(resolvedModelUUID)
668669
}
669670

670671
if err == nil {
671-
defer func() {
672-
err := srv.statePool.Release(resolvedModelUUID)
673-
if err != nil {
674-
logger.Errorf("error releasing %v back into the state pool: %v", resolvedModelUUID, err)
675-
}
676-
}()
672+
defer releaser()
677673
h, err = newAPIHandler(srv, st, conn, modelUUID, host)
678674
}
679675

apiserver/apiserver_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func (s *apiserverBaseSuite) sampleConfig(c *gc.C) apiserver.ServerConfig {
5151
Hub: centralhub.New(machineTag),
5252
NewObserver: func() observer.Observer { return &fakeobserver.Instance{} },
5353
AutocertURL: "https://0.1.2.3/no-autocert-here",
54+
StatePool: state.NewStatePool(s.State),
5455
}
5556
}
5657

apiserver/backup.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ type backupHandler struct {
3232
func (h *backupHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
3333
// Validate before authenticate because the authentication is dependent
3434
// on the state connection that is determined during the validation.
35-
st, err := h.ctxt.stateForRequestAuthenticatedUser(req)
35+
st, releaser, err := h.ctxt.stateForRequestAuthenticatedUser(req)
3636
if err != nil {
3737
h.sendError(resp, err)
3838
return
3939
}
40-
defer h.ctxt.release(st)
40+
defer releaser()
4141

4242
backups, closer := newBackups(st)
4343
defer closer.Close()

apiserver/charms.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func (h *CharmsHTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
7676
type charmsHandler struct {
7777
ctxt httpContext
7878
dataDir string
79-
stateAuthFunc func(*http.Request) (*state.State, error)
79+
stateAuthFunc func(*http.Request) (*state.State, func(), error)
8080
}
8181

8282
// bundleContentSenderFunc functions are responsible for sending a
@@ -92,11 +92,11 @@ func (h *charmsHandler) ServePost(w http.ResponseWriter, r *http.Request) error
9292
return errors.Trace(emitUnsupportedMethodErr(r.Method))
9393
}
9494

95-
st, err := h.stateAuthFunc(r)
95+
st, releaser, err := h.stateAuthFunc(r)
9696
if err != nil {
9797
return errors.Trace(err)
9898
}
99-
defer h.ctxt.release(st)
99+
defer releaser()
100100

101101
// Add a charm to the store provider.
102102
charmURL, err := h.processPost(r, st)
@@ -111,11 +111,11 @@ func (h *charmsHandler) ServeGet(w http.ResponseWriter, r *http.Request) error {
111111
return errors.Trace(emitUnsupportedMethodErr(r.Method))
112112
}
113113

114-
st, _, err := h.ctxt.stateForRequestAuthenticated(r)
114+
st, releaser, _, err := h.ctxt.stateForRequestAuthenticated(r)
115115
if err != nil {
116116
return errors.Trace(err)
117117
}
118-
defer h.ctxt.release(st)
118+
defer releaser()
119119

120120
// Retrieve or list charm files.
121121
// Requires "url" (charm URL) and an optional "file" (the path to the

apiserver/common/apihttp/handler.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,10 @@ import (
1313
// field of HandlerSpec.
1414
type NewHandlerArgs struct {
1515
// Connect is the function that is used to connect to Juju's state
16-
// for the given HTTP request.
17-
Connect func(*http.Request) (*state.State, state.Entity, error)
18-
19-
// Release indicates that the state is finished with and should be
20-
// closed.
21-
Release func(*state.State) error
16+
// for the given HTTP request. It is the caller's responsibility
17+
// to call the release function returned. If the error arg is nil
18+
// the release function will always be a valid function.
19+
Connect func(*http.Request) (*state.State, func(), state.Entity, error)
2220
}
2321

2422
// HandlerConstraints describes conditions under which a handler

apiserver/debuglog.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,12 @@ func (h *debugLogHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
7474
socket := &debugLogSocketImpl{conn}
7575
defer conn.Close()
7676

77-
st, _, err := h.ctxt.stateForRequestAuthenticatedTag(req, names.MachineTagKind, names.UserTagKind)
77+
st, releaser, _, err := h.ctxt.stateForRequestAuthenticatedTag(req, names.MachineTagKind, names.UserTagKind)
7878
if err != nil {
7979
socket.sendError(err)
8080
return
8181
}
82-
defer h.ctxt.release(st)
82+
defer releaser()
8383

8484
params, err := readDebugLogParams(req.URL.Query())
8585
if err != nil {

apiserver/gui.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,11 @@ func (gr *guiRouter) ensureFileHandler(h func(gh *guiHandler, w http.ResponseWri
136136
// and archive hash.
137137
func (gr *guiRouter) ensureFiles(req *http.Request) (rootDir string, hash string, err error) {
138138
// Retrieve the Juju GUI info from the GUI storage.
139-
st, err := gr.ctxt.stateForRequestUnauthenticated(req)
139+
st, releaser, err := gr.ctxt.stateForRequestUnauthenticated(req)
140140
if err != nil {
141141
return "", "", errors.Annotate(err, "cannot open state")
142142
}
143-
defer gr.ctxt.release(st)
143+
defer releaser()
144144
storage, err := st.GUIStorage()
145145
if err != nil {
146146
return "", "", errors.Annotate(err, "cannot open GUI storage")
@@ -415,11 +415,11 @@ func (h *guiArchiveHandler) ServeHTTP(w http.ResponseWriter, req *http.Request)
415415
// handleGet returns information on Juju GUI archives in the controller.
416416
func (h *guiArchiveHandler) handleGet(w http.ResponseWriter, req *http.Request) error {
417417
// Open the GUI archive storage.
418-
st, err := h.ctxt.stateForRequestUnauthenticated(req)
418+
st, releaser, err := h.ctxt.stateForRequestUnauthenticated(req)
419419
if err != nil {
420420
return errors.Annotate(err, "cannot open state")
421421
}
422-
defer h.ctxt.release(st)
422+
defer releaser()
423423
storage, err := st.GUIStorage()
424424
if err != nil {
425425
return errors.Annotate(err, "cannot open GUI storage")
@@ -483,11 +483,11 @@ func (h *guiArchiveHandler) handlePost(w http.ResponseWriter, req *http.Request)
483483
}
484484

485485
// Open the GUI archive storage.
486-
st, err := h.ctxt.stateForRequestAuthenticatedUser(req)
486+
st, releaser, err := h.ctxt.stateForRequestAuthenticatedUser(req)
487487
if err != nil {
488488
return errors.Annotate(err, "cannot open state")
489489
}
490-
defer h.ctxt.release(st)
490+
defer releaser()
491491
storage, err := st.GUIStorage()
492492
if err != nil {
493493
return errors.Annotate(err, "cannot open GUI storage")
@@ -559,11 +559,11 @@ func (h *guiVersionHandler) handlePut(w http.ResponseWriter, req *http.Request)
559559
}
560560

561561
// Authenticate the request and retrieve the Juju state.
562-
st, err := h.ctxt.stateForRequestAuthenticatedUser(req)
562+
st, releaser, err := h.ctxt.stateForRequestAuthenticatedUser(req)
563563
if err != nil {
564564
return errors.Annotate(err, "cannot open state")
565565
}
566-
defer h.ctxt.release(st)
566+
defer releaser()
567567

568568
var selected params.GUIVersionRequest
569569
decoder := json.NewDecoder(req.Body)

0 commit comments

Comments
 (0)