func (svc *DynamoDB) Infof(format string, v ...interface{}) {
	svc.logger.Infof(serviceName, format, v...)
}
========================
misc
========================
Infof logging information.
package dynamodb
import (
	"fmt"
	"sync"
	"github.com/aws/aws-sdk-go/aws/session"
	SDK "github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/evalphobia/aws-sdk-go-wrapper/config"
	"github.com/evalphobia/aws-sdk-go-wrapper/log"
	"github.com/evalphobia/aws-sdk-go-wrapper/private/errors"
	"github.com/evalphobia/aws-sdk-go-wrapper/private/pointers"
)
const (
	serviceName = "DynamoDB"
)
type DynamoDB struct {
	client *SDK.DynamoDB
	logger log.Logger
	prefix string
	tablesMu    sync.RWMutex
	tables      map[string]*Table
	writeTables map[string]struct{}
}
func New(conf config.Config) (*DynamoDB, error) {
	sess, err := conf.Session()
	if err != nil {
		return nil, err
	}
	svc := NewFromSession(sess)
	svc.prefix = conf.DefaultPrefix
	return svc, nil
}
func NewFromSession(sess *session.Session) *DynamoDB {
	return &DynamoDB{
		client:      SDK.New(sess),
		logger:      log.DefaultLogger,
		tables:      make(map[string]*Table),
		writeTables: make(map[string]struct{}),
	}
}
func (svc *DynamoDB) GetClient() *SDK.DynamoDB {
	return svc.client
}
func (svc *DynamoDB) SetLogger(logger log.Logger) {
	svc.logger = logger
}
func (svc *DynamoDB) SetPrefix(prefix string) {
	svc.prefix = prefix
}
func (svc *DynamoDB) CreateTable(design *TableDesign) error {
	if design.HashKey == nil {
		err := fmt.Errorf("error on `CreateTable`; cannot find hashkey in TableDesign;")
		svc.Errorf("%s", err.Error())
		return err
	}
	originalName := design.name
	design.name = svc.prefix + design.name
	in := design.CreateTableInput()
	out, err := svc.client.CreateTable(in)
	if err != nil {
		svc.Errorf("error on `CreateTable` operation; table=%s; error=%s;", design.GetName(), err.Error())
		design.name = originalName
		return err
	}
	design = newTableDesignFromDescription(NewTableDescription(out.TableDescription))
	svc.Infof("success on `CreateTable` operation; table=%s; status=%s;", design.GetName(), design.status)
	return nil
}
func (svc *DynamoDB) ForceDeleteTable(name string) error {
	tableName := svc.prefix + name
	in := &SDK.DeleteTableInput{
		TableName: pointers.String(tableName),
	}
	out, err := svc.client.DeleteTable(in)
	if err != nil {
		svc.Errorf("error on `DeleteTable` operation; table=%s; error=%s;", tableName, err.Error())
		return err
	}
	svc.tablesMu.Lock()
	delete(svc.tables, name)
	svc.tablesMu.Unlock()
	desc := NewTableDescription(out.TableDescription)
	svc.Infof("success on `DeleteTable` operation; table=%s; status=%s;", tableName, desc.TableStatus)
	return nil
}
func (svc *DynamoDB) GetTable(name string) (*Table, error) {
	if tbl := svc.GetCachedTable(name); tbl != nil {
		return tbl, nil
	}
	t, err := NewTable(svc, name)
	if err != nil {
		return nil, err
	}
	tableName := svc.prefix + name
	svc.tablesMu.Lock()
	svc.tables[tableName] = t
	svc.tablesMu.Unlock()
	return t, nil
}
func (svc *DynamoDB) GetCachedTable(name string) *Table {
	tableName := svc.prefix + name
	svc.tablesMu.RLock()
	defer svc.tablesMu.RUnlock()
	return svc.tables[tableName]
}
func (svc *DynamoDB) ListTables() ([]string, error) {
	res, err := svc.client.ListTables(&SDK.ListTablesInput{})
	if err != nil {
		return nil, err
	}
	list := make([]string, len(res.TableNames))
	for i, name := range res.TableNames {
		list[i] = *name
	}
	return list, nil
}
func (svc *DynamoDB) DescribeTable(name string) (TableDescription, error) {
	res, err := svc.client.DescribeTable(&SDK.DescribeTableInput{
		TableName: pointers.String(name),
	})
	switch {
	case err != nil:
		svc.Errorf("error on `DescribeTable` operation; table=%s; error=%s;", name, err.Error())
		return TableDescription{}, err
	case res == nil:
		err := fmt.Errorf("response is nil")
		svc.Errorf("error on `DescribeTable` operation; table=%s; error=%s;", name, err.Error())
		return TableDescription{}, err
	}
	return NewTableDescription(res.Table), nil
}
func (svc *DynamoDB) PutAll() error {
	errList := errors.NewErrors(serviceName)
	for name := range svc.writeTables {
		err := svc.tables[name].Put()
		if err != nil {
			errList.Add(err)
			svc.Errorf("error on `Put` operation; table=%s; error=%s;", name, err.Error())
		}
		svc.removeWriteTable(name)
	}
	if errList.HasError() {
		return errList
	}
	return nil
}
func (svc *DynamoDB) BatchPutAll() error {
	errList := errors.NewErrors(serviceName)
	for name := range svc.writeTables {
		err := svc.tables[name].BatchPut()
		if err != nil {
			errList.Add(err)
			svc.Errorf("error on `BatchPut` operation; table=%s; error=%s;", name, err.Error())
		}
		svc.removeWriteTable(name)
	}
	if errList.HasError() {
		return errList
	}
	return nil
}
func (svc *DynamoDB) addWriteTable(tbl *Table) {
	svc.tablesMu.Lock()
	defer svc.tablesMu.Unlock()
	name := tbl.nameWithPrefix
	svc.writeTables[name] = struct{}{}
	if _, ok := svc.tables[name]; !ok {
		svc.tables[name] = tbl
	}
}
func (svc *DynamoDB) removeWriteTable(name string) {
	svc.tablesMu.Lock()
	defer svc.tablesMu.Unlock()
	delete(svc.writeTables, name)
}
func (svc *DynamoDB) DoQuery(in *SDK.QueryInput) (*QueryResult, error) {
	req, err := svc.client.Query(in)
	if err != nil {
		svc.Errorf("error on `Query` operation; table=%s; error=%s", *in.TableName, err.Error())
		return nil, err
	}
	res := &QueryResult{
		Items:            req.Items,
		LastEvaluatedKey: req.LastEvaluatedKey,
		Count:            *req.Count,
		ScannedCount:     *req.ScannedCount,
	}
	return res, nil
}