1
0
mirror of https://github.com/kataras/iris.git synced 2026-01-04 02:37:14 +00:00

Update to 8.2.0 | BoltDB session database, fix file sessiondb, faster, simpler and improvement Session Database API

Former-commit-id: 4034737a65b78a77277e4283fd9289c17f4a452e
This commit is contained in:
kataras
2017-08-07 06:04:35 +03:00
parent 36e6fb37b8
commit 48e352e1df
24 changed files with 1128 additions and 430 deletions

68
core/memstore/gob.go Normal file
View File

@@ -0,0 +1,68 @@
package memstore
import (
"bytes"
"encoding/gob"
"io"
"time"
)
// why?
// on the future we may change how these encoders/decoders
// and we may need different method for store and other for entry.
func init() {
gob.Register(Store{})
gob.Register(Entry{})
gob.Register(time.Time{})
}
// GobEncode accepts a store and writes
// as series of bytes to the "w" writer.
func GobEncode(store Store, w io.Writer) error {
enc := gob.NewEncoder(w)
err := enc.Encode(store)
return err
}
// GobSerialize same as GobEncode but it returns
// the bytes using a temp buffer.
func GobSerialize(store Store) ([]byte, error) {
w := new(bytes.Buffer)
err := GobEncode(store, w)
return w.Bytes(), err
}
// GobEncodeEntry accepts an entry and writes
// as series of bytes to the "w" writer.
func GobEncodeEntry(entry Entry, w io.Writer) error {
enc := gob.NewEncoder(w)
err := enc.Encode(entry)
return err
}
// GobSerializeEntry same as GobEncodeEntry but it returns
// the bytes using a temp buffer.
func GobSerializeEntry(entry Entry) ([]byte, error) {
w := new(bytes.Buffer)
err := GobEncodeEntry(entry, w)
return w.Bytes(), err
}
// GobDecode accepts a series of bytes and returns
// the store.
func GobDecode(b []byte) (store Store, err error) {
dec := gob.NewDecoder(bytes.NewBuffer(b))
// no reference because of:
// gob: decoding into local type *memstore.Store, received remote type Entry
err = dec.Decode(&store)
return
}
// GobDecodeEntry accepts a series of bytes and returns
// the entry.
func GobDecodeEntry(b []byte) (entry Entry, err error) {
dec := gob.NewDecoder(bytes.NewBuffer(b))
err = dec.Decode(&entry)
return
}

View File

@@ -16,7 +16,7 @@ type (
// Entry is the entry of the context storage Store - .Values()
Entry struct {
Key string
value interface{}
ValueRaw interface{}
immutable bool // if true then it can't change by its caller.
}
@@ -29,7 +29,7 @@ type (
func (e Entry) Value() interface{} {
if e.immutable {
// take its value, no pointer even if setted with a rreference.
vv := reflect.Indirect(reflect.ValueOf(e.value))
vv := reflect.Indirect(reflect.ValueOf(e.ValueRaw))
// return copy of that slice
if vv.Type().Kind() == reflect.Slice {
@@ -48,18 +48,16 @@ func (e Entry) Value() interface{} {
// if was *value it will return value{}.
return vv.Interface()
}
return e.value
return e.ValueRaw
}
// the id is immutable(true or false)+key
// so the users will be able to use the same key
// to store two different entries (one immutable and other mutable).
// or no? better no, that will confuse and maybe result on unexpected results.
// I will just replace the value and the immutable bool value when Set if
// a key is already exists.
// func (e Entry) identifier() string {}
func (r *Store) save(key string, value interface{}, immutable bool) {
// Save same as `Set`
// However, if "immutable" is true then saves it as immutable (same as `SetImmutable`).
//
//
// Returns the entry and true if it was just inserted, meaning that
// it will return the entry and a false boolean if the entry exists and it has been updated.
func (r *Store) Save(key string, value interface{}, immutable bool) (Entry, bool) {
args := *r
n := len(args)
@@ -71,15 +69,15 @@ func (r *Store) save(key string, value interface{}, immutable bool) {
// if called by `SetImmutable`
// then allow the update, maybe it's a slice that user wants to update by SetImmutable method,
// we should allow this
kv.value = value
kv.ValueRaw = value
kv.immutable = immutable
} else if kv.immutable == false {
// if it was not immutable then user can alt it via `Set` and `SetImmutable`
kv.value = value
kv.ValueRaw = value
kv.immutable = immutable
}
// else it was immutable and called by `Set` then disallow the update
return
return *kv, false
}
}
@@ -89,25 +87,29 @@ func (r *Store) save(key string, value interface{}, immutable bool) {
args = args[:n+1]
kv := &args[n]
kv.Key = key
kv.value = value
kv.ValueRaw = value
kv.immutable = immutable
*r = args
return
return *kv, true
}
// add
kv := Entry{
Key: key,
value: value,
ValueRaw: value,
immutable: immutable,
}
*r = append(args, kv)
return kv, true
}
// Set saves a value to the key-value storage.
// Returns the entry and true if it was just inserted, meaning that
// it will return the entry and a false boolean if the entry exists and it has been updated.
//
// See `SetImmutable` and `Get`.
func (r *Store) Set(key string, value interface{}) {
r.save(key, value, false)
func (r *Store) Set(key string, value interface{}) (Entry, bool) {
return r.Save(key, value, false)
}
// SetImmutable saves a value to the key-value storage.
@@ -116,10 +118,13 @@ func (r *Store) Set(key string, value interface{}) {
// An Immutable entry should be only changed with a `SetImmutable`, simple `Set` will not work
// if the entry was immutable, for your own safety.
//
// Returns the entry and true if it was just inserted, meaning that
// it will return the entry and a false boolean if the entry exists and it has been updated.
//
// Use it consistently, it's far slower than `Set`.
// Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081
func (r *Store) SetImmutable(key string, value interface{}) {
r.save(key, value, true)
func (r *Store) SetImmutable(key string, value interface{}) (Entry, bool) {
return r.Save(key, value, true)
}
// Get returns the entry's value based on its key.
@@ -205,3 +210,9 @@ func (r *Store) Len() int {
args := *r
return len(args)
}
// Serialize returns the byte representation of the current Store.
func (r Store) Serialize() []byte { // note: no pointer here, ignore linters if shows up.
b, _ := GobSerialize(r)
return b
}

View File

@@ -487,6 +487,7 @@ func (rb *APIBuilder) StaticServe(systemPath string, requestPath ...string) *Rou
}
if err := ctx.ServeFile(spath, true); err != nil {
ctx.Application().Logger().Warnf("while trying to serve static file: '%v' on IP: '%s'", err, ctx.RemoteAddr())
ctx.StatusCode(http.StatusInternalServerError)
}
})