2015-06-21 23:42:29 -07:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
/* Copyright (c) FIRST 2015. All Rights Reserved. */
|
|
|
|
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
|
|
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
|
|
|
/* the project. */
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#ifndef NT_STORAGE_H_
|
|
|
|
|
#define NT_STORAGE_H_
|
|
|
|
|
|
2015-07-19 16:02:21 -07:00
|
|
|
#include <atomic>
|
2015-06-27 10:22:59 -07:00
|
|
|
#include <cstddef>
|
2015-07-17 07:21:07 -07:00
|
|
|
#include <functional>
|
2015-07-14 23:15:08 -07:00
|
|
|
#include <iosfwd>
|
|
|
|
|
#include <memory>
|
2015-07-18 01:29:51 -07:00
|
|
|
#include <mutex>
|
2015-06-27 10:22:59 -07:00
|
|
|
|
2015-06-21 23:42:29 -07:00
|
|
|
#include "llvm/StringMap.h"
|
2015-07-20 23:36:22 -07:00
|
|
|
#include "atomic_static.h"
|
2015-07-29 23:45:04 -07:00
|
|
|
#include "Message.h"
|
2015-07-18 01:29:51 -07:00
|
|
|
#include "ntcore_cpp.h"
|
2015-07-17 23:41:25 -07:00
|
|
|
#include "SequenceNumber.h"
|
2015-06-21 23:42:29 -07:00
|
|
|
|
2015-07-17 07:21:07 -07:00
|
|
|
namespace nt {
|
2015-06-21 23:42:29 -07:00
|
|
|
|
2015-07-29 23:45:04 -07:00
|
|
|
class NetworkConnection;
|
2015-07-19 16:36:30 -07:00
|
|
|
class StorageTest;
|
|
|
|
|
|
2015-06-25 22:57:43 -07:00
|
|
|
class StorageEntry {
|
|
|
|
|
public:
|
2015-07-26 10:28:20 -07:00
|
|
|
StorageEntry(llvm::StringRef name) : m_name(name), m_id(0xffff) {
|
|
|
|
|
m_flags = 0;
|
|
|
|
|
}
|
2015-06-21 23:42:29 -07:00
|
|
|
|
2015-07-19 16:02:21 -07:00
|
|
|
bool IsPersistent() const { return (m_flags & NT_PERSISTENT) != 0; }
|
2015-06-28 21:52:06 -07:00
|
|
|
|
2015-07-28 22:29:58 -07:00
|
|
|
std::shared_ptr<Value> value() const {
|
2015-07-19 16:02:21 -07:00
|
|
|
#ifdef HAVE_SHARED_PTR_ATOMIC_LOAD
|
|
|
|
|
return std::atomic_load(&m_value);
|
|
|
|
|
#else
|
|
|
|
|
std::lock_guard<std::mutex> lock(m_value_mutex);
|
|
|
|
|
return m_value;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
void set_value(std::shared_ptr<Value> value) {
|
|
|
|
|
#ifdef HAVE_SHARED_PTR_ATOMIC_LOAD
|
|
|
|
|
std::atomic_store(&m_value, value);
|
|
|
|
|
#else
|
|
|
|
|
std::lock_guard<std::mutex> lock(m_value_mutex);
|
|
|
|
|
m_value = value;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int flags() const { return m_flags; }
|
|
|
|
|
void set_flags(unsigned int flags) { m_flags = flags; }
|
|
|
|
|
|
2015-07-26 10:28:20 -07:00
|
|
|
StringRef name() const { return m_name; }
|
|
|
|
|
|
2015-07-19 16:02:21 -07:00
|
|
|
unsigned int id() const { return m_id; }
|
|
|
|
|
void set_id(unsigned int id) { m_id = id; }
|
|
|
|
|
|
|
|
|
|
SequenceNumber seq_num() const { return m_seq_num; }
|
|
|
|
|
void set_seq_num(SequenceNumber seq_num) { m_seq_num = seq_num; }
|
2015-07-29 20:33:13 -07:00
|
|
|
SequenceNumber seq_num_inc() { return ++m_seq_num; }
|
2015-07-19 16:02:21 -07:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// These variables are accessed by both Dispatcher and user, so must use
|
|
|
|
|
// atomic accesses. Unfortunately, atomic shared_ptr is not yet available
|
|
|
|
|
// on most compilers, so we need an explicit mutex instead.
|
|
|
|
|
#ifndef HAVE_SHARED_PTR_ATOMIC_LOAD
|
2015-07-28 22:29:58 -07:00
|
|
|
mutable std::mutex m_value_mutex;
|
2015-07-19 16:02:21 -07:00
|
|
|
#endif
|
|
|
|
|
std::shared_ptr<Value> m_value;
|
|
|
|
|
std::atomic_uint m_flags;
|
|
|
|
|
|
|
|
|
|
// Only accessed from the Dispatcher, so these are NOT mutex-protected.
|
2015-07-26 10:28:20 -07:00
|
|
|
std::string m_name;
|
2015-07-19 16:02:21 -07:00
|
|
|
unsigned int m_id;
|
|
|
|
|
SequenceNumber m_seq_num;
|
2015-06-21 23:42:29 -07:00
|
|
|
};
|
|
|
|
|
|
2015-06-25 22:57:43 -07:00
|
|
|
class Storage {
|
2015-07-19 16:36:30 -07:00
|
|
|
friend class StorageTest;
|
2015-06-25 22:57:43 -07:00
|
|
|
public:
|
|
|
|
|
static Storage& GetInstance() {
|
2015-07-20 23:36:22 -07:00
|
|
|
ATOMIC_STATIC(Storage, instance);
|
|
|
|
|
return instance;
|
2015-06-25 22:57:43 -07:00
|
|
|
}
|
2015-07-14 23:15:08 -07:00
|
|
|
~Storage();
|
2015-06-21 23:42:29 -07:00
|
|
|
|
2015-07-18 01:29:51 -07:00
|
|
|
struct Update {
|
2015-07-26 20:41:48 -07:00
|
|
|
enum Kind {
|
|
|
|
|
kNone,
|
|
|
|
|
kAssign,
|
|
|
|
|
kValueUpdate,
|
|
|
|
|
kFlagsUpdate,
|
|
|
|
|
kValueFlagsUpdate,
|
|
|
|
|
kDelete,
|
|
|
|
|
kDeleteAll
|
|
|
|
|
};
|
|
|
|
|
Update() : flags(0), kind(kNone) {}
|
|
|
|
|
|
2015-07-21 22:43:44 -07:00
|
|
|
std::shared_ptr<StorageEntry> entry;
|
2015-07-26 20:41:48 -07:00
|
|
|
std::shared_ptr<Value> value;
|
|
|
|
|
unsigned int flags;
|
2015-07-18 01:29:51 -07:00
|
|
|
Kind kind;
|
|
|
|
|
};
|
2015-07-26 20:41:48 -07:00
|
|
|
typedef llvm::StringMap<Update> UpdateMap;
|
2015-07-18 01:29:51 -07:00
|
|
|
|
2015-07-29 23:45:04 -07:00
|
|
|
typedef std::function<void(std::shared_ptr<Message> msg,
|
|
|
|
|
NetworkConnection* only,
|
|
|
|
|
NetworkConnection* except)> QueueOutgoingFunc;
|
|
|
|
|
void SetOutgoing(QueueOutgoingFunc queue_outgoing, bool server);
|
|
|
|
|
void ClearOutgoing();
|
|
|
|
|
|
|
|
|
|
NT_Type GetEntryType(unsigned int id) const;
|
|
|
|
|
|
|
|
|
|
void ProcessIncoming(std::shared_ptr<Message> msg, NetworkConnection* conn,
|
|
|
|
|
unsigned int proto_rev);
|
|
|
|
|
|
2015-07-19 16:02:21 -07:00
|
|
|
// Finds, but does not create entry. Returns nullptr if not found.
|
|
|
|
|
std::shared_ptr<StorageEntry> FindEntry(StringRef name) const;
|
2015-06-21 23:42:29 -07:00
|
|
|
|
2015-07-20 22:24:47 -07:00
|
|
|
// Accessors required by Dispatcher.
|
2015-07-26 20:41:48 -07:00
|
|
|
void GetUpdates(UpdateMap* updates, bool* delete_all);
|
2015-07-26 09:42:14 -07:00
|
|
|
std::mutex& mutex() { return m_mutex; }
|
2015-07-18 01:29:51 -07:00
|
|
|
|
2015-07-20 22:24:47 -07:00
|
|
|
// User functions
|
2015-07-18 01:29:51 -07:00
|
|
|
std::shared_ptr<Value> GetEntryValue(StringRef name) const;
|
|
|
|
|
bool SetEntryValue(StringRef name, std::shared_ptr<Value> value);
|
|
|
|
|
void SetEntryTypeValue(StringRef name, std::shared_ptr<Value> value);
|
|
|
|
|
void SetEntryFlags(StringRef name, unsigned int flags);
|
|
|
|
|
unsigned int GetEntryFlags(StringRef name) const;
|
|
|
|
|
void DeleteEntry(StringRef name);
|
|
|
|
|
void DeleteAllEntries();
|
|
|
|
|
std::vector<EntryInfo> GetEntryInfo(StringRef prefix, unsigned int types);
|
|
|
|
|
|
2015-06-27 10:22:59 -07:00
|
|
|
void SavePersistent(std::ostream& os) const;
|
2015-07-17 07:21:07 -07:00
|
|
|
bool LoadPersistent(
|
|
|
|
|
std::istream& is,
|
|
|
|
|
std::function<void(std::size_t line, const char* msg)> warn);
|
2015-06-27 10:22:59 -07:00
|
|
|
|
2015-06-25 22:57:43 -07:00
|
|
|
private:
|
|
|
|
|
Storage();
|
|
|
|
|
Storage(const Storage&) = delete;
|
|
|
|
|
Storage& operator=(const Storage&) = delete;
|
2015-06-21 23:42:29 -07:00
|
|
|
|
2015-07-26 20:41:48 -07:00
|
|
|
void AddUpdate(std::shared_ptr<StorageEntry> entry, Update::Kind kind);
|
2015-07-20 22:24:47 -07:00
|
|
|
|
2015-07-19 16:36:30 -07:00
|
|
|
typedef llvm::StringMap<std::shared_ptr<StorageEntry>> EntriesMap;
|
2015-07-29 23:45:04 -07:00
|
|
|
typedef std::vector<std::shared_ptr<StorageEntry>> IdMap;
|
2015-07-19 16:36:30 -07:00
|
|
|
|
2015-07-18 01:29:51 -07:00
|
|
|
mutable std::mutex m_mutex;
|
2015-06-27 10:02:20 -07:00
|
|
|
EntriesMap m_entries;
|
2015-07-29 23:45:04 -07:00
|
|
|
IdMap m_idmap;
|
2015-07-26 20:41:48 -07:00
|
|
|
UpdateMap m_updates;
|
|
|
|
|
bool m_updates_delete_all;
|
2015-06-27 10:02:20 -07:00
|
|
|
|
2015-07-29 23:45:04 -07:00
|
|
|
QueueOutgoingFunc m_queue_outgoing;
|
|
|
|
|
bool m_server;
|
|
|
|
|
|
2015-07-20 23:36:22 -07:00
|
|
|
ATOMIC_STATIC_DECL(Storage)
|
2015-06-21 23:42:29 -07:00
|
|
|
};
|
|
|
|
|
|
2015-07-17 07:21:07 -07:00
|
|
|
} // namespace nt
|
2015-06-21 23:42:29 -07:00
|
|
|
|
2015-06-25 22:57:43 -07:00
|
|
|
#endif // NT_STORAGE_H_
|