How to close graphhopper

Hello!

I have a situation, where I have to delete graphHopper’s files.
The problem is:

I get IOException at some devices, because graphHopper is using “edges” and it can’t be deleted.

Question is:

How to close graphHopper after:
graphHopper.load(new File(mapFolder , currentArea).getAbsolutePath());

I tried with graphHopper.close(); and graphHopper.clean(); but it does’nt help.

On which operating system are you on and which GH version are you using?

Normally graphHopper.close should release all resources and give also access of the underlying files back to the OS. The problem might be that e.g. if you are using Android the memory mapping is on per default and releasing resources cannot be forced, one can give the OS only a hint and hope the best when using Java APIs only :confused:

Can you try the following:

 graphHopper.close()
 for loop from 1 to 10 {
    System.gc()
    sleep 1 second
    try {
       graphHopper.clean()
       break
    } catch(IOException ex) {
       continue 
    }
  }

Also some kind of a native cleanup (which requires changes to GH itself) could help, not sure.

Oh, sorry.
I am using graphhopper 0.6 on Android.
Well, thank you for quick response and advice.
The problem is that I have to periodically update graphHopper’s files on the device. When update is ready, user can see specifical button on the screen.
But graphHopper already could be loaded here (user used some routes and came back on activity from stack).
So, I think that the best way is here - hide update button if gh was loaded, because we really can’t release resources (tried your advice).
What is your opinion in this case?

1 Like

Thanks for describing your use case. That is indeed ugly and we have to fix it somehow or at least try to find a good solution.

What if you download the update to a new folder, then close the old GraphHopper instance and create a new one pointing to a different folder?

And a new start of your application could then remove the old, now no longer used folder. To avoid the restart you could try to remove the old folder after you have loaded the new GraphHopper instance as the garbage collector could be forced to clean up a bit more.

Good option, but more expensive on storage memory.
I use at least 12 different folders for graphHopper in application (depends on city).
User can download all of them.
And update is coming at the same time for all of them. That’s why I can’t afford it.
But it’s not a big deal, I’m more inclined to hide this update button, if user ignored it at 1st time.

Okay. Would you please create an issue referencing this discussion? At some point we would need to find a solution for this.

I guess you offer also to switch between cities at runtime - is this working properly via close?

Yes, user can switch between cities, in this case new graphHopper object will be initialized.

After that, user can delete previous city’s folder without problem, even without graphHopper.close(); :worried:

Thanks, this is good to know! And it indicates that if you force the garbage collector to do his work it will release the file resources. Maybe you can try to allocate some memory in the loop to force the GC without duplicating storage?

 graphHopper.close()
 for loop from 1 to 10 {
    temp_store = new int[5 * 1024 * 1024]
    // or instead temporarily load a different city here?
    System.gc()
    sleep 1 second
    try {
       graphHopper.clean()
       break
    } catch(IOException ex) {
       continue 
    }
  }

I posted an issue here
About waiting for allocation - I don’t want make users wait till memory allocation ends. :pensive:

1 Like

I meant: if the graphhopper.load succeed then you can delete the old folder afterwards, right? So why not load city B if you need to delete folder of city A? (memory mapping should be relative cheap)

This looks like a really good idea:

  1. User downloads new graphHopper’s files into a new folder.
  2. After that:

graphHopper = new GraphHopper().forMobile();
graphHopper.setCHEnable(false);
graphHopper.load(new File(mapFolder , currentArea).getAbsolutePath()); //new folder

  1. Then we can try to delete old files.

Did I understand you correctly?

Yes. (Maybe it is more secure to do this in a loop)

But you said you cannot effort the extra disc space? And to avoid the extra disc space you could try to load a different city B first, remove the old city A, download city A and do graphhopper.load city A and then throw away graphhHopper with city B.

1 Like

I got it, but we can’t avoid creating new folder in situation when user updates only one city.

If you have other cities ‘laying around’ that you can load then you could try to avoid even this.

Yes, in this case I can do it.:slight_smile:
To be honest, I think that 95% of users will use only one city.
And I really started to think about your advice in creating new folder for update in this situation.
Or rename old gh files (if I can), download new files, initialize new graphHopper object and remove old files.

When you say this: I really wonder why removing is not possible under linux/Android. What is the exact error that you are getting when trying this?

I tried at 5 devices and 2 of them throws

java.io.IOException: EBUSY (Device or resource busy)

Sorry, I can’t get full trace right now. But I remember the reference on “edges”, which as we know is using by graphHopper.
Three other devices made it without exception.
I think, this could be because of different OS version or smth like that.

1 Like

Following steps helped me with my problem

  1. Download .zip with new graphHopper files;
  2. Rename all current files (edges -> edges_old, nodes -> nodes_old etc);
  3. Unzip downloaded folder with new files;
  4. Initialize graphHopper with new files;
  5. Delete all “old” files.

:slight_smile:

1 Like

Interesting that you can rename but not delete them - thanks for sharing!

1 Like

I agree, but it works…
Thanks for help!