-
-
Notifications
You must be signed in to change notification settings - Fork 347
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
Cache downloads globally #2185
Cache downloads globally #2185
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! It's exciting to see this one moving forward; it's one of those "why doesn't it already work this way" projects, but of course someone has to actually write the code to make it happen.
I previously started my own version of this change in a local branch, so some of my comments are based on that investigation. I had it to the point of automatically importing all the old separate caches into the global cache at launch, mostly by rewriting KSP.DownloadCacheDir(). I can share that branch if needed, but it's not too different from what you already have.
Core/Net/NetFileCache.cs
Outdated
// If the above didn't work, fall back to "~/.local/" | ||
if (string.IsNullOrWhiteSpace(baseDirectory)) | ||
{ | ||
baseDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".local/share"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we fully allow Path.Combine
to handle the path separators?
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal),
".local", "share")
Core/Net/NetFileCache.cs
Outdated
// If the above didn't work, fall back to "~/.local/" | ||
if (string.IsNullOrWhiteSpace(baseDirectory)) | ||
{ | ||
baseDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".local/share"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should let Mono handle the specifics of the path to use; it gave me a ~/.local/share
prefix for Environment.SpecialFolder.LocalApplicationData
on Linux, and a similarly good location on WIndows; can we use that?
// /home/MyUserName/.local/share/CKAN/downloads
// C:/Users/MyUserName/AppData/Local/CKAN/downloads
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"CKAN", "downloads")
Core/Net/NetFileCache.cs
Outdated
// TODO: Start a new transaction | ||
|
||
// Get a list of all the files in the old cache and move them over | ||
var files = Directory.GetFiles(cachePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe Directory.EnumerateFiles(cachePath, "*")
would be more performant for very large caches, as it does not load the entire list of files into memory all at once but instead loads them one at a time for our code to handle.
Core/Net/NetFileCache.cs
Outdated
/// Moves the old cache folder to a new one. | ||
/// </summary> | ||
/// <param name="newPath">The path to move to.</param> | ||
/// <param name="move"></param> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Description missing
|
||
if (move) | ||
{ | ||
tx_file.Move(file, newFilePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the moment my CKAN cache is on a non-HOME partition and slightly larger than the free space on my HOME partition. This loop could fill my disk; we at least need exception handling, if not explicit space checks.
$ du -h /media/DataTrove/Games/CKAN_downloads ; df -h $HOME
28G /media/DataTrove/Games/CKAN_downloads
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 217G 180G 27G 88% /
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do some research for checking disk space later this week.
Core/Net/NetFileCache.cs
Outdated
foreach (string file in files) | ||
{ | ||
if (tx_file.FileExists(file)) | ||
tx_file.Delete(file); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This loop looks like it should not be here. If move
was true
, then we moved the files and they're no longer there to delete. If move
was false
, then we copied them and presumably want to retain the old copies.
Core/Net/NetFileCache.cs
Outdated
} | ||
|
||
// Append the CKAN folder structure | ||
string directory = Path.Combine(baseDirectory, "CKAN/downloads"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment about letting Path.Combine
handle all path separators.
Path.Combine(baseDirectory, "CKAN", "downloads")
Core/Net/NetFileCache.cs
Outdated
|
||
public NetFileCache(string _cachePath) | ||
public NetFileCache(string _cachePath = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This parameter is still being passed from KSP.cs:61, so this change would not yet have an effect in the full app. The KSP.DownloadCacheDir()
function probably needs to be retired, with some kind of migration process for old downloads.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rewrote the KSP.DownloadCacheDir()
and cache gets moved when new path was specified.
// Check that we have list permission | ||
try | ||
{ | ||
Directory.GetFiles(newPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will load the entire list of files in the target directory into memory, which could be a performance hit if there are already a bunch of files there (e.g., if merging multiple separate instance caches). Is there another check we could do instead? What if we just created the test file?
Core/Net/NetFileCache.cs
Outdated
|
||
foreach (string file in files) | ||
{ | ||
string newFilePath = Path.Combine(newPath, Path.GetFileName(file)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're combining multiple old caches, there's a good chance there will be collisions, as eliminating redundant downloads and disk space is one of the reasons this project was requested. We should check whether newFilePath
already exists and do something intelligent if it does. Maybe print an error, maybe just delete it if we're moving and the file contents are the same.
I made a start on this one, too! I have a CLI Cache command that can probably be converted to work with this. I've opened a PR on your branch with my CLI code. If you want to look at the rest of what I had done (for whatever it is worth), it is here. |
b45b438
to
2339ae9
Compare
Core functions are in place this will mostly be bugfixes now. @politas, I wil add your CLI code later. Same for Test cases if needed. |
I am new to KSP and looked for how to do this, which led me here. I can do testing for you on Mac OS and Windows 10. My Mac kung fu is okay, windows not so much though it is my main KSP machine. |
Thanks that you want to test this out, this needs some testing on Mac OS. Here is a compiled version of |
Issues, yes. I have a Mac Mini (Late 2012) but play on a PC. I installed your ckan.exe and getting it to run involved a little trial and a lot of error. Even with the wiki install-on-a-mac I think someone with purely point-and-click mindset would give up before getting the app running. |
On the plus side, it works great on windows 10 pro. IF you start with clean installs and double check the settings before you start accessing the cache. I started with a test setup that had three installs in various states of mods applied and the results were unpredictable. The first install I tested worked okay fine. Switching to other installs, I could not get them to transition to the one, new cache. My three new installs are working well after adding/removing mods on each many times. I will put more effort into testing on a Mac later. |
ad78bf3
to
5479760
Compare
wtf, how did this happen? I didn't push anything to this branch or repo. Now I lost everything |
Apologies for my previous message, I think that was a copy of my own changes on this topic. Here's what I have of yours: |
If you know the commit IDs, you should be able to cherry pick them from the refs in your local repo. Checkout a new branch from master and cherry pick them all. It's hard to lose stuff, but it's also hard to find stuff sometimes :-/ |
All I have is the exe's you sent me. |
This is what I have - I've reverted the commit of mine you didn't accept and cherry-picked all the commits I had in my local view of your branch https://github.com/politas/CKAN/tree/feature/cache-global That has changes up to Nov 25 |
Ok, got it back to where I had it and triggered it so it to reopen. I don't know why it included the last merged PR but it should be fine. |
The problem with the permissions test is that C# doesn't have octal numeric literals, just hex and decimal. So 0000400 is 400 decimal, etc., and the final EDIT: That also explains why the latest commit passed, btw. 100 | 200 | 400 = 492, not 700, so that substitution changed the value being passed to chmod. |
return KSPPathUtils.NormalizePath( | ||
Path.Combine(CkanDir(), "downloads") | ||
); | ||
var registry = RegistryManager.Instance(this).registry; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This causes all of the instances of the registry to be loaded at start. Since a current registry is 20 MB, this would be quite a delay on systems with many instances. It also causes an unworkaroundable exception if you have an instance with a corrupted registry.json (as I do).
|
||
private const uint S_IRUSR = 0000400; | ||
private const uint S_IWUSR = 0000200; | ||
private const uint S_IXUSR = 0000100; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try Convert.ToUInt32("0400", 8)
, etc. C# doesn't have octal numeric literals.
// If the above didn't work, fall back to "~/.local/" | ||
if (string.IsNullOrWhiteSpace(baseDirectory)) | ||
{ | ||
baseDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".local", "share"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same as SpecialFolder.LocalApplicationData
on Linux as far as I can tell. Opportunity to consolidate with below code here.
|
||
namespace CKAN.CmdLine | ||
{ | ||
public class Cache : ISubCommand |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A new VerbOption
should be added to the Actions
class in Options.cs
to make this new command show up in ckan help
.
This is the beginning of a global cache for downloads. There is a test for read/write access, and an option for moving a cache. Currently, there is no way to go from the local cache in the client into the global cache.
KSP.DownloadCacheDir()
to use new pathSet Cache
commandMove
command to move an old cache to the new oneCloses #584, closes #960