Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 1 | package server |
| 2 | |
| 3 | import ( |
| 4 | "errors" |
| 5 | |
| 6 | "veyron/services/store/service" |
| 7 | |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 8 | "veyron2/ipc" |
Matt Rosencrantz | 4b86886 | 2014-05-15 15:16:10 -0700 | [diff] [blame] | 9 | "veyron2/query" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 10 | "veyron2/services/mounttable" |
| 11 | "veyron2/services/store" |
Tilak Sharma | 79cfb41 | 2014-05-27 18:34:57 -0700 | [diff] [blame] | 12 | "veyron2/services/watch" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 13 | "veyron2/storage" |
Todd Wang | e5d67b4 | 2014-05-27 10:48:07 -0700 | [diff] [blame] | 14 | "veyron2/vdl" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 15 | ) |
| 16 | |
| 17 | type object struct { |
| 18 | name string |
| 19 | obj service.Object |
| 20 | server *Server |
| 21 | } |
| 22 | |
| 23 | var ( |
| 24 | errNotAValue = errors.New("not a storage.Value") |
| 25 | errNotAnAttribute = errors.New("not a storage.Attr") |
| 26 | |
| 27 | _ store.ObjectService = (*object)(nil) |
| 28 | |
| 29 | nullEntry store.Entry |
| 30 | nullStat store.Stat |
| 31 | ) |
| 32 | |
| 33 | func fillServiceStat(result *store.Stat, stat *storage.Stat) { |
| 34 | result.ID = stat.ID |
| 35 | result.MTimeNS = stat.MTime.UnixNano() |
| 36 | result.Attrs = attrsToAnyData(stat.Attrs) |
| 37 | } |
| 38 | |
| 39 | func makeServiceStat(stat *storage.Stat) store.Stat { |
| 40 | if stat == nil { |
| 41 | return nullStat |
| 42 | } |
| 43 | var result store.Stat |
| 44 | fillServiceStat(&result, stat) |
| 45 | return result |
| 46 | } |
| 47 | |
| 48 | func makeServiceEntry(e *storage.Entry) store.Entry { |
| 49 | if e == nil { |
| 50 | return nullEntry |
| 51 | } |
| 52 | result := store.Entry{Value: e.Value} |
| 53 | fillServiceStat(&result.Stat, &e.Stat) |
| 54 | return result |
| 55 | } |
| 56 | |
| 57 | func (o *object) String() string { |
| 58 | return o.name |
| 59 | } |
| 60 | |
| 61 | func (o *object) Attributes(arg string) map[string]string { |
| 62 | return map[string]string{ |
| 63 | "health": "ok", |
| 64 | "servertype": o.String(), |
| 65 | } |
| 66 | } |
| 67 | |
Todd Wang | e5d67b4 | 2014-05-27 10:48:07 -0700 | [diff] [blame] | 68 | func attrsFromAnyData(attrs []vdl.Any) ([]storage.Attr, error) { |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 69 | typedAttrs := make([]storage.Attr, len(attrs)) |
| 70 | for i, x := range attrs { |
| 71 | a, ok := x.(storage.Attr) |
| 72 | if !ok { |
| 73 | return nil, errNotAnAttribute |
| 74 | } |
| 75 | typedAttrs[i] = a |
| 76 | } |
| 77 | return typedAttrs, nil |
| 78 | } |
| 79 | |
Todd Wang | e5d67b4 | 2014-05-27 10:48:07 -0700 | [diff] [blame] | 80 | func attrsToAnyData(attrs []storage.Attr) []vdl.Any { |
| 81 | uattrs := make([]vdl.Any, len(attrs)) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 82 | for i, x := range attrs { |
| 83 | uattrs[i] = x |
| 84 | } |
| 85 | return uattrs |
| 86 | } |
| 87 | |
| 88 | // Exists returns true iff the Entry has a value. |
| 89 | func (o *object) Exists(ctx ipc.Context, tid store.TransactionID) (bool, error) { |
| 90 | t, ok := o.server.findTransaction(tid) |
| 91 | if !ok { |
| 92 | return false, errTransactionDoesNotExist |
| 93 | } |
| 94 | return o.obj.Exists(ctx.RemoteID(), t) |
| 95 | } |
| 96 | |
| 97 | // Get returns the value for the Object. The value returned is from the |
| 98 | // most recent mutation of the entry in the Transaction, or from the |
| 99 | // Transaction's snapshot if there is no mutation. |
| 100 | func (o *object) Get(ctx ipc.Context, tid store.TransactionID) (store.Entry, error) { |
| 101 | t, ok := o.server.findTransaction(tid) |
| 102 | if !ok { |
| 103 | return nullEntry, errTransactionDoesNotExist |
| 104 | } |
| 105 | entry, err := o.obj.Get(ctx.RemoteID(), t) |
| 106 | if err != nil { |
| 107 | return nullEntry, err |
| 108 | } |
| 109 | return makeServiceEntry(entry), err |
| 110 | } |
| 111 | |
| 112 | // Put modifies the value of the Object. |
Todd Wang | e5d67b4 | 2014-05-27 10:48:07 -0700 | [diff] [blame] | 113 | func (o *object) Put(ctx ipc.Context, tid store.TransactionID, val vdl.Any) (store.Stat, error) { |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 114 | t, ok := o.server.findTransaction(tid) |
| 115 | if !ok { |
| 116 | return nullStat, errTransactionDoesNotExist |
| 117 | } |
| 118 | stat, err := o.obj.Put(ctx.RemoteID(), t, interface{}(val)) |
| 119 | if err != nil { |
| 120 | return nullStat, err |
| 121 | } |
| 122 | return makeServiceStat(stat), nil |
| 123 | } |
| 124 | |
| 125 | // Remove removes the Object. |
| 126 | func (o *object) Remove(ctx ipc.Context, tid store.TransactionID) error { |
| 127 | t, ok := o.server.findTransaction(tid) |
| 128 | if !ok { |
| 129 | return errTransactionDoesNotExist |
| 130 | } |
| 131 | return o.obj.Remove(ctx.RemoteID(), t) |
| 132 | } |
| 133 | |
| 134 | // SetAttr changes the attributes of the entry, such as permissions and |
| 135 | // replication groups. Attributes are associated with the value, not the |
| 136 | // path. |
Todd Wang | e5d67b4 | 2014-05-27 10:48:07 -0700 | [diff] [blame] | 137 | func (o *object) SetAttr(ctx ipc.Context, tid store.TransactionID, attrs []vdl.Any) error { |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 138 | t, ok := o.server.findTransaction(tid) |
| 139 | if !ok { |
| 140 | return errTransactionDoesNotExist |
| 141 | } |
| 142 | typedAttrs, err := attrsFromAnyData(attrs) |
| 143 | if err != nil { |
| 144 | return err |
| 145 | } |
| 146 | return o.obj.SetAttr(ctx.RemoteID(), t, typedAttrs...) |
| 147 | } |
| 148 | |
| 149 | // Stat returns entry info. |
| 150 | func (o *object) Stat(ctx ipc.Context, tid store.TransactionID) (store.Stat, error) { |
| 151 | t, ok := o.server.findTransaction(tid) |
| 152 | if !ok { |
| 153 | return nullStat, errTransactionDoesNotExist |
| 154 | } |
| 155 | stat, err := o.obj.Stat(ctx.RemoteID(), t) |
| 156 | if err != nil { |
| 157 | return nullStat, err |
| 158 | } |
| 159 | return makeServiceStat(stat), nil |
| 160 | } |
| 161 | |
Matt Rosencrantz | 4b86886 | 2014-05-15 15:16:10 -0700 | [diff] [blame] | 162 | // Query returns a sequence of objects that match the given query. |
Matt Rosencrantz | 90c2feb | 2014-05-23 11:13:48 -0700 | [diff] [blame] | 163 | func (o *object) Query(ctx ipc.Context, tid store.TransactionID, q query.Query, stream store.ObjectServiceQueryStream) error { |
| 164 | t, ok := o.server.findTransaction(tid) |
| 165 | if !ok { |
| 166 | return errTransactionDoesNotExist |
| 167 | } |
| 168 | it, err := o.obj.Query(ctx.RemoteID(), t, q) |
| 169 | if err != nil { |
| 170 | return err |
| 171 | } |
| 172 | for it.Next() { |
| 173 | if err := stream.Send(*it.Get()); err != nil { |
| 174 | it.Abort() |
| 175 | return err |
| 176 | } |
| 177 | } |
| 178 | return it.Err() |
Matt Rosencrantz | 4b86886 | 2014-05-15 15:16:10 -0700 | [diff] [blame] | 179 | } |
| 180 | |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 181 | type globStreamAdapter struct { |
| 182 | stream mounttable.GlobableServiceGlobStream |
| 183 | } |
| 184 | |
| 185 | func (a *globStreamAdapter) Send(item string) error { |
| 186 | return a.stream.Send(mounttable.MountEntry{ |
| 187 | Name: item, |
| 188 | }) |
| 189 | } |
| 190 | |
| 191 | // Glob streams a series of names that match the given pattern. |
| 192 | func (o *object) Glob(ctx ipc.Context, pattern string, stream mounttable.GlobableServiceGlobStream) error { |
| 193 | return o.GlobT(ctx, nullTransactionID, pattern, &globStreamAdapter{stream}) |
| 194 | } |
| 195 | |
| 196 | // Glob streams a series of names that match the given pattern. |
| 197 | func (o *object) GlobT(ctx ipc.Context, tid store.TransactionID, pattern string, stream store.ObjectServiceGlobTStream) error { |
| 198 | t, ok := o.server.findTransaction(tid) |
| 199 | if !ok { |
| 200 | return errTransactionDoesNotExist |
| 201 | } |
| 202 | it, err := o.obj.Glob(ctx.RemoteID(), t, pattern) |
| 203 | if err != nil { |
| 204 | return err |
| 205 | } |
| 206 | for ; it.IsValid(); it.Next() { |
| 207 | if ctx.IsClosed() { |
| 208 | break |
| 209 | } |
| 210 | if err := stream.Send(it.Name()); err != nil { |
| 211 | return err |
| 212 | } |
| 213 | } |
| 214 | return nil |
| 215 | } |
Tilak Sharma | 79cfb41 | 2014-05-27 18:34:57 -0700 | [diff] [blame] | 216 | |
| 217 | // Watch returns a stream of changes. |
| 218 | func (o *object) Watch(ctx ipc.Context, req watch.Request, stream watch.WatcherServiceWatchStream) error { |
| 219 | panic("not implemented") |
| 220 | } |