git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/mmdb/reader_mmap.go (about)

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