Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |