Adding kafka logging in framework.

This commit is contained in:
stephb9959
2022-01-20 22:56:41 -08:00
parent 22cc12e24d
commit fc23b4d0d7
6 changed files with 310 additions and 75 deletions

View File

@@ -309,6 +309,7 @@ namespace OpenWifi::ProvObjects {
field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
field_to_json( Obj,"rrm",rrm);
field_to_json( Obj,"managementPolicy",managementPolicy);
field_to_json( Obj,"state",state);
}
bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -326,6 +327,7 @@ namespace OpenWifi::ProvObjects {
field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
field_from_json( Obj,"rrm",rrm);
field_from_json( Obj,"managementPolicy",managementPolicy);
field_from_json( Obj,"state",state);
return true;
} catch(...) {
@@ -333,6 +335,20 @@ namespace OpenWifi::ProvObjects {
return false;
}
void InventoryTagList::to_json(Poco::JSON::Object &Obj) const {
field_to_json( Obj,"taglist",taglist);
}
bool InventoryTagList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json( Obj,"taglist",taglist);
return false;
} catch (...) {
}
return false;
};
void DeviceConfigurationElement::to_json(Poco::JSON::Object &Obj) const {
field_to_json( Obj,"name", name);
field_to_json( Obj,"description", description);

View File

@@ -284,12 +284,22 @@ namespace OpenWifi::ProvObjects {
std::string deviceConfiguration;
std::string rrm;
Types::UUID_t managementPolicy;
std::string state;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
typedef std::vector<InventoryTag> InventoryTagVec;
struct InventoryTagList {
InventoryTagVec taglist;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct Report {
uint64_t snapShot=0;
Types::CountedMap tenants;

View File

@@ -100,7 +100,8 @@ namespace OpenWifi {
EXPIRED_TOKEN,
RATE_LIMIT_EXCEEDED,
BAD_MFA_TRANSACTION,
MFA_FAILURE
MFA_FAILURE,
SECURITY_SERVICE_UNREACHABLE
};
class AppServiceRegistry {
@@ -238,6 +239,23 @@ namespace OpenWifi::RESTAPI_utils {
Obj.set(Field,A);
}
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::Counted3DMapSII &M) {
Poco::JSON::Array A;
for(const auto &[OrgName,MonthlyNumberMap]:M) {
Poco::JSON::Object OrgObject;
OrgObject.set("tag",OrgName);
Poco::JSON::Array MonthlyArray;
for(const auto &[Month,Counter]:MonthlyNumberMap) {
Poco::JSON::Object Inner;
Inner.set("value", Month);
Inner.set("counter", Counter);
MonthlyArray.add(Inner);
}
OrgObject.set("index",MonthlyArray);
A.add(OrgObject);
}
}
template<typename T> void field_to_json(Poco::JSON::Object &Obj,
const char *Field,
const T &V,
@@ -1078,6 +1096,53 @@ namespace OpenWifi {
typedef std::map<std::string,ConfigurationEntry> ConfigurationMap_t;
template <typename T> class FIFO {
public:
explicit FIFO(uint32_t Size) : Size_(Size) {
Buffer_->reserve(Size_);
}
mutable Poco::BasicEvent<bool> Writable_;
mutable Poco::BasicEvent<bool> Readable_;
inline bool Read(T &t) {
{
std::lock_guard M(Mutex_);
if (Write_ == Read_) {
return false;
}
t = (*Buffer_)[Read_++];
if (Read_ == Size_) {
Read_ = 0;
}
}
bool flag = true;
Writable_.notify(this, flag);
return true;
}
inline bool Write(const T &t) {
{
std::lock_guard M(Mutex_);
(*Buffer_)[Write_++] = t;
if (Write_ == Size_) {
Write_ = 0;
}
}
bool flag = true;
Readable_.notify(this, flag);
return false;
}
private:
std::mutex Mutex_;
uint32_t Size_;
uint32_t Read_=0;
uint32_t Write_=0;
std::unique_ptr<std::vector<T>> Buffer_=std::make_unique<std::vector<T>>();
};
template <class Record, typename KeyType = std::string, int Size=256, int Expiry=60000> class RecordCache {
public:
explicit RecordCache( KeyType Record::* Q) :
@@ -1643,11 +1708,14 @@ namespace OpenWifi {
if (!ContinueProcessing())
return;
bool Expired=false;
if (AlwaysAuthorize_ && !IsAuthorized(Expired, SubOnlyService_)) {
bool Expired=false, Contacted=false;
if (AlwaysAuthorize_ && !IsAuthorized(Expired, Contacted, SubOnlyService_)) {
if(Expired)
return UnAuthorized(RESTAPI::Errors::ExpiredToken, EXPIRED_TOKEN);
return UnAuthorized(RESTAPI::Errors::InvalidCredentials, INVALID_TOKEN);
if(Contacted)
return UnAuthorized(RESTAPI::Errors::InvalidCredentials, INVALID_TOKEN);
else
return UnAuthorized(RESTAPI::Errors::InvalidCredentials, SECURITY_SERVICE_UNREACHABLE);
}
std::string Reason;
@@ -2029,7 +2097,7 @@ namespace OpenWifi {
return true;
}
inline bool IsAuthorized(bool & Expired, bool SubOnly = false );
inline bool IsAuthorized(bool & Expired, bool & Contacted, bool SubOnly = false );
inline void ReturnObject(Poco::JSON::Object &Object) {
PrepareResponse();
@@ -2105,20 +2173,20 @@ namespace OpenWifi {
virtual void DoPost() = 0 ;
virtual void DoPut() = 0 ;
Poco::Net::HTTPServerRequest *Request= nullptr;
Poco::Net::HTTPServerResponse *Response= nullptr;
SecurityObjects::UserInfoAndPolicy UserInfo_;
protected:
BindingMap Bindings_;
Poco::URI::QueryParameters Parameters_;
Poco::Logger &Logger_;
std::string SessionToken_;
SecurityObjects::UserInfoAndPolicy UserInfo_;
std::vector<std::string> Methods_;
QueryBlock QB_;
bool Internal_=false;
bool RateLimited_=false;
bool QueryBlockInitialized_=false;
bool SubOnlyService_=false;
Poco::Net::HTTPServerRequest *Request= nullptr;
Poco::Net::HTTPServerResponse *Response= nullptr;
bool AlwaysAuthorize_=true;
Poco::JSON::Parser IncomingParser_;
RESTAPI_GenericServer & Server_;
@@ -2239,6 +2307,26 @@ namespace OpenWifi {
Poco::JSON::Object Body_;
};
class OpenAPIRequestDelete {
public:
explicit OpenAPIRequestDelete( const std::string & Type,
const std::string & EndPoint,
const Types::StringPairVec & QueryData,
uint64_t msTimeout):
Type_(Type),
EndPoint_(EndPoint),
QueryData_(QueryData),
msTimeout_(msTimeout){};
inline Poco::Net::HTTPServerResponse::HTTPStatus Do(const std::string & BearerToken = "");
private:
std::string Type_;
std::string EndPoint_;
Types::StringPairVec QueryData_;
uint64_t msTimeout_;
Poco::JSON::Object Body_;
};
class KafkaProducer : public Poco::Runnable {
public:
inline void run();
@@ -2424,16 +2512,24 @@ namespace OpenWifi {
inline bool RetrieveTokenInformation(const std::string & SessionToken,
SecurityObjects::UserInfoAndPolicy & UInfo,
bool & Expired, bool Sub=false) {
bool & Expired, bool & Contacted, bool Sub=false) {
try {
Types::StringPairVec QueryData;
QueryData.push_back(std::make_pair("token",SessionToken));
OpenAPIRequestGet Req( uSERVICE_SECURITY,
Sub ? "/api/v1/validateSubToken" : "/api/v1/validateToken",
QueryData,
5000);
10000);
Poco::JSON::Object::Ptr Response;
if(Req.Do(Response)==Poco::Net::HTTPServerResponse::HTTP_OK) {
auto StatusCode = Req.Do(Response);
if(StatusCode==Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT) {
Contacted = false;
return false;
}
Contacted = true;
if(StatusCode==Poco::Net::HTTPServerResponse::HTTP_OK) {
if(Response->has("tokenInfo") && Response->has("userInfo")) {
UInfo.from_json(Response);
if(IsTokenExpired(UInfo.webtoken)) {
@@ -2444,17 +2540,18 @@ namespace OpenWifi {
std::lock_guard G(Mutex_);
Cache_.update(SessionToken, UInfo);
return true;
}
} else {
return false;
}
}
} catch (...) {
}
Expired = false;
return false;
}
inline bool IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo,
bool & Expired, bool Sub = false) {
bool & Expired, bool & Contacted, bool Sub = false) {
std::lock_guard G(Mutex_);
auto User = Cache_.get(SessionToken);
if(!User.isNull()) {
@@ -2466,7 +2563,7 @@ namespace OpenWifi {
UInfo = *User;
return true;
}
return RetrieveTokenInformation(SessionToken, UInfo, Expired, Sub);
return RetrieveTokenInformation(SessionToken, UInfo, Expired, Contacted, Sub);
}
private:
@@ -3519,11 +3616,51 @@ namespace OpenWifi {
KafkaEnabled_ = MicroService::instance().ConfigGetBool("openwifi.kafka.enable",false);
}
inline void KafkaLoggerFun(cppkafka::KafkaHandleBase & handle, int level, const std::string & facility, const std::string &messqge) {
switch ((cppkafka::LogLevel) level) {
case cppkafka::LogLevel::LogNotice: {
KafkaManager()->Logger().notice(Poco::format("kafka-log: facility: %s message: %s",facility, messqge));
}
break;
case cppkafka::LogLevel::LogDebug: {
KafkaManager()->Logger().debug(Poco::format("kafka-log: facility: %s message: %s",facility, messqge));
}
break;
case cppkafka::LogLevel::LogInfo: {
KafkaManager()->Logger().information(Poco::format("kafka-log: facility: %s message: %s",facility, messqge));
}
break;
case cppkafka::LogLevel::LogWarning: {
KafkaManager()->Logger().warning(Poco::format("kafka-log: facility: %s message: %s",facility, messqge));
}
break;
case cppkafka::LogLevel::LogAlert:
case cppkafka::LogLevel::LogCrit: {
KafkaManager()->Logger().critical(Poco::format("kafka-log: facility: %s message: %s",facility, messqge));
}
break;
case cppkafka::LogLevel::LogErr:
case cppkafka::LogLevel::LogEmerg:
default: {
KafkaManager()->Logger().error(Poco::format("kafka-log: facility: %s message: %s",facility, messqge));
}
break;
}
}
inline void KafkaErrorFun(cppkafka::KafkaHandleBase & handle, int error, const std::string &reason) {
KafkaManager()->Logger().error(Poco::format("kafka-error: %d, reason: %s", error, reason));
}
inline void KafkaProducer::run() {
cppkafka::Configuration Config({
{ "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") },
{ "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") }
});
Config.set_log_callback(KafkaLoggerFun);
Config.set_error_callback(KafkaErrorFun);
KafkaManager()->SystemInfoWrapper_ = R"lit({ "system" : { "id" : )lit" +
std::to_string(MicroService::instance().ID()) +
R"lit( , "host" : ")lit" + MicroService::instance().PrivateEndPoint() +
@@ -3564,6 +3701,9 @@ namespace OpenWifi {
{ "enable.partition.eof", false }
});
Config.set_log_callback(KafkaLoggerFun);
Config.set_error_callback(KafkaErrorFun);
cppkafka::TopicConfiguration topic_config = {
{ "auto.offset.reset", "smallest" }
};
@@ -3930,6 +4070,52 @@ namespace OpenWifi {
return Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT;
}
inline Poco::Net::HTTPServerResponse::HTTPStatus OpenAPIRequestDelete::Do(const std::string & BearerToken) {
try {
auto Services = MicroService::instance().GetServices(Type_);
for(auto const &Svc:Services) {
Poco::URI URI(Svc.PrivateEndPoint);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
URI.setPath(EndPoint_);
for (const auto &qp : QueryData_)
URI.addQueryParameter(qp.first, qp.second);
std::string Path(URI.getPathAndQuery());
Session.setTimeout(Poco::Timespan(msTimeout_/1000, msTimeout_ % 1000));
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_DELETE,
Path,
Poco::Net::HTTPMessage::HTTP_1_1);
std::ostringstream obody;
Poco::JSON::Stringifier::stringify(Body_,obody);
Request.setContentType("application/json");
Request.setContentLength(obody.str().size());
if(BearerToken.empty()) {
Request.add("X-API-KEY", Svc.AccessKey);
Request.add("X-INTERNAL-NAME", MicroService::instance().PublicEndPoint());
} else {
// Authorization: Bearer ${token}
Request.add("Authorization", "Bearer " + BearerToken);
}
std::ostream & os = Session.sendRequest(Request);
os << obody.str();
Poco::Net::HTTPResponse Response;
Session.receiveResponse(Response);
return Response.getStatus();
}
}
catch (const Poco::Exception &E)
{
std::cerr << E.displayText() << std::endl;
}
return Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT;
}
inline void RESTAPI_GenericServer::InitLogging() {
std::string Public = MicroService::instance().ConfigGetString("apilogging.public.methods","PUT,POST,DELETE");
@@ -3946,7 +4132,7 @@ namespace OpenWifi {
#ifdef TIP_SECURITY_SERVICE
[[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired , bool Sub );
#endif
inline bool RESTAPIHandler::IsAuthorized( bool & Expired , bool Sub ) {
inline bool RESTAPIHandler::IsAuthorized( bool & Expired , bool & Contacted , bool Sub ) {
if(Internal_ && Request->has("X-INTERNAL-NAME")) {
auto Allowed = MicroService::instance().IsValidAPIKEY(*Request);
if(!Allowed) {
@@ -3978,7 +4164,7 @@ namespace OpenWifi {
#ifdef TIP_SECURITY_SERVICE
if (AuthServiceIsAuthorized(*Request, SessionToken_, UserInfo_, Expired, Sub)) {
#else
if (AuthClient()->IsAuthorized( SessionToken_, UserInfo_, Expired, Sub)) {
if (AuthClient()->IsAuthorized( SessionToken_, UserInfo_, Expired, Contacted, Sub)) {
#endif
if(Server_.LogIt(Request->getMethod(),true)) {
Logger_.debug(Poco::format("X-REQ-ALLOWED(%s): User='%s@%s' Method='%s' Path='%s'",

View File

@@ -14,22 +14,24 @@
#include <set>
namespace OpenWifi::Types {
typedef std::pair<std::string,std::string> StringPair;
typedef std::vector<StringPair> StringPairVec;
typedef std::queue<StringPair> StringPairQueue;
typedef std::vector<std::string> StringVec;
typedef std::set<std::string> StringSet;
typedef std::map<std::string,std::set<std::string>> StringMapStringSet;
typedef std::function<void(std::string, std::string)> TopicNotifyFunction;
typedef std::list<std::pair<TopicNotifyFunction,int>> TopicNotifyFunctionList;
typedef std::map<std::string, TopicNotifyFunctionList> NotifyTable;
typedef std::map<std::string,uint64_t> CountedMap;
typedef std::vector<uint64_t> TagList;
typedef std::string UUID_t;
typedef std::vector<UUID_t> UUIDvec_t;
typedef std::pair<std::string,std::string> StringPair;
typedef std::vector<StringPair> StringPairVec;
typedef std::queue<StringPair> StringPairQueue;
typedef std::vector<std::string> StringVec;
typedef std::set<std::string> StringSet;
typedef std::map<std::string,std::set<std::string>> StringMapStringSet;
typedef std::function<void(std::string, std::string)> TopicNotifyFunction;
typedef std::list<std::pair<TopicNotifyFunction,int>> TopicNotifyFunctionList;
typedef std::map<std::string, TopicNotifyFunctionList> NotifyTable;
typedef std::map<std::string,uint64_t> CountedMap;
typedef std::vector<uint64_t> TagList;
typedef std::string UUID_t;
typedef std::vector<UUID_t> UUIDvec_t;
typedef std::map<std::string,std::map<uint32_t,uint64_t>> Counted3DMapSII;
}
namespace OpenWifi {
inline void UpdateCountedMap(OpenWifi::Types::CountedMap &M, const std::string &S, uint64_t Increment=1) {
auto it = M.find(S);
if(it==M.end())
@@ -37,4 +39,22 @@ namespace OpenWifi {
else
it->second += Increment;
}
inline void UpdateCountedMap(OpenWifi::Types::Counted3DMapSII &M, const std::string &S, uint32_t Index, uint64_t Increment=1) {
auto it = M.find(S);
if(it==M.end()) {
std::map<uint32_t,uint64_t> E;
E[Index] = Increment;
M[S] = E;
}
else {
std::map<uint32_t,uint64_t> & IndexMap = it->second;
auto it_index = IndexMap.find(Index);
if(it_index == IndexMap.end()) {
IndexMap[Index] = Increment;
} else {
it_index->second += Increment;
}
}
}
}

View File

@@ -14,7 +14,7 @@ namespace OpenWifi::RESTAPI::Errors {
static const std::string CouldNotBeDeleted{"Element could not be deleted."};
static const std::string NameMustBeSet{"The name property must be set."};
static const std::string ConfigBlockInvalid{"Configuration block type invalid."};
static const std::string UnknownId{"Unknown management policy."};
static const std::string UnknownId{"Unknown UUID."};
static const std::string InvalidDeviceTypes{"Unknown or invalid device type(s)."};
static const std::string RecordNotCreated{"Record could not be created."};
static const std::string RecordNotUpdated{"Record could not be updated."};
@@ -59,5 +59,6 @@ namespace OpenWifi::RESTAPI::Errors {
static const std::string MissingAuthenticationInformation{"Missing authentication information."};
static const std::string InsufficientAccessRights{"Insufficient access rights to complete the operation."};
static const std::string ExpiredToken{"Token has expired, user must login."};
static const std::string SubscriberMustExist{"Subscriber must exist."};
}

View File

@@ -171,6 +171,9 @@ namespace ORM {
template <typename RecordTuple, typename RecordType> class DB {
public:
typedef const char * field_name_t;
DB( OpenWifi::DBType dbtype,
const char *TableName,
const FieldVec & Fields,
@@ -258,27 +261,27 @@ namespace ORM {
[[nodiscard]] const std::string & SelectList() const { return SelectList_; };
[[nodiscard]] const std::string & UpdateFields() const { return UpdateFields_; };
inline std::string OP(const char *F, SqlComparison O , bool V) {
inline std::string OP(field_name_t F, SqlComparison O , bool V) {
assert( FieldNames_.find(F) != FieldNames_.end() );
return std::string{"("} + F + SQLCOMPS[O] + (V ? "true" : "false") + ")" ;
}
inline std::string OP(const char *F, SqlComparison O , int V) {
inline std::string OP(field_name_t F, SqlComparison O , int V) {
assert( FieldNames_.find(F) != FieldNames_.end() );
return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ;
}
inline std::string OP(const char *F, SqlComparison O , uint64_t V) {
inline std::string OP(field_name_t F, SqlComparison O , uint64_t V) {
assert( FieldNames_.find(F) != FieldNames_.end() );
return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ;
}
std::string OP(const char *F, SqlComparison O , const std::string & V) {
std::string OP(field_name_t F, SqlComparison O , const std::string & V) {
assert( FieldNames_.find(F) != FieldNames_.end() );
return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ;
}
std::string OP(const char *F, SqlComparison O , const char * V) {
std::string OP(field_name_t F, SqlComparison O , const char * V) {
assert( FieldNames_.find(F) != FieldNames_.end() );
return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ;
}
@@ -299,9 +302,12 @@ namespace ORM {
return std::string{"("} + P1 + BOPS[BOP] + OP(true, P2, More...);
}
inline bool Create() {
std::string S;
bool Upgrade() {
uint32_t To;
return Upgrade(0, To);
}
inline bool Create() {
switch(Type_) {
case OpenWifi::DBType::mysql: {
try {
@@ -309,12 +315,10 @@ namespace ORM {
std::string Statement = IndexCreation_.empty() ? "create table if not exists " + TableName_ +" ( " + CreateFields_ + " )" :
"create table if not exists " + TableName_ +" ( " + CreateFields_ + " ), " + IndexCreation_[0] + " )";
Session << Statement , Poco::Data::Keywords::now;
return true;
} catch (const Poco::Exception &E) {
Logger_.error("Failure to create MySQL DB resources.");
Logger_.log(E);
}
return false;
}
break;
@@ -326,7 +330,6 @@ namespace ORM {
for(const auto &i:IndexCreation_) {
Session << i , Poco::Data::Keywords::now;
}
return true;
} catch (const Poco::Exception &E) {
Logger_.error("Failure to create SQLITE DB resources.");
Logger_.log(E);
@@ -342,7 +345,6 @@ namespace ORM {
for(const auto &i:IndexCreation_) {
Session << i , Poco::Data::Keywords::now;
}
return true;
} catch (const Poco::Exception &E) {
Logger_.error("Failure to create POSTGRESQL DB resources.");
Logger_.log(E);
@@ -350,7 +352,7 @@ namespace ORM {
}
break;
}
return false;
return Upgrade();
}
[[nodiscard]] std::string ConvertParams(const std::string & S) const {
@@ -400,7 +402,7 @@ namespace ORM {
return false;
}
template<typename T> bool GetRecord( const char * FieldName, const T & Value, RecordType & R) {
template<typename T> bool GetRecord(field_name_t FieldName, const T & Value, RecordType & R) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
@@ -438,7 +440,7 @@ namespace ORM {
typedef std::vector<std::string> StringVec;
template < typename T,
typename T0, typename T1> bool GR(const char *FieldName, T & R,T0 &V0, T1 &V1) {
typename T0, typename T1> bool GR(field_name_t FieldName, T & R,T0 &V0, T1 &V1) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
@@ -495,7 +497,7 @@ namespace ORM {
return false;
}
template <typename T> bool UpdateRecord( const char *FieldName, const T & Value, const RecordType & R) {
template <typename T> bool UpdateRecord(field_name_t FieldName, const T & Value, const RecordType & R) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
@@ -522,7 +524,7 @@ namespace ORM {
return false;
}
template <typename T> bool ReplaceRecord( const char *FieldName, const T & Value, RecordType & R) {
template <typename T> bool ReplaceRecord(field_name_t FieldName, const T & Value, RecordType & R) {
try {
if(Exists(FieldName, Value)) {
return UpdateRecord(FieldName,Value,R);
@@ -534,7 +536,7 @@ namespace ORM {
return false;
}
template <typename T> bool GetNameAndDescription(const char *FieldName, const T & Value, std::string & Name, std::string & Description ) {
template <typename T> bool GetNameAndDescription(field_name_t FieldName, const T & Value, std::string & Name, std::string & Description ) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
Poco::Data::Session Session = Pool_.get();
@@ -561,7 +563,7 @@ namespace ORM {
return false;
}
template <typename T> bool DeleteRecord( const char *FieldName, const T & Value) {
template <typename T> bool DeleteRecord(field_name_t FieldName, const T & Value) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
@@ -599,7 +601,7 @@ namespace ORM {
return false;
}
bool Exists(const char *FieldName, const std::string & Value) {
bool Exists(field_name_t FieldName, const std::string & Value) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
@@ -613,15 +615,15 @@ namespace ORM {
return false;
}
bool Iterate( std::function<bool(const RecordType &R)> F) {
bool Iterate( std::function<bool(const RecordType &R)> F, const std::string & WhereClause = "" ) {
try {
uint64_t Offset=1;
uint64_t Offset=0;
uint64_t Batch=50;
bool Done=false;
while(!Done) {
std::vector<RecordType> Records;
if(GetRecords(Offset,Batch,Records)) {
if(GetRecords(Offset,Batch,Records, WhereClause)) {
for(const auto &i:Records) {
if(!F(i))
return true;
@@ -691,7 +693,7 @@ namespace ORM {
return 0;
}
template <typename X> bool ManipulateVectorMember( X T, const char *FieldName, std::string & ParentUUID, std::string & ChildUUID, bool Add) {
template <typename X> bool ManipulateVectorMember( X T, field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID, bool Add) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
@@ -751,89 +753,89 @@ namespace ORM {
return true;
}
inline bool AddChild( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool AddChild(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, true);
}
inline bool DeleteChild( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool DeleteChild(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, false);
}
inline bool AddLocation( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool AddLocation(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, true);
}
inline bool DeleteLocation( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool DeleteLocation(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, false);
}
inline bool AddContact( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool AddContact(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, true);
}
inline bool DeleteContact( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool DeleteContact(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, false);
}
inline bool AddVenue( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool AddVenue(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, true);
}
inline bool DeleteVenue( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool DeleteVenue(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, false);
}
inline bool AddDevice( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool AddDevice(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, true);
}
inline bool DeleteDevice( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool DeleteDevice(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, false);
}
inline bool AddEntity( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool AddEntity(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, true);
}
inline bool DeleteEntity( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool DeleteEntity(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, false);
}
inline bool AddUser( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool AddUser(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, true);
}
inline bool DelUser( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
inline bool DelUser(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, false);
}
inline bool AddInUse(const char *FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) {
inline bool AddInUse(field_name_t FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) {
std::string FakeUUID{ Prefix + ":" + ChildUUID};
return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, true);
}
inline bool DeleteInUse(const char *FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) {
inline bool DeleteInUse(field_name_t FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) {
std::string FakeUUID{ Prefix + ":" + ChildUUID};
return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, false);
}
inline bool DeleteContact(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
inline bool DeleteContact(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::contacts,FieldName, ParentUUID, ChildUUID, false);
}
inline bool AddContact(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
inline bool AddContact(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::contacts,FieldName, ParentUUID, ChildUUID, true);
}
inline bool DeleteLocation(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
inline bool DeleteLocation(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::locations,FieldName, ParentUUID, ChildUUID, false);
}
inline bool AddLocation(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
inline bool AddLocation(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::locations,FieldName, ParentUUID, ChildUUID, true);
}
inline bool GetInUse(const char *FieldName, std::string & UUID, std::vector<std::string> & UUIDs ) {
inline bool GetInUse(field_name_t FieldName, const std::string & UUID, std::vector<std::string> & UUIDs ) {
RecordType R;
if(GetRecord(FieldName,UUID,R)) {
UUIDs = R.inUse;