-
Notifications
You must be signed in to change notification settings - Fork 257
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor imapsql ExternalStore to use modules
Closes #303
- Loading branch information
Showing
8 changed files
with
255 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
maddy-blob(5) "maddy mail server" "maddy reference documentation" | ||
|
||
; TITLE Message blob storage | ||
|
||
Some IMAP storage backends support pluggable message storage that allows | ||
message contents to be stored separately from IMAP index. | ||
|
||
Modules described in this page are what can be used with such storage backends. | ||
In most cases they have to be specified using the 'msg_store' directive, like | ||
this: | ||
``` | ||
storage.imapsql local_mailboxes { | ||
msg_store fs /var/lib/email | ||
} | ||
``` | ||
|
||
Unless explicitly configured, storage backends with pluggable storage will | ||
store messages in state_dir/messages (e.g. /var/lib/maddy/messages) FS | ||
directory. | ||
|
||
# FS directory storage (storage.blob.fs) | ||
|
||
This module stores message bodies in a file system directory. | ||
|
||
``` | ||
storage.blob.fs { | ||
root <directory> | ||
} | ||
``` | ||
``` | ||
storage.blob.fs <directory> | ||
``` | ||
|
||
## Configuration directives | ||
|
||
*Syntax:* root _path_ ++ | ||
*Default:* not set | ||
|
||
Path to the FS directory. Must be readable and writable by the server process. | ||
If it does not exist - it will be created (parent directory should be writable | ||
for this). Relative paths are interpreted relatively to server state directory. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package module | ||
|
||
import ( | ||
"errors" | ||
"io" | ||
) | ||
|
||
type Blob interface { | ||
Sync() error | ||
io.Reader | ||
io.Writer | ||
io.Closer | ||
} | ||
|
||
var ErrNoSuchBlob = errors.New("blob_store: no such object") | ||
|
||
// BlobStore is the interface used by modules providing large binary object | ||
// storage. | ||
type BlobStore interface { | ||
Create(key string) (Blob, error) | ||
|
||
// Open returns the reader for the object specified by | ||
// passed key. | ||
// | ||
// If no such object exists - ErrNoSuchBlob is returned. | ||
Open(key string) (io.ReadCloser, error) | ||
|
||
// Delete removes a set of keys from store. Non-existent keys are ignored. | ||
Delete(keys []string) error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package fs | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/foxcpp/maddy/framework/config" | ||
"github.com/foxcpp/maddy/framework/module" | ||
) | ||
|
||
// FSStore struct represents directory on FS used to store blobs. | ||
type FSStore struct { | ||
instName string | ||
root string | ||
} | ||
|
||
func New(_, instName string, _, inlineArgs []string) (module.Module, error) { | ||
switch len(inlineArgs) { | ||
case 0: | ||
return &FSStore{instName: instName}, nil | ||
case 1: | ||
return &FSStore{instName: instName, root: inlineArgs[0]}, nil | ||
default: | ||
return nil, fmt.Errorf("storage.blob.fs: 1 or 0 arguments expected") | ||
} | ||
} | ||
|
||
func (s FSStore) Name() string { | ||
return "storage.blob.fs" | ||
} | ||
|
||
func (s FSStore) InstanceName() string { | ||
return s.instName | ||
} | ||
|
||
func (s *FSStore) Init(cfg *config.Map) error { | ||
cfg.String("root", false, false, s.root, &s.root) | ||
if _, err := cfg.Process(); err != nil { | ||
return err | ||
} | ||
|
||
if s.root == "" { | ||
return config.NodeErr(cfg.Block, "storage.blob.fs: directory not set") | ||
} | ||
|
||
if err := os.MkdirAll(s.root, os.ModeDir|os.ModePerm); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (s *FSStore) Open(key string) (io.ReadCloser, error) { | ||
f, err := os.Open(filepath.Join(s.root, key)) | ||
if err != nil { | ||
if os.IsNotExist(err) { | ||
return nil, module.ErrNoSuchBlob | ||
} | ||
return nil, err | ||
} | ||
return f, nil | ||
} | ||
|
||
func (s *FSStore) Create(key string) (module.Blob, error) { | ||
f, err := os.Create(filepath.Join(s.root, key)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return f, nil | ||
} | ||
|
||
func (s *FSStore) Delete(keys []string) error { | ||
for _, key := range keys { | ||
if err := os.Remove(filepath.Join(s.root, key)); err != nil { | ||
if os.IsNotExist(err) { | ||
continue | ||
} | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func init() { | ||
var _ module.BlobStore = &FSStore{} | ||
module.Register(FSStore{}.Name(), New) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package imapsql | ||
|
||
import ( | ||
"io" | ||
|
||
imapsql "github.com/foxcpp/go-imap-sql" | ||
"github.com/foxcpp/maddy/framework/module" | ||
) | ||
|
||
type ExtBlob struct { | ||
io.ReadCloser | ||
} | ||
|
||
func (e ExtBlob) Sync() error { | ||
panic("not implemented") | ||
} | ||
|
||
func (e ExtBlob) Write(p []byte) (n int, err error) { | ||
panic("not implemented") | ||
} | ||
|
||
type ExtBlobStore struct { | ||
base module.BlobStore | ||
} | ||
|
||
func (e ExtBlobStore) Create(key string) (imapsql.ExtStoreObj, error) { | ||
blob, err := e.base.Create(key) | ||
if err != nil { | ||
return nil, imapsql.ExternalError{ | ||
NonExistent: err == module.ErrNoSuchBlob, | ||
Key: key, | ||
Err: err, | ||
} | ||
} | ||
return blob, nil | ||
} | ||
|
||
func (e ExtBlobStore) Open(key string) (imapsql.ExtStoreObj, error) { | ||
blob, err := e.base.Open(key) | ||
if err != nil { | ||
return nil, imapsql.ExternalError{ | ||
NonExistent: err == module.ErrNoSuchBlob, | ||
Key: key, | ||
Err: err, | ||
} | ||
} | ||
return ExtBlob{ReadCloser: blob}, nil | ||
} | ||
|
||
func (e ExtBlobStore) Delete(keys []string) error { | ||
err := e.base.Delete(keys) | ||
if err != nil { | ||
return imapsql.ExternalError{ | ||
Key: "", | ||
Err: err, | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters