#ifndef ND_AGENTMAIN_H
#define ND_AGENTMAIN_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

//HPLOG:changes for websocket
//HPLOG:TODO
#ifndef __unix__
#include <WinSock2.h>
#endif
//HPEND

#include "apr_pools.h"
#include "apr_atomic.h"
#include "apr_strings.h"
#include "apr.h"
#include "apr_general.h"
#include "apr_hash.h"
#include "apr_network_io.h"
#include "apr_thread_proc.h"

//HPLOG:Changes for websocket
#include "libwebsockets.h"
//HPEND

//#include "NDCommonHeader.h"
#include "Server.h"
#include "nd_agent.h"
#include "NDDigest.h"
#include "NDTDigest.h"
#include "cdigest/tslb_cdigest.h"
#define METHOD_BEGIN_REQUEST "Profiler.Cavisson.BeginRequest"

#define PROXY_INITIAL_CONNECTIONS   32
#define AGENT_INITIAL_CONNECTIONS   2
#define PROXY_DELTA_CONNECTIONS     16

#define INSTRUMENTED      1
#define REINSTRUMENTED   2
#define REMOVE              3

/* Macro for hashmap type */
#define INSTPROF    1
#define METHODMON  2
#define ENTRYPOINT 3 

#define METHOD  1
#define BT      2
#define IP      3
#define HTTP_HEADER    4
#define METHOD_MON    5
#define CUSTOM_CALL   6

#define MAX_TRANSACTION_TAGS 128

#define DB_BACKEND_NAME "JDBC"
#define DB_BACKEND_NAME_CASSANDRA "CASSANDRA"
#define UNKNOWN_QUERY "Unknown"
#define QUERYSTRXASTART "XA TRANSACTION START"
#define QUERYSTRXACOMMIT "XA TRANSACTION COMMIT"
#define QUERYSTRXAEND  "XA TRANSACTION END"
#define QUERYSTRXAROLLBACK  "XA TRANSACTION ROLLBACK"

#define EXCEPTION_UNWIND_PC 3
#define EXCEPTION_THROWN_PC 4

//#define DEFAULT_DB_BACKEND_NAME "SQLDB"
#define DEFAULT_DB_BACKEND_NAME "DB_SQLDB"
#define DEFAULT_REDIS_BACKEND_NAME "DB_REDIS"
#define DEFAULT_MONGO_BACKEND_NAME "DB_MONGO"
#define DEFAULT_ORACLE_BACKEND_NAME "DB_ORACLE"
#define DEFAULT_MYSQL_BACKEND_NAME "DB_MYSQL"
#define DEFAULT_PGSQL_BACKEND_NAME "DB_PGSQL"
#define DEFAULT_MEMCACHED_BACKEND_NAME "DB_MEMCACHED"
#define DEFAULT_ODBC_BACKEND_NAME "DB_ODBC"
#define DEFAULT_CASSANDRA_BACKEND_NAME "DB_CASSANDRA"
#define DEFAULT_SQLITE_BACKEND_NAME "DB_SQLITE"
#define DEFAULT_DB2_BACKEND_NAME "DB_DB2"
#define DEFAULT_FIREBIRD_BACKEND_NAME "DB_FIREBIRD"
#define DEFAULT_COUCHBASE_DB_BACKEND_NAME "DB_COUCHBASE"
#define DEFAULT_RABBIT_MQ_BACKEND_NAME "MQ_RABBIT"

//Protocol Negotiation Changes
#define SupportedProtocolTCP 1
#define SupportedProtocolWS  2
#define SupportedProtocolWSS 3
#define SupportedProtocolNameTCP "TCP"
#define SupportedProtocolNameWS  "WS"
#define SupportedProtocolNameWSS "WSS"

#define OTL_TRACEPARENT "traceparent"
#define OTL_TRACESTATE "tracestate"
#define PROP_XB3_Traceid "X-B3-TraceId"
#define PROP_XB3_parentspanid "X-B3-ParentSpanId"
#define PROP_XB3_spanId "X-B3-SpanId"
#define PROP_XB3_Sampled "X-B3-Sampled"
#define PROP_B3 "b3"
#define PROP_xB3 "x-b3"
#define OpenTelemetry "OpenTelemetry"
#define CAVNDFPINSTANCE "CavNDFPInstance"
#define TRANSACTION_SPAN "Transaction"
#define HTTP_SPAN "HTTP"
#define DB_SPAN "DB" 
#define MESSAGING_SPAN "Messaging"
#define METHODS_SPAN "Methods"
#ifdef __unix__
#define LinuxScript "/scripts/script.sh"
#define AWSLinuxScript "/scripts/awsmetadataresolver.sh"
#define AZURELinuxScript "/scripts/azuremetadataresolve.sh"
#define JSONLinuxscript "/scripts/jsonfilemetadataresolve.sh"
#define GCPLinuxScript "/scripts/gcpmetadataresolve.sh"
#else
#define WindowsScript "\\scripts\\script.bat"
#define AWSWindowsScript "\\scripts\\awsmetadataresolver.bat"
#define JSONWindowsScript "\\scripts\\jsonfilemetadataresolve.bat"
#define AZUREWindowsScript "\\scripts\\azuremetadataresolve.bat"
#define GCPWindowsScript "\\scripts\\gcpmetadataresolve.bat"
#endif






/*ASGraphData structure */
typedef struct ASGraphData_t
{
  long long MinTimeAllHotSpotThread;
  long long MaxTimeAllHotSpotThread;
  int TotalCountAllHotSpotThreads;
  long long TotalTimeAllHotSpotThreads;

  int TotalCountNewHotSpotThreads;
  long long TotalTimeNewHotSpotThreads;
  long long MinTimeNewHotSpotThreads;
  long long MaxTimeNewHotSpotThreads;

  int numOfBlockedThreads;
  int numOfRunnableThreads;
  int numOfTerminatedThreads;
  int numOfTimedWaitingThreads;
  int numOfWaitingThreads;
  long long totalNumOfThreads;
}ASGraphData_t;

extern double getAvgTimeNewHotSpotThreads();
extern double getMinTimeNewHotSpotThreads();
extern double getMaxTimeNewHotSpotThreads();
extern void asGraphDataInit();

extern double getAvgTimeAllHotSpotThreads();
extern double getMinTimeAllHotSpotThread();
extern double getMaxTimeAllHotSpotThread();
extern int getTotalCountNewHotSpotThreads();
extern int getTotalCountAllHotSpotThreads();
extern long long getTotalNumOfThread();
//extern void setHotSpotDuration(long long time , char isNew, int totalNumOfThreads);

/*NDLB_Sock structure */
#define NDLB_PARTIAL_LINE -1
#define NDLB_CONNECTION_CLOSE -2
#define NDLB_CONNECTION_TIMEOUT -3
#define NDLB_APR_ERROR -4
#define NDLB_DATALEN_ZERO -5

extern int nslb_encode_base64_ex(unsigned char* input, int input_length, unsigned char* output, int output_size);
//extern char* nslb_encode_text_to_base64(char* text_input, int text_len, int* enc_len);
//HPLOG:changes for websocket
typedef struct {
  struct lws* wsi;
  struct lws_context* context;
} lws_handler_t;

typedef struct {
  struct lws* wsi;
  char buf_to_send[1];
  int send_size;
} proxy_lws_handler_t;
//HPEND

extern apr_socket_t* ndlb_create_client_con(char* hostname, int port, char* error_buf, int error_buf_len, apr_pool_t* pool);
extern int ndlb_read_line(apr_socket_t* skt, char* read_buf, int buf_size, char** partial_buf, int* partial_buf_len, char* error_buf, int error_buf_len);
extern int ndlb_read_n_bytes(apr_socket_t* skt, char* read_buf, int buf_size, char* error_buf, int error_buf_len);
extern int ndlb_read_bytes(apr_socket_t* skt, char* read_buf, int buf_size, char* error_buf, int error_buf_len);
extern int ndlb_receive_bytes(apr_sockaddr_t *saddr, apr_socket_t *skt, char *read_buf, int buf_size, char *error_buf, int error_buf_len);
extern int ndlb_send_n_bytes(apr_socket_t* skt, char* buffer, int buf_size, char* error_buf, int error_buf_len);
extern int ndlb_sendto_n_bytes(apr_socket_t *skt, apr_sockaddr_t *saddr, char *buffer, size_t buf_size);
extern int get_src_addr(apr_socket_t* sock, char* buf, int len, int* port);
extern int get_dst_addr(apr_socket_t* sock, char* buf, int len, int* port);


typedef void (*ad_callback_php)(char *methodFiltersPatternList[], char *classFiltersPatternList[], int msize, int csize);
extern ad_callback_php ad_callback_func_php;
void register_AD_callback_php(ad_callback_php adfunc_php);

#ifdef __cplusplus
extern "C" void handleMessageForDiscovery(char* str);
#else
extern void handleMessageForDiscovery(char *str);
#endif

/*Control_thread structure */
#define ERROR_BUFFER_SIZE 1024
#define SLEEP_INTERVAL 60000000 
#define LOG_MSG_SLEEP_INTERVAL 2000000
#define FLUSH_INTERVAL 100000 //100 ms

enum span_message_type {
  SPAN_TYPE_TRANSACTION = 0,
  SPAN_TYPE_HTTP_CALLOUT,
  SPAN_TYPE_DB_CALLOUT,
  SPAN_TYPE_MESSAGING,
  SPAN_TYPE_METHODS
};
enum ND_AGENT_TYPE {
  ND_AGENT_PYTHON=0,
  ND_AGENT_PHP=1,
  ND_AGENT_DOTNET=2,
  ND_AGENT_JAVA=3,
  ND_AGENT_GO=4
};


enum udp_data_type {
  UDP_DATA_ALL,
  UDP_DATA_NDCOOKIE,
  UDP_DATA_NVCOOKIE,
  UDP_DATA_TEST,
  UDP_DATA_BACKEND_RULE,
  UDP_DATA_CORELATION,
  UDP_DATA_OTEL,
  UDP_DATA_DBBACKENDNAME
};

typedef struct
{
  char sourceIp[16];
  char dstIp[16];
  //char* partial_buf;
  int srcPort;
  int dstPort;
  //int partial_buf_len;
  apr_socket_t* skt;
  lws_handler_t lws_handler;
}socketInfo_t;

typedef struct
{
  char* read_socket_buf;
  apr_size_t read_len;
  int readOffset;
  int writeOffset;
  int readBytes;
}controlSocketBuffer_t;

//HPLOG:changes for websocekt
//lws_handler.h
//void create_lws_control_connection(char* host, char* port);
//void create_lws_data_connection(char* host, char* port);
//void create_lws_as_connection(char* host, char* port);
//void create_lws_discovery_connection(char* host, char* port);
//void create_lws_bulk_data_connection(lws_handler_t* bulkDataHandler, char* host, char* port);

int get_lws_src_addr(lws_handler_t* lwsHandler, char* ip, int* port);

int send_control_data_via_lws_socket(char* buf, int len);
int send_pending_control_data();
int send_data_via_lws_socket(char* buf, int len);
int send_as_data_via_lws_socket(char* buf, int len);
int send_discovery_data_via_lws_socket(char* buf, int len);
int send_bulk_data_via_lws_socket(struct lws_context* context,struct lws *wsi, char* buf, int len);
void create_lws_bulk_data_connection(lws_handler_t* bulkDataHandler, char* host, int port);

void clean_control_conn(int destroy_context);
void clean_data_conn();
void clean_as_conn();
void clean_discovery_conn();
void clean_bulk_data_conn(lws_handler_t* handler);
void clean_log_conn(int del_context);

int rec_control_conn_response_lws(controlSocketBuffer_t* localctrlBufInfo);
int handle_msg_from_ndc_lws(controlSocketBuffer_t* localctrlBufInfo);
int start_control_connection_service(controlSocketBuffer_t* localctrlBufInfo);
void lws_control_connection_add_to_buffer(char* data, int len);
int read_data_from_lws(struct lws_context* context, char* recv_buf, int len);

char* get_file_from_NDC_lws(char* keyword, int kwIdx);
char* get_inst_profile_lws(char* keyword, int kwIdx);



//NDSocketManager.h
/*void create_control_conn(struct NDProxyInstance_t* tlndApplication, char* hostname, int port, char* error_buf, int error_buf_len, struct apr_pool_t* pool);
  void create_data_conn(struct NDProxyInstance_t* tlndApplication, char* hostname, int port, char* error_buf, int error_buf_len, struct apr_pool_t* pool);
  void create_as_conn(struct NDProxyInstance_t* tlndApplication, char* hostname, int port, char* error_buf, int error_buf_len, struct apr_pool_t* pool);
  void create_discovery_conn(struct NDProxyInstance_t* tlndApplication, char* hostname, int port, char* error_buf, int error_buf_len, struct apr_pool_t* pool);
  int get_src_addr_wrapper(socketInfo_t* socket, char* buf, int len, int* port);
  void send_AS_data();
  int send_discovey_data(char* buffer, int buf_size, char* error_buf, int error_buf_len);
  int send_bulk_data(char* buffer, int buf_size, char* error_buf, int error_buf_len);*/
//HPEND
extern enum span_message_type arSpanType[SPAN_TYPE_METHODS+1];
//extern int isMasterNdc;
//extern int heartbeat_count;
//extern controlSocketBuffer_t ctrlBufInfo;
extern char* partial_buf;
extern int partial_buf_len;
extern void* control_thread_entry_fun(apr_thread_t* thd, void* data);
//extern socketInfo_t control;
extern void controlSockBufInit();
extern void processControlConnectionMessage(controlSocketBuffer_t* localctrlBufInfo);
//extern controlSocketBuffer_t ctrlBufInfo;

/*Msg Handling structure */
extern void message_handling(char* msg);

/*NDASSetting structure */
typedef struct NDASSettings_t
{
  char ASNegativeThreadFilter;
  char ASPositiveThreadFilters;
  char onlyAPICall;
  //char ASDoNotFilterBlocked;
  char ASEnableFPInSummaryReport;       // If true, FP instace will be set in hot spot hasp map when new flow path starts
  //char changeDone;
  //short deadlockCaptureLevel;
  int threadSampleInterval;             //This will be sent from NDCollector side to set the duration for the API Call of stackTarce of all the
  // threads
  int thresholdMatchCount;              //threadHotSpotThresold/threadSampleInterval
  int threadReportDumpMode;             //this mode decides where to dump the 51 and 52 records - modes : 0 none 1 socket(default) 2 file 3 
  //both file and socket for filtering
  int threadStackCompareDepth;          //to compare depth basis stacks
  int threadStackCompareOption;         //to compare mode basis for comparing either with hashcode or with stackTraceElements
  int threadFilteringStackDepth;        //to check a threads depth for filtering
  //TODO ArrayList<String> blackListThreadCollection = new ArrayList(200);//The collection which has all the latest StackTraces for each Individual threads coming in each sample.
  //TODO ArrayList<String> whiteListThreadCollection = new ArrayList(200);//The collection which has all the latest StackTraces for each Individual threads coming in each sample.
  int threadStateReport;
  int autoSensorTraceLevel;
  int enableFPInSummaryReport;

  //TODO NIOSettings nioSettings = new NIOSettings();

  long long threadReportInterval;       //after every this interval  we need to send and dump hotspotThreadInfo
  //long long progressReportInterval;     //added progress Interval
  int enableHotspotRecord;   //if = 2, Enable Method HotSpot (For Debugging Only)

}NDASSettings_t;

#ifdef __cplusplus
extern "C" NDASSettings_t NDASSettings;
#else
extern NDASSettings_t NDASSettings;
#endif
extern char isOnlyAPICall();
extern int getThreadSampleInterval();
extern char* toString();
extern long long getThreadReportInterval();
extern char setThreadSampleInterval(char* strKeywordValue, char* keyword, int index);
extern char setThreadReportInterval(char* strKeywordValue, char* keyword, int index);
extern char setThresholdMatchCount(char* strKeywordValue, char* keyword, int index);
extern char setThreadStackCompareDepth(char* strKeywordValue, char* keyword, int index);
extern void setNDMonitorInterval(char* strKeywordValue, char* keyword, int kwIdx);
extern char setThreadReportDumpMode(char* strKeywordValue, char* keyword, int index);
extern void setASEnableHotspotRecord(char* strKeywordValue, char* keyword, int kwIdx);   //if = 2, Enable Method HotSpot (For Debugging Only)
extern void NDASSettingInit();

/*NDAutoDiscoverHandler structure */
typedef struct NDAutoDiscoveryHandler_t
{
  char connId[256];
  char* methodFiltersPatternList[BUFFER_LEN];
  int methodListLength;
  int classListLength;
  char* classFiltersPatternList[BUFFER_LEN];

}NDAutoDiscoveryHandler_t;

//extern NDAutoDiscoveryHandler_t *NDAutoDiscoveryHandler;

extern void startLoadedClassDiscovery(char* clientMsg);


/*NDAutoInstrumentation structure */
typedef struct ndAutoInstrumentation_t
{
  int isDDObject;                                                       //keyword to determine whether the structure contains keyword configuration for DD
  int autoInstrSampleThreshold;                         //keyword for sample threshold count
  int autoInstrTraceLevel;                                      //separate trace level for AI
  int autoInstrMapSize;                                         //max size of maps used
  double autoInstrPct;                                          //percentage for AI of methods from map
  int autoInstrDurationThreshold;                       // max average duration of method used for uninstrumentation of methods
  double autoUnInstrPct;                                        // percentage for uninstrumentation of methods from map
  long long int autoInstrSessionInterval;       // duration of the debug session for AI entered by user 
  int exceptionWeight;                                          //weight for exception classes
  int exitPointWeight;                                          //weight for exit points
  long long int autoInstrTotalDuration;         //duration of the debug session for AI entered by user in milli seconds
  long long int autoInstrStartTime;                     //counter to denote the start of the debug session.
  char isDebugSessionMode;                                      // keyword to enable or disable AI
  char isSessionCompleted;                                      // keyword to enable or disable AI
  char AutoInstrRetainChanges;                  // keyword to retain changes in next AI cycle
  char* autoInstrSessionName;                   // name of the session to be used for dumping AI files
  int minStackDepthDebugSession;                        //min stack depth to be considered for auto instrumentation
}ndAutoInstrumentation_t;


// #ifdef __cplusplus
// extern "C" ndAutoInstrumentation_t ndAutoInstrumentation;
// #else
// extern ndAutoInstrumentation_t ndAutoInstrumentation;
// #endif

//extern void DumpDataForAutoInstrumentation(ndAutoInstrumentation_t ndAutoInstrKeyword);
extern void setdefaultValues();
extern void setClassWeight(char* exceptionWeight, char* keyword, int kwIdx);

extern void setMinStackDepthForDebugSession(char* minStackDepthDebugSession, char* keyword, int kwIdx);
extern void setAutoInstrSessionInterval(char* value, char* keyword, int kwIdx);
extern void setRetainAutoInstrMethods(char* value, char* keyword, int kwIdx);
extern void setDebugSessionMode(char* value, char* keyword, int kwIdx);
extern void parseAutoInstrClientMsgAndSendResp(char* clientMsg);


/*NDAutoSensorUsingStackTrace structure */
typedef struct ndAutoSensorUsingStackTrace_t
{
  char isNewMonitorRecordEnabled;

}ndAutoSensorUsingStackTrace_t;

#define MAX_REPORT_SIZE 262144 // 256k
#define ND_VECTOR_PREFIX_ID_SIZE 128
#define ND_VECTOR_PREFIX_SIZE 128
extern apr_thread_mutex_t* counterLock;
extern void setMonitorEnabledForID(int isBackendMonitor);
extern void NDAutoSensorUsingStackTraceInit();
extern void* start_autoSensor_thread(apr_thread_t* thd, void* data);
//extern void sendHotSpotRecord(long long ThreadID, char *ThreadName, long long hotSpotStartTime, long long hotSpotDuration, char isNewHotspot, char *ThreadState, int ThreadPriority, int ThreadStackDepth, long long timeStamp, char *fpi, char *stackTrace, long long FlowpathId);
extern void setToStopThread(char flag);

#ifdef __cplusplus
extern "C" void sendHotSpotRecord(long long ThreadID, char* ThreadName, long long hotSpotStartTime, long long hotSpotDuration, char isNewHotspot, char* ThreadState, int ThreadPriority, int ThreadStackDepth, long long timeStamp, char* fpi, char* stackTrace, long long FlowpathId);
extern "C" void sendGCReport(int id,char* GC_report);
#else
extern void sendHotSpotRecord(long long ThreadID, char* ThreadName, long long hotSpotStartTime, long long hotSpotDuration, char isNewHotspot, char* ThreadState, int ThreadPriority, int ThreadStackDepth, long long timeStamp, char* fpi, char* stackTrace, long long FlowpathId);
extern void sendGCReport(int id,char* GC_report);
#endif

extern void setToStopThread(char flag);
/*NDBCISetting Structure */
#define MAX_READ_LENGTH 128*1024
#define BUF_4K 4*1024
#define FORCED_INSTRUMENTATION_DISABLED = 0
#define FORCED_INSTRUMENTATION_ENABLED = 1
#define FORCED_INSTRUMENTATION_ENABLED_ENTRY_EXIT = 2
#define AUTOSCALINGMODE_POOLSTAR 0
#define AUTOSCALINGMODE_POOLPID 1
#define AUTOSCALINGMODE_NDC 2
#define AUTOSCALINGMODE_POOL 3


typedef struct
{
  char* agentType;
  char* tierName;
  char* appServerName;
  char* appServerName_NDC;
  char* appName;
  char* encodedtierName;
  char* encodedappServerName;
  char* encodedappName;
  char* ndcHost;
  int CAV_INSTANCE_AS_TIER;
  char btErrorArray[600];
  char machineType[128];
  char fileBasedKeywordMode;
  char data_thread_running;
  char log_thread_running;
  char autoSensor_thread_running;
  char serverIp[1024];
  char controlConnectionReqMessage[2048];
  char control_conn_heartbeat_msg[2048];
  char controlDataReqMessage[2048];
  char controlAutoSensorReqMessage[2048];
  //char enableJsrInlinerForAll;
  //char enableComputeFrame;
  int  tierID;
  int  serverID;
  int  appID;
  int  ndcPort;
  int  num_ndc_config;
  int  bciPort;
  int pastLog;
  int fpMaxAllowedAgeInSec;
  //int  bciStartupDelay;
  //int  sleepInterval;
  int  controlConnectionReqMessage_len;
  int  controlDataReqMessage_len;
  int  controlAutoSensorReqMessage_len;
  int  control_conn_heartbeat_msg_len;
  //int  enableAutoInstrumentation;
  //int  removeSafetyNetMode;
  int autoScalingMode;
  int flagForHandlingProxy;
  long long lastModifiedDate;
  long long  prevFileSize;
  //char* protocol;
  //char* backupHost;
  //int backupPort;
  char* tierAttr;
  char* agentAppName;
  char* endPointPrefix;
  //char* tierTag;
  //char* agentLogMode;
  char saasMode;
  char *saasHost;
  int  saasPort;
  char *projectKey;
  char *authToken;
  //char *projectName;
  int ProtoVer;
  //char* errMsg;
  //int errorCode;
  char isEnableEnvVar;
  int ndc_TCP_Port; //Protocol Negotiation Changes
  int ndc_WS_Port;
  int ndc_WSS_Port;
  int stackSize;
  apr_hash_t* taglist;
  apr_hash_t* attributelist;
  char* json_tag;
  char* tagnew;
  char* agentVersion;
  enum ND_AGENT_TYPE ndAgentType;
  int connId;
}NDBCISetting_t;

extern NDBCISetting_t NDBCISetting;

extern void setPastLogTime(char*);
extern void setconctimeout(char* conc_timeout);
extern void setTierName(char*, char* keyword, int kwIdx);
extern char* getTierName();
extern char* getencodedTierName();
extern void setAppServerName(char*, char* keyword, int kwIdx);
extern void setAppServerName_NDC(char*, char* keyword, int kwIdx);
extern char* getAppServerName();
extern char* getencodedAppServerName();
extern void setAppName(char* instance, char* keyword, int index);
extern char* getAppName();
extern char* getencodedAppName();
extern void setTierID(int tierId, char* keyword, int idx);
extern int getTierID();
extern void setServerID(int serverId, char* keyword, int sidx);
extern int getServerID();
extern void setAppID(int InstanceID, char* keyword, int idx);
extern int getAppID();
extern void setNDCHost(char*);
extern char* getNDHost();
extern void setNDCPort(int);
extern int getNDCPort();
extern void setBCIPort(int);
extern int getBCIPort();
//extern void setBciStartupDelay(int delay);
//extern int getBciStartupDelay();
// extern int getSleepInterval();
// extern void setSleepInterval(int);
extern void setControlConnectionReqMessage();
extern char* getControlConnectionReqMessage();
extern long long getLastModifiedDate();
extern void setLastModifiedDate(long long);
extern long long getPrevEditedSize();
extern void setPrevEditedSize(long long);
//extern char isEnableComputeFrame();
//extern void setEnableComputeFrame(char*);
//extern int getEnableAutoInstrumentation();
//extern void setEnableAutoInstrumentation(char*);
//extern int getRemoveSafetyNetMode();
//extern char isEnableJsrInlinerForAll();
//extern void setEnableJsrInlinerForAll(char*);
extern void setControlDataReqMessage();
extern void setControlAutoSensorReqMessage();
extern void NDBCISettingInit();
extern void setAutoScalingMode(int mode);
extern void resetNDCHostAndPort();
extern void setAgentType(char* agentType);
extern void setAgentVersion(char* agentVersion);
extern int read_env_var();
//extern void setComProt(char* Prot);
//extern void setBackUpHostName(char* hostname);
//extern void setBackUpPort(int Port);
extern void setTierAttr(char* tierAttr, char* keyword, int kwIdx);

extern void setAgentAppName(char* agentAppName);
extern void setEndPointPrefix(char* prefix);
//extern void setTierTag(char* tierTag);
//extern void setAgentLogMode(char* agentMode);
extern void setProjKey(char* projKey);
extern void setSaasHostPort(char* saasUrl);
extern void setAuthtoken(char* authtoken);
//extern void setProjName(char* projName);
extern void setProtoVer(char* ProtVer);
extern int parseSAASClientMsg(char* buf);
//extern void setErrorMsg(char* errorMsg);
//extern void setErrCode(char* errCode);
extern void setNDC_TCP_Port(int port);  //Protocol Negotiation Changes
extern void setNDC_WS_Port(int port);
extern void setNDC_WSS_Port(int port);
extern void setStackSize(int stack_size);

/*NDBT_Define Structure */
#define MAX_FILE_NAME_LEN     1024
#define MAX_LINE_SIZE        2048
#define MAX_TIME_LEN          128
#define RULE_TABLE_INIT_SIZE  32
#define BT_MAP_INIT_SIZE      32
#define MAX_HEADER_LEN        256
#define MAX_URL_LEN           256
#define MAX_PARAM_LEN         256
#define MAX_BT_NAME_LEN       256 
#define MAX_RULE_FIELDS        10
#define MAX_URI_NUM_SEG        32
#define MAX_CUSTOM_RULE_FIELDS  16

// ------------------------------------------------------------------------------------------------------------
/************ TRUE/FALSE ************/
#define ND_TRUE         1
#define ND_FALSE        0

#define NDLB_STRCPY(dst,src,size)  \
{ \
  if(dst && src && (size > 0)) { \
    strncpy(dst,src,size); \
    dst[size] = '\0'; \
  } \
  else \
  {   \
    NDTL1(NULL, NULL, NULL, TL_ERROR, "Invalid string copy operation from %p to %p size %d",src,dst,size); \
  } \
}
// ------------------------------------------------------------------------------------------------------------

#define  GLOBAL_RULE_TYPE     1
#define  CUSTOM_RULE_TYPE     2
#define  EXCLUSION_RULE_TYPE  3

//GLOBAL rule mode
#define  COMPLETE_URI                   1
#define  SEGMENT_OF_URI                 2
#define  COMPLETE_URI_WITH_REQ_PARAM    3
#define  SEGMENT_OF_URI_WITH_REQ_PARAM  4

//GLOBAL Rule REQ naming constants
#define  USE_URI_STARTS_WITH    1
#define  USE_URI_ENDS_WITH      2
#define  USE_URI_IS_IN_LIST     3
#define  USE_HTTP_METHOD        4
#define  USE_PARAMETERS         5
#define  USE_HEADERS            6
#define  URI_IN_SEGMENT      2
#define  DEFAULT_SEGMENT_VAL  "1%2C2"

// ------------------------------------------------------------------------------------------------------------
//Matching constraint
#define START_WITH      0x1
#define END_WITH        0x2
#define CONTAINS        0x3 
#define EQUALS          0x4
#define MATCH_REGEX     0x5
#define NOT_EMPTY       0x6
#define IS_IN_LIST      0x7


/*NDBT_RULE Execute Structure */

// ##### constant used with pattern based rule #####
#define BT_PATTERN_BASED_EXCLUDE_ID        -2
#define BT_PATTERN_BASED_NOT_FOUND_ID      -1
#define EXACT_MATCH_MODE                    0
#define STARTS_WITH_MODE                    1

// ##### custom rule mode #####
#define MATCH_ONLY_METHOD               1
#define MATCH_ONLY_URI                  2
#define MATCH_ONLY_PARAMETERS           3
#define MATCH_ALL_CRITERIA              8
#define MATCH_URI_WITH_SPLIT            21

// ##### constant defining HTTP method with matching criteria #####
#define HTTP_METHOD_TYPE_GET            0
#define HTTP_METHOD_TYPE_POST           1
#define HTTP_METHOD_TYPE_PUT            2
#define HTTP_METHOD_TYPE_DELETE         3

// ##### constants for splitting mode #####
#define SPLIT_UPON_URI                  0
#define SPLIT_UPON_PARAM                1
#define SPLIT_UPON_METHOD               2

// ##### constants for defining splitting mode based upon #####
#define INCLUDE_URI_WITH_FIRST_N_SEGMENTS       0
#define INCLUDE_URI_WITH_LAST_N_SEGMENTS        1
#define INCLUDE_URI_WITH_LIST_OF_SEGMENTS       2

#define PARENT_RULE_ID      -1
#define SELF_RULE_ID        -1

typedef struct NDBTGlobalRule
{
  int  rule_mode;
  //int  match_type;
  char parameter[MAX_PARAM_LEN + 1];
  char parameter_at_start[MAX_PARAM_LEN + 5];
  int parameter_at_start_len;
  char parameter_at_end[MAX_PARAM_LEN + 5];
  int parameter_at_end_len;
  char header[MAX_HEADER_LEN + 1];
  int  include_uri_in_name_order;
  int  include_uri_in_name_segment;
  int  seg_type;
  int  uri_seg_no_list[MAX_URI_NUM_SEG];
  int  uri_seg_no_list_length;
}NDBTGlobalRule;

typedef struct NDBTPatternBasedRule
{
  char transactionName[256];
  int transactionId;
  char matchType;
  char pattern[256];
  char excludeMode;
  char patternMode;
  char parameter[256];
  char httpMethod[256];
  char BTHeaderName[256];
  char BTHeaderValue[256];
  int selfRuleId;
  int parentRuleId;
}NDBTPatternBasedRule;


typedef struct URIParamObject
{
  //char ruleName[256];
  char parameterName[256];
  char checkExistence;
  char parameterValue[256];
  char parameterOperation;
}URIParamObject;

typedef struct NDBTHeaderBasedRule
{
  char headerName[MAX_HEADER_LEN];
  char headerValue[MAX_HEADER_LEN];
}NDBTHeaderBasedRule;

typedef struct Threshold
{
  int slow;
  int very_slow;
}Threshold;

extern NDBTGlobalRule* global_rule;
extern NDBTHeaderBasedRule* header_rule;

extern char* ndbt_execute_global_rule(char* uri, char* param, char* method, char* header, char* btName, int size);
extern void ndbt_execute_header_rule(char* url, char* bt_name, int len);
extern char* ndbt_execute_custom_rule(char* uri, char* parameter, char* httpMethod, char* btName, int size);




/*NDBtManager structure */
#define   CATEGORY_TRANSACTION_NORMAL        10
#define   CATEGORY_TRANSACTION_SLOW          11
#define   CATEGORY_TRANSACTION_VERY_SLOW     12
#define   CATEGORY_TRANSACTION_ERROR         13
#define   CATEGORY_TRANSACTION_STALLED       14//not supported at intiital phase
#define   CATEGORY_TRANSACTION_UNKNWON       15//not supported at intiital phas

//extern void dumpBtMetaData(char* BtName, int BtId);




/*NDBT_Custom Structure */
#define CHAR_TO_INDEX(ch)       ((int)ch - 32) // shift every character by 32 as from 0-31 are non printable characters

#define MAX_CHARACTERS          95             // For only character that are printable
#define TOTAL_STATES            256            // should be greater than sum of the length of all keywords present in dictionary, by default 
#define MAX_URI_N_PARAM         256

#define MAX_KEYWORD_SIZE        256
#define MAX_BT_SIZE             128
#define DEFAULT_LEXICON_SIZE    20


typedef struct NDLBKeywordLexicon
{
  char keyword[MAX_KEYWORD_SIZE];
  char bt_name[MAX_BT_SIZE];
  char match_constraint;
  unsigned int priority;
  unsigned int elements_len;
}NDLBKeywordLexicon;

typedef struct NDBTCustomRule
{
  char chkExistence;
  char activateReversCondition;
  char setEnabled;
  char UriOperationType;
  char matchHttpMethod;
  char HTTPMethod[64];
  char rule_name[128];
  char setRuleName[256];
  char MatchUriValue[256];
  int rule_mode;
  int match_only_uri_count;
  unsigned int match_only_param_count;
  unsigned int priority;
  unsigned int keyword_count;
  NDLBKeywordLexicon* dictionary;
  URIParamObject* matchingURIParamObj[MAX_URI_N_PARAM];
}NDBTCustomRule;

typedef struct ndlbTrie
{
  unsigned int total_states;
  int** childrens;
}ndlbTrie;



extern int ndlb_init_automaton(ndlbTrie* trie_node, NDBTCustomRule* rule);
extern int dealloc_match_machine(ndlbTrie* trie_node, NDBTCustomRule* rule);
extern char* search_match_machine(char* input, ndlbTrie* trie_node, NDBTCustomRule* rule);

extern int add_to_lexicon(NDBTCustomRule* rule, char* keyword, int priority, char* bt_name, char match_constraint);
extern int dealloc_lexicon(NDBTCustomRule* rule);
extern NDLBKeywordLexicon* DictionaryHeadPointer;
extern unsigned int all_keyword_len;

//extern NDBTCustomRule custom_rule;
//extern ndlbTrie trie_node;


typedef struct uniquetagrecord {
  int tagid;
  int dumpTagValue;
}UniqueTagRecord;


/*Newly added NDBT_BT_OBJ structure */
typedef struct BTObject
{
  char bt_name[MAX_BT_NAME_LEN + 1];
  //char bt_header_name[MAX_HEADER_LEN+1];
  //char bt_header_value[MAX_HEADER_LEN+1];
  char bt_category;
  int is_meta_data_dumped;
  int bt_id;

  // following fields will be set after parsing the DD_Configuration file when DD is enabled.
  long long bt_startTime;
  long long bt_endTime;
  long long dd_IntervalTime;
  char AIFlag;
  int inactive;
  Threshold bt_threshold;
  int enableBodyCapture;
  int maxBodySize;
  int selfID;
  int parentID;
  int prevPID;
  int isBTOverride;
  int btCounter;
}BTObject;

typedef struct BTObjectMap
{
  //BTObject* *bt_obj;
  //int bt_obj_max_enteries;
  //int bt_obj_total_enteries;
  apr_hash_t* hash;
}BTObjectMap;

typedef struct NDBTConfigModel
{

  BTObjectMap bt_obj_map;
  int max_bt_count;
  int total_bt_count;
}NDBTConfigModel;


typedef struct NDBTManager
{
  apr_thread_mutex_t* bt_obj_map_lock;
  BTObjectMap bt_obj_map;

}NDBTManager;

typedef struct NDBTTagManager
{
  apr_thread_mutex_t* tag_obj_map_lock;
  apr_hash_t *tag_obj_map;

  apr_thread_mutex_t* bt_tag_obj_map_lock;
  apr_hash_t *bt_tag_obj_map;
}NDBTTagManager;

#ifdef __unix__
extern char* getBTHeaderName();
#endif

/*extern NDBTManager manager;
  extern NDBTConfigModel config;*/
extern BTObjectMap bt_obj_map;

extern void reset_BTObjMap(int val);
extern BTObject* get_obj_from_bt_name(char* bt_name, char* parameters, char* btHeaderValue, apr_thread_mutex_t* updateBTLock, char* method);
extern BTObject* find_bt_obj_in_manager_map(char* bt_name);
extern BTObject* find_bt_obj_in_config_map(char* bt_name, int bt_id, int slow, int verySlow, int selfID, int parentID);
extern BTObject* make_new_bt_obj(char* bt_name, int bt_id, int slow, int verySlow);
extern void insert_bt_obj_in_map(BTObjectMap* map, char* bt_name, BTObject* bt_obj);
extern void NDBTConfigModelInit();
extern BTObject* updateBTObject(char* bt_name);



/* Structuretruct node_t */
typedef struct node_t
{
  void* ptr;
//  void* dynamic_ptr;
  int ref_count;
  char type;
  long long timeStamp;
  struct node_t* next;
}node_t;


extern void addNodeToLinklist(node_t* node);
extern void checkAndDeleteNode();
extern int checkForLinkList();
extern void checkAndClearHashMapNode(int deleteNode);


/*NDMethodManager Structure */
typedef struct methodArgList_t
{
  char* argName;
  char* type;
}methodArgList_t;
typedef struct span_callout_fields {
  char callout_span_id[20];
  char host[1024];
  char port[20];
  char url_query[2048];
  char dbtype[20];
  apr_time_t start_time;
  apr_time_t end_time;
}Span_Callouts_Fields;

typedef struct methodPropProperties
{
  char type;
  char callOutValue;
  char* moduleName;
  char* methodName;
  char* mon_methodName;
  char* customCalloutName;
  char* aliasMethodName;
  char* methodRetType;
  char autoDeInstrFlg;
  char isInBlackListFlg;
  int methodId;
  int isEntryPoint;
  int usedFlag;
  int instrumentationProp;
  int instrumentationStatus;
  int isAsyncCall;
  int methodArgIndex;
  unsigned int methodArgsListCount;
  methodArgList_t* methodArgList;
  struct methodPropProperties* customCalloutptr;
  Span_Callouts_Fields spanFields;
}methodPropProperties;

typedef struct autoInstrumentation_t
{
  char* completeName;
  char* className;
  long int addedTimeStamp;
  char* methodName;
  int count;
  long duration;
  methodPropProperties* mPP;
}autoInstrumentation_t;

//extern apr_thread_mutex_t* methodEntryLock;
//extern apr_thread_mutex_t* nodeOperationLock;

//extern methodPropProperties* DefaultMethod;
//extern int dbBackendId;
extern int readInstrProfFile(apr_pool_t* pool, char* buffer);
extern methodPropProperties* getMethodPropFromMethodName(char* mName, node_t* return_ptr);
extern void dumpMethodMetaData();
extern void setMethodHashMapNode(char* buffer);
extern methodPropProperties* updateMethodHashMap(char* backendName, int isEntryPointPtr, int type, node_t* return_ptr, int callOutValue);
extern int readingFileInstrProfile();
extern void hashMapForAgent();
extern void makeHashmapCopyAndaddToLL();
extern void free_methodHashMapNode();
extern void resetmethodHashMapNode(void* hashMap, int type);
extern int readingEntryPointfile();
extern void dumpMetadataForSig(methodPropProperties* v1);

/*NDBackendMonitor Data Counter */
typedef struct _NDBackendMonitorDataCounters
{
  //common counters
  long long cumCount; // Total Business Transaction invocations since start of instrumentation.
  long long count;
  long long errorCount;
  long long duration;
  long long minDuration;
  long long maxDuration;

  //Lock between AS thread and App thraed
  methodPropProperties* mpp;
  char dataExist;

  //tdigest percentile calculation
  tdg_key *tdigest_key;
  char tdigestDataExist;

  //cdigest percentile calculation
  tslb_cdigest_t *cdigest_key;
  char cdigestDataExist;
}NDBackendMonitorDataCounters;

extern void initNDBackendMonitorDataCounters(NDBackendMonitorDataCounters* ptr);
extern void updateBackendDataCountersForAggregate(NDBackendMonitorDataCounters* aggDataObject, NDBackendMonitorDataCounters* currentObj);
extern void initOnStartInstrumentationIP(NDBackendMonitorDataCounters* ptr);



#define     INT_MAX_VALUE           0x7FFFFFFF
#define     LONG_MAX_VALUE          0x7FFFFFFFFFFFFFFF
//#define     DOUBLE_MAX_VALUE        0x1.fffffffffffffP+1023;
#define     DOUBLE_MAX_VALUE        500000

typedef struct _NDBTMonitorDataCounters
{
  //common counters
  int count; // Total Business Transaction invocations since start of instrumentation.
  long long duration; // Sum of duration(ms) of the Business Transaction invocation in the sample period.
  long long minDuration;
  long long maxDuration;

  //cpu time counters
  long long  cpuTime;
  long long minCpuTime;
  long long maxCpuTime;

  //Normal counters
  int normalCount; // Total Business Transaction invocations since start of instrumentation.
  long long normalDuration; // Sum of duration(ms) of the Business Transaction invocation in the sample period.
  long long minNormalDuration;
  long long maxNormalDuration;

  //Slow counters
  int slowCount; // Total Business Transaction invocations since start of instrumentation.
  long long slowDuration; // Sum of duration(ms) of the Business Transaction invocation in the sample period.
  long long minSlowDuration;
  long long maxSlowDuration;

  //VerySlow counters
  int verySlowCount; // Total Business Transaction invocations since start of instrumentation.
  long long verySlowDuration; // Sum of duration(ms) of the Business Transaction invocation in the sample period.
  long long minVerySlowDuration;
  long long maxVerySlowDuration;

  //Error counters
  int errorCount; // Total error occurred from Business Transaction invocations since start of instrumentation.
  long long errorDuration; // Sum of duration(ms) of the Business Transaction invocation in the sample period.
  long long minErrorDuration;
  long long maxErrorDuration;

  //wait time counters
  int waitCount;
  long long cumWaitTime;
  long long minWaitTime;
  long long maxWaitTime;


  //Sync Time Counters
  int syncCount;
  long long cumSyncTime;
  long long minSyncTime;
  long long maxSyncTime;

  //Queue Time
  int queueCount;
  long long minQueueTime;
  long long maxQueueTime;
  long long cumQueueTime;

  BTObject* tlBTObj;
  //Lock between AS thread and App thraed
  char dataExist;

  //tdigest data
  tdg_key *tdigest_key;
  char tdigestDataExist;
  
  //cdigest data
  tslb_cdigest_t* cdigest_key;
  char cdigestDataExist;
  char *tagName;
  int unique_id;
  int btId;
}NDBTMonitorDataCounters;



/*MethodMoniotrData Counter structure */

#define     INT_MAX_VALUE           0x7FFFFFFF
#define     LONG_MAX_VALUE          0x7FFFFFFFFFFFFFFF
//#define     DOUBLE_MAX_VALUE        0x1.fffffffffffffP+1023;
#define     DOUBLE_MAX_VALUE        500000

typedef struct _NDMethodMonitorDataCounters
{
  int count;
  int cumCount;
  long long duration;
  long long minDuration;
  long long maxDuration;

  //Lock between AS thread and App thraed
  methodPropProperties* mpp;
  char dataExist;
}NDMethodMonitorDataCounters;

typedef struct currMonitoringExcepStruct_t
{
  int excepmethodid;            //method Id
  int setEnableExceptionMon;    //flag
  char* exceptionMethodName;    //FQM
  char* aliasMName;             //Display Name
}currMonitoringExcepStruct_t;

typedef struct _NDExceptionMonitorDataCounters_t
{
  int count;
  int cumCount;

  currMonitoringExcepStruct_t* expData;
  char dataExist;
}NDExceptionMonitorDataCounters;

typedef struct _NDExceptionMonitor_t
{
  int aggExceptionArraySize;
  NDExceptionMonitorDataCounters* aggExceptionDataArr;

  char vectorPrefix[1024]; //vector prefix containing tier server and app name  TODO check size
  char vectorPrefixID[64]; //vector prefix containing tier server and app name TODO check size
  int currentReportingCount;
  //int monitorIntervalInSecs;
  char isExceptionMonitorOn;
  int maxMethodCount;
  int numberOfThreads;
  //methodPropProperties *mpp;
}NDExceptionMonitor_t;

enum nd_tag_namespace {
  namespace_inline=0,
  namespace_http_url_query_param,
  namespace_http_request_headers,
  namespace_http_response_headers,
  //namespace_http_cookies,
  //namespace_http_sessions_param,
  //namespace_method_argument_value,
  //namespace_method_return_value,
  namespace_notused1,
  //  namespace_notused2,
  //  namespace_notused3,
  namespace_json,
  namespace_enviournment,
  namespace_nds,
  namespace_propfile,
 //   namespace_technology,
    //namespace_commandline   (commandline)
  namespace_kubernetes,
  namespace_aws,
  namespace_gcp,
    //namespace_docker (docker)
  //  namespace_cf,
    namespace_ms_azure,
    namespace_system
};

#define ND_TAG_TYPE_REQUEST_HEADERS  "Request_Headers"
#define ND_TAG_TYPE_RESPONSE_HEADERS  "Response_Headers"
#define ND_TAG_TYPE_ENV   "env"
#define ND_TAG_TYPE_NDS   "nds"
#define ND_TAG_TYPE_INLINE   "inline"
#define ND_TAG_TYPE_GCP   "gcp"
#define ND_TAG_TYPE_AWS   "aws"
#define ND_TAG_TYPE_KBNT   "k8s"
#define ND_TAG_TYPE_PROPFILE "prop"
#define ND_TAG_TYPE_SYSTEM "sys"
#define ND_TAG_TYPE_AZURE "azure"
#define ND_TAG_TYPE_JSON "json"


/*NDMonitorCommon Structure */
#define    INCREAMENT_TIME                2
#define    DEFAULT_SIZE_OF_DATA_OBJ      128
typedef struct BTTagArray {
  char* key;
  char *tagField;
  char* resolvedValue;
  enum nd_tag_namespace type;
  struct BTTagArray *next;
}BTTagArray;

typedef struct BTTagSeqArray {
  char *tagSeq;
  int tagId;
  long long flowpathInstance;
  struct BTTagSeqArray *next;
}BTTagSeqArray;

typedef struct _NDMonitorDataModel
{
  int                                 currentSizeOfBTArray;
  int                                 currentSizeOfBackendArray;
  int                                 currentSizeOfMethodArray;
  int 				                        currentSizeOfExcepMonArray;
  int                                 currentSizeOfBTSeqArray;
  int                                 currentSizeOfBTPerThreadArray;
  long long                           lastUpdateTimeStamp;
  apr_thread_mutex_t*                 lockForBT;
  apr_thread_mutex_t*                 lockForMM;
  apr_thread_mutex_t*                 lockForIP;
  apr_thread_mutex_t*                 lockForEM;
  apr_thread_mutex_t*                 lockForTA;
  NDBTMonitorDataCounters**           btmDataArray;
  BTTagArray**                        btPerThreadArray;
  BTTagSeqArray**                     btTagSeqArray;
  NDMethodMonitorDataCounters**       mmDataArray;
  NDBackendMonitorDataCounters**      ipmDataArray;
  NDExceptionMonitorDataCounters**    excepDataArray;
}NDMonitorDataModel;

//extern apr_hash_t* threadBasedModelMap;
extern void initThreadBasedModelMap();
void destroyNDMonitorDataModel();

/*BackeMonitor structure */

#define DEFAULT_MAX_IP_COUNT 32;
#define DEFAULT_MAX_AGG_DATA_SIZE_IP 128;
typedef struct
{
  int ndBackendMonTraceLevel;
  int maxIPCount;
  char vectorPrefix[1024]; //vector prefix containing tier server and app name  TODO check size
  char vectorPrefixID[64]; //vector prefix containing tier server and app name TODO check size
  char isBackendMonitorOn;
  int numberOfThreads;
  int aggDataArraySize;
  //int monitorIntervalInSecs;
  int backendIDCounter;
  NDBackendMonitorDataCounters* aggIPDataArr;
}NDBackendMonitor_t;


/* NDMethodMonitor_t structure */
#define DEFAULT_MAX_METHOD_COUNT 256
#define DEFAULT_MAX_AGG_METHOD_DATA_SIZE 128


typedef struct NDMethodMonitor_t
{
  int aggDataArraySize;
  NDMethodMonitorDataCounters* aggMethodDataArr;

  char vectorPrefix[1024]; //vector prefix containing tier server and app name  TODO check size
  char vectorPrefixID[64]; //vector prefix containing tier server and app name TODO check size
  int currentReportingCount;
  //int monitorIntervalInSecs;
  char isMethodMonitorOn;
  int methodMonitorTraceLevel;
  int methodMonitorErrorLevel;
  char sendReSetEventOnAggDataConn;
  int maxMethodCount;
  int numberOfThreads;
  char doNotDisacrdAnyTransaction;
  char ndMethodMonTraceLevel;
  methodPropProperties* mpp;
}NDMethodMonitor_t;


/*NDBTMonitor  Structure */

#define DEFAULT_MAX_BT_COUNT 256
#define DEFAULT_MAX_AGG_DATA_SIZE 128


typedef struct NDBTMonitor_t
{
  int aggDataArraySize;
  NDBTMonitorDataCounters* aggBTDataArr;
  int                                 currentSizeOfBTTagArray;
  char vectorPrefix[1024]; //vector prefix containing tier server and app name  TODO check size
  char vectorPrefixID[64]; //vector prefix containing tier server and app name TODO check size
  int currentReportingCount;
  //int monitorIntervalInSecs;
  char isBTMonitorOn;
  //int btMonitorTraceLevel;
  int btMonitorErrorLevel;
  //char sendReSetEventOnAggDataConn;
  int maxBTCount;
  int numberOfThreads;
  char doNotDisacrdAnyTransaction;
  BTTagArray             **           btTagArray;
  BTTagArray              *           btGlobalTag;
  apr_thread_mutex_t      *           btGlobalTag_lock;
}NDBTMonitor_t;

//aws account structure
/*typedef struct awscredential
{
 char *access_key_id;
 char *account_name;
 char *secret_access_key;
 char *region[25];
}awscredential;*/


//extern apr_hash_t *awsmap;


/*NDSQLProcessor Structure */

typedef struct NDSQLProcessor_t
{
  char isDefaultQueryRecordsDumped;
  char* DBIPName;
  int preparedQueryRecordID;
  long long sqlQueryID;
  apr_hash_t* preparedQueryIDLookup;
}NDSQLProcessor_t;

  ///Changes to capture method walltime and cput time in case of sdk

#if defined ND_SDK || defined ND_GOAGENT
typedef struct sdkAgentTimeDetails
{
  char key[20];
  long long startTime;
#ifdef __unix__
  long long mCPUTime;
#else
  clock_t mCPUTime;
#endif
}SDKAgentTimeDetails_t;
#endif

typedef struct sqlProp
{
  int DBCallDepth;
  long long sqlId;
  long long startTime;
  //long long backendId;
  char* DBQueryParam;
}sqlProp;


//extern NDSQLProcessor_t NDSQLProcessor;
//extern void  getSqlLock();
//extern void releaseSqlLock();

//extern void free_preparedQueryIDLookup();
extern void NDSQLProcessorInit();
extern void setDBIPName(char* dBIPName, char* keyword, int index);
extern void escapeHTML(char* sb, int len, char* msgData, int is_underscore);
extern void DBQueryParamEncoding(char* sb, int len, char* msgData);
extern void check_and_remove_slash_n(char *ptr);
extern void encode_n_tag(char *sb, int len, char *msgData);
extern char*decode_n_tag(char *msgData);
extern void decodeUnderscore(char *sb, char *msgData);
extern void encoded_with_underscore(char *sb, int len,char *msgData);

/*NDSQL Setting Structure */

typedef struct NDSQLSetting_t
{
  int sqlTraceLevel;
  /*ArrayList<String> SQLPreparedQueryFilterList = null;
    ArrayList<String> SQLNonPreparedQueryFilterList = null;*/

}NDSQLSetting_t;


extern char* decode_fun(const char* str);

/*NDCommonFrameWork structure */
#define MAX_BYTE_ARRAY_SIZE 16384 // 16 K
#define CONTEXT_HEADER "Custom_Header"

typedef struct NDPerThreadData_t
{
  char tlIsFPCaptured;
  char tlIsBTExcluded;
  char tlIsForceDump;
  char* prevTierSeq;                            //Used to store previous sequence number with dot(.).
  char tlCorrelationIdHeader[1024];              // thread local is used to store the value of correltionheader
  //char tlLogCompleteFlowPath;
  char sequenceBlob[MAX_BYTE_ARRAY_SIZE];       //A threadlocal SB to store seq of method entry and exit records
  char tlIsFPHeaderDumped;                      // A buffer to contain flow path header record (2 record)
  char tlCategory;
  char tlURL[512];                              //used for storing URL at thread level
  char tlURLParameters[512];                    //used for checking either the mode of flowpath generation is changed at run time and
  // accordingly change the mode
  int tlStatusCode;
  int tlServiceMethodDepth;                     //Entry depth of every call for each individual request thread
  int tlServiceMethodCount;
  int sequenceBlobLen;
  int tlNonServiceMethodCount;
  int httpCallOutDepth;

  char flowpathInstanceStr[32];
  long long flowpathInstance;
  long long tlsIdx;
  long long seqNum;
  /**
   * This will be used for storing URL at thread level
   */
  long long tlTestRunNumber;

  long long tlFlowPathTimeStampInMS;            //Threadlocal timestamp
  long long tlThreadId;                         //proxy/agent unique id for monitoring data
  long long tsid;                               //transaction thread id
  long long tlFpCPUTime;
  long long tlDuration;
  long long firstFlowpathInstance;
  long long prevFlowpathInstance;
 // long long tlTierStartTime;

  char* tierCallOutHeader;
  int tierCallOutHeaderLen;
  long long tierCallOutSeqNum;
  BTObject* tlBTObj;                            //This will be used for storing business transaction id
  sqlProp tlSQLObj;
  NDMonitorDataModel* tlMonitorDataModel;

  void* hasMapNodePtr; //for hashmap node

  //use for method stack
  //NS_STACK methodStack;
  struct NDPerThreadData_t* free_next; ////we cant make busy & free as union
  struct NDPerThreadData_t* free_prev; //busy list node can be added in another queue
  struct NDPerThreadData_t* busy_next; //and later on moved to free list
  struct NDPerThreadData_t* busy_prev;
  char setEndFPFlag;
  char reset_delayed_transaction;
  long long ndSessionId;
  long long cur_ndSessionId;
//  long long prev_fp_start_time;
  int instrumented;
  int btCategory;
  int exceptionCount;
  int totalFpcount;
  int tierID;
  int ndAppServerID;
  int appID;
  int tlFlowpathType;
  long long cavSID;
  long long NDPageID;
  long long last_fptimestamp_from_cookie;
  //long long agentThreadID;
  unsigned short threadIndex;
  long long int syncTime;
  long long int waitTime;
  long long int qTimeInMS;
  int debugModeLen;
  char debugModeBuf[128];
  int bitFlags;
  apr_thread_mutex_t* sequenceBlobLock;
  apr_thread_mutex_t* updateBTLock;

  //Vaibhav: Exception Variables
  char* excepMessage;
  int dumpERecordFlag;
  unsigned long long unwindfID;
  int exceptionFlagForEventType;
  char* excepClassName;
  char* throwingCName;
  char* throwingMName;
  char* exceptionBackendName;
  char* exceptionStackTrace;
  long long int fpStartTimeforReset;
  int prevPID;

  int methodEntryExitCounter[8*1024]; //Counter to restrict method Exit over method Entry

  int OTL_version;
  int OTL_traceflag;
  char* OTL_traceID;
  char* OTL_parentID;
  char trans_span_id[32];
  char callout_span_id[32];
  char* OTL_tracestate;
  int tracerequest;
  ///Changes to capture method walltime and cput time in case of sdk
#if defined ND_SDK || defined ND_GOAGENT
    apr_hash_t * sdkAgentHash;
#endif

} NDPerThreadData_t;

typedef struct Propheaderdata
{
  char* OTL_traceparent;
  char* OTL_tracestate;
  char* XB3_traceID;
  char* XB3_ParentSpanId;
  int XB3_sampled;
  char* XB3_SpanId;
  char* B3;
} Propheaderdata;

enum PropagationHeaderSupported{
  HEADER_OPENTELEMETRY=0,
  HEADER_XB3,
  HEADER_B3,
};

/*copy of above struct before some fields removal for optimization*/
/*typedef struct NDPerThreadData_t
  {
//char* tlTierBackendName;
char tlIsFPCaptured;
char tlIsBTExcluded;
char tlIsForceDump;
char* prevTierSeq;                            //Used to store previous sequence number with dot(.).
//char* seqPfx;
//char* tlFPInstanceForFPHdr;
//char* reqURI;
//char* backendMetaRecord;
//char* trxId;
//char* methodRecord;
char tlCorrelationIdHeader[128];              // thread local is used to store the value of correltionheader
//char tlLogHttpConditionFlowpath;
//char* tlFirstTierFPID;                        // contains first tier flow path id.
char tlLogCompleteFlowPath;
//char* currThreadSeq;                          //It will containin current thread sequence
//char tlThreadFromPool;                        //responsible whether the thread call out is normal call out or it lies in a thread pool.
char sequenceBlob[MAX_BYTE_ARRAY_SIZE];       //A threadlocal SB to store seq of method entry and exit records
char tlIsFPHeaderDumped;                      // A buffer to contain flow path header record (2 record)
char tlCategory;
//char isHttpCallOut;
//char* tlCassandraSQL;
//char* tlCassandraAdd;
//char* tlFPSeqBlockRecordBuffer;
char tlURL[512];                              //used for storing URL at thread level
char tlURLParameters[512];                    //used for checking either the mode of flowpath generation is changed at run time and
// accordingly change the mode
//short tlUnCaughtExceptionCount;               //contains exception count.
//short tlExceptionCount;                       //contains exception count
//int tlTierBackendType;
int tlStatusCode;
//int byteArrayVar;
int tlServiceMethodDepth;                     //Entry depth of every call for each individual request thread
//int tlServiceMethodId;                        //contains service method id for dumping service method exit record
int tlServiceMethodCount;
int sequenceBlobLen;
int tlNonServiceMethodCount;
//int tlSyntheticMonitor;
//int tlTargetDepth;                            //To check weather service method is to dump or not with 2 cases 1. depth is less than
// specified depth and level1DepthEnabled
int httpCallOutDepth;

char flowpathInstanceStr[32];
long long flowpathInstance;
long long tlsIdx;
long long seqNum;
// This will be used for storing URL at thread level

long long tlTestRunNumber;
//long long tlSeqNumberForTierCallOut;          //Determines whether header is set for backend call out


long long tlFlowPathTimeStampInMS;            //Threadlocal timestamp
long long tlThreadId;
long long tlFpCPUTime;
long long tlDuration;
long long firstFlowpathInstance;
long long prevFlowpathInstance;
//long long tlBackendSubType;                   //creating a new threadlocal to store the value of sqlID in case of DBcallout.
//Adding new threadLocals for storing BackendType ,BackendName,and StartTime
//long long tlTierStartTime;

char* tierCallOutHeader;
int tierCallOutHeaderLen;
long long tierCallOutSeqNum;
BTObject* tlBTObj;                            //This will be used for storing business transaction id
sqlProp tlSQLObj;
NDMonitorDataModel* tlMonitorDataModel;

void* hasMapNodePtr; //for hashmap node

//use for method stack
//NS_STACK methodStack;
struct NDPerThreadData_t* free_next;
struct NDPerThreadData_t* free_prev;
struct NDPerThreadData_t* busy_next;
struct NDPerThreadData_t* busy_prev;
char setEndFPFlag;
long long ndSessionId;
long long prev_fp_start_time;
int instrumented;
int btCategory;
int exceptionCount;
int totalFpcount;
int tierID;
int ndAppServerID;
int appID;
int tlFlowpathType;
long long cavSID;
long long NDPageID;
long long last_fptimestamp_from_cookie;
long long agentThreadID;
long long int syncTime;
long long int waitTime;
long long int qTimeInMS;
int debugModeLen;
char debugModeBuf[128];
int bitFlags;
apr_thread_mutex_t* sequenceBlobLock;
apr_thread_mutex_t* updateBTLock;

//Vaibhav: Exception Variables
char* excepMessage;
int dumpERecordFlag;
unsigned long long unwindfID;
int exceptionFlagForEventType;
char* excepClassName;
char* throwingCName;
char* throwingMName;
char* exceptionBackendName;
char* exceptionStackTrace;
long long int fpStartTimeforReset;
int prevPID;
int isBTOverride;
} NDPerThreadData_t; */


extern char findCategoryOfBT(Threshold bt_threshold, long long duration, int statusCode, NDPerThreadData_t* ndTD);
typedef struct TLSDataStruct
{
  NDPerThreadData_t* Tlsdata;
  long long threadId;
  unsigned long long timestamp;
}TLSDataStruct;

#ifdef __cplusplus
extern "C" TLSDataStruct *tlsdatastruct;
#else
extern TLSDataStruct *tlsdatastruct;
#endif
//extern TLSDataStruct *tlsdatastruct;



#if defined(ND_SDK) || defined(__unix__)
extern void agent_init(char* pool, int connect_to_ndc, char* process_name, char* agentType,char* agentVersion);
extern void agent_shutdown();
#ifdef OLD_CODE
extern void ndMethodEntry(NDPerThreadData_t* ndTD, char* mName, char* url, char* urlParameter, long long threadID, char* pName);
extern void ndMethodExit(NDPerThreadData_t* ndTD, char* mName, long long fpCPUTime, int statusCode, char* backendName, long long threadID);
#else
extern void* ndMethodEntry(void* methodPtr, NDPerThreadData_t* ndTD, char* mName, char* url, char* urlParameter, long long threadID, char* pName, char* TLS, long long startTime,char *Qparameter);
extern void* ndMethodExit(void* methodPtr, NDPerThreadData_t* ndTD, char* mName, long long fpCPUTime, int statusCode, char* backendName, long long methodWallTime, long long threadID, int isCalOutDone, char* TLS, int event_type, char* argValue, long long endTime, char ** strSpan);
extern void* startFP(char* flowpathinstance, char* url, char* btHeaderValue, char* TLS, char* NDCookieStr, char* NVCokieStr, char* correlationIdHeader, long long int qTimeInMS, long long startTimeFP);
extern void startFPTemp(char* flowpathinstance, char* url, char* buf);
extern void endFP(NDPerThreadData_t* ndTD, int statusCode, char* TLS, long long endTime, long long fpCPUTime,int tracerequest, char ** strSpan);
extern void dumpIncompleteFPAtTestStop(NDPerThreadData_t* ndTD);
extern char *getNDSessionCookie(NDPerThreadData_t *ndTD);
extern char *getNVSessionCookieName();
extern int enableNVNDSession();
extern int isMethodInHashMap(char *mName);
extern void getstacktracearray(NDPerThreadData_t* ndTD, char* stacktracearray, char* fileName, char* className, char* throwingClassName, char* message, char* throwingmethodName, int lineNumber, char* ExceptionCause);
extern int getCookieMethodPosition();
//extern void setEndFPFlag(NDPerThreadData_t *ndTD);
#endif
#endif

extern methodPropProperties* mPP;
//extern apr_pool_t *control_pool;
extern int setTierCallOut(NDPerThreadData_t* ndTD, char* str);

#ifdef __unix__
extern void getMethodHashMapLock();
extern void releaseMethodHashMapLock();
//extern void getNodeOperationLock();
//extern void releaseNodeOperationLock();
extern char *getTierCallOut(NDPerThreadData_t *ndTD, char *backendName);
extern  char *get_otl_traceparent_header(NDPerThreadData_t *ndTD);
extern  char *get_otl_tracestate_header(NDPerThreadData_t *ndTD);
extern void get_propagation_header(NDPerThreadData_t *ndTD, char *str);
extern void reset(NDPerThreadData_t *ndTD);
extern int *hashMapGetAndRemoveIntKey_c(int hashMapType, int key);
extern char hashMapPutIntKey_c(int hashMapType, int key, int *value);
extern char *retrivedXpathList();
extern int setHttpBodyBasedBT(NDPerThreadData_t *ndTD, char *xpath, char *value, int valueIndex);
extern void parseHttpBodyBtName(char *lineBuf);
extern void dumpHttpBody(NDPerThreadData_t *ndTD, char *httpBodyStr);
extern int getHttpBodyBasedBTSize(NDPerThreadData_t *ndTD);
extern char setExceptionCaptureTraceLevel(char *strKeywordValue);
extern void NDExceptionCaptureSettingsInit();
#ifdef __cplusplus
extern "C" void handleExceptionParameters(NDPerThreadData_t *ndTD, methodPropProperties *mPP, long long starttime, char *exceptionClassName, char *exceptionMessage, char *throwingClassName,
    char *throwingMethodName, char *getexceptionCause, int exceptionLineNum, char *stackTraceArr);
#else
extern void handleExceptionParameters(NDPerThreadData_t *ndTD, methodPropProperties *mPP, long long starttime, char *exceptionClassName, char *exceptionMessage, char *throwingClassName,
    char *throwingMethodName, char *getexceptionCause, int exceptionLineNum, char *stackTraceArr);
#endif
#else
//extern char *getTierCallOut(NDPerThreadData_t *ndTD);
//extern void reset(NDPerThreadData_t *ndTD);
//extern int *hashMapGetAndRemoveIntKey_c(int hashMapType, int key);
//extern char hashMapPutIntKey_c(int hashMapType, int key, int *value);
//extern char *retrivedXpathList();
//extern int setHttpBodyBasedBT(NDPerThreadData_t *ndTD, char *xpath, char *value, int valueIndex);
//extern void parseHttpBodyBtName(char *lineBuf);
//extern void dumpHttpBody(NDPerThreadData_t *ndTD, char *httpBodyStr);
//extern int getHttpBodyBasedBTSize(NDPerThreadData_t *ndTD);
//extern char setExceptionCaptureTraceLevel(char *strKeywordValue);
//extern void NDExceptionCaptureSettingsInit();
//#ifdef __cplusplus
//extern "C" void handleExceptionParameters(NDPerThreadData_t *ndTD, methodPropProperties *mPP, long long starttime, char *exceptionClassName, char *exceptionMessage, char *throwingClassName,
//        char *throwingMethodName, char *getexceptionCause, int exceptionLineNum, char *stackTraceArr);
//#else
//extern void handleExceptionParameters(NDPerThreadData_t *ndTD, methodPropProperties *mPP, long long starttime, char *exceptionClassName, char *exceptionMessage, char *throwingClassName,
//        char *throwingMethodName, char *getexceptionCause, int exceptionLineNum, char *stackTraceArr);
//#endif
#endif

extern void addMethodInHash(char* method_name);
extern void updateMethodInHash(char *method_name, int duration);
//extern NDPerThreadData_t NDPerThreadData;



/*Flowpath structure */
typedef struct
{
  int maxCharactersInSeqBlob;

}NDFlowpathGenerator_t;

//typedef struct
//{
//  int methodId;
//  long long methodTimeStampMS;
//}NDStackClientData_t;

//extern apr_hash_t* ndTDHashMap;
extern apr_thread_mutex_t* ndTDHashMapLock;
//NDFlowpathGenerator_t NDFlowpathGenerator;
//extern NDFlowpathGenerator_t NDFlowpathGenerator;
//extern int bciInstrSessionPct;
extern int getMaxCharactersInSeqBlob();
extern void setMaxCharactersInSeqBlob(int maxCharactersInSeqBlob);
extern void parse_flowpath_mask(char* ndflowpathMask);
//extern static void checkToDumpFPSeqBlob(NDPerThreadData_t *ndTD);
extern void updateFPSeqBlobWithTierCallOutRecord(NDPerThreadData_t* ndTD, long long methodStartTime, long long duration, methodPropProperties* mPP, long long resourceID);
extern void appendExceptionRecordInSeqBlob(NDPerThreadData_t* ndTD);
//extern  methodPropProperties *searchAndUpdateMethodHashMap(char *mName, node_t *methodHashMapNodeLocal, int updateFlag, int type);
extern void dumpIncompleteFPAtTestStop(NDPerThreadData_t* ndTD);
//extern void reset( NDPerThreadData_t *ndTD );

/*NDPerThread Structure */
extern void resetAllThreadLocals(NDPerThreadData_t* ndTD, TLSDataStruct* tlsdatastruct);
extern void resetMonitorDataModel(NDPerThreadData_t* ndTD);
extern void free_NDPerThreadData();

/*NDHttpCapture structure */
#define HTTP_REQ 12
#define HTTP_REP 13

#define HTTP_MSG_SIZE 4 * 1024

typedef struct
{
  char* name;
  char* type;
  int valueAsId;
  int id;
}httpHeaderInfo;

typedef struct ndHttpCapture_t
{
  char* hdrListValue;
}ndHttpCapture_t;

//extern node_t *httpHashMapNode;
//extern apr_thread_mutex_t* httpEntryLock;
extern void parseBufferAndGenerateHttpHeaderValueid(NDPerThreadData_t* ndTD, char* buffer);
extern void updateHashMapForhdrListForValueAsId(char* headerslistForValueAsId);
extern void setHttpHashMapNode(char* fileData);
//extern void free_HttpHashMapNode();
extern void sethdrListForValueAsId(char* value, char* keyword, int kwIdx);
extern void NDHttpInit();
extern void setEnableNDSession(char* strKeywordValue, char* keyword, int kwIdx);
extern void setNVCookie(char* cookie, char* keyword, int kwidx);
extern int tokenize(char* read_buf, char* fields[], char* token, int max_flds);
extern httpHeaderInfo* searchAndUpdatehttpHashMapNode(char* name, node_t* httpHashMapNodeLocal, int updateFlag);


/*NDRespHeaderBT structure */
typedef struct
{
  char* headerValue;
  int operationCode;
  char* btName;
} httpRespValueConditions;

typedef struct
{
  char* responseHeader;
  int type;
  httpRespValueConditions* httpRespValueConditions;
  int conditionCount;
} httpRespBtRule_t;

extern void parseRespHeaderDataBtRule(char* buffer);
//extern void setHttpRespHeaderBT(NDPerThreadData_t *ndTD, char *header_buf);


/*NDReqHeader Bt */
typedef struct
{
  char* headerValue;
  int operationCode;
  char* btName;
} httpReqValueConditions;

typedef struct
{
  char* reqHeader;
  int type;
  httpReqValueConditions* httpReqValueConditions;
  int conditionCount;
} httpReqBtRule_t;

//extern httpReqBtRule_t* httpReqBtRule;
extern void parseReqHeaderDataBtRule(char* buffer);
extern int setHttpReqHeaderBT(NDPerThreadData_t* ndTD, char* header_buf);


/*Ndbt_HttpBody_Rule_parser */
typedef struct
{
  char* value;
  int operationCode;
  char* btName;

} httpBodyValueConditions;

typedef struct
{
  char* type;
  char* xPath;
  int opcode_type;
  httpBodyValueConditions* httpBodyValueConditions;
  int conditionCount;
  int xPathCountVar;
  int enableBodyCapture;
  int maxBodySize;
} httpBodyBtRule_t;


#define OPERATION_EQUALS_STRING 0
#define OPERATION_CONTAINS_STRING 1
#define OPERATION_STARTSWITH_STRING 2
#define OPERATION_ENDSWITH_STRING 3
#define OPERATION_EQUAL_TO 4
#define OPERATION_NOT_EQUAL_TO 5
#define OPERATION_LESS_THAN 6
#define OPERATION_GREATER_THAN 7
#define OPERATION_LESS_THAN_EQUAL_TO 8
#define OPERATION_GREATER_THAN_EQUAL_TO 9
#define OPERATION_TRUE 10
#define OPERATION_FALSE 11
#define OPERATION_EXCEPTION 12
#define OPERATION_NOT_EQUALS_STRING 13
#define OPERATION_CAPTURE_DATA 14
#define OPERATION_EXTRACT_SUBPART 15
#define OPERATION_INVOCATION 16
#define OPERATION_VALUE 17
#define OPERATION_OCCURS 18

typedef struct methodDataValueConditions
{
  char* value;
  int operationCode;
  char* btName;
}methodDataValueConditions;

typedef struct methodDataBtRule_t
{
  char* FQM;
  int isMethodArgumentEnabled;
  int argumentIDx;

  /**
   * all custom types are defined below.
   * 0 - Numeric
   * 1 - String or Object
   * 2 - Boolean
   * 3 - Char or Byte
   */
  int argumentType;
  int type;
  methodDataValueConditions* methodDataValueConditions;
  int conditionCount;
  int selfRuleId;
  int parentRuleId;
}methodDataBtRule_t;

extern void parseMethodDataBtRule(char* lineBuf);
//extern void iterate_method_base_bt_hash();
extern void BtMethodInvoked(NDPerThreadData_t* ndTD, char* FQM, char* value, int type);
extern void checkPolicyToUpdateBtObject(NDPerThreadData_t* ndTD, char* btName);



/* NDCServerConfig structure */
#define NUM_NDC_SERVER_ARR  5
#define ACTIVE_ND 1
#define BACKUP_ND 0

#define STATE           "state"
#define RETRY_POLICY    "retryPolicy"
#define PROTO_VERSION   "ProtoVersion"

typedef struct ndc_servers
{
  char state;
  unsigned int ndc_port;
  char* ndc_host;
  int saasServer;
}ndc_servers_t;


typedef struct retryPolicy
{
  //char version[32];
  char num_retry;
  int count;
  int reply_unsuccessful_count;
  int heartbeat_reply_timeout_check;
  apr_interval_time_t time_interval;
  //apr_interval_time_t health_check_request_interval;
}retryPolicy_t;


//extern ndc_servers_t* ndc_server_arr;
//extern retryPolicy_t retry_policy;
//extern unsigned int server_arr_size;
//extern char nd_dr_state;
//extern char health_check_fail;
//extern char is_switch_over;

/**** Exposed C API ****/
void init_ndc_server_config();
ndc_servers_t* get_active_ndc();
void connection_retry_failed();
void make_control_conn_heartbeat_msg();
void clear_ndc_server_setting();
int parse_policy_from_clientMsg(char*);

/*NDDataDispatcher Structure */
extern apr_thread_mutex_t* read_raw_file;
extern int check_data_thread();
extern void* start_data_thread(apr_thread_t* thd, void* data);
extern void dumpData(char* data, int len);
extern int sendBufferDataCon(char* buf, int len);
extern void flushCommonData();
//extern void flushData();

/*NDEnableResource Structure */
typedef struct NDEnableResource_t
{
  long long resourceID;
  char* resourceName;
  int formatIPResourceURLCaptureMode;
  int urlOffsetValue;
  int maxUrlLength;
  int maxURLChar;

}NDEnableResource_t;
extern long long getIDForIPResourceURL(char* buffer, int buffer_len);
extern void parseFormatIPResourceURL(char* val, char* keyword, int index);
extern void dumpResourceMetaRecord(long long id, char* resourceName);

/*NDExceptionCaptureSetting Structure */
//typedef struct
//{
//  int exceptionCaptureTraceLevel;
//
//}NDExceptionCaptureSettings_t;
//
//NDExceptionCaptureSettings_t NDExceptionCaptureSettings;
//
//#ifdef __cplusplus
//extern "C" NDExceptionCaptureSettings_t NDExceptionCaptureSettings;
//#else
//extern NDExceptionCaptureSettings_t NDExceptionCaptureSettings;
//#endif

/*NDFileBasedKeyword Structure */
#define MAX_LENGTH 8192

typedef struct
{
  char fileName[2 * 1024];
  char* content;
  long long lmd;
  long long size;
}keywordInfo;

extern void handleFileBasedKeyword(char* line, char* keyword, int kwIdx);
extern void handleInstrProfileKeyword(InstrProfile* instProfileValue, char* keyword, int kwIdx);
extern void ndFileBasedKeywordInit();
extern int mkdir_ex(char* path);

/*NDInterFace structure */
extern void parseInterfaceInstrumentationTraceLevel(char* val);

typedef struct
{
  char isInterfacesTargeted;
  int interfaceTraceLevel;
}NDInterfaceProcessor_t;

//extern NDInterfaceProcessor_t NDInterfaceProcessor;

/*NDLB_HashMapMethod structure */
extern apr_hash_t* create_hashmap(apr_pool_t* mp);
extern void iterate_hashtab_s_s(apr_hash_t* ht);
extern void* search_hashmap(void* s1, apr_hash_t* ht);
extern time_t *search_int_hashmap(int *s1, apr_hash_t *ht);
extern void *search_uint16_hashmap(apr_port_t *s1, apr_hash_t *ht);
#ifdef __cplusplus
extern "C" void modify_hashmap(void* key, void* value, apr_hash_t * ht);
extern "C" void modify_int_hashmap(int *key, time_t *value, apr_hash_t *ht);
extern "C" void modify_uint16_hashmap(apr_port_t *key, void *value, apr_hash_t *ht);
#else
extern void modify_hashmap(void* key, void* value, apr_hash_t* ht);
extern void modify_int_hashmap(int *key, time_t *value, apr_hash_t *ht);
extern void modify_uint16_hashmap(apr_port_t *key, void *value, apr_hash_t *ht);
#endif

extern void iterate_hashtable_and_free_hashmap(apr_hash_t* ht);
//extern void clearHashMapTable();


/*NDLB_MEM_Pool structure */

#define NUM_TLS_SLOTS 64

//extern NDPerThreadData_t* gFreeTLSHead;
//extern NDPerThreadData_t* gBusyTLSTail;
//extern NDPerThreadData_t* gBusyTLSHEAD;


extern NDPerThreadData_t* create_tls_pool(int);
extern NDPerThreadData_t* get_free_tls_slot();
extern void free_tls_slot(NDPerThreadData_t* NDPerThreadData);
extern void resetMonitorDataModelFromTLS();
extern void dumpFpFromBusyList();
// #ifdef __cplusplus
// extern "C" TLSDataStruct * tlsdatastruct;
// #else
// extern TLSDataStruct* tlsdatastruct;
// #endif



/*NDLB_Stack structure */

struct ns_stack_t
{
  void** client_data;
  int* size;
  int top;
  int alloc_size;
};
typedef struct ns_stack_t NS_STACK;

extern void nsStackPush(NS_STACK* s, void* data, int datasize);
extern void* nsStackPop(NS_STACK* s);
extern void nsStackInit(NS_STACK* s);
extern void nsStackFree(NS_STACK* s);


/*NDLB_State_Machine structure */
#define HASH_MAX_INPUT 128 
#define MAX_HASH_TABLE_ROW (HASH_MAX_INPUT+3)
#define HASH_TABLE_INIT_SIZE 128
#define STARTS_WITH_ROW  128
#define EXACT_MATCH_ROW  129
#define SKIP_CHAR_ROW    130
#define SKIP_CHAR        '*'

typedef struct state_machine
{
  int* state_machine[MAX_HASH_TABLE_ROW];
  int state_count;
  int max_state;
  int delta_state;
}ndlbStateMachine;

typedef struct state_machine_for_header
{
  int* state_machine[MAX_HASH_TABLE_ROW];
  int state_count;
  int max_state;
  int delta_state;
}ndlbStateMachineforHeader;

extern int ndlb_state_machine_init(ndlbStateMachine* state_machine, int size);
extern int ndlb_state_machine_init_for_header(ndlbStateMachineforHeader* state_machine, int size);
extern int ndlb_state_machine_free(ndlbStateMachine* state_machine);
extern int ndlb_state_machine_free_for_header(ndlbStateMachineforHeader* state_machine);
extern int ndlb_state_machine_add(ndlbStateMachine* state_machine, char* entry, int len,char* httpMethod,int method_len, int id, char match_type, int patternMode , int skip_count);
extern int ndlb_state_machine_add_for_header(ndlbStateMachineforHeader* state_machine,char* BTHeaderName,int BTHeaderName_len,  int id, char match_type, int skip_count);
extern int ndlb_state_machine_get(ndlbStateMachine* state_machine, char* entry, int len,char* parameters,int param_len, char* httpMethod,int method_len, int skipCount);
extern int ndlb_state_machine_get_for_header(ndlbStateMachineforHeader* state_machine, char* BTHeaderName,int BTHeaderName_len , int skipCount,int id);
extern unsigned long ndlb_state_machine_size(ndlbStateMachine* state_machine);
extern unsigned long ndlb_state_machine_size_for_header(ndlbStateMachineforHeader* state_machine);


/*Only for NSLB_O1_HASH_MACHINE*/

#ifdef _NSLB_DEF_HASH_MACHINE

#define NSLB_HASH_DEBUG_LOG(X,...) \
{\
  if(state_machine && state_machine->log)\
  state_machine->log(X,_FLN_,__VA_ARGS__);\
}

#define NSLB_HASH_ERROR_LOG(...)  NSLB_HASH_DEBUG_LOG(0,__VA_ARGS__)
#define NSLB_HASH_DEBUG_LOG1(...) NSLB_HASH_DEBUG_LOG(1,__VA_ARGS__)
#define NSLB_HASH_DEBUG_LOG2(...) NSLB_HASH_DEBUG_LOG(2,__VA_ARGS__)
#define NSLB_HASH_DEBUG_LOG3(...) NSLB_HASH_DEBUG_LOG(3,__VA_ARGS__)
#define NSLB_HASH_DEBUG_LOG4(...) NSLB_HASH_DEBUG_LOG(4,__VA_ARGS__)
#endif

extern int check_captureAppLog_thread();
extern void dumpDataforLog(char* data, int len);
extern void setbciNDNFDataBufferSetting(char* keyword_val, char* keyword, int kwIdx);
extern void setenableNDNFDataTransfer(char* keyword_val, char* keyword, int kwIdx);
extern void setNDNFLogPath(char* keyword_val, char* keyword, int kwIdx);
extern void initKeywordForNDFDataTransfer();

/*NDManageTIDManager Structure */
//extern apr_hash_t* threadIdToThreadLocal;
extern void initNDManageTIdToTLocal();
extern void updateChildThreadPrevFPI(NDPerThreadData_t* ndTD, long long threadId);


/*NDParsing Structure */
typedef struct backendRuleProperties_t
{
  char* type;
  char* backendValue;
}backendRuleProperties_t;

extern backendRuleProperties_t* backendRuleProperties;

typedef struct methodProperties
{
  char* moduleName;
  char* methodName;
  char* className;
}methodProperties;

typedef struct DelayMethodPropProperties
{
  char* methodName;              //FQM for method
  int fromRange;                 //starting range for generating random delay time
  int toRange;                   //last range for generating random delay time
  //char isAutoInstrument;         //is method autoinsturmented flag.
  //char withLoop;                 //field to increase cpu by delay with cpu hogging
  //char dumpStackTrace;           //field to take stacktrace
}DelayMethodPropProperties;

//extern apr_hash_t* backendNameHashMap;
extern char* settingBackendName(char* buffer, char* backendValue, char* backendName, int backend_len);
extern  void parseBackendRuleFile(char* buffer);
//extern void parseBackendRuleMonitor(char *buffer);
extern void parseMethodMonitor(char* buffer);
extern void parseEntryFile(char* buffer);
extern void parseAgentFile(char* buffer, int keyword_id);
extern void setndCriticalFileList(char* buffer);
extern void setDefaultCriticalFile();
extern void setblackListForDebugSession(char* buffer);
extern void DelayMethodPropPropertiesInit();
extern void setDelayMethodKeyword(char* keyValue, char* keyword, int index);
extern void dumpFileforGoAgent(char* fileName, char* fileData);


/*NDSetting Strucure */

//Parsing for the values of following keywords are done inside MethodMonitor
//Monitor Vector Seperator - Used while generating method monitoring report
//TODO- In future we will move them to NDBCISettings as these are global keywords
typedef struct  NDSettings_t
{
  char ndVectorSeperator;
  /**
   * Monitor Reporting Interval(in MilliSeconds)
   * Default Value - 10,000 ms or 10 sec
   */
  long ndMonitorInterval;
  int ndMonitorIntervalInSecs;
  //progress interval
  //long ndProgressInterval;
  /**
   * This is a configurable keyword provided from nd.conf which will be used for cleaning up of dead threads
   * Count for cleaning up dead threads.
   */
  //int threadCleanUpCount;

  //int monitorDataDumpMode;//0- no dump , 1- only to socket-TR , 2- only file , 3- both socket and file
} NDSettings_t;

#ifdef __cplusplus
extern "C" NDASSettings_t NDASSettings;
#else
extern NDASSettings_t NDASSettings;
#endif

enum nd_evet_enum
{
  ND_EV_SEQ_BLOB_HEADER = 2,
  ND_EV_SEQ_BLOB_INCOMPLETE,
  ND_EV_SEQ_BLOB_COMPLETE,
  ND_EV_METHOD_DISCOVERY,
  ND_EV_URL_DISCOVERY,
  ND_DATA_OVER = 10,
  ND_SENDING_META_DATA, /*Before Mata data BCI send this event*/
  ND_EV_SQL_PREPARED_DISCOVERY = 22, /* added NDSQL Table */
  EXCEPTION_CLASS_RECORD_ID = 32,
  THROWING_CLASS_RECORD_ID = 33,
  THROWING_METHOD_RECORD_ID = 34,
  EXCEPTION_MESSAGE_RECORD_ID = 35,
  EXCEPTION_CAUSE_RECORD_ID = 36,
  ND_EXCP_MONITOR = 38,
  ND_EV_SEQ_BLOB_INCOMPLETE_EXIT = 43,
  ND_EV_SEQ_BLOB_COMPLETE_EXIT,
  ND_EV_AUTO_SENSOR_HOTSPOT_THREADS = 52,
  ND_EV_AUTO_SENSOR_THREADS_COUNT_NEW,
  ND_EV_METHOD_MON_COUNT = 61,
  ND_EV_EXCEPTION_MON_COUNT=63,
  ND_EV_BT_MON_COUNT = 74,
  ND_EV_BACKENDCALL_MON_COUNT = 75,
  ND_EV_GARBAGECOLLECTOR_COUNT = 79,
  ND_EV_NEW_CONNECTION = 99,
  CAPTURE_DEBUG_DATA = 100,
  CATPURE_TAG_STATIC = 110,
  CATPURE_ATTRIBUTES_STATIC = 111,
  CATPURE_TAG_PER_BT = 112,
  __NUM_ND_EVENTS__
};


//extern NDSettings_t NDSettings;


/*NDThreadMoniotr Structure */
typedef struct
{
  //int threadMonitoringTraceLevel;
  //long long threadMonitoringReportInterval;
  //double targetedCpuTime;
  char doNotDeleteReported;
}NDThreadMonitor_t;


extern void NDThreadMonitorInit();
extern void setThreadMonitoringTraceLevel(int traceLevel);

/*NIODataDispatcher Structure */
extern int check_autoSensor_thread();
extern void* start_autoSensor_thread();
extern int dumpASData(char* data, int len);
extern char startASNDCollectorCommunication();
extern int create_autoSensor_thread();
extern void ASNioInit();
extern char* nioASDataDispatcherToString();
extern char stopNIO();
//extern void flushData();
extern int sendDataToNDC();
extern void moveCommonPartialToReadList();
//extern void movePartialToReadList();
extern void cleanAutoSensorThread();



struct rudp_hdr {
 uint16_t version;
 uint16_t type;
 uint32_t seqno;
 int duplicate_flag;

} __attribute__((packed));

struct rudp_packet {
 struct rudp_hdr header;
 int payload_length;
 char payload[65000];
};

typedef struct rudp_packet_wrapper{

apr_socket_t *file;
apr_sockaddr_t *sender;
struct rudp_packet received_packet;
struct rudp_packet_wrapper *next;
}rudp_packet_wrapper;



/*NIOSetting Structure */
typedef struct nioSettings_t
{
  char* buff;
  int use_len;
  int send_len;
  int buff_size;
  struct nioSettings_t* next;
}nioSettings_t;

/*NDExceptionMonitor structure */

# define DEFAULT_MAX_AGG_EXCEPTION_DATA_SIZE 128
typedef struct NDException_t
{
  int exceptionCaptureMode;
  int stackTraceCaptureMode;
  int exceptionCauseCaptureMode;
  int exceptionType;
  int stackTraceMaxDepth;
  int exceptionCaptureTraceLevel;
  char enableLogger;
  char enableTrycatch;
  char* exceptionClassName;
  int exceptionClassID;
  char* throwingClassName;
  int throwingClassID;
  char* throwingMethodName;
  int throwingMethodID;
  char* exceptionMsg;
  int exceptionMsgID;
  char* exceptionCauseRsn;
  int exceptionCauseID;
  int traceLevel;
  char** currElement;
  int filterSizeCount;
  int currSize;
  char isFilteringEnabled;
  int maxExceptionMessageLength;
}NDException_t;


typedef struct
{
  int exceptionClassNameID; //To reset the values of exception meta data ID's
  int throwingClassNameID;
  int throwingMethodNameID;
  int msgID;
  int causeID;
}NDExceptionIDS_t;

//Protocol Negotiation Changes
typedef struct
{
  char* protocolName;
  int protocolPort;
} supportedProtocols_t;

extern void getExcepMonHashMapLock();
extern void releaseExcepMonHashMapLock();
extern void parseExceptionMonFile(char* buffer);
extern int handleSizeDataArr(void** ptr, int oldLength, int id, int sizeOfStruct);
extern void updatePropertiesOfException(NDPerThreadData_t* tlData, char* methodName, int methodID);
extern void updateExceptionDataCountersForAggregate(NDExceptionMonitorDataCounters* aggDataObject, NDExceptionMonitorDataCounters* currentObj);
extern void checkAndIncrementAggrExceptionDataArray(currMonitoringExcepStruct_t* expData);
extern void initNDExceptionMonitorDataCounters(NDExceptionMonitorDataCounters*);
extern void initNDMonitorDataModel(NDPerThreadData_t* tlData);

//#ifdef __cplusplus
//extern "C" NDException_t ndException;
//#else
//extern NDException_t ndException;
//#endif


extern int getExceptionCaptureMode();
extern apr_thread_mutex_t* exceptionEntryLock;
extern apr_hash_t* currentMonitoringExceptionMap;


//extern apr_hash_t* exceptionMessageMap;
//extern apr_hash_t* exceptionCauseMap;
//extern apr_hash_t* exceptionThrowingMethodMap;
//extern apr_hash_t* exceptionThrowingClassMap;
//extern apr_hash_t* exceptionClassNameMap;
//extern apr_hash_t* exceptionCauseMap;

extern void setdefaultValuesForException();
extern void setBackendErrorDetectionMode(char* value, char* keyword, int kwIdx);
extern void setEnableExceptionInSeqBlob(char* keyword_val, char* keyword, int kwIdx);
extern void setExceptionCaptureSettings(char* buffer, char* keyword, int kwIdx);
extern void parseExceptionFilteringList(char* buffer, char* keyword, int kwIdx);
//extern void releaseMethodHashMapLock();
extern void getexceptionEntryLock();
extern void getexceptionClassNameLock();
extern void releaseexceptionClassNameLock();
extern void getexceptionThrowingClassLock();
extern void releaseexceptionThrowingClassLock();
extern void getexceptionThrowingMethodLock();
extern void releaseexceptionThrowingMethodLock();
extern void getexceptionMessageLock();
extern void releaseexceptionMessageLock();
extern void getexceptionCauseLock();
extern void releaseexceptionCauseLock();
//extern void exceptionMapInit();




/*BackenMonitor structure */
//extern NDBackendMonitor_t NDBackendMonitor;
extern void createVectorPrefixBackend(NDBackendMonitor_t* ptr);
extern char generateAndDumpBackendMonitoringRecord(char* buff, int* len);
extern void parseMaxIPCount(char* strKeywordValue);
extern char updateCounterAndDurationForBackend(NDPerThreadData_t* ndTl, methodPropProperties* mpp, long long duration, char isError);
extern void checkAndIncrementAggrBackendDataArray(methodPropProperties* mpp);
extern void NDBackendMonitorInit();
extern void setBackendMonTraceLevel(int level);



/*NDMethodMoniotr structure */
extern void NDMethodMonitorInit();
extern void parseBTMonitorKeyword(char* strKeywordValue, char* keywords, int index);
extern void parseBTMonitorTraceLevel(char* strKeywordValue, char* keywords, int index);;
extern void parseMaxBTCount(char* strKeywordValue, char* keywords, int index);
extern void parseDoNotDiscardVal(char* strKeywordValue, char* keywords, int index);
extern void parseBTMonitorErrorLevel(char* strKeywordValue, char* keywords, int index);

extern char generateAndDumpBTMonitoringRecord(char* buff, int* len);

extern void checkAndIncrementAggrBTDataArray(BTObject* tlBTObj);
extern char updateCounterAndDurationForMethod(NDPerThreadData_t* ndTl, methodPropProperties* mpp, long long duration);
extern char generateAndDumpMethodMonitoringRecord(char* buff, int* len);
extern void createVectorPrefixMethod(NDMethodMonitor_t* ptr);


/*NDBtMoniotr structure */
extern void NDBTMonitorInit();
extern void createVectorPrefix(NDBTMonitor_t* ptr);
extern void parseBTMonitorKeyword(char* strKeywordValue, char* keywords, int index);
extern void parseBTMonitorTraceLevel(char* strKeywordValue, char* keywords, int index);
extern void parseMaxBTCount(char* strKeywordValue, char* keywords, int index);
extern void parseDoNotDiscardVal(char* strKeywordValue, char* keywords, int index);
extern void parseBTMonitorErrorLevel(char* strKeywordValue, char* keywords, int index);

extern char generateAndDumpBTMonitoringRecord(char* buff, int* len);

extern char updateCounterAndDurationForBT(NDPerThreadData_t* ndTl);
extern void checkAndIncrementAggrBTDataArray(BTObject* tlBTObj);
extern void parseBTAggDataArraySize(char* strKeywordValue, char* keywords, int index); //Keyword parse

                                                                                       
//NDExceptionMonitor Structure
extern void NDExceptionMonitorInit();
extern void createVectorPrefixException(NDExceptionMonitor_t* ptr);
extern char updateCounterAndDurationForException(NDPerThreadData_t* ndTl, char* exceptionClassName);
extern char generateAndDumpExceptionMonitoringRecord(char* buff, int* len);

//HPLOG:changes for websocket
//extern void create_control_conn(struct NDProxyInstance_t* tlndApplication, char* hostname, int port, char* error_buf, int error_buf_len, struct apr_pool_t* pool);
//extern void create_data_conn(struct NDProxyInstance_t* tlndApplication, char* hostname, int port, char* error_buf, int error_buf_len, struct apr_pool_t* pool);
//extern void create_as_conn(struct NDProxyInstance_t* tlndApplication, char* hostname, int port, char* error_buf, int error_buf_len, struct apr_pool_t* pool);
//extern void create_discovery_conn(struct NDProxyInstance_t* tlndApplication, char* hostname, int port, char* error_buf, int error_buf_len, struct apr_pool_t* pool);
//extern int get_src_addr_wrapper(socketInfo_t* socket, char* buf, int len, int* port);
//extern void send_AS_data();
//extern int send_discovery_data(char* buffer, int buf_size, char* error_buf, int error_buf_len);

//Proxy lws functions
void ndProxyInitWrapper();
int get_dst_addr_wrapper(apr_socket_t* sock, struct lws* wsi, char* buf, int len, int* port, int lws);

int create_proxy_server(int port, controlSocketBuffer_t* bufInfoLocal);

#ifdef __cplusplus
extern "C" int create_a_temp_connection(void** skt, lws_handler_t* handler, void* pool);
extern "C" int send_data_through_connection(void* skt, lws_handler_t handler, char* buf, int len);
extern "C" void close_temp_connection(void** skt, lws_handler_t* handler);
#else
int create_a_temp_connection(void** skt, lws_handler_t* handler, void* pool);
int send_data_through_connection(void* skt, lws_handler_t handler, char* buf, int len);
void close_temp_connection(void** skt, lws_handler_t* handler);
#endif

int send_on_wsi(struct lws_context* context, proxy_lws_handler_t* handler, char* buf, int len);
void remove_wsi(struct lws_context* context, struct lws* wsi);
char *GenerateTransactionSpan(NDPerThreadData_t* ndTD);
//HPEND

//char *getTierCallOut(NDPerThreadData_t *ndTD);
#endif
