blob: f077cf134cb701c1aef8b3cd39f6ce454e978c82 [file] [log] [blame]
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001package impl
2
3import (
4 "errors"
Jiri Simsa5293dcb2014-05-10 09:56:38 -07005
6 "veyron/services/mgmt/profile"
7
8 "veyron2/ipc"
Adam Sadovsky04c5eef2014-07-30 17:33:27 -07009 "veyron2/naming"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070010 "veyron2/storage"
Adam Sadovskyffac12c2014-08-20 14:23:16 -070011 "veyron2/storage/vstore"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070012 "veyron2/vlog"
13)
14
Jiri Simsaddbfebb2014-06-20 15:56:06 -070015// invoker holds the profile repository invocation.
Jiri Simsa5293dcb2014-05-10 09:56:38 -070016type invoker struct {
Adam Sadovskyffac12c2014-08-20 14:23:16 -070017 // storeRoot is a name in the Store under which all data will be stored.
18 storeRoot string
Jiri Simsa5293dcb2014-05-10 09:56:38 -070019 // suffix is the suffix of the current invocation that is assumed to
Bogdan Capritad9281a32014-07-02 14:40:39 -070020 // be used as a relative object name to identify a profile
Jiri Simsa5293dcb2014-05-10 09:56:38 -070021 // specification.
22 suffix string
23}
24
25var (
26 errNotFound = errors.New("not found")
27 errOperationFailed = errors.New("operation failed")
28)
29
30// NewInvoker is the invoker factory.
Adam Sadovskyffac12c2014-08-20 14:23:16 -070031func NewInvoker(storeRoot, suffix string) *invoker {
32 return &invoker{storeRoot: storeRoot, suffix: suffix}
Jiri Simsa5293dcb2014-05-10 09:56:38 -070033}
34
35// STORE MANAGEMENT INTERFACE IMPLEMENTATION
36
37// dir is used to organize directory contents in the store.
38type dir struct{}
39
40// makeParentNodes creates the parent nodes if they do not already exist.
Adam Sadovskyffac12c2014-08-20 14:23:16 -070041func makeParentNodes(context ipc.ServerContext, tx storage.Transaction, path string) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070042 pathComponents := storage.ParsePath(path)
43 for i := 0; i < len(pathComponents); i++ {
44 name := pathComponents[:i].String()
Adam Sadovskyffac12c2014-08-20 14:23:16 -070045 object := tx.Bind(name)
Adam Sadovsky04c5eef2014-07-30 17:33:27 -070046 if _, err := object.Get(context); err != nil {
47 if _, err := object.Put(context, &dir{}); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070048 return errOperationFailed
49 }
50 }
51 }
52 return nil
53}
54
Matt Rosencrantzf5afcaf2014-06-02 11:31:22 -070055func (i *invoker) Put(context ipc.ServerContext, profile profile.Specification) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070056 vlog.VI(0).Infof("%v.Put(%v)", i.suffix, profile)
Adam Sadovskyffac12c2014-08-20 14:23:16 -070057 tx := vstore.New().NewTransaction(context, i.storeRoot)
58 path := naming.Join("/profiles", i.suffix)
59 if err := makeParentNodes(context, tx, path); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070060 return err
61 }
Adam Sadovskyffac12c2014-08-20 14:23:16 -070062 object := tx.Bind(path)
Adam Sadovsky04c5eef2014-07-30 17:33:27 -070063 if _, err := object.Put(context, profile); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070064 return errOperationFailed
65 }
Adam Sadovskyffac12c2014-08-20 14:23:16 -070066 if err := tx.Commit(context); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070067 return errOperationFailed
68 }
69 return nil
70}
71
Matt Rosencrantzf5afcaf2014-06-02 11:31:22 -070072func (i *invoker) Remove(context ipc.ServerContext) error {
Cosmos Nicolaouef43dc42014-06-13 14:38:51 -070073 vlog.VI(0).Infof("%v.Remove()", i.suffix)
Adam Sadovskyffac12c2014-08-20 14:23:16 -070074 tx := vstore.New().NewTransaction(context, i.storeRoot)
75 path := naming.Join("/profiles", i.suffix)
76 object := tx.Bind(path)
Adam Sadovsky04c5eef2014-07-30 17:33:27 -070077 found, err := object.Exists(context)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070078 if err != nil {
79 return errOperationFailed
80 }
81 if !found {
82 return errNotFound
83 }
Adam Sadovsky04c5eef2014-07-30 17:33:27 -070084 if err := object.Remove(context); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070085 return errOperationFailed
86 }
Adam Sadovskyffac12c2014-08-20 14:23:16 -070087 if err := tx.Commit(context); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070088 return errOperationFailed
89 }
90 return nil
91}
92
93// PROFILE INTERACE IMPLEMENTATION
94
Matt Rosencrantzf5afcaf2014-06-02 11:31:22 -070095func (i *invoker) lookup(context ipc.ServerContext) (profile.Specification, error) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070096 empty := profile.Specification{}
Adam Sadovskyffac12c2014-08-20 14:23:16 -070097 path := naming.Join(i.storeRoot, "/profiles", i.suffix)
98 entry, err := vstore.New().Bind(path).Get(context)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070099 if err != nil {
100 return empty, errNotFound
101 }
102 s, ok := entry.Value.(profile.Specification)
103 if !ok {
104 return empty, errOperationFailed
105 }
106 return s, nil
107}
108
Matt Rosencrantzf5afcaf2014-06-02 11:31:22 -0700109func (i *invoker) Label(context ipc.ServerContext) (string, error) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700110 vlog.VI(0).Infof("%v.Label()", i.suffix)
Matt Rosencrantzf5afcaf2014-06-02 11:31:22 -0700111 s, err := i.lookup(context)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700112 if err != nil {
113 return "", err
114 }
115 return s.Label, nil
116}
117
Matt Rosencrantzf5afcaf2014-06-02 11:31:22 -0700118func (i *invoker) Description(context ipc.ServerContext) (string, error) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700119 vlog.VI(0).Infof("%v.Description()", i.suffix)
Matt Rosencrantzf5afcaf2014-06-02 11:31:22 -0700120 s, err := i.lookup(context)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700121 if err != nil {
122 return "", err
123 }
124 return s.Description, nil
125}
126
Matt Rosencrantzf5afcaf2014-06-02 11:31:22 -0700127func (i *invoker) Specification(context ipc.ServerContext) (profile.Specification, error) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700128 vlog.VI(0).Infof("%v.Specification()", i.suffix)
Matt Rosencrantzf5afcaf2014-06-02 11:31:22 -0700129 return i.lookup(context)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700130}