Skip to content

Commit 797e14b

Browse files
committed
Go 1.8 Plug-in Support
This patch introduces support for loading Linux shared object (.so) files as Go 1.8 plug-ins. This feature requires Linux.
1 parent b79ec99 commit 797e14b

6 files changed

Lines changed: 94 additions & 2 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ GO_STDLIB := archive archive/tar archive/zip bufio builtin bytes compress \
305305
runtime/trace sort strconv strings sync sync/atomic syscall \
306306
testing testing/iotest testing/quick text text/scanner \
307307
text/tabwriter text/template text/template/parse time unicode \
308-
unicode/utf16 unicode/utf8 unsafe
308+
unicode/utf16 unicode/utf8 unsafe context plugin
309309

310310

311311
################################################################################

api/mods/mods.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// +build go1.8,linux
2+
3+
package mods
4+
5+
import (
6+
"io/ioutil"
7+
"plugin"
8+
"strings"
9+
"sync"
10+
11+
"github.com/akutz/gotil"
12+
13+
"github.com/codedellemc/libstorage/api/types"
14+
)
15+
16+
var (
17+
loadedMods = map[string]bool{}
18+
loadedModsLock = sync.Mutex{}
19+
)
20+
21+
// LoadModules loads the shared objects present on the file system
22+
// as libStorage plug-ins.
23+
func LoadModules(
24+
ctx types.Context,
25+
pathConfig *types.PathConfig) {
26+
27+
loadedModsLock.Lock()
28+
defer loadedModsLock.Unlock()
29+
30+
if !gotil.FileExists(pathConfig.Mod) {
31+
return
32+
}
33+
modFiles, err := ioutil.ReadDir(pathConfig.Mod)
34+
if err != nil {
35+
ctx.WithField("path", pathConfig.Mod).Warn(
36+
"failed to list module files")
37+
return
38+
}
39+
for _, f := range modFiles {
40+
modFilePath := f.Name()
41+
ctx.WithField(
42+
"path", modFilePath).Debug(
43+
"loading module")
44+
lcModFilePath := strings.ToLower(modFilePath)
45+
if loaded, ok := loadedMods[lcModFilePath]; ok && loaded {
46+
ctx.WithField(
47+
"path", modFilePath).Debug(
48+
"already loaded")
49+
continue
50+
}
51+
_, err := plugin.Open(modFilePath)
52+
if err != nil {
53+
ctx.WithError(err).WithField(
54+
"path", modFilePath).Error(
55+
"error opening module")
56+
continue
57+
}
58+
loadedMods[lcModFilePath] = true
59+
ctx.WithField(
60+
"path", modFilePath).Info(
61+
"loaded module")
62+
}
63+
}

api/mods/nomods.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// +build !go1.8 !linux
2+
3+
package mods
4+
5+
import (
6+
"github.com/codedellemc/libstorage/api/types"
7+
)
8+
9+
// LoadModules loads the shared objects present on the file system
10+
// as libStorage plug-ins.
11+
func LoadModules(
12+
ctx types.Context,
13+
pathConfig *types.PathConfig) {
14+
15+
// NOOP
16+
}

api/types/types_paths.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ type PathConfig struct {
1818
// Log is the path to the log directory.
1919
Log string
2020

21+
// Mod is the path to the mod directory.
22+
Mod string
23+
2124
// Run is the path to the run directory.
2225
Run string
2326

api/utils/utils_paths.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ func NewPathConfig(ctx types.Context, home, token string) *types.PathConfig {
3636
envVarHomeEtc = fmt.Sprintf("%s_HOME_ETC", ucTok)
3737
envVarHomeEtcTLS = fmt.Sprintf("%s_HOME_ETC_TLS", ucTok)
3838
envVarHomeLib = fmt.Sprintf("%s_HOME_LIB", ucTok)
39+
envVarHomeLibMod = fmt.Sprintf("%s_HOME_LIB_MOD", ucTok)
3940
envVarHomeLog = fmt.Sprintf("%s_HOME_LOG", ucTok)
4041
envVarHomeRun = fmt.Sprintf("%s_HOME_RUN", ucTok)
4142
envVarHomeLSX = fmt.Sprintf("%s_HOME_LSX", ucTok)
@@ -57,6 +58,7 @@ func NewPathConfig(ctx types.Context, home, token string) *types.PathConfig {
5758
initPathConfigFieldWithEnvVar(ctx, envVarHomeEtc, &pathConfig.Etc)
5859
initPathConfigFieldWithEnvVar(ctx, envVarHomeEtcTLS, &pathConfig.TLS)
5960
initPathConfigFieldWithEnvVar(ctx, envVarHomeLib, &pathConfig.Lib)
61+
initPathConfigFieldWithEnvVar(ctx, envVarHomeLibMod, &pathConfig.Mod)
6062
initPathConfigFieldWithEnvVar(ctx, envVarHomeLog, &pathConfig.Log)
6163
initPathConfigFieldWithEnvVar(ctx, envVarHomeRun, &pathConfig.Run)
6264
initPathConfigFieldWithEnvVar(ctx, envVarHomeLSX, &pathConfig.LSX)
@@ -84,6 +86,8 @@ func NewPathConfig(ctx types.Context, home, token string) *types.PathConfig {
8486
ctx, false, true, token, pathConfig.Etc, "tls", &pathConfig.TLS)
8587
initPathConfigFieldWithPath(
8688
ctx, root, true, token, pathConfig.Home, "var/lib", &pathConfig.Lib)
89+
initPathConfigFieldWithPath(
90+
ctx, false, true, token, pathConfig.Lib, "mod", &pathConfig.Mod)
8791
initPathConfigFieldWithPath(
8892
ctx, root, true, token, pathConfig.Home, "var/log", &pathConfig.Log)
8993
initPathConfigFieldWithPath(

cli/lsx/lsx.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/akutz/goof"
1515

1616
"github.com/codedellemc/libstorage/api/context"
17+
apimods "github.com/codedellemc/libstorage/api/mods"
1718
"github.com/codedellemc/libstorage/api/registry"
1819
apitypes "github.com/codedellemc/libstorage/api/types"
1920
"github.com/codedellemc/libstorage/api/utils"
@@ -31,7 +32,12 @@ var cmdRx = regexp.MustCompile(
3132
func Run() {
3233

3334
ctx := context.Background()
34-
ctx = ctx.WithValue(context.PathConfigKey, utils.NewPathConfig(ctx, "", ""))
35+
pathConfig := utils.NewPathConfig(ctx, "", "")
36+
ctx = ctx.WithValue(context.PathConfigKey, pathConfig)
37+
38+
// load shared objects
39+
apimods.LoadModules(ctx, pathConfig)
40+
3541
registry.ProcessRegisteredConfigs(ctx)
3642

3743
args := os.Args

0 commit comments

Comments
 (0)