...

Source file src/github.com/go-kivik/kivik/v4/x/memorydb/memory.go

Documentation: github.com/go-kivik/kivik/v4/x/memorydb

     1  // Licensed under the Apache License, Version 2.0 (the "License"); you may not
     2  // use this file except in compliance with the License. You may obtain a copy of
     3  // the License at
     4  //
     5  //  http://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     9  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    10  // License for the specific language governing permissions and limitations under
    11  // the License.
    12  
    13  package memorydb
    14  
    15  import (
    16  	"context"
    17  	"encoding/json"
    18  	"errors"
    19  	"fmt"
    20  	"net/http"
    21  	"regexp"
    22  	"sync"
    23  
    24  	"github.com/go-kivik/kivik/v4"
    25  	"github.com/go-kivik/kivik/v4/driver"
    26  )
    27  
    28  type memDriver struct{}
    29  
    30  var _ driver.Driver = &memDriver{}
    31  
    32  func init() {
    33  	kivik.Register("memory", &memDriver{})
    34  }
    35  
    36  type client struct {
    37  	version *driver.Version
    38  	mutex   sync.RWMutex
    39  	dbs     map[string]*database
    40  }
    41  
    42  var _ driver.Client = &client{}
    43  
    44  // Identifying constants
    45  const (
    46  	Version = "0.0.1"
    47  	Vendor  = "Kivik Memory Adaptor"
    48  )
    49  
    50  func (d *memDriver) NewClient(string, driver.Options) (driver.Client, error) {
    51  	return &client{
    52  		version: &driver.Version{
    53  			Version:     Version,
    54  			Vendor:      Vendor,
    55  			RawResponse: json.RawMessage(fmt.Sprintf(`{"version":"%s","vendor":{"name":"%s"}}`, Version, Vendor)),
    56  		},
    57  		dbs: make(map[string]*database),
    58  	}, nil
    59  }
    60  
    61  func (c *client) AllDBs(context.Context, driver.Options) ([]string, error) {
    62  	dbs := make([]string, 0, len(c.dbs))
    63  	for k := range c.dbs {
    64  		dbs = append(dbs, k)
    65  	}
    66  	return dbs, nil
    67  }
    68  
    69  func (c *client) DBExists(_ context.Context, dbName string, _ driver.Options) (bool, error) {
    70  	c.mutex.RLock()
    71  	defer c.mutex.RUnlock()
    72  	_, ok := c.dbs[dbName]
    73  	return ok, nil
    74  }
    75  
    76  // Copied verbatim from http://docs.couchdb.org/en/2.0.0/api/database/common.html#head--db
    77  var (
    78  	validDBName = regexp.MustCompile("^[a-z][a-z0-9_$()+/-]*$")
    79  	validNames  = map[string]struct{}{
    80  		"_users":      {},
    81  		"_replicator": {},
    82  	}
    83  )
    84  
    85  func (c *client) CreateDB(ctx context.Context, dbName string, options driver.Options) error {
    86  	if exists, _ := c.DBExists(ctx, dbName, options); exists {
    87  		return statusError{status: http.StatusPreconditionFailed, error: errors.New("database exists")}
    88  	}
    89  	if _, ok := validNames[dbName]; !ok {
    90  		if !validDBName.MatchString(dbName) {
    91  			return statusError{status: http.StatusBadRequest, error: errors.New("invalid database name")}
    92  		}
    93  	}
    94  	c.mutex.Lock()
    95  	defer c.mutex.Unlock()
    96  	c.dbs[dbName] = &database{
    97  		docs:     make(map[string]*document),
    98  		security: &driver.Security{},
    99  	}
   100  	return nil
   101  }
   102  
   103  func (c *client) DestroyDB(ctx context.Context, dbName string, options driver.Options) error {
   104  	if exists, _ := c.DBExists(ctx, dbName, options); !exists {
   105  		return statusError{status: http.StatusNotFound, error: errors.New("database does not exist")}
   106  	}
   107  	c.mutex.Lock()
   108  	defer c.mutex.Unlock()
   109  	c.dbs[dbName].mu.Lock()
   110  	defer c.dbs[dbName].mu.Unlock()
   111  	c.dbs[dbName].deleted = true // To invalidate any outstanding db handles
   112  	delete(c.dbs, dbName)
   113  	return nil
   114  }
   115  
   116  func (c *client) DB(dbName string, _ driver.Options) (driver.DB, error) {
   117  	return &db{
   118  		client: c,
   119  		dbName: dbName,
   120  		db:     c.dbs[dbName],
   121  	}, nil
   122  }
   123  
   124  // Version returns the configured server info.
   125  func (c *client) Version(_ context.Context) (*driver.Version, error) {
   126  	return c.version, nil
   127  }
   128  

View as plain text