1+ /*
2+ Copyright 2013 CoreOS Inc.
3+
4+ Licensed under the Apache License, Version 2.0 (the "License");
5+ you may not use this file except in compliance with the License.
6+ You may obtain a copy of the License at
7+
8+ http://www.apache.org/licenses/LICENSE-2.0
9+
10+ Unless required by applicable law or agreed to in writing, software
11+ distributed under the License is distributed on an "AS IS" BASIS,
12+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ See the License for the specific language governing permissions and
14+ limitations under the License.
15+ */
16+
117package store
218
319import (
420 "encoding/json"
521 "fmt"
6- etcdErr "github.com/coreos/etcd/error"
722 "path"
823 "strconv"
924 "sync"
1025 "time"
26+
27+ etcdErr "github.com/coreos/etcd/error"
1128)
1229
1330//------------------------------------------------------------------------------
@@ -325,75 +342,81 @@ func (s *Store) Get(key string) ([]byte, error) {
325342 return json .Marshal (resps )
326343}
327344
328- func (s * Store ) RawGet (key string ) ([]* Response , error ) {
329- // Update stats
330- s .BasicStats .Gets ++
345+ func (s * Store ) rawGetNode (key string , node * Node ) ([]* Response , error ) {
346+ resps := make ([]* Response , 1 )
331347
332- key = path .Clean ("/" + key )
333-
334- nodes , keys , ok := s .Tree .list (key )
348+ isExpire := ! node .ExpireTime .Equal (PERMANENT )
335349
336- if ok {
350+ resps [0 ] = & Response {
351+ Action : "GET" ,
352+ Index : s .Index ,
353+ Key : key ,
354+ Value : node .Value ,
355+ }
337356
338- node , ok := nodes .(* Node )
357+ // Update ttl
358+ if isExpire {
359+ TTL := int64 (node .ExpireTime .Sub (time .Now ()) / time .Second )
360+ resps [0 ].Expiration = & node .ExpireTime
361+ resps [0 ].TTL = TTL
362+ }
339363
340- if ok {
341- resps := make ([] * Response , 1 )
364+ return resps , nil
365+ }
342366
343- isExpire := ! node .ExpireTime .Equal (PERMANENT )
367+ func (s * Store ) rawGetNodeList (key string , keys []string , nodes []* Node ) ([]* Response , error ) {
368+ resps := make ([]* Response , len (nodes ))
344369
345- resps [0 ] = & Response {
346- Action : "GET" ,
347- Index : s .Index ,
348- Key : key ,
349- Value : node .Value ,
350- }
370+ // TODO: check if nodes and keys are the same length
371+ for i := 0 ; i < len (nodes ); i ++ {
372+ var TTL int64
373+ var isExpire bool = false
351374
352- // Update ttl
353- if isExpire {
354- TTL := int64 (node .ExpireTime .Sub (time .Now ()) / time .Second )
355- resps [0 ].Expiration = & node .ExpireTime
356- resps [0 ].TTL = TTL
357- }
375+ isExpire = ! nodes [i ].ExpireTime .Equal (PERMANENT )
358376
359- return resps , nil
377+ resps [i ] = & Response {
378+ Action : "GET" ,
379+ Index : s .Index ,
380+ Key : path .Join (key , keys [i ]),
360381 }
361382
362- nodes , _ := nodes .([]* Node )
363-
364- resps := make ([]* Response , len (nodes ))
365- for i := 0 ; i < len (nodes ); i ++ {
366-
367- var TTL int64
368- var isExpire bool = false
383+ if len (nodes [i ].Value ) != 0 {
384+ resps [i ].Value = nodes [i ].Value
385+ } else {
386+ resps [i ].Dir = true
387+ }
369388
370- isExpire = ! nodes [i ].ExpireTime .Equal (PERMANENT )
389+ // Update ttl
390+ if isExpire {
391+ TTL = int64 (nodes [i ].ExpireTime .Sub (time .Now ()) / time .Second )
392+ resps [i ].Expiration = & nodes [i ].ExpireTime
393+ resps [i ].TTL = TTL
394+ }
371395
372- resps [i ] = & Response {
373- Action : "GET" ,
374- Index : s .Index ,
375- Key : path .Join (key , keys [i ]),
376- }
396+ }
377397
378- if len (nodes [i ].Value ) != 0 {
379- resps [i ].Value = nodes [i ].Value
380- } else {
381- resps [i ].Dir = true
382- }
398+ return resps , nil
399+ }
383400
384- // Update ttl
385- if isExpire {
386- TTL = int64 (nodes [i ].ExpireTime .Sub (time .Now ()) / time .Second )
387- resps [i ].Expiration = & nodes [i ].ExpireTime
388- resps [i ].TTL = TTL
389- }
401+ func (s * Store ) RawGet (key string ) ([]* Response , error ) {
402+ // Update stats
403+ s .BasicStats .Gets ++
390404
391- }
405+ key = path . Clean ( "/" + key )
392406
393- return resps , nil
407+ nodes , keys , ok := s .Tree .list (key )
408+ if ! ok {
409+ return nil , etcdErr .NewError (100 , "get: " + key )
394410 }
395411
396- return nil , etcdErr .NewError (100 , "get: " + key )
412+ switch node := nodes .(type ) {
413+ case * Node :
414+ return s .rawGetNode (key , node )
415+ case []* Node :
416+ return s .rawGetNodeList (key , keys , node )
417+ default :
418+ panic ("invalid cast " )
419+ }
397420}
398421
399422func (s * Store ) Delete (key string , index uint64 ) ([]byte , error ) {
@@ -415,43 +438,41 @@ func (s *Store) internalDelete(key string, index uint64) ([]byte, error) {
415438
416439 node , ok := s .Tree .get (key )
417440
418- if ok {
419-
420- resp := Response {
421- Action : "DELETE" ,
422- Key : key ,
423- PrevValue : node .Value ,
424- Index : index ,
425- }
441+ if ! ok {
442+ return nil , etcdErr .NewError (100 , "delete: " + key )
443+ }
426444
427- if node .ExpireTime .Equal (PERMANENT ) {
445+ resp := Response {
446+ Action : "DELETE" ,
447+ Key : key ,
448+ PrevValue : node .Value ,
449+ Index : index ,
450+ }
428451
429- s . Tree . delete ( key )
452+ if node . ExpireTime . Equal ( PERMANENT ) {
430453
431- } else {
432- resp .Expiration = & node .ExpireTime
433- // Kill the expire go routine
434- node .update <- PERMANENT
435- s .Tree .delete (key )
454+ s .Tree .delete (key )
436455
437- }
456+ } else {
457+ resp .Expiration = & node .ExpireTime
458+ // Kill the expire go routine
459+ node .update <- PERMANENT
460+ s .Tree .delete (key )
438461
439- msg , err := json . Marshal ( resp )
462+ }
440463
441- s . watcher . notify (resp )
464+ msg , err := json . Marshal (resp )
442465
443- // notify the messager
444- if s .messager != nil && err == nil {
445- s .messager <- string (msg )
446- }
466+ s .watcher .notify (resp )
447467
448- s .addToResponseMap (index , & resp )
468+ // notify the messager
469+ if s .messager != nil && err == nil {
470+ s .messager <- string (msg )
471+ }
449472
450- return msg , err
473+ s . addToResponseMap ( index , & resp )
451474
452- } else {
453- return nil , etcdErr .NewError (100 , "delete: " + key )
454- }
475+ return msg , err
455476}
456477
457478// Set the value of the key to the value if the given prevValue is equal to the value of the key
@@ -465,12 +486,16 @@ func (s *Store) TestAndSet(key string, prevValue string, value string, expireTim
465486 resp := s .internalGet (key )
466487
467488 if resp == nil {
468- return nil , etcdErr .NewError (100 , "testandset: " + key )
489+ if prevValue != "" {
490+ errmsg := fmt .Sprintf ("TestAndSet: key not found and previousValue is not empty %s:%s " , key , prevValue )
491+ return nil , etcdErr .NewError (100 , errmsg )
492+ }
493+ return s .internalSet (key , value , expireTime , index )
469494 }
470495
471496 if resp .Value == prevValue {
472497
473- // If test success , do set
498+ // If test succeed , do set
474499 return s .internalSet (key , value , expireTime , index )
475500 } else {
476501
0 commit comments