fixes for user indexes

tests pending
This commit is contained in:
Radu Ioan Fericean
2015-07-13 17:30:49 +03:00
parent 7b1b8cac63
commit 3b14b399cb
5 changed files with 137 additions and 52 deletions

View File

@@ -82,6 +82,8 @@ func executeCommand(command string) {
switch param.(type) {
case *console.StringWrapper:
param = param.(*console.StringWrapper).Item
case *console.StringSliceWrapper:
param = param.(*console.StringSliceWrapper).Items
}
//log.Printf("Param: %+v", param)

View File

@@ -58,6 +58,6 @@ func (self *CmdUserShowIndexes) PostprocessRpcParams() error {
}
func (self *CmdUserShowIndexes) RpcResult() interface{} {
s := []string{}
s := map[string][]string{}
return &s
}

View File

@@ -1,6 +1,7 @@
package engine
import (
"log"
"strings"
"github.com/cgrates/cgrates/utils"
@@ -33,13 +34,14 @@ type UserService interface {
UpdateUser(UserProfile, *string) error
GetUsers(UserProfile, *[]*UserProfile) error
AddIndex([]string, *string) error
GetIndexes(string, *[]string) error
GetIndexes(string, *map[string][]string) error
}
type UserMap struct {
table map[string]map[string]string
index map[string][]string
ratingDb RatingStorage
table map[string]map[string]string
index map[string]map[string]bool
indexKeys []string
ratingDb RatingStorage
}
func NewUserMap(ratingDb RatingStorage) (*UserMap, error) {
@@ -58,27 +60,29 @@ func NewUserMap(ratingDb RatingStorage) (*UserMap, error) {
func newUserMap(ratingDb RatingStorage) *UserMap {
return &UserMap{
table: make(map[string]map[string]string),
index: make(map[string][]string),
index: make(map[string]map[string]bool),
ratingDb: ratingDb,
}
}
func (um *UserMap) SetUser(up UserProfile, reply *string) error {
um.table[up.GetId()] = up.Profile
if err := um.ratingDb.SetUser(&up); err != nil {
*reply = err.Error()
return err
}
um.table[up.GetId()] = up.Profile
um.addIndex(&up)
*reply = utils.OK
return nil
}
func (um *UserMap) RemoveUser(up UserProfile, reply *string) error {
delete(um.table, up.GetId())
if err := um.ratingDb.RemoveUser(up.GetId()); err != nil {
*reply = err.Error()
return err
}
delete(um.table, up.GetId())
um.deleteIndex(&up)
*reply = utils.OK
return nil
}
@@ -90,20 +94,32 @@ func (um *UserMap) UpdateUser(up UserProfile, reply *string) error {
return utils.ErrNotFound
}
if m == nil {
um.table[up.GetId()] = make(map[string]string, 0)
m = make(map[string]string)
}
oldM := make(map[string]string, len(m))
for k, v := range m {
oldM[k] = v
}
oldUp := &UserProfile{
Tenant: up.Tenant,
UserName: up.UserName,
Profile: oldM,
}
for key, value := range up.Profile {
um.table[up.GetId()][key] = value
m[key] = value
}
finalUp := &UserProfile{
Tenant: up.Tenant,
UserName: up.UserName,
Profile: um.table[up.GetId()],
Profile: m,
}
if err := um.ratingDb.SetUser(finalUp); err != nil {
*reply = err.Error()
return err
}
um.table[up.GetId()] = m
um.deleteIndex(oldUp)
um.addIndex(finalUp)
*reply = utils.OK
return nil
}
@@ -115,21 +131,21 @@ func (um *UserMap) GetUsers(up UserProfile, results *[]*UserProfile) error {
// search index
if up.Tenant != "" {
if keys, found := um.index[utils.ConcatenatedKey("Tenant", up.Tenant)]; found {
for _, key := range keys {
for key := range keys {
indexUnionKeys[key] = true
}
}
}
if up.UserName != "" {
if keys, found := um.index[utils.ConcatenatedKey("UserName", up.UserName)]; found {
for _, key := range keys {
for key := range keys {
indexUnionKeys[key] = true
}
}
}
for k, v := range up.Profile {
if keys, found := um.index[utils.ConcatenatedKey(k, v)]; found {
for _, key := range keys {
for key := range keys {
indexUnionKeys[key] = true
}
}
@@ -172,38 +188,97 @@ func (um *UserMap) GetUsers(up UserProfile, results *[]*UserProfile) error {
}
func (um *UserMap) AddIndex(indexes []string, reply *string) error {
um.indexKeys = indexes
for key, values := range um.table {
ud := &UserProfile{Profile: values}
ud.SetId(key)
for _, index := range indexes {
if index == "Tenant" {
if ud.Tenant != "" {
um.index[utils.ConcatenatedKey(index, ud.Tenant)] = append(um.index[utils.ConcatenatedKey(index, ud.Tenant)], key)
}
continue
}
if index == "UserName" {
if ud.UserName != "" {
um.index[utils.ConcatenatedKey(index, ud.UserName)] = append(um.index[utils.ConcatenatedKey(index, ud.UserName)], key)
}
continue
}
for k, v := range ud.Profile {
if k == index && v != "" {
um.index[utils.ConcatenatedKey(k, v)] = append(um.index[utils.ConcatenatedKey(k, v)], key)
}
}
}
up := &UserProfile{Profile: values}
up.SetId(key)
um.addIndex(up)
}
*reply = utils.OK
return nil
}
func (um *UserMap) GetIndexes(in string, reply *[]string) error {
var indexes []string
for key := range um.index {
indexes = append(indexes, key)
func (um *UserMap) addIndex(up *UserProfile) {
key := up.GetId()
for _, index := range um.indexKeys {
if index == "Tenant" {
if up.Tenant != "" {
indexKey := utils.ConcatenatedKey(index, up.Tenant)
if um.index[indexKey] == nil {
um.index[indexKey] = make(map[string]bool)
}
um.index[indexKey][key] = true
}
continue
}
if index == "UserName" {
if up.UserName != "" {
indexKey := utils.ConcatenatedKey(index, up.UserName)
if um.index[indexKey] == nil {
um.index[indexKey] = make(map[string]bool)
}
um.index[indexKey][key] = true
}
continue
}
for k, v := range up.Profile {
if k == index && v != "" {
indexKey := utils.ConcatenatedKey(k, v)
if um.index[indexKey] == nil {
um.index[indexKey] = make(map[string]bool)
}
um.index[indexKey][key] = true
}
}
}
}
func (um *UserMap) deleteIndex(up *UserProfile) {
log.Printf("Delete index: %s: %v", up.GetId(), up.Profile)
key := up.GetId()
for _, index := range um.indexKeys {
if index == "Tenant" {
if up.Tenant != "" {
indexKey := utils.ConcatenatedKey(index, up.Tenant)
delete(um.index[indexKey], key)
if len(um.index[indexKey]) == 0 {
delete(um.index, indexKey)
}
}
continue
}
if index == "UserName" {
if up.UserName != "" {
indexKey := utils.ConcatenatedKey(index, up.UserName)
delete(um.index[indexKey], key)
if len(um.index[indexKey]) == 0 {
delete(um.index, indexKey)
}
}
continue
}
for k, v := range up.Profile {
if k == index && v != "" {
indexKey := utils.ConcatenatedKey(k, v)
delete(um.index[indexKey], key)
if len(um.index[indexKey]) == 0 {
delete(um.index, indexKey)
}
}
}
}
}
func (um *UserMap) GetIndexes(in string, reply *map[string][]string) error {
indexes := make(map[string][]string)
for key, values := range um.index {
var vs []string
for val := range values {
vs = append(vs, val)
}
indexes[key] = vs
}
*reply = indexes
return nil
@@ -243,6 +318,6 @@ func (ps *ProxyUserService) AddIndex(indexes []string, reply *string) error {
return ps.Client.Call("UsersV1.AddIndex", indexes, reply)
}
func (ps *ProxyUserService) GetIndexes(in string, reply *[]string) error {
func (ps *ProxyUserService) GetIndexes(in string, reply *map[string][]string) error {
return ps.Client.Call("UsersV1.AddIndex", in, reply)
}

View File

@@ -13,7 +13,7 @@ var testMap = UserMap{
"test:": map[string]string{"t": "v"},
"test1:user1": map[string]string{"t": "v", "x": "y"},
},
index: make(map[string][]string),
index: make(map[string]map[string]bool),
}
func TestUsersAdd(t *testing.T) {
@@ -267,7 +267,7 @@ func TestUsersAddIndex(t *testing.T) {
func TestUsersAddIndexFull(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
if r != utils.OK ||
len(testMap.index) != 6 ||
@@ -278,7 +278,7 @@ func TestUsersAddIndexFull(t *testing.T) {
func TestUsersAddIndexNone(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"test"}, &r)
if r != utils.OK ||
len(testMap.index) != 0 {
@@ -288,7 +288,7 @@ func TestUsersAddIndexNone(t *testing.T) {
func TestUsersGetFullindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Tenant: "test",
@@ -306,7 +306,7 @@ func TestUsersGetFullindex(t *testing.T) {
func TestUsersGetTenantindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Tenant: "testX",
@@ -324,7 +324,7 @@ func TestUsersGetTenantindex(t *testing.T) {
func TestUsersGetUserNameindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Tenant: "test",
@@ -342,7 +342,7 @@ func TestUsersGetUserNameindex(t *testing.T) {
func TestUsersGetNotFoundProfileindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Tenant: "test",
@@ -360,7 +360,7 @@ func TestUsersGetNotFoundProfileindex(t *testing.T) {
func TestUsersGetMissingTenantindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
UserName: "user",
@@ -377,7 +377,7 @@ func TestUsersGetMissingTenantindex(t *testing.T) {
func TestUsersGetMissingUserNameindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Tenant: "test",
@@ -394,7 +394,7 @@ func TestUsersGetMissingUserNameindex(t *testing.T) {
func TestUsersGetMissingIdindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Profile: map[string]string{
@@ -410,7 +410,7 @@ func TestUsersGetMissingIdindex(t *testing.T) {
func TestUsersGetMissingIdTwoINdex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Profile: map[string]string{

View File

@@ -32,6 +32,14 @@ func IsSliceMember(ss []string, s string) bool {
return false
}
func SliceWithoutMember(ss []string, s string) []string {
sort.Strings(ss)
if i := sort.SearchStrings(ss, s); i < len(ss) && ss[i] == s {
ss[i], ss = ss[len(ss)-1], ss[:len(ss)-1]
}
return ss
}
//Iterates over slice members and returns true if one starts with prefix
func SliceMemberHasPrefix(ss []string, prfx string) bool {
for _, mbr := range ss {