github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/pkg/executor/wasm/loader.go (about)

     1  package wasm
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/filecoin-project/bacalhau/pkg/model"
    10  	"github.com/filecoin-project/bacalhau/pkg/storage"
    11  	"github.com/rs/zerolog/log"
    12  	"github.com/tetratelabs/wazero"
    13  	"golang.org/x/exp/maps"
    14  )
    15  
    16  func LoadModule(ctx context.Context, runtime wazero.Runtime, path string) (wazero.CompiledModule, error) {
    17  	bytes, err := os.ReadFile(path)
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  
    22  	module, err := runtime.CompileModule(ctx, bytes)
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  
    27  	return module, nil
    28  }
    29  
    30  func LoadRemoteModule(
    31  	ctx context.Context,
    32  	runtime wazero.Runtime,
    33  	provider storage.StorageProvider,
    34  	spec model.StorageSpec,
    35  ) (wazero.CompiledModule, error) {
    36  	volumes, err := storage.ParallelPrepareStorage(ctx, provider, []model.StorageSpec{spec})
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	volume := maps.Values(volumes)[0]
    41  
    42  	programPath := volume.Source
    43  	info, err := os.Stat(programPath)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  
    48  	// We expect the input to be a single WASM file. It is common however for
    49  	// IPFS implementations to wrap files into a directory. So we make a special
    50  	// case here – if the input is a single file in a directory, we will assume
    51  	// this is the program file and load it.
    52  	if info.IsDir() {
    53  		files, err := os.ReadDir(programPath)
    54  		if err != nil {
    55  			return nil, err
    56  		}
    57  
    58  		if len(files) != 1 {
    59  			return nil, fmt.Errorf("should be %d file in %s but there are %d", 1, programPath, len(files))
    60  		}
    61  		programPath = filepath.Join(programPath, files[0].Name())
    62  	}
    63  
    64  	log.Ctx(ctx).Debug().Msgf("Loading WASM module from %q", programPath)
    65  	return LoadModule(ctx, runtime, programPath)
    66  }