1/* 2 * Copyright (c) 2013 IBM Corp. 3 * 4 * All rights reserved. This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License v1.0 6 * which accompanies this distribution, and is available at 7 * http://www.eclipse.org/legal/epl-v10.html 8 * 9 * Contributors: 10 * Seth Hoenig 11 * Allan Stockdill-Mander 12 * Mike Robertson 13 */ 14 15package mqtt 16 17import ( 18 "sync" 19 20 "github.com/eclipse/paho.mqtt.golang/packets" 21) 22 23// MemoryStore implements the store interface to provide a "persistence" 24// mechanism wholly stored in memory. This is only useful for 25// as long as the client instance exists. 26type MemoryStore struct { 27 sync.RWMutex 28 messages map[string]packets.ControlPacket 29 opened bool 30} 31 32// NewMemoryStore returns a pointer to a new instance of 33// MemoryStore, the instance is not initialized and ready to 34// use until Open() has been called on it. 35func NewMemoryStore() *MemoryStore { 36 store := &MemoryStore{ 37 messages: make(map[string]packets.ControlPacket), 38 opened: false, 39 } 40 return store 41} 42 43// Open initializes a MemoryStore instance. 44func (store *MemoryStore) Open() { 45 store.Lock() 46 defer store.Unlock() 47 store.opened = true 48 DEBUG.Println(STR, "memorystore initialized") 49} 50 51// Put takes a key and a pointer to a Message and stores the 52// message. 53func (store *MemoryStore) Put(key string, message packets.ControlPacket) { 54 store.Lock() 55 defer store.Unlock() 56 if !store.opened { 57 ERROR.Println(STR, "Trying to use memory store, but not open") 58 return 59 } 60 store.messages[key] = message 61} 62 63// Get takes a key and looks in the store for a matching Message 64// returning either the Message pointer or nil. 65func (store *MemoryStore) Get(key string) packets.ControlPacket { 66 store.RLock() 67 defer store.RUnlock() 68 if !store.opened { 69 ERROR.Println(STR, "Trying to use memory store, but not open") 70 return nil 71 } 72 mid := mIDFromKey(key) 73 m := store.messages[key] 74 if m == nil { 75 CRITICAL.Println(STR, "memorystore get: message", mid, "not found") 76 } else { 77 DEBUG.Println(STR, "memorystore get: message", mid, "found") 78 } 79 return m 80} 81 82// All returns a slice of strings containing all the keys currently 83// in the MemoryStore. 84func (store *MemoryStore) All() []string { 85 store.RLock() 86 defer store.RUnlock() 87 if !store.opened { 88 ERROR.Println(STR, "Trying to use memory store, but not open") 89 return nil 90 } 91 keys := []string{} 92 for k := range store.messages { 93 keys = append(keys, k) 94 } 95 return keys 96} 97 98// Del takes a key, searches the MemoryStore and if the key is found 99// deletes the Message pointer associated with it. 100func (store *MemoryStore) Del(key string) { 101 store.Lock() 102 defer store.Unlock() 103 if !store.opened { 104 ERROR.Println(STR, "Trying to use memory store, but not open") 105 return 106 } 107 mid := mIDFromKey(key) 108 m := store.messages[key] 109 if m == nil { 110 WARN.Println(STR, "memorystore del: message", mid, "not found") 111 } else { 112 delete(store.messages, key) 113 DEBUG.Println(STR, "memorystore del: message", mid, "was deleted") 114 } 115} 116 117// Close will disallow modifications to the state of the store. 118func (store *MemoryStore) Close() { 119 store.Lock() 120 defer store.Unlock() 121 if !store.opened { 122 ERROR.Println(STR, "Trying to close memory store, but not open") 123 return 124 } 125 store.opened = false 126 DEBUG.Println(STR, "memorystore closed") 127} 128 129// Reset eliminates all persisted message data in the store. 130func (store *MemoryStore) Reset() { 131 store.Lock() 132 defer store.Unlock() 133 if !store.opened { 134 ERROR.Println(STR, "Trying to reset memory store, but not open") 135 } 136 store.messages = make(map[string]packets.ControlPacket) 137 WARN.Println(STR, "memorystore wiped") 138} 139