Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: client/cipd/client.go

Issue 1870263002: cipd: instance cache (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-go@master
Patch Set: addressed comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | client/cipd/internal/instancecache.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Package cipd implements client side of Chrome Infra Package Deployer. 5 // Package cipd implements client side of Chrome Infra Package Deployer.
6 // 6 //
7 // Binary package file format (in free form representation): 7 // Binary package file format (in free form representation):
8 // <binary package> := <zipped data> 8 // <binary package> := <zipped data>
9 // <zipped data> := DeterministicZip(<all input files> + <manifest json>) 9 // <zipped data> := DeterministicZip(<all input files> + <manifest json>)
10 // <manifest json> := File{ 10 // <manifest json> := File{
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 // RPC requests. 330 // RPC requests.
331 AuthenticatedClientFactory HTTPClientFactory 331 AuthenticatedClientFactory HTTPClientFactory
332 332
333 // AnonymousClientFactory lazily creates http.Client to use for making 333 // AnonymousClientFactory lazily creates http.Client to use for making
334 // requests to storage. 334 // requests to storage.
335 AnonymousClientFactory HTTPClientFactory 335 AnonymousClientFactory HTTPClientFactory
336 336
337 // UserAgent is put into User-Agent HTTP header with each request. 337 // UserAgent is put into User-Agent HTTP header with each request.
338 UserAgent string 338 UserAgent string
339 339
340 » // CacheDir is a directory for shared cache. If empty, tags are cached 340 » // CacheDir is a directory for shared cache. If empty, instances are not
341 » // inside the site root. If both Root and CacheDir are empty, tag cache 341 » // cached and tags are cached inside the site root. If both Root and
342 » // is disabled. 342 » // CacheDir are empty, tag cache is disabled.
343 CacheDir string 343 CacheDir string
344 } 344 }
345 345
346 // NewClient initializes CIPD client object. 346 // NewClient initializes CIPD client object.
347 func NewClient(opts ClientOptions) Client { 347 func NewClient(opts ClientOptions) Client {
348 if opts.ServiceURL == "" { 348 if opts.ServiceURL == "" {
349 opts.ServiceURL = ServiceURL 349 opts.ServiceURL = ServiceURL
350 } 350 }
351 if opts.Logger == nil { 351 if opts.Logger == nil {
352 opts.Logger = logging.Null() 352 opts.Logger = logging.Null()
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 storage storage 387 storage storage
388 388
389 // deployer knows how to install packages to local file system. Thread s afe. 389 // deployer knows how to install packages to local file system. Thread s afe.
390 deployer local.Deployer 390 deployer local.Deployer
391 391
392 // tagCache is used to cache (pkgname, tag) -> instanceID mapping. 392 // tagCache is used to cache (pkgname, tag) -> instanceID mapping.
393 // Thread safe, but lazily initialized under lock. 393 // Thread safe, but lazily initialized under lock.
394 tagCache *internal.TagCache 394 tagCache *internal.TagCache
395 tagCacheInit sync.Once 395 tagCacheInit sync.Once
396 396
397 // instanceCache is a file-system based cache of instances.
398 instanceCache *internal.InstanceCache
399 instanceCacheInit sync.Once
400
397 // authClient is a lazily created http.Client to use for authenticated 401 // authClient is a lazily created http.Client to use for authenticated
398 // requests. Thread safe, but lazily initialized under lock. 402 // requests. Thread safe, but lazily initialized under lock.
399 authClient *http.Client 403 authClient *http.Client
400 404
401 // anonClient is a lazily created http.Client to use for anonymous reque sts. 405 // anonClient is a lazily created http.Client to use for anonymous reque sts.
402 // Thread safe, but lazily initialized under lock. 406 // Thread safe, but lazily initialized under lock.
403 anonClient *http.Client 407 anonClient *http.Client
404 } 408 }
405 409
406 // doAuthenticatedHTTPRequest is used by remote implementation to make HTTP call s. 410 // doAuthenticatedHTTPRequest is used by remote implementation to make HTTP call s.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 out, err := client.tagCache.Save() 484 out, err := client.tagCache.Save()
481 if err == nil { 485 if err == nil {
482 err = local.EnsureFile(fs, path, bytes.NewReader(out)) 486 err = local.EnsureFile(fs, path, bytes.NewReader(out))
483 } 487 }
484 if err != nil { 488 if err != nil {
485 client.Logger.Warningf("cipd: failed to update tag cache - %s", err) 489 client.Logger.Warningf("cipd: failed to update tag cache - %s", err)
486 } 490 }
487 client.tagCache = nil 491 client.tagCache = nil
488 } 492 }
489 493
494 // instanceCachePath returns path to the instance cache directory or "" if
495 // instance cache is disabled.
496 func (client *clientImpl) instanceCachePath() string {
497 if client.CacheDir == "" {
498 return ""
499 }
500 return filepath.Join(client.CacheDir, "instances")
501 }
502
503 // getInstanceCache lazy-initializes instanceCache and returns it.
504 func (client *clientImpl) getInstanceCache() *internal.InstanceCache {
505 client.instanceCacheInit.Do(func() {
506 if path := client.instanceCachePath(); path != "" {
507 cachePath := local.NewFileSystem(path, client.Logger)
508 client.instanceCache = internal.LoadInstanceCache(cacheP ath, client.Logger, client.clock.now())
509 }
510 })
511 return client.instanceCache
512 }
513
514 // closeInstanceCache dumps any changes made to instance cache to disk, if neces sary.
515 func (client *clientImpl) closeInstanceCache() {
516 if client.instanceCache == nil || !client.instanceCache.Dirty() {
517 return
518 }
519
520 if err := client.instanceCache.Save(); err != nil {
521 client.Logger.Warningf("cipd: failed to save instance cache - %s ", err)
522 }
523 client.instanceCache = nil
524 }
525
490 func (client *clientImpl) FetchACL(packagePath string) ([]PackageACL, error) { 526 func (client *clientImpl) FetchACL(packagePath string) ([]PackageACL, error) {
491 return client.remote.fetchACL(packagePath) 527 return client.remote.fetchACL(packagePath)
492 } 528 }
493 529
494 func (client *clientImpl) ModifyACL(packagePath string, changes []PackageACLChan ge) error { 530 func (client *clientImpl) ModifyACL(packagePath string, changes []PackageACLChan ge) error {
495 return client.remote.modifyACL(packagePath, changes) 531 return client.remote.modifyACL(packagePath, changes)
496 } 532 }
497 533
498 func (client *clientImpl) ListPackages(path string, recursive bool) ([]string, e rror) { 534 func (client *clientImpl) ListPackages(path string, recursive bool) ([]string, e rror) {
499 pkgs, dirs, err := client.remote.listPackages(path, recursive) 535 pkgs, dirs, err := client.remote.listPackages(path, recursive)
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 } 778 }
743 779
744 func (client *clientImpl) FetchInstanceRefs(pin common.Pin, refs []string) ([]Re fInfo, error) { 780 func (client *clientImpl) FetchInstanceRefs(pin common.Pin, refs []string) ([]Re fInfo, error) {
745 err := common.ValidatePin(pin) 781 err := common.ValidatePin(pin)
746 if err != nil { 782 if err != nil {
747 return nil, err 783 return nil, err
748 } 784 }
749 return client.remote.fetchRefs(pin, refs) 785 return client.remote.fetchRefs(pin, refs)
750 } 786 }
751 787
752 func (client *clientImpl) FetchInstance(pin common.Pin, output io.WriteSeeker) e rror { 788 func (client *clientImpl) FetchInstance(pin common.Pin, output io.WriteSeeker) e rror {
Vadim Sh. 2016/04/11 23:47:50 I think I prefer func ... FetchInstance(...) ...
nodir 2016/04/13 02:05:30 Done.
753 err := common.ValidatePin(pin) 789 err := common.ValidatePin(pin)
754 if err != nil { 790 if err != nil {
755 return err 791 return err
756 } 792 }
793
794 now := client.clock.now()
795
796 cache := client.getInstanceCache()
797 if cache != nil {
798 switch err := cache.Get(pin, output, now); {
799 case os.IsNotExist(err):
800 // output is not corrupted.
801
802 case err != nil:
803 client.Logger.Warningf("cipd: could not get %s from cach e - %s", pin, err)
804 // Output may be corrupted. Rewinding back.
805 if _, err := output.Seek(0, 0); err != nil {
806 return err
807 }
808
809 default:
810 client.Logger.Infof("cipd: cache hit for %s", pin)
811 return nil
812 }
813 }
814
757 client.Logger.Infof("cipd: resolving fetch URL for %s", pin) 815 client.Logger.Infof("cipd: resolving fetch URL for %s", pin)
758 fetchInfo, err := client.remote.fetchInstance(pin) 816 fetchInfo, err := client.remote.fetchInstance(pin)
759 » if err == nil { 817 » fetchFailed := func(err error) {
760 » » err = client.storage.download(fetchInfo.fetchURL, output) 818 » » client.Logger.Errorf("cipd: failed to fetch %s - %s", pin, err)
761 } 819 }
762 if err != nil { 820 if err != nil {
763 » » client.Logger.Errorf("cipd: failed to fetch %s - %s", pin, err) 821 » » fetchFailed(err)
764 return err 822 return err
765 } 823 }
824
825 if cache == nil {
826 if err := client.storage.download(fetchInfo.fetchURL, output); e rr != nil {
827 fetchFailed(err)
828 return err
829 }
830 } else {
831 // With cache, we need to download the instance to two places.
832 // Download to the cache and then read from there.
833 err := cache.Put(pin, now, func(f *os.File) error {
834 err := client.storage.download(fetchInfo.fetchURL, f)
835 if err != nil {
836 fetchFailed(err)
837 }
838 return err
839 })
840 if err != nil {
841 return err
842 }
843
844 // Now read it back.
845 if err := cache.Get(pin, output, now); err != nil {
846 return err
847 }
848 }
849
766 client.Logger.Infof("cipd: successfully fetched %s", pin) 850 client.Logger.Infof("cipd: successfully fetched %s", pin)
767 return nil 851 return nil
768 } 852 }
769 853
770 func (client *clientImpl) FetchAndDeployInstance(pin common.Pin) error { 854 func (client *clientImpl) FetchAndDeployInstance(pin common.Pin) error {
771 err := common.ValidatePin(pin) 855 err := common.ValidatePin(pin)
772 if err != nil { 856 if err != nil {
773 return err 857 return err
774 } 858 }
775 859
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
942 client.Logger.Infof("All changes applied.") 1026 client.Logger.Infof("All changes applied.")
943 return actions, nil 1027 return actions, nil
944 } 1028 }
945 return actions, ErrEnsurePackagesFailed 1029 return actions, ErrEnsurePackagesFailed
946 } 1030 }
947 1031
948 func (client *clientImpl) Close() { 1032 func (client *clientImpl) Close() {
949 client.lock.Lock() 1033 client.lock.Lock()
950 defer client.lock.Unlock() 1034 defer client.lock.Unlock()
951 client.closeTagCache() 1035 client.closeTagCache()
1036 client.closeInstanceCache()
952 client.authClient = nil 1037 client.authClient = nil
953 client.anonClient = nil 1038 client.anonClient = nil
954 } 1039 }
955 1040
956 //////////////////////////////////////////////////////////////////////////////// 1041 ////////////////////////////////////////////////////////////////////////////////
957 // Private structs and interfaces. 1042 // Private structs and interfaces.
958 1043
959 type clock interface { 1044 type clock interface {
960 now() time.Time 1045 now() time.Time
961 sleep(time.Duration) 1046 sleep(time.Duration)
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 } 1118 }
1034 1119
1035 // buildInstanceIDMap builds mapping {package name -> instance ID}. 1120 // buildInstanceIDMap builds mapping {package name -> instance ID}.
1036 func buildInstanceIDMap(pins []common.Pin) map[string]string { 1121 func buildInstanceIDMap(pins []common.Pin) map[string]string {
1037 out := map[string]string{} 1122 out := map[string]string{}
1038 for _, p := range pins { 1123 for _, p := range pins {
1039 out[p.PackageName] = p.InstanceID 1124 out[p.PackageName] = p.InstanceID
1040 } 1125 }
1041 return out 1126 return out
1042 } 1127 }
OLDNEW
« no previous file with comments | « no previous file | client/cipd/internal/instancecache.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698