reader_mmap.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. //go:build !appengine && !plan9 && !js && !wasip1 && !wasi
  2. // +build !appengine,!plan9,!js,!wasip1,!wasi
  3. package maxminddb
  4. import (
  5. "os"
  6. "runtime"
  7. )
  8. // Open takes a string path to a MaxMind DB file and returns a Reader
  9. // structure or an error. The database file is opened using a memory map
  10. // on supported platforms. On platforms without memory map support, such
  11. // as WebAssembly or Google App Engine, the database is loaded into memory.
  12. // Use the Close method on the Reader object to return the resources to the system.
  13. func Open(file string) (*Reader, error) {
  14. mapFile, err := os.Open(file)
  15. if err != nil {
  16. _ = mapFile.Close()
  17. return nil, err
  18. }
  19. stats, err := mapFile.Stat()
  20. if err != nil {
  21. _ = mapFile.Close()
  22. return nil, err
  23. }
  24. fileSize := int(stats.Size())
  25. mmap, err := mmap(int(mapFile.Fd()), fileSize)
  26. if err != nil {
  27. _ = mapFile.Close()
  28. return nil, err
  29. }
  30. if err := mapFile.Close(); err != nil {
  31. //nolint:errcheck // we prefer to return the original error
  32. munmap(mmap)
  33. return nil, err
  34. }
  35. reader, err := FromBytes(mmap)
  36. if err != nil {
  37. //nolint:errcheck // we prefer to return the original error
  38. munmap(mmap)
  39. return nil, err
  40. }
  41. reader.hasMappedFile = true
  42. runtime.SetFinalizer(reader, (*Reader).Close)
  43. return reader, nil
  44. }
  45. // Close returns the resources used by the database to the system.
  46. func (r *Reader) Close() error {
  47. var err error
  48. if r.hasMappedFile {
  49. runtime.SetFinalizer(r, nil)
  50. r.hasMappedFile = false
  51. err = munmap(r.buffer)
  52. }
  53. r.buffer = nil
  54. return err
  55. }