Unable to add list to the record - aerospike

I'm trying to add a record to the database having 3 bins, one of which is a list using my c++ program(I'm using Aerospike's C client library) but after I execute my program, only 2 of the bins are added in the record. For some reasons, I'm not able to add the 3rd bin having the list value.
Given below is the program:
#include<aerospike/aerospike.h>
#include<aerospike/as_arraylist.h>
#include <aerospike/as_record.h>
#include<aerospike/as_record_iterator.h>
#include <aerospike/as_policy.h>
#include<aerospike/aerospike_key.h>
#include<aerospike/as_std.h>
#include<aerospike/as_integer.h>
#include<aerospike/as_string.h>
#include<iostream>
#include<aerospike/as_hashmap.h>
#include<string>
using namespace std;
int main()
{
as_error err;
as_config config;
as_config_init(&config);
config.policies.write.key = AS_POLICY_KEY_SEND;
as_config_add_host(&config, "182.18.182.192", 3000);
aerospike as;
aerospike_init(&as, &config);
if(aerospike_connect(&as, &err)!=AEROSPIKE_OK)
{
printf("error(%d) %s at [%s:%d]", err.code, err.message, err.file, err.line);
}
as_key key;
as_record rec;
as_record_init(&rec, 2);
int n;
cout<<endl<<"Enter the number of records to enter: ";
cin>>n;
for(int i=0;i<n;i++)
{
cout<<endl<<"Enter the name: ";
string pk;
getline(cin>>ws,pk);
as_key_init(&key, "test", "vishal_set", pk.c_str());
cout<<endl<<"Enter the age: ";
int age;
cin>>age;
as_record_set_int64(&rec, "age", age);
cout<<endl<<"Enter the contact no: ";
string contact_no;
getline(cin>>ws,contact_no);
as_record_set_str(&rec, "contact_no", contact_no.c_str());
as_arraylist list;
as_arraylist_inita(&list,2);
as_arraylist_append_str (&list, "playing football");
as_arraylist_append_str (&list, "playing cricket");
cout<<endl<<"Number of elements in the list: "<<as_arraylist_size(&list)<<endl;
if(!(as_record_set_list(&rec, "hobbies", (as_list *)&list)))
{
printf("\n[%s::%d]Error\n",__FILE__,__LINE__);
}
if (aerospike_key_put(&as, &err,NULL, &key, &rec) != AEROSPIKE_OK)
{
printf("error(%d) %s at [%s:%d]", err.code, err.message, err.file, err.line);
}
}
if(aerospike_close(&as,&err)!=AEROSPIKE_OK)
{
printf("error(%d) %s at [%s:%d]", err.code, err.message, err.file, err.line);
}
aerospike_destroy(&as);
return 0;
}

Fortunately, I've found the reason why my list was not getting added to the record myself. It turned out to be really silly mistake.
The reason was that I had done a mistake in initializing as_record. Since I was adding 3 bins to the record therefore, I should have initialised it as as_record_init(&rec, 3);.

Related

What is the best way to read/write objects in a file with the following conditions

I am willing to store objects in a database. The purpose is to be able to read / write these objects with the program. The requirements are the following:
Objects can be complex using Qt classes such as QList, QString ... or even can contain other objects that use QObjects
The database should not be readable or modified by human (no text file, and if I use sqlite database, it has to be encrypted in a way)
I should be able to remove, read an object by its name and count the number of objects in the database, without loading everything in the memory
I asked a question here, to do this with a QDataStream with a minimalist example. But it seems it is not the best way to proceed.
Would you have some suggestions regarding the solutions that exist for this purpose?
I have tried the following but it does not fulfill the requirements:
Storing text in sqlite with QtSQL: but the data is accessible by using sqlitemanager for example, can be modified or removed by humans. Moreover, I have no idea regarding the way to store QList for example or other objects that I created and contain QObject (for example, 2 QList)
Storing binary data using QDataStream: in this case, I cannot count the number of objects in my file, neither read or remove a specific object without loading the entire file in memory.
I would be grateful if you could give me some suggestions or provide example, even if the example is minimalist.
I finally found a solution, especially thanks to Igor Tandetnik and thanks to the topic here
I haven't quite finalized, there is a small imperfection because I have to define an object of my user class that I don't use in order to call the readFromDB function to generate my object from the db.
On the other hand, I get this error message "QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed" each time I call my database.
Anyway, it's a bit late now, and I think it might help some people so I post this minimalist imperfect code below. I'll post an update in the next few days.
Thanks again.
#include "QString"
#include "QFile"
#include "QDataStream"
#include "qdebug.h"
#include "QtSql"
#include "QSqlDatabase"
#include "qmessagebox.h"
class User
{
protected:
QString name;
QList<QString> childrens;
public:
QString getName(){ return name;}
QList<QString> getChildrens(){ return childrens;}
void setName(QString x) {name = x;}
void setChildrens(QList<QString> x) {childrens = x;}
friend QDataStream &operator<<(QDataStream &out, const User &t)
{
out << t.name << t.childrens;
return out;
}
friend QDataStream &operator>>(QDataStream &in, User &t)
{
QString inname;
QList<QString> inchildrens;
in >> inname >> inchildrens;
t.name = inname;
t.childrens = inchildrens;
return in;
}
QByteArray object2blob( const User& user )
{
QByteArray result;
QDataStream bWrite( &result, QIODevice::WriteOnly );
bWrite << user;
return result;
}
User blob2object( const QByteArray& buffer )
{
User result;
QDataStream bRead( buffer );
bRead >> result;
return result;
}
int saveToDB( const User& user )
{
QSqlDatabase myDB = QSqlDatabase::addDatabase("QSQLITE");
myDB.setDatabaseName( "file.db");
if (!myDB.open())
{
qDebug()<<"Failed to open SQL database of registered users";
}
else
{
qDebug()<<"Successfully opening SQL database of registered users";
QSqlQuery query;
query.prepare( "CREATE TABLE IF NOT EXISTS users (name TEXT, childrens BLOB)" );
if( !query.exec() )
{
qDebug() << query.lastError();
}
else
{
qDebug() << "Table created!";
query.prepare( "INSERT INTO users (name,childrens) VALUES (:name,:childrens)" );
query.bindValue(":name", name);
query.bindValue( ":childrens", object2blob(user) );
query.exec();
}
query.clear();
myDB.close();
}
QSqlDatabase::removeDatabase("UserConnection");
return 0;
}
User readFromDB( QString name )
{
User result;
QSqlDatabase myDB = QSqlDatabase::addDatabase("QSQLITE");
myDB.setDatabaseName( "file.db");
if (!myDB.open())
{
qDebug()<<"Failed to open SQL database of registered users";
}
else
{
QSqlQuery query;
query.prepare( "SELECT * FROM users WHERE name ='"+ name +"'" );
//query.bindValue( 0, name );
if ( query.exec() && query.next() ) {
result = blob2object( query.value( 1 ).toByteArray() );
}
query.clear();
myDB.close();
}
QSqlDatabase::removeDatabase("UserConnection");
qDebug()<<result.getChildrens();
return result;
}
};
////////////////////////////////////////////////////////////////
int main()
{
User u;
u.setName("Georges");
u.setChildrens(QList<QString>()<<"Jeanne"<<"Jean");
u.saveToDB(u);
User v;
v.setName("Alex");
v.setChildrens(QList<QString>()<<"Matthew");
v.saveToDB(v);
User w;
w.setName("Mario");
w.saveToDB(w);
User to_read; //to improve here
User a = to_read.readFromDB("Georges");
qDebug()<<a.getChildrens();
return 0;
}

How to get selected adapter's MAC address in WinPcap?

For example, when program runs, I entered 1 as input and wanted to get MAC address of that interface in here. How can I do that?
I did a lot of work trying to figure out how to both get the mac address for an arbitrary interface under Windows, and matching that to the device info you get back from WinPCap.
A lot of posts say you should use GetAdaptersInfo or similar functions to get the mac address, but unfortunately, those functions only work with an interface that has ipv4 or ipv6 bound to it. I had a network card that purposely wasn't bound to anything, so that Windows wouldn't send any data over it.
GetIfTable(), however, seems to actually get you every interface on the system (there were 40 some odd on mine). It has the hardware mac address for each interface, so you just need to match it to the corresponding WinPCap device. The device name in WinPCap has a long GUID, which is also present in the name field of the interface table entries you get from GetIfTable. The names don't match exactly, though, so you have to extract the GUID from each name and match that. An additional complication is that the name field in the WinPCap device is a regular character string, but the name in the data you get from GetIfTable is a wide character string. The code below worked for me on two different systems, one Windows 7 and another Windows 10. I used the Microsoft GetIfTable example code as a starting point:
#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "IPHLPAPI.lib")
#include <pcap.h>
// Compare the guid parts of both names and see if they match
int compare_guid(wchar_t *wszPcapName, wchar_t *wszIfName)
{
wchar_t *pc, *ic;
// Find first { char in device name from pcap
for (pc = wszPcapName; ; ++pc)
{
if (!*pc)
return -1;
if (*pc == L'{'){
pc++;
break;
}
}
// Find first { char in interface name from windows
for (ic = wszIfName; ; ++ic)
{
if (!*ic)
return 1;
if (*ic == L'{'){
ic++;
break;
}
}
// See if the rest of the GUID string matches
for (;; ++pc,++ic)
{
if (!pc)
return -1;
if (!ic)
return 1;
if ((*pc == L'}') && (*ic == L'}'))
return 0;
if (*pc != *ic)
return *ic - *pc;
}
}
// Find mac address using GetIFTable, since the GetAdaptersAddresses etc functions
// ony work with adapters that have an IP address
int get_mac_address(pcap_if_t *d, u_char mac_addr[6])
{
// Declare and initialize variables.
wchar_t* wszWideName = NULL;
DWORD dwSize = 0;
DWORD dwRetVal = 0;
int nRVal = 0;
unsigned int i;
/* variables used for GetIfTable and GetIfEntry */
MIB_IFTABLE *pIfTable;
MIB_IFROW *pIfRow;
// Allocate memory for our pointers.
pIfTable = (MIB_IFTABLE *)malloc(sizeof(MIB_IFTABLE));
if (pIfTable == NULL) {
return 0;
}
// Make an initial call to GetIfTable to get the
// necessary size into dwSize
dwSize = sizeof(MIB_IFTABLE);
dwRetVal = GetIfTable(pIfTable, &dwSize, FALSE);
if (dwRetVal == ERROR_INSUFFICIENT_BUFFER) {
free(pIfTable);
pIfTable = (MIB_IFTABLE *)malloc(dwSize);
if (pIfTable == NULL) {
return 0;
}
dwRetVal = GetIfTable(pIfTable, &dwSize, FALSE);
}
if (dwRetVal != NO_ERROR)
goto done;
// Convert input pcap device name to a wide string for compare
{
size_t stISize,stOSize;
stISize = strlen(d->name) + 1;
wszWideName = malloc(stISize * sizeof(wchar_t));
if (!wszWideName)
goto done;
mbstowcs_s(&stOSize,wszWideName,stISize, d->name, stISize);
}
for (i = 0; i < pIfTable->dwNumEntries; i++) {
pIfRow = (MIB_IFROW *)& pIfTable->table[i];
if (!compare_guid(wszWideName, pIfRow->wszName)){
if (pIfRow->dwPhysAddrLen != 6)
continue;
memcpy(mac_addr, pIfRow->bPhysAddr, 6);
nRVal = 1;
break;
}
}
done:
if (pIfTable != NULL)
free(pIfTable);
pIfTable = NULL;
if (wszWideName != NULL)
free(wszWideName);
wszWideName = NULL;
return nRVal;
}

Making cin take selective inputs [Turbo C++]

Don't hate cause of Turbo, I already hate my school!
I wish to show an error msg if a character is entered instead of an int or float in some file such as age or percentage.
I wrote this function:
template <class Type>
Type modcin(Type var) {
take_input: //Label
int count = 0;
cin>>var;
if(!cin){
cin.clear();
cin.ignore();
for ( ; count < 1; count++) { //Printed only once
cout<<"\n Invalid input! Try again: ";
}
goto take_input;
}
return var;
}
but the output is not desirable:
How do I stop the error msg from being repeated multiple times?
Is there a better method?
NOTE: Please make sure that this is TurboC++ that we are talking about, I tried using the approach in this question, but even after including limits.h, it doesn't work.
Here, a code snippet in C++.
template <class Type>
Type modcin(Type var) {
int i=0;
do{
cin>>var;
int count = 0;
if(!cin) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
for ( ; count < 1; count++) { //Printed only once
cout<<"\n Invalid input! Try again: ";
cin>>var;
}
}
} while (!cin);
return var;
}
The variables are tailored to match yours' so you can understand better. This code isn't perfect though.
It can't handle cases like "1fff", here you would just get a 1 in return. I tried solving it but then a infinite loop was being encountered, when I'll fix it, I'll update the code.
It also can't function in TurboC++ effectively. I don't know if there are alternatives but the numeric_limits<streamsize>::max() argument gives a compiler error ('undefined symbol' error for numeric_limits & streamsize and 'prototype must be defined' error for max()) in Turbo C++.
So, to make it work in Turbo C++. Replace the numeric_limits<streamsize>::max() argument with some big int value such as 100.
This will make it so that the buffer is only ignored/cleared till 100 characters are reached or '\n' (enter button/newline character) is pressed.
EDIT
The following code can be executed on both Turbo C++ or proper C++. The comments are provided to explain the functioning:
template <class Type> //Data Integrity Maintenance Function
Type modcin(Type var) { //for data types: int, float, double
cin >> var;
if (cin) { //Extracted an int, but it is unknown if more input exists
//---- The following code covers cases: 12sfds** -----//
char c;
if (cin.get(c)) { // Or: cin >> c, depending on how you want to handle whitespace.
cin.putback(c); //More input exists.
if (c != '\n') { // Doesn't work if you use cin >> c above.
cout << "\nType Error!\t Try Again: ";
cin.clear(); //Clears the error state of cin stream
cin.ignore(100, '\n'); //NOTE: Buffer Flushed <|>
var = modcin(var); //Recursive Repeatation
}
}
}
else { //In case, some unexpected operation occurs [Covers cases: abc**]
cout << "\nType Error!\t Try Again: ";
cin.clear(); //Clears the error state of cin stream
cin.ignore(100, '\n'); //NOTE: Buffer Flushed <|>
var = modcin(var);
}
return var;
//NOTE: The '**' represent any values from ASCII. Decimal, characters, numbers, etc.
}

Determine types from a variadic function's arguments in C

I'd like a step by step explanation on how to parse the arguments of a variadic function
so that when calling va_arg(ap, TYPE); I pass the correct data TYPE of the argument being passed.
Currently I'm trying to code printf.
I am only looking for an explanation preferably with simple examples but not the solution to printf since I want to solve it myself.
Here are three examples which look like what I am looking for:
https://stackoverflow.com/a/1689228/3206885
https://stackoverflow.com/a/5551632/3206885
https://stackoverflow.com/a/1722238/3206885
I know the basics of what typedef, struct, enum and union do but can't figure out some practical application cases like the examples in the links.
What do they really mean? I can't wrap my brain around how they work.
How can I pass the data type from a union to va_arg like in the links examples? How does it match?
with a modifier like %d, %i ... or the data type of a parameter?
Here's what I've got so far:
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "my.h"
typedef struct s_flist
{
char c;
(*f)();
} t_flist;
int my_printf(char *format, ...)
{
va_list ap;
int i;
int j;
int result;
int arg_count;
char *cur_arg = format;
char *types;
t_flist flist[] =
{
{ 's', &my_putstr },
{ 'i', &my_put_nbr },
{ 'd', &my_put_nbr }
};
i = 0;
result = 0;
types = (char*)malloc( sizeof(*format) * (my_strlen(format) / 2 + 1) );
fparser(types, format);
arg_count = my_strlen(types);
while (format[i])
{
if (format[i] == '%' && format[i + 1])
{
i++;
if (format[i] == '%')
result += my_putchar(format[i]);
else
{
j = 0;
va_start(ap, format);
while (flist[j].c)
{
if (format[i] == flist[j].c)
result += flist[i].f(va_arg(ap, flist[i].DATA_TYPE??));
j++;
}
}
}
result += my_putchar(format[i]);
i++;
}
va_end(ap);
return (result);
}
char *fparser(char *types, char *str)
{
int i;
int j;
i = 0;
j = 0;
while (str[i])
{
if (str[i] == '%' && str[i + 1] &&
str[i + 1] != '%' && str[i + 1] != ' ')
{
i++;
types[j] = str[i];
j++;
}
i++;
}
types[j] = '\0';
return (types);
}
You can't get actual type information from va_list. You can get what you're looking for from format. What it seems you're not expecting is: none of the arguments know what the actual types are, but format represents the caller's idea of what the types should be. (Perhaps a further hint: what would the actual printf do if a caller gave it format specifiers that didn't match the varargs passed in? Would it notice?)
Your code would have to parse the format string for "%" format specifiers, and use those specifiers to branch into reading the va_list with specific hardcoded types. For example, (pseudocode) if (fspec was "%s") { char* str = va_arg(ap, char*); print out str; }. Not giving more detail because you explicitly said you didn't want a complete solution.
You will never have a type as a piece of runtime data that you can pass to va_arg as a value. The second argument to va_arg must be a literal, hardcoded specification referring to a known type at compile time. (Note that va_arg is a macro that gets expanded at compile time, not a function that gets executed at runtime - you couldn't have a function taking a type as an argument.)
A couple of your links suggest keeping track of types via an enum, but this is only for the benefit of your own code being able to branch based on that information; it is still not something that can be passed to va_arg. You have to have separate pieces of code saying literally va_arg(ap, int) and va_arg(ap, char*) so there's no way to avoid a switch or a chain of ifs.
The solution you want to make, using the unions and structs, would start from something like this:
typedef union {
int i;
char *s;
} PRINTABLE_THING;
int print_integer(PRINTABLE_THING pt) {
// format and print pt.i
}
int print_string(PRINTABLE_THING pt) {
// format and print pt.s
}
The two specialized functions would work fine on their own by taking explicit int or char* params; the reason we make the union is to enable the functions to formally take the same type of parameter, so that they have the same signature, so that we can define a single type that means pointer to that kind of function:
typedef int (*print_printable_thing)(PRINTABLE_THING);
Now your code can have an array of function pointers of type print_printable_thing, or an array of structs that have print_printable_thing as one of the structs' fields:
typedef struct {
char format_char;
print_printable_thing printing_function;
} FORMAT_CHAR_AND_PRINTING_FUNCTION_PAIRING;
FORMAT_CHAR_AND_PRINTING_FUNCTION_PAIRING formatters[] = {
{ 'd', print_integer },
{ 's', print_string }
};
int formatter_count = sizeof(formatters) / sizeof(FORMAT_CHAR_AND_PRINTING_FUNCTION_PAIRING);
(Yes, the names are all intentionally super verbose. You'd probably want shorter ones in the real program, or even anonymous types where appropriate.)
Now you can use that array to select the correct formatter at runtime:
for (int i = 0; i < formatter_count; i++)
if (current_format_char == formatters[i].format_char)
result += formatters[i].printing_function(current_printable_thing);
But the process of getting the correct thing into current_printable_thing is still going to involve branching to get to a va_arg(ap, ...) with the correct hardcoded type. Once you've written it, you may find yourself deciding that you didn't actually need the union nor the array of structs.

unable to add columns to a existing table using C

The following program tries to insert a new row and a new column to an already existing database with a table "people" containing four cols (id, lastname, firstname, phonenumber). While the row gets inserted successfully, the column is not getting added.
#include <stdio.h>
#include <stdlib.h>
#include <libpq-fe.h>
#include <string.h>
int main()
{
PGconn *conn;
PGresult *res;
int rec_count;
int row;
int col;
conn = PQconnectdb("dbname=test host=localhost user=abc1 password=xyz1");
if(PQstatus(conn) == CONNECTION_BAD) {
puts("We were unable to connect to the database");
exit(0);
}
res = PQexec(conn,"INSERT INTO people VALUES (5, 'XXX', 'YYY', '7633839276');");
if(PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "Insertion Failed1: %s", PQerrorMessage(conn));
PQclear(res);
}
else
printf("Successfully inserted value in Table..... \n");
res = PQexec(conn,"update people set phonenumber=\'5055559999\' where id=3");
if(PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "Insertion Failed2: %s", PQerrorMessage(conn));
PQclear(res);
}
res = PQexec(conn, "ALTER TABLE people ADD comment VARCHAR(100) DEFAULT 'TRUE'");
if(PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "Insertion Failed3: %s", PQerrorMessage(conn));
PQclear(res);
}
rec_count = PQntuples(res);
printf("We received %d records.\n", rec_count);
puts("==========================");
for(row=0; row<rec_count; row++) {
for(col=0; col<3; col++) {
printf("%s\t", PQgetvalue(res, row, col));
}
puts("");
}
puts("==========================");
PQclear(res);
PQfinish(conn);
return 0;
}
The program after being compiled and linked gives the following output:
$ ./test
Successfully inserted value in Table.....
We received 0 records.
==========================
==========================
In the postgresql environment, the table "people" is updated with an extra row and a column containing "TRUE".
This is my first program with C embedded with postgresql. Please help!!
This line:
res = PQexec(conn, "EXEC('UPDATE people SET comment = ''TRUE'';');");
should be:
res = PQexec(conn, "UPDATE people SET comment = 'TRUE'");
The EXEC syntax is part of embedded SQL in C with ECPG. It's not to be combined with PQexec from the C libpq library, which is clearly what you're using given the rest of the source code.
Also the result of an UPDATE with no RETURNING clause has PQresultStatus(res)==PGRES_COMMAND_OK, not PGRES_TUPLES_OK
PGRES_COMMAND_OK
Successful completion of a command returning no data.
See Command Execution Functions
You also want to test any PGresult returned by PQexec, not only the result of your last query, because any query may fail.
How can you retrieve data without doing a SELECT statement ?
Never used PQexec, but i guess the code to add might be like this:
res = PQexec(conn, "ALTER TABLE people ADD comment VARCHAR(100) DEFAULT 'TRUE'");
if(PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "Insertion Failed3: %s", PQerrorMessage(conn));
PQclear(res);
}
//Add PQexec and select statement here.
//Something "like" this.
res = PQexec(conn, "SELECT * FROM people;");
if(PQresultStatus(res) != PGRES_TUPLES_OK) {
fprintf(stderr, "Select Failed: %s", PQerrorMessage(conn));
PQclear(res);
}
rec_count = PQntuples(res);
printf("We received %d records.\n", rec_count);