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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 385 // storage knows how to upload and download raw binaries using signed UR Ls. | 385 // storage knows how to upload and download raw binaries using signed UR Ls. |
| 386 // Thread safe. | 386 // Thread safe. |
| 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 // tagCacheLock is used to synchronize access to the tag cache file. | 392 // tagCacheLock is used to synchronize access to the tag cache file. |
| 393 tagCacheLock sync.Mutex | 393 tagCacheLock sync.Mutex |
| 394 | 394 |
| 395 // instanceCache is a file-system based cache of instances. | |
| 396 instanceCache *internal.InstanceCache | |
| 397 instanceCacheInit sync.Once | |
| 398 | |
| 395 // authClient is a lazily created http.Client to use for authenticated | 399 // authClient is a lazily created http.Client to use for authenticated |
| 396 // requests. Thread safe, but lazily initialized under lock. | 400 // requests. Thread safe, but lazily initialized under lock. |
| 397 authClient *http.Client | 401 authClient *http.Client |
| 398 | 402 |
| 399 // anonClient is a lazily created http.Client to use for anonymous reque sts. | 403 // anonClient is a lazily created http.Client to use for anonymous reque sts. |
| 400 // Thread safe, but lazily initialized under lock. | 404 // Thread safe, but lazily initialized under lock. |
| 401 anonClient *http.Client | 405 anonClient *http.Client |
| 402 } | 406 } |
| 403 | 407 |
| 404 // doAuthenticatedHTTPRequest is used by remote implementation to make HTTP call s. | 408 // doAuthenticatedHTTPRequest is used by remote implementation to make HTTP call s. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 if err != nil { | 486 if err != nil { |
| 483 client.Logger.Warningf("cipd: failed to update tag cache - %s", err) | 487 client.Logger.Warningf("cipd: failed to update tag cache - %s", err) |
| 484 } | 488 } |
| 485 } | 489 } |
| 486 | 490 |
| 487 if loadSaveTime > time.Second { | 491 if loadSaveTime > time.Second { |
| 488 client.Logger.Warningf("cipd: loading and saving tag cache with %d entries took %s", cache.Len(), loadSaveTime) | 492 client.Logger.Warningf("cipd: loading and saving tag cache with %d entries took %s", cache.Len(), loadSaveTime) |
| 489 } | 493 } |
| 490 } | 494 } |
| 491 | 495 |
| 496 // getInstanceCache lazy-initializes instanceCache and returns it. | |
| 497 // May return nil if instance cache is disabled. | |
| 498 func (client *clientImpl) getInstanceCache() *internal.InstanceCache { | |
| 499 client.instanceCacheInit.Do(func() { | |
| 500 if client.CacheDir == "" { | |
| 501 return | |
| 502 } | |
| 503 path := filepath.Join(client.CacheDir, "instances") | |
| 504 fs := local.NewFileSystem(path, client.Logger) | |
| 505 client.instanceCache = internal.NewInstanceCache(fs, client.Logg er) | |
| 506 }) | |
| 507 return client.instanceCache | |
| 508 } | |
| 509 | |
| 492 func (client *clientImpl) FetchACL(packagePath string) ([]PackageACL, error) { | 510 func (client *clientImpl) FetchACL(packagePath string) ([]PackageACL, error) { |
| 493 return client.remote.fetchACL(packagePath) | 511 return client.remote.fetchACL(packagePath) |
| 494 } | 512 } |
| 495 | 513 |
| 496 func (client *clientImpl) ModifyACL(packagePath string, changes []PackageACLChan ge) error { | 514 func (client *clientImpl) ModifyACL(packagePath string, changes []PackageACLChan ge) error { |
| 497 return client.remote.modifyACL(packagePath, changes) | 515 return client.remote.modifyACL(packagePath, changes) |
| 498 } | 516 } |
| 499 | 517 |
| 500 func (client *clientImpl) ListPackages(path string, recursive bool) ([]string, e rror) { | 518 func (client *clientImpl) ListPackages(path string, recursive bool) ([]string, e rror) { |
| 501 pkgs, dirs, err := client.remote.listPackages(path, recursive) | 519 pkgs, dirs, err := client.remote.listPackages(path, recursive) |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 751 | 769 |
| 752 func (client *clientImpl) FetchInstanceRefs(pin common.Pin, refs []string) ([]Re fInfo, error) { | 770 func (client *clientImpl) FetchInstanceRefs(pin common.Pin, refs []string) ([]Re fInfo, error) { |
| 753 err := common.ValidatePin(pin) | 771 err := common.ValidatePin(pin) |
| 754 if err != nil { | 772 if err != nil { |
| 755 return nil, err | 773 return nil, err |
| 756 } | 774 } |
| 757 return client.remote.fetchRefs(pin, refs) | 775 return client.remote.fetchRefs(pin, refs) |
| 758 } | 776 } |
| 759 | 777 |
| 760 func (client *clientImpl) FetchInstance(pin common.Pin, output io.WriteSeeker) e rror { | 778 func (client *clientImpl) FetchInstance(pin common.Pin, output io.WriteSeeker) e rror { |
| 761 » err := common.ValidatePin(pin) | 779 » cache := client.getInstanceCache() |
|
Vadim Sh.
2016/04/13 21:49:02
you lost this check
nodir
2016/04/13 23:23:51
Done.
| |
| 762 » if err != nil { | 780 » if cache == nil { |
| 781 » » return client.fetchInstanceNoCache(pin, output) | |
| 782 » } | |
| 783 » return client.fetchInstanceWithCache(pin, cache, output) | |
| 784 } | |
| 785 | |
| 786 func (client *clientImpl) fetchInstanceNoCache(pin common.Pin, output io.WriteSe eker) error { | |
| 787 » if err := client.remoteFetchInstance(pin, output); err != nil { | |
| 763 return err | 788 return err |
| 764 } | 789 } |
| 790 client.Logger.Infof("cipd: successfully fetched %s", pin) | |
| 791 return nil | |
| 792 } | |
| 793 | |
| 794 func (client *clientImpl) fetchInstanceWithCache(pin common.Pin, cache *internal .InstanceCache, output io.WriteSeeker) error { | |
| 795 // Try to get the instance from cache. | |
| 796 now := client.clock.now() | |
| 797 switch err := cache.Get(pin, output, now); { | |
| 798 case os.IsNotExist(err): | |
| 799 // output is not corrupted. | |
| 800 | |
| 801 case err != nil: | |
| 802 client.Logger.Warningf("cipd: could not get %s from cache - %s", pin, err) | |
| 803 // Output may be corrupted. Rewinding back. | |
|
Vadim Sh.
2016/04/13 21:49:02
you still need to truncate the file :(
nodir
2016/04/13 23:23:52
it is not required. I've improved the comment
| |
| 804 if _, err := output.Seek(0, 0); err != nil { | |
| 805 return err | |
| 806 } | |
| 807 | |
| 808 default: | |
| 809 client.Logger.Debugf("cipd: instance cache hit for %s", pin) | |
| 810 return nil | |
| 811 } | |
| 812 | |
| 813 return cache.Put(pin, now, func(f *os.File) error { | |
| 814 // Fetch to the file. | |
| 815 if err := client.remoteFetchInstance(pin, f); err != nil { | |
| 816 return err | |
| 817 } | |
| 818 | |
| 819 // Copy fetched content to output. | |
| 820 if _, err := f.Seek(0, 0); err != nil { | |
| 821 return err | |
| 822 } | |
| 823 if _, err := io.Copy(output, f); err != nil { | |
|
Vadim Sh.
2016/04/13 21:49:02
eh.. probably good enough for now, but it is a bit
nodir
2016/04/13 23:23:52
Acknowledged.
| |
| 824 return err | |
| 825 } | |
| 826 client.Logger.Infof("cipd: successfully fetched %s", pin) | |
| 827 return nil | |
| 828 }) | |
| 829 } | |
| 830 | |
| 831 func (client *clientImpl) remoteFetchInstance(pin common.Pin, output io.WriteSee ker) error { | |
| 765 client.Logger.Infof("cipd: resolving fetch URL for %s", pin) | 832 client.Logger.Infof("cipd: resolving fetch URL for %s", pin) |
| 766 fetchInfo, err := client.remote.fetchInstance(pin) | 833 fetchInfo, err := client.remote.fetchInstance(pin) |
| 767 if err == nil { | 834 if err == nil { |
| 768 err = client.storage.download(fetchInfo.fetchURL, output) | 835 err = client.storage.download(fetchInfo.fetchURL, output) |
| 769 } | 836 } |
| 770 if err != nil { | 837 if err != nil { |
| 771 client.Logger.Errorf("cipd: failed to fetch %s - %s", pin, err) | 838 client.Logger.Errorf("cipd: failed to fetch %s - %s", pin, err) |
| 772 return err | |
| 773 } | 839 } |
| 774 » client.Logger.Infof("cipd: successfully fetched %s", pin) | 840 » return err |
| 775 » return nil | |
| 776 } | 841 } |
| 777 | 842 |
| 778 func (client *clientImpl) FetchAndDeployInstance(pin common.Pin) error { | 843 func (client *clientImpl) FetchAndDeployInstance(pin common.Pin) error { |
| 779 err := common.ValidatePin(pin) | 844 err := common.ValidatePin(pin) |
| 780 if err != nil { | 845 if err != nil { |
| 781 return err | 846 return err |
| 782 } | 847 } |
| 783 | 848 |
| 784 // Use temp file for storing package file. Delete it when done. | 849 // Use temp file for storing package file. Delete it when done. |
| 785 var instance local.PackageInstance | 850 var instance local.PackageInstance |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1040 } | 1105 } |
| 1041 | 1106 |
| 1042 // buildInstanceIDMap builds mapping {package name -> instance ID}. | 1107 // buildInstanceIDMap builds mapping {package name -> instance ID}. |
| 1043 func buildInstanceIDMap(pins []common.Pin) map[string]string { | 1108 func buildInstanceIDMap(pins []common.Pin) map[string]string { |
| 1044 out := map[string]string{} | 1109 out := map[string]string{} |
| 1045 for _, p := range pins { | 1110 for _, p := range pins { |
| 1046 out[p.PackageName] = p.InstanceID | 1111 out[p.PackageName] = p.InstanceID |
| 1047 } | 1112 } |
| 1048 return out | 1113 return out |
| 1049 } | 1114 } |
| OLD | NEW |