Skip to content

Add file downloader cache to make faster the library/boards manager #9023

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
Jul 18, 2019

Conversation

mattiabertorello
Copy link
Contributor

@mattiabertorello mattiabertorello commented Jun 28, 2019

  • Add the cache for the library and boards files
  • Fix the delete of the files when something fail during the signature check
  • Add this configuration: http.connection_timeout_ms with 5000 as a default value, cache.enable with true as a default value
  • Add logging on local file Arduino15/logs/application.log (rotation policy: compress if the log is bigger than 50MB, delete when there are more than 20 compressed log files. See app/src/log4j2.xml)

Fixed issues: #8936, #6333, #7690 (comment)
Mitigated: #8988

The cache will consider the "Cache-Control" and the ETag headers.
So if the server delivers a file, setting a Cache-Control="private, max-age=14400" http header, the file will be cached for 4 hours without make any http request. When the cached file expires the download will make a HEAD request to check for ETag header changes, before making an actual download request.
Trying to emulate the browser behavior: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching

The metadata of the cached files will be store in the Arduino15/cache/cache.json
example:

{
  "files" : [ {
    "eTag" : "a778ceeb5945afa31275495b8ccd5434",
    "remoteURL" : "https://downloads.arduino.cc/packages/package_index.json.sig",
    "localPath" : "/Users/mattiabertorello/Library/Arduino15/cache/downloads.arduino.cc/packages/package_index.json.sig",
    "md5" : "MD5:a778ceeb5945afa31275495b8ccd5434",
    "createdAt" : "2019-07-03T15:46:58.877",
    "cacheControl" : {
      "maxAge" : 14400,
      "public" : false,
      "private" : true,
      "mustRevalidate" : false,
      "noCache" : false,
      "noStore" : false,
      "noTransform" : false,
      "proxyRevalidate" : false,
      "smaxAge" : -1
    },
    "expires" : "2019-07-03T19:46:58.877"
  }]
}

@per1234
Copy link
Collaborator

per1234 commented Jun 29, 2019

I did a test using a throwaway Boards Manager JSON file I published here:
https://gist.github.com/per1234/ed63fa1f88e7cff876620053378e895b/raw/80bc2b996db7fd878dfbe86dd2024490f57fecc6/package_foo_index.json
This file intentionally has a bad package file URL for the 1.0.4 release so installation is expected to fail. With Arduino IDE 1.8.10 Hourly Build 2019/05/21 09:33 I get this clear error message:

 Error downloading https://MCUdude.github.io/MicroCoreFoo/MicroCore-1.0.4.tar.bz2
java.lang.RuntimeException: java.lang.Exception: Error downloading https://MCUdude.github.io/MicroCoreFoo/MicroCore-1.0.4.tar.bz2
	at cc.arduino.contributions.packages.ui.ContributionManagerUI.lambda$onInstallPressed$2(ContributionManagerUI.java:175)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.Exception: Error downloading https://MCUdude.github.io/MicroCoreFoo/MicroCore-1.0.4.tar.bz2
	at cc.arduino.contributions.DownloadableContributionsDownloader.download(DownloadableContributionsDownloader.java:139)
	at cc.arduino.contributions.DownloadableContributionsDownloader.download(DownloadableContributionsDownloader.java:73)
	at cc.arduino.contributions.DownloadableContributionsDownloader.download(DownloadableContributionsDownloader.java:55)
	at cc.arduino.contributions.packages.ContributionInstaller.install(ContributionInstaller.java:101)
	at cc.arduino.contributions.packages.ui.ContributionManagerUI.lambda$onInstallPressed$2(ContributionManagerUI.java:172)
	... 1 more
Caused by: java.io.IOException: Received invalid http status code from server: 404
	at cc.arduino.utils.network.FileDownloader.downloadFile(FileDownloader.java:205)
	at cc.arduino.utils.network.FileDownloader.download(FileDownloader.java:132)
	at cc.arduino.contributions.DownloadableContributionsDownloader.download(DownloadableContributionsDownloader.java:137)
	... 5 more

But with build 871 I get this:

 Error downloading https://MCUdude.github.io/MicroCoreFoo/MicroCore-1.0.4.tar.bz2
java.lang.RuntimeException: java.lang.Exception: Error downloading https://MCUdude.github.io/MicroCoreFoo/MicroCore-1.0.4.tar.bz2
	at cc.arduino.contributions.packages.ui.ContributionManagerUI.lambda$onInstallPressed$2(ContributionManagerUI.java:175)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.Exception: Error downloading https://MCUdude.github.io/MicroCoreFoo/MicroCore-1.0.4.tar.bz2
	at cc.arduino.contributions.DownloadableContributionsDownloader.download(DownloadableContributionsDownloader.java:142)
	at cc.arduino.contributions.DownloadableContributionsDownloader.download(DownloadableContributionsDownloader.java:76)
	at cc.arduino.contributions.DownloadableContributionsDownloader.download(DownloadableContributionsDownloader.java:58)
	at cc.arduino.contributions.packages.ContributionInstaller.install(ContributionInstaller.java:103)
	at cc.arduino.contributions.packages.ui.ContributionManagerUI.lambda$onInstallPressed$2(ContributionManagerUI.java:172)
	... 1 more
Caused by: java.nio.file.FileSystemException: C:\Users\per\AppData\Local\Arduino15\staging\packages\MicroCore-1.0.4.tar.bz2: The process cannot access the file because it is being used by another process.

	at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
	at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
	at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
	at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269)
	at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
	at java.nio.file.Files.delete(Files.java:1126)
	at cc.arduino.utils.network.FileDownloader.downloadFile(FileDownloader.java:189)
	at cc.arduino.utils.network.FileDownloader.download(FileDownloader.java:129)
	at cc.arduino.contributions.DownloadableContributionsDownloader.download(DownloadableContributionsDownloader.java:140)
	... 5 more

Note the error message now says "The process cannot access the file because it is being used by another process." instead of "Received invalid http status code from server: 404".

C:\Users\per\AppData\Local\Arduino15\staging\packages\MicroCore-1.0.4.tar.bz2 didn't exist on my computer before the installation attempt. It is a 0 byte file that was created during the installation. The error message "The process cannot access the file because it is being used by another process." makes me think of a conflict with an antivirus software's on-access file scanner, but this is not the case because I tried with the antivirus disabled and it still happens. I feel like this error message could be very misleading to someone trying to troubleshoot this problem because it acts as a distraction from the real problem that the file couldn't be downloaded, and also blocks the helpful HTTP response code from being shown.

I also tried with build 871 running in portable mode, with the same error message.

On my Linux machine, I get the "Received invalid http status code from server: 404" error from build 871.

- The file will be close before delete it
- Some refactoring of the downloader cache
@facchinm
Copy link
Member

facchinm commented Jul 1, 2019

@ArduinoBot build this please

@arduino arduino deleted a comment from ArduinoBot Jul 1, 2019
@facchinm facchinm added this to the Release 1.8.10 milestone Jul 1, 2019
@mattiabertorello
Copy link
Contributor Author

I should fix the problem but I can't test on windows, could you test it ? @per1234
Thanks

@per1234
Copy link
Collaborator

per1234 commented Jul 2, 2019

@mattiabertorello looks good. Thanks!

@feikname
Copy link
Contributor

feikname commented Jul 3, 2019

Does this solve #6333?

@facchinm
Copy link
Member

facchinm commented Jul 3, 2019

@ArduinoBot build this please

@rsora
Copy link

rsora commented Jul 3, 2019

@feikname yes, this PR should address also your issue.
It would be great if you can help us in testing the preview binary available in the comment below (this one: #9023 (comment)) and attach in a comment here the logs (available in the Arduino15/logs/application.log folder as described in the PR summary) if you experience any sort of issues.
Thanks a lot!

edit : changed build download link due to some bugfixing

Mattia Bertorello added 3 commits July 11, 2019 14:32
Add the possibility to configure them `http.max_redirect_number`
and will be downloaded only one time
@rsora
Copy link

rsora commented Jul 11, 2019

@per1234 consider the signature whitelisting a foundation for implementing in near future a 3rd party indexes security mechanism without breaking retro-compatibility.

Currently the signature check mechanism uses a public and private keys and consists in signing the Arduino's package_index.json server side with our private key, and checking the signature in the IDE using the Arduino's public key bundled in the IDE.

We are investigating in ways to make more secure also 3rd party cores indexes, maybe starting using our own key end ending up having some sort of CA mechanism similar to the one used by web browsers. But this is not so easy to implement so we implemented only the first bits of the feature.

I hope that this clarifies your doubts, otherwise, feel free to ask for details :)

@red-scorp
Copy link

Germany. Same error https://downloads.arduino.cc/packages/package_index.json.sig file signature verification failed. File ignored.
I put 882 in portable mode and this is my log:
application.log

@mattiabertorello mattiabertorello force-pushed the add-file-cache branch 2 times, most recently from 024dab7 to 8b90f1a Compare July 12, 2019 11:35
@rsora
Copy link

rsora commented Jul 15, 2019

@ArduinoBot build this please

@facchinm facchinm merged commit 324a9bc into arduino:master Jul 18, 2019
per1234 added a commit to per1234/arduino-ci-script that referenced this pull request Jan 9, 2020
…E 1.8.10

arduino/Arduino#9023 changed the Arduino IDE CLI's output. Due to this, when no boardsmanager.additional.urls preference is set, the output from Arduino IDE 1.8.10 (and onwards likely) caused priorBoardsmanagerAdditionalURLs to be set to "Set log4j store directory /home/travis/.arduino15". The solution was to check the exit status of the arduino --get-pref command and if it is 4 (Preference passed to --get-pref does not exist), overwrite the spurious value.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants