A more efficient way to Retrieve records into a JSON array in MySQL? C - mysql

I am using MySQL in my C application. I have created a function
GetInDB(char *query, cJSON **json){...
that will allocate the json as a json array, query the db, and store the records in the array. The problem is that it seems difficult to quickly get the field name of each column in a table. Since I don't know the string length of each name in advance, I have to iterate through the results and dynamically allocate (!) a string that is large enough to hold each one. Then, I have to iterate through each record. Is there a better way?
int GetInDB(const char *query, cJSON **json)
{
if(*json != NULL){
cJSON_Delete(*json);
}
*json = cJSON_CreateArray();
if (mysql_query(mysqldb, query))
{
fprintf(stderr, "%s\n", mysql_error(mysqldb));
return -1;
}
MYSQL_RES *result = mysql_store_result(mysqldb);
if (result == NULL)
{
fprintf(stderr, "%s\n", mysql_error(mysqldb));
return -1;
}
int num_fields = mysql_num_fields(result);
int i;
MYSQL_ROW row;
MYSQL_FIELD *field;
char *Columns[num_fields];
int which = 0;
while((field = mysql_fetch_field(result)))
{
Columns[which] = (char*)malloc(strlen(field->name)+1);
strcpy(Columns[which], field->name);
which++;
}
while ((row = mysql_fetch_row(result)))
{
cJSON *obj = cJSON_CreateObject();
for(i = 0; i < num_fields; i++)
{
cJSON_AddStringToObject(obj, Columns[i], row[i] ? row[i] : "NULL");
}
cJSON_AddItemToArray(*json,obj);
}
mysql_free_result(result);
for(i=0; i<num_fields; i++){
free(Columns[i]);
}
return 0;
}

Related

CUB sum reduction with 2D pitched arrays

I am trying to perform a sum reduction using CUB and 2D arrays of type float/double.
Although it works for certain combinations of rows+columns, for relatively larger arrays, I get an illegal memory access error during the last transfer.
A minimal example is the following:
#include <stdio.h>
#include <stdlib.h>
#include <cub/device/device_reduce.cuh>
#include "cuda_runtime.h"
#ifdef DP
#define real double
#else
#define real float
#endif
void generatedata(const int num, real* vec, real start, real finish) {
real rrange = finish - start;
for (auto i = 0; i < num; ++i)
vec[i] = rand() / float(RAND_MAX) * rrange + start;
}
real reduce_to_sum(const int num, const real* vec) {
real total = real(0.0);
for (auto i = 0; i < num; ++i)
total += vec[i];
return total;
}
int main() {
int rows = 2001;
int cols = 3145;
size_t msize = rows * cols;
real* data = (real*)malloc(msize * sizeof(real));
if (!data)
return -999;
generatedata(msize, data, 0., 50.);
real ref_sum = reduce_to_sum(msize, data);
real* d_data_in = nullptr;
real* d_data_out = nullptr;
size_t pitch_in, pitch_out;
cudaError_t err = cudaMallocPitch(&d_data_in, &pitch_in, cols * sizeof(real), rows);
if (err != cudaSuccess) {
printf("data_in :: %s \n", cudaGetErrorString(err));
return -999;
}
err = cudaMallocPitch(&d_data_out, &pitch_out, cols * sizeof(real), rows);
if (err != cudaSuccess) {
printf("data_out :: %s \n", cudaGetErrorString(err));
return -999;
}
err = cudaMemset(d_data_in, 0, rows * pitch_in);
if (err != cudaSuccess) {
printf("set data_in :: %s \n", cudaGetErrorString(err));
return -999;
}
err = cudaMemcpy2D(d_data_in, pitch_in, data, cols * sizeof(real), cols * sizeof(real), rows, cudaMemcpyHostToDevice);
if (err != cudaSuccess) {
printf("copy data :: %s \n", cudaGetErrorString(err));
return -999;
}
void* d_temp = nullptr;
size_t temp_bytes = 0;
cub::DeviceReduce::Sum(d_temp, temp_bytes, d_data_in, d_data_out, rows * pitch_out);
err = cudaMalloc(&d_temp, temp_bytes);
if (err != cudaSuccess) {
printf("temp :: %s \n", cudaGetErrorString(err));
return -999;
}
err = cudaMemset(d_data_out, 0, rows * pitch_out);
if (err != cudaSuccess) {
printf("set temp :: %s \n", cudaGetErrorString(err));
return -999;
}
// Run sum-reduction
cub::DeviceReduce::Sum(d_temp, temp_bytes, d_data_in, d_data_out, rows * pitch_out);
err = cudaGetLastError();
if (err != cudaSuccess) {
printf("reduction :: %s \n", cudaGetErrorString(err));
return -999;
}
real gpu_sum = real(0.0);
err = cudaMemcpy(&gpu_sum, d_data_out, sizeof(real), cudaMemcpyDeviceToHost);
if (err != cudaSuccess) {
printf("copy final :: %s \n", cudaGetErrorString(err));
return -999;
}
printf("Difference in sum (h)%f - (d)%f = %f \n", ref_sum, gpu_sum, ref_sum - gpu_sum);
if (data) free(data);
if (d_data_in) cudaFree(d_data_in);
if (d_data_out) cudaFree(d_data_out);
if (d_temp) cudaFree(d_temp);
cudaDeviceReset();
return 0;
}
The error is thrown at "copy final ::". I am bit confused as to why certain rows x columns work and others don't. I did notice it's the larger values that cause it, but can't get my head around.
Any suggestions would be much appreciated.
The 5th parameter of cub::DeviceReduce::Sum should be the number of input elements. However, rows * pitch_out is the size of the output buffer in bytes.
Assuming pitch_in % sizeof(real) == 0, the following call may work.
cub::DeviceReduce::Sum(d_temp, temp_bytes, d_data_in, d_data_out, rows * (pitch_in / sizeof(real)));
Also note that cub::DeviceReduce::Sum may return before the reduction is complete. In this case, if any error happened during execution, this error will be reported by cudaMemcpy.

ICMP recvfrom function always receive data even though the destination was shutdown

I wrote a program in C to ping a machine and receive the echo from that machine to detect if the machine is still alive. My code as following please:
#define PING_PKT_S 64
#define PORT_NO 0
#define PING_SLEEP_RATE 1000000
#define RECV_TIMEOUT 1
int pingloop=1;
struct ping_pkt {
struct icmphdr hdr;
char msg[PING_PKT_S-sizeof(struct icmphdr)];
};
unsigned short checksum(void *b, int len) {
unsigned short *buf = b;
unsigned int sum=0;
unsigned short result;
for ( sum = 0; len > 1; len -= 2 )
sum += *buf++;
if ( len == 1 )
sum += *(unsigned char*)buf;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
result = ~sum;
return result;
}
//to check if this machine is actively working
int isActiveNow(){
const char *pre = "161.";
char *prefixArr[] = {pre};
char myIp[64];
memset(myIp, 0, sizeof(myIp));
get_local_ip(myIp, prefixArr);
printf("---isActiveNow:%s\n",myIp);
if(myIp[0]=='\0'){
printf("Not Active Now!\n");
return 0;
}
return 1;
}
void intHandler(int dummy) {
pingloop=0;
}
long current_timestamp() {
struct timeval te;
gettimeofday(&te, NULL);
long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000;
return milliseconds;
}
void display(void *buf, int bytes){
int i;
struct iphdr *ip = buf;
struct icmphdr *icmp = buf+ip->ihl*4;
printf("---------------------Start Display\n");
for ( i = 0; i < bytes; i++ ){
printf("%c", ((unsigned char*)buf)[i]);
}
printf("---------------------End Display\n");
}
int failedNum = 0;
// make a ping request
void send_ping(int ping_sockfd, char *ping_ip) {
int ttl_val=64, msg_count=0, i, addr_len, msg_received_count=0;
struct ping_pkt pckt;
struct sockaddr_in r_addr;
struct timespec time_start, time_end;
// set socket options at ip to TTL and value to 64,
if (setsockopt(ping_sockfd, SOL_IP, IP_TTL, &ttl_val, sizeof(ttl_val)) != 0) {
printf("Setting socket options to TTL failed!\n");
return;
}else{
printf("\nSocket set to TTL..\n");
}
// send icmp packet in an infinite loop
while(pingloop) {
sleep(2);
if(isActiveNow()){
printf("--current is active!");
continue;
}
//filling packet
bzero(&pckt, sizeof(pckt));
pckt.hdr.type = ICMP_ECHO;
pckt.hdr.un.echo.id = getpid();
for ( i = 0; i < 10; i++ ){
pckt.msg[i] = 'w';
}
pckt.msg[i] = 0;
pckt.hdr.un.echo.sequence = msg_count++;
pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));
long s1 = current_timestamp();
struct hostent *hostentObj;
hostentObj = gethostbyname(ping_ip);
struct sockaddr_in ping_addr;
ping_addr.sin_port = 0;
ping_addr.sin_family = hostentObj->h_addrtype;
ping_addr.sin_addr.s_addr = *(long*) hostentObj->h_addr;
//Using synchronize
if ( sendto(ping_sockfd, &pckt, sizeof(pckt), 0, (struct sockaddr*) &ping_addr, sizeof(ping_addr)) <= 0) {
printf("\nPacket Sending Failed!\n");
}
struct timeval tv_out;
tv_out.tv_sec = 10;
tv_out.tv_usec = 0;
// setsockopt(ping_sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv_out, sizeof tv_out);
struct sockaddr_in myAddr;
unsigned char buf[1024];
int len=sizeof(myAddr);
bzero(buf, sizeof(buf));
struct ping_pkt pckt2;
int bytes = recvfrom(ping_sockfd, &pckt2, sizeof(pckt2), 0, (struct sockaddr*)&myAddr, &len);
printf("---------------------bytes len:%d\n",bytes);
if ( bytes > 0 ){
display(&pckt2, bytes);
long s2 = current_timestamp();
printf("from %s msg_seq=%d ttl=%d rtt = %ld ms. pckt.hdr.type=%d \n", ping_ip, msg_count,ttl_val, (s2-s1), pckt.hdr.type);
}else{
printf("-------NO RESPONSE!!!!!!\n");
failedNum++;
//maximum detected failed number is 10
if(failedNum>3){
printf("--The other server dead!!!\n");
}
}
}
}
bool prefix(const char *pre, const char *str){
return strncmp(pre, str, strlen(pre)) == 0;
}
void get_local_ip(char *pubIp, char *prefixArr[]){
char *ip;
int fd, intrface, retn = 0;
struct ifreq buf[INET_ADDRSTRLEN];
struct ifconf ifc;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0){
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = (caddr_t)buf;
if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc)){
intrface = ifc.ifc_len/sizeof(struct ifreq);
while (intrface-- > 0){
if (!(ioctl(fd, SIOCGIFADDR, (char *)&buf[intrface]))){
ip=(inet_ntoa(((struct sockaddr_in*)(&buf[intrface].ifr_addr))->sin_addr));
int len = 0,i = 0;
len = sizeof(prefixArr) / sizeof(*prefixArr);
for (i = 0; i < len; i++) {
if(prefix(prefixArr[i],ip)){
strcpy(pubIp,ip);
return;
}
}
}
}
}
close(fd);
}
}
// Driver Code
int main(int argc, char *argv[]){
int sockfd;
char *pingIp;
char *prefixArr[] = { "11.","10.","172."};
char myIp[64];
memset(myIp, 0, sizeof(myIp));
get_local_ip(myIp, prefixArr);
//the other server's ip for detecting it's alive or dead
pingIp = argv[1];
printf("my ip:%s-----ping ip:%s\n", myIp, pingIp);
//socket()
sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
struct sockaddr_in r_addr;
r_addr.sin_family = AF_INET;
r_addr.sin_addr.s_addr = inet_addr(myIp);
r_addr.sin_port = 0;
bind(sockfd, (struct sockaddr *) &r_addr, sizeof(r_addr));
if(sockfd<0){
printf("\nSocket file descriptor not received!!\n");
return 0;
}else{
printf("\nSocket file descriptor %d received\n", sockfd);
}
//once error seen, it will stop the loop
signal(SIGINT, intHandler);//catching interrupt
//send pings continuously
send_ping(sockfd, pingIp);
return 0;
}
The problem is that the value of myReceiveBytes is alway 64, even though the destination server has already been shutdown.
Your code is not actually decoding the received packet. In all likelihood, what you are receiving is an ICMP Destination Unreachable packet either from your own host or from your gateway.
Something along these lines:
#include <netinet/ip.h> /* struct iphdr */
...
...
struct sockaddr_in peerAddr;
unsigned char buf[1024];
unsigned int len = sizeof(peerAddr);
int bytes_received = recvfrom(sockfd, buf, sizeof(buf), 0,
(struct sockaddr *) &peerAddr, &len);
if (bytes_received > 0) {
printf("ICMP packet received from %s\n", inet_ntoa(peerAddr.sin_addr));
struct icmphdr *icmp = (struct icmphdr *) (buf + sizeof(struct iphdr));
switch (icmp->type) {
case ICMP_ECHOREPLY: printf("Type: ICMP_ECHOREPLY\n"); break;
case ICMP_DEST_UNREACH: printf("Type: ICMP_DEST_UNREACH\n"); break;
case ICMP_SOURCE_QUENCH: printf("Type: ICMP_SOURCE_QUENCH\n"); break;
case ICMP_REDIRECT: printf("Type: ICMP_REDIRECT\n"); break;
case ICMP_ECHO: printf("Type: ICMP_ECHO\n"); break;
case ICMP_TIME_EXCEEDED: printf("Type: ICMP_TIME_EXCEEDED\n"); break;
case ICMP_PARAMETERPROB: printf("Type: ICMP_PARAMETERPROB\n"); break;
case ICMP_TIMESTAMP: printf("Type: ICMP_TIMESTAMP\n"); break;
case ICMP_TIMESTAMPREPLY: printf("Type: ICMP_TIMESTAMPREPLY\n"); break;
case ICMP_INFO_REQUEST: printf("Type: ICMP_INFO_REQUEST\n"); break;
case ICMP_INFO_REPLY: printf("Type: ICMP_INFO_REPLY\n"); break;
case ICMP_ADDRESS: printf("Type: ICMP_ADDRESS\n"); break;
case ICMP_ADDRESSREPLY: printf("Type: ICMP_ADDRESSREPLY\n"); break;
default: printf("Type: <0x%02x>\n", icmp->type); break;
}
}

json_spirit usage issue

i was able to compile the program successfully but not able to retrieve the values from json object. i am pasting the code below , the code is simple , any help appreciated.
#include <cstdio>
#include <cstring>
#include <json_spirit.h>
using namespace std;
using namespace json_spirit;
//A sample get file request
char *jsonInput =
"{\"request\" : { \
\"service\" : \"fmgr\" \
\"cookie\" : \"Abxruyyeziyrolsu\" \
\"req\" : \"read\" \
\"fname\" : \"Junk.txt\" \
\"size\" : 1024 \
\"data\" : \"data\" \
}}";
int main(int argc, char **argv)
{
Value val;
const string s = jsonInput;
read(s, val); //read the jsonInput to the value
Object obj = val.get_obj();
std::string service, cookie, req, fname, data;
uint32_t size;
for(Object::size_type i = 0; i != obj.size(); ++i) {
const Pair& pair = obj[i];
const string& name = pair.name_;
const Value& value = pair.value_;
if( name == "service" ) service = value.get_str();
else if( name == "cookie") cookie = value.get_str();
else if( name == "req" ) req = value.get_str();
else if( name == "fname" ) fname = value.get_str();
else if( name == "size" ) size = value.get_int();
else if( name == "data" ) data = value.get_str();
}
std::cout<<service << " " << cookie << " " << req << " " << fname << " " << size << " " << data ;
return 0;
}
There are two things problems:
The jsonInput string is not valid JSON, the commas to separate object pairs are missing.
The next issue is more complicated to explain. The toplevel Value is itself an Object so calling val.get_obj() returns the Object containing all the data. There is only one Pair in this object, named "request". Calling val.get_obj()[0] will retrieve this pair. You then need to get the Object out of this Pair's Value.
Value val; read(s, val); //read the jsonInput to the value
const Pair& pair = val.get_obj()[0]; //gets the name:value pair, named "request"
const Object& obj = pair.value_.get_obj(); //gets the service, cookie... object
To keep things simple, as they should be with json_spirit, try the following after correcting the missing ',' delimiters in the JSON string.
std::string json_input = <your valid JSON string>
json_spirit::Value value;
auto success = json_spirit::read_string(json_input, value);
if (success == true) {
auto object = value.get_obj();
for (auto entry : object) {
if (entry.name_ == "service") service = entry.value_.get_str();
else if...
.
.
}
}

C: Dynamic resultSet for MySQL SELECT

I'm currently passing a multidimensional char array to my MySQL function. cmd contains the command and resultSet[2][50] is my array.
How can I make this more dynamic so that I'm able to retrieve as many items as I want?
int
selectDB(char * cmd, char resultSet[2][50])
{
MYSQL *conn;
MYSQL_RES *result;
MYSQL_ROW row;
int i;
char *c1;
conn = mysql_init(NULL);
if (conn == NULL) {
printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
exit(1);
}
if (mysql_real_connect(conn, "localhost", "root",
"mypassword", "myDBName", 0, NULL, 0) == NULL)
{
printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
exit(1);
}
if (mysql_query(conn, cmd))
{
printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
exit(1);
}
if (!(result = mysql_store_result(conn)))
{
printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
exit(1);
}
while((row = mysql_fetch_row(result))) {
for (i=0 ; i < mysql_num_fields(result); i++)
{
snprintf(resultSet[i], 999, "%s", row[i]);
}
}
if (!mysql_eof(result))
{
printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
exit(1);
}
mysql_free_result(result);
mysql_close(conn);
return 0;
}
You could accept a triple pointer as an argument like this and an int, that will tell the size of the array
int selectDB( char* cmd, char*** resultSet, int* m, int* n )
{
// allocate two dimentional array with any size you want, using malloc
// store the size into m and n
// do stuff with resultSet
// watch out when using snprintf - check if i is smaller
// than the size of the array. If so - just use snprintf
// otherwise, you'll need to allocate some larger memory,
// and copy "move" the current records into the new location
// then free the old memory, etc.
//
// return
}
This way you'll know the size of the array, but you'll need to take care of freeing the memory, allocated for resultSet.

C program: Segmentation fault when selecting from MySQL with field that contains NULL

It all seems to work, but if there is a MySQL field with NULL in it I get a Segmentation Fault.
Here's the code:
int
selectDB(char * cmd)
{
printf("Cmd: %s\n", cmd);
MYSQL *conn;
MYSQL_RES *result;
MYSQL_ROW row;
int i;
conn = mysql_init(NULL);
if (conn == NULL) {
printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
exit(1);
}
if (mysql_real_connect(conn, "localhost", "root",
"myPassword", "myDB", 0, NULL, 0) == NULL)
{
printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
exit(1);
}
if (mysql_query(conn, cmd))
{
printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
exit(1);
}
if (!(result = mysql_store_result(conn)))
{
printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
exit(1);
}
while((row = mysql_fetch_row(result))) {
for (i=0 ; i < mysql_num_fields(result); i++)
printf("%s\n", row[i]);
}
if (!mysql_eof(result))
{
printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
exit(1);
}
mysql_free_result(result);
mysql_close(conn);
return 0;
}
I'm calling it with
char cmd[1000];
snprintf(cmd, 999, "SELECT * FROM users WHERE id = %s", valueptr);
selectDB(cmd);
From the MySQL docs:
NULL values in the row are indicated by NULL pointers.
You need something like:
for (i=0 ; i < mysql_num_fields(result); i++)
printf("%s\n", row[i] ? row[i] : "NULL" );
My only guess:
When you do:
printf("%s\n", row[i]);
it expects a pointer to a string. When you give it NULL (not a pointer to a string containing NULL, but NULL), it tries to print what's at memory location 0x00 and gives a segmentation fault.
Try checking for row[i] being a valid pointer (non-NULL) before printing it.
Also if your row has any integers in it or anything besides strings you will also get a segfault.