/
memscaffold.go
129 lines (100 loc) · 2.96 KB
/
memscaffold.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package gowork
import (
"reflect"
"sync"
"fmt"
"time"
"log"
)
type MemTable struct {
Table map[string]interface{}
mutex *sync.Mutex
Debug bool
}
// Create makes a new table entry with the provided id. An error is never returned from this function and is intended for use in overriding functions.
func (mt *MemTable) Create(id string, o interface{}) error {
mt.mutex.Lock()
defer mt.mutex.Unlock()
if mt.Debug {
log.Printf("%s: %s; %v\n", CurrentFunctionName(4), id, o)
}
//dereference underlying entity and store a copy as we don't want it being changed behind our back.
v := reflect.Indirect(reflect.ValueOf(o))
mt.Table[id] = v.Interface()
return nil
}
func (mt *MemTable) Get(id string) (interface{}, error) {
mt.mutex.Lock()
defer mt.mutex.Unlock()
if mt.Debug {
log.Printf("%s: %v\n", CurrentFunctionName(4), id)
}
r, e := mt.Table[id]
if !e {
return nil, NewNotFoundError()
}
return r, nil
}
func (mt *MemTable) Update(id string, o interface{}) error {
mt.mutex.Lock()
defer mt.mutex.Unlock()
if mt.Debug {
log.Printf("%s: %v; %v\n", CurrentFunctionName(4), id, o)
}
if _, e := mt.Table[id]; !e {
return NewNotFoundError()
}
//dereference underlying entity and store a copy as we don't want it being changed behind our back.
v := reflect.Indirect(reflect.ValueOf(o))
mt.Table[id] = v.Interface()
return nil
}
//TODO:Stan date is a project specific item. Should really move it out of here and into the various other projects.
func (mt *MemTable) GetAll(date time.Time, limit int, entity interface{}) (interface{}, error) {
mt.mutex.Lock()
defer mt.mutex.Unlock()
if mt.Debug {
log.Printf("%s: time: %s, limit: %d\n", CurrentFunctionName(4), date, limit)
}
//Create slice
ev := reflect.Indirect(reflect.ValueOf(entity))
slice := reflect.MakeSlice(reflect.SliceOf(ev.Type()), 0, len(mt.Table))
//Create pointer to slice
x := reflect.New(slice.Type())
x.Elem().Set(slice)
i := 0
for _, v := range mt.Table {
value := reflect.Indirect(reflect.ValueOf(v))
if !date.IsZero() {
//Create ptr to value as all stored entities should be values not ptrs. If they weren't we made them values with reflect.Indirect above.
ptr := reflect.New(reflect.TypeOf(v))
temp := ptr.Elem()
temp.Set(value)
dv := temp.Addr().MethodByName("Date") //TODO:Stan Date still leaks the cassandra partition information in. Look at resolving this when I have nothing better to do.
if dv.IsValid() {
fn := dv.Call([]reflect.Value{})
t := fn[0].Interface().(time.Time)
if !t.Equal(date) {
continue
}
}
}
x.Elem().SetLen(i + 1)
x.Elem().Index(i).Set(value)
i++
}
return x.Elem().Interface(), nil
}
func (mt *MemTable) All() interface{} {
mt.mutex.Lock()
defer mt.mutex.Unlock()
return StringMapToSlice(mt.Table)
}
func (mt MemTable) Dump() {
for k, v := range mt.Table {
fmt.Printf("\n%s: %v\n", k, v)
}
}
func NewMemTable() *MemTable {
return &MemTable{Table: make(map[string]interface{}), mutex: &sync.Mutex{}}
}