So I have a this program in windows that relies on each other. And I have a loop that checks a certain condition and spawns GTime_mod.exe if the condition is true. As you can see in my code below it has an aux variable coming from a database, the variables default value is 1. Now if GTime_mod.exe is executed the and then when the user were able to give the right username and password, the value of aux will change to 0. Then when the user logout aux will change to 1 again. Now my problem is, I wan't the aux value to change to 1 again besides logging-out. Because there are cases when the **[case 1]** user will just press (X) button to close the program. Or the **[case 2]** user might stop the program by pressing Ctrl + C. And lastly **[case 3]** the user might close the program via task manager. Can anyone please help me or give me a suggestion on how to tackle this problem, your help will be highly appreciated.
int main(void){
sqlite3 *db;
time_t now;
struct tm *local;
int er;
char *sqlCom;
char *errMsg = 0;
hr_mn high,low;
int sdur = 0;
int opt = 0;
int cond = 0;
int aux = 0;
er = sqlite3_open("GTime.db",&db);
if(er != SQLITE_OK) sqlite3_close(db),Err(sqlite3_errmsg(db));
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 1;",hrmn,&low,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 2;",hrmn,&high,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 3;",hrmn,&aux,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
time(&now);
local = localtime(&now);
sdur = 30 - (local->tm_sec <= 30 ? local->tm_sec : (local->tm_sec - 30));
do{
cond = (local->tm_hour >= low.hrs && local->tm_min < low.min) ||
(local->tm_hour <= high.hrs && local->tm_min < high.min);
if(!cond && aux){
spawnl(P_WAIT,"C:\\WINDOWS\\System32\\shutdown.exe","C:\\WINDOWS\\System32\\shutdown.exe","/r /f /t 60 /c \" \"",NULL);
opt = MessageBoxA( NULL, "System is shutting down", "GTime", MB_OKCANCEL|MB_ICONSTOP|MB_SYSTEMMODAL|MB_SETFOREGROUND|MB_TOPMOST );
if(opt == 2){
spawnl(P_WAIT,"GTime_mod.exe","GTime_mod.exe",NULL,NULL);
}else
exit(0);
time(&now);
local = localtime(&now);
sleep(30 - (local->tm_sec <= 30 ? local->tm_sec : (local->tm_sec - 30)));
}else
sleep(sdur);
time(&now);
local = localtime(&now);
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 1;",hrmn,&low,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 2;",hrmn,&high,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 3;",hrmn,&aux,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
sdur = 30;
}while(1);
return 0;
}
[Edit]
As for me case 1 is the highest priority to be solved as it is the most likely scenario
From reading the spawnl documentaion you can get the exit value by using the P_WAIT flag.
So you just need to check that response value:
int exit_val;
[...]
exit_val = spawnl( P_WAIT, "GTime_mod.exe","GTime_mod.exe", NULL, NULL);
if ( exit_val == 1 )
{
// manage exit
}
Move the code that changes the value back to 1 to a function, and register the function with atexit so it is always called when exiting the program.
Related
My C application uses SQLite 3.36. I am using WAL mode for my DB. But on inserting ~50K records with 7 columns, the WAL file grows up to 1.5 GB.
I have disabled auto checkpointing and doing manual checkpointing after all insertions.
I already went through many articles which blame checkpointing for the huge WAL size.
But,I guess checkpointing is not the issue here because other tables exist in the same DB where the record count is more than 50k but the WAL file size remains in MBs on insertion.
Before insertion, I am doing deletion but in that case, table contains hardly 2-3 records so WAL size is not impacted much (Confirmed by debugging the code).
During debugging I observed, the WAL size increasing very fast in for loop used for insertion (See below code). Loop completed within seconds.
Below is the code - (Added comments for a few local methods and macros )
Note- Code is running fine without any error and on checkpointing, I am getting desired records in the original DB. No other read operation going on this table during the execution of this routine.
Kindly, help me to know what I am doing wrong here which is causing the WAL file to grow up to 1.5GB.
Is insert after delete causing some issues?
int generatefMap(struct ixdb* xdb)
{
struct fmap* fmap;
uint64_t max_id, size;
int status = 0;
sqlite3_stmt* stmt = NULL;
int stmt_id = 0;
int retry_count = 0;
char* sql = NULL;
max_id = 0;
fmap = NULL;
status = ixdb_largest_id(xdb, &max_id);
if (status != 0 || max_id == 0) {
if (status == E_NOTFOUND) {
status = 0;
}
else {
return E_INVALID;
}
}
sql = "DELETE FROM fmap; ";
status = sqlite3_exec(xdb->dbh->db, sql, NULL, NULL, NULL);
if (status != 0) {
return status;
}
size = (max_id + 1) * sizeof(struct fnode);
fmap = (struct fmap*)mem_alloc(sizeof(struct fmap)); // #define mem_alloc(size) calloc(1, (size))
if (fmap == NULL) {
status = E_MEM;
return status;
}
fmap->hash = (struct fnode*)mem_alloc((size_t)size);// #define mem_alloc(size) calloc(1, (size))
if (fmap->hash == NULL) {
free(fmap);
status = E_MEM;
return status;
}
fmap->size = size;
fmap->max_id = max_id;
status = __fmap_gen(fmap, xdb); //Gives fmap by selecting/querying data from other table in same DB
if (status != 0) {
free(fmap->hash);
free(fmap);
return status;
}
//Insert into DB
stmt_id = XDB_FMAP_INSERT; //INSERT OR REPLACE INTO fmap(id,pid,xt,size,xtime,ytime,selected) values (:id,:pid,:xt,:size,:xtime,:ytime,:selected);
stmt = get_prepared_stmt(xdb, stmt_id); // This will get me prepared statement for above query
for (uint64_t i = 0; i < max_id + 1; ++i) {
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
sqlite3_bind_int64(stmt, 1, (uint64_t)(i + 1));
sqlite3_bind_int64(stmt, 2, fmap->hash[i].pid);
sqlite3_bind_int64(stmt, 3, fmap->hash[i].xtid);
sqlite3_bind_int64(stmt, 4, fmap->hash[i].size);
sqlite3_bind_int64(stmt, 5, fmap->hash[i].xtime);
sqlite3_bind_int64(stmt, 6, fmap->hash[i].ytime);
sqlite3_bind_int64(stmt, 7, fmap->hash[i].selected);
retry:
status = sqlite3_step(stmt);
if (status == SQLITE_BUSY || status == SQLITE_IOERR_BLOCKED) {
printf("sqlite_step returned: %d . Hence retrying ", status);
++retry_count;
if (retry_count <= ATTEMPTS) { //#define ATTEMPTS 5
sleep(SLEEP); //#define SLEEP 1
goto retry;
}
printf("Maximum number of retries(%d) exhausted|stmt=%s|err=%d", ATTEMPTS, sqlite3_expanded_sql(stmt), status);
goto err;
}
else if (status != SQLITE_DONE) {
printf("\nsqlite3_step() failed with error[%d].\n", status);
status = ERR_SQLITE;
goto err;
}
status = 0;
}
if (stmt) {
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
}
err:
if (fmap->hash) {
free(fmap->hash);
fmap->hash = NULL;
}
if (fmap) {
free(fmap);
fmap = NULL;
}
return status;
}
I am trying to build a function that will return the cpu usage of my vm's processors over a period of 1 second. The goal is to use pretty basic C library function. The method takes 3 arguments: the path, a cpu_stats *prev structure and a cpu_stats *curr structure. Both structures are used to store previous and current values so that the method gets accurate as soon as it ran twice. The problem I seem to have is about accurately returning the value. For now I am adding every value of the first line of /proc/stat and using that as my total value, and taking the value of the 3rd column as my idle value ( no idea if it is this one, different sites different answers about what each column is). Let me know if you know where to start and what to change. For now all the tests my code go through says that my results are always 100.0% but the values expected are like 32.2%/72.1%/49.0%/etc...
Here is my code:
double pfs_cpu_usage(char *proc_dir, struct cpu_stats *prev, struct cpu_stats *curr)
{
long idleOne, idleTwo, totalOne, totalTwo=0;
idleOne = prev->idle;
totalOne = prev->total;
int fd = open_path(proc_dir, "stat");
if (fd <= 0) {
perror("open_path");
return -1;
}
size_t line_sz = 0;
char line[256];
while ((line_sz = one_lineread(fd, line, 256)) > 0) {
char *next_tok = line;
char *curr_tok;
char *endPtr;
int counter = 1;
while ((curr_tok = next_token(&next_tok, "\n\t: ")) != NULL) {
if(counter == 5) {
counter++;
idleTwo = strtol(curr_tok, &endPtr, 32);
curr->idle = idleTwo;
}
else if(strcmp(curr_tok,"cpu") == 0){
counter++;
}
else{
counter++;
totalTwo += strtol(curr_tok, &endPtr, 32);
curr->total = totalTwo;
}
}
}
long diffIdle = idleTwo - idleOne;
long diffTotal = totalTwo - totalOne;
double cpuUsage = (1.0 - ((double)diffIdle)*1.0/((double)diffTotal)*100);
close(fd);
return cpuUsage;
}
Here is the first line of my /proc/stat file:
cpu 12836188 17450 280277082 121169501 1538 0 2490 5206 0 0
Apparently, the idle value stored seems off from my debugging.
Ok, then this article? https://stackoverflow.com/a/23376195/13307070
This answer based on https://htop.dev/ which using /proc/stat
I have made an sqlite3 database that saves entries that sensors create. I am checking on leaks with valgrind, now I was wondering how to 'simulate' a broken SQL server. I am using this function:
rc = sqlite3_prepare_v2(conn, sql, -1, &res, 0);
This function works correctly, is there a way to simulate it failing? Setting rc to another value manually is an option, but doesn't make sense since a database does get created while the program thinks it doesn't.
I will add the code bellow, although I don't think this is necessary for this question.
This is the insert function that inserts a sensor into the database. This is where I want to test what happens when the prepare function fails.
void *insert_sensor(void *argument) {
storagemgr_insert_argument_t *storagemgr_insert_argument = (storagemgr_insert_argument_t *) argument;
DBCONN *conn = storagemgr_insert_argument->db_connection;
sqlite3_stmt *res = NULL;
uint16_t sensor_id_read;
double temperature_value_read;
time_t timestamp_read;
sensor_data_t data;
int buffer_working_check;
data.id = 0;
data.value = 0;
data.ts = 0;
buffer_working_check = 1;
while (connmgr_loopt_bool == 1 || buffer_working_check == 0) { //connmgr aan -> moet blijven lopen, connmgr uit maar nog data beschikbaar -> moet blijven lopen
pthread_mutex_lock(&lock);
// printf("gelockt in storagemgr\n");
buffer_working_check = sbuffer_read(shared_buffer, &data, 0, 1);
pthread_mutex_unlock(&lock);
int failed_tries = 0;
if (data.id != 0 && buffer_working_check != -1 && buffer_working_check != 1) {
res = NULL;
sensor_id_read = data.id;
temperature_value_read = data.value;
timestamp_read = data.ts;
while(failed_tries<3) {
char *sql = "INSERT INTO "TO_STRING(TABLE_NAME)" (sensor_id, sensor_value, timestamp) VALUES (#sensor_id, #sensor_value, #timestamp)";
rc = sqlite3_prepare_v2(conn, sql, -1, &res, 0);
if (rc == SQLITE_OK) {
int idx1 = sqlite3_bind_parameter_index(res, "#sensor_id");
sqlite3_bind_int(res, idx1, sensor_id_read);
int idx2 = sqlite3_bind_parameter_index(res, "#sensor_value");
sqlite3_bind_double(res, idx2, temperature_value_read);
int idx = sqlite3_bind_parameter_index(res, "#timestamp");
sqlite3_bind_int(res, idx, timestamp_read);
break;
}
else {
write_to_fifo("Insert to the SQL server failed, trying again. ", 4);
failed_tries++;
// char *err_msg = 0;
//
// fprintf(stderr, "Failed to execute statement: %s\n", sqlite3_errmsg(conn));
// sqlite3_free(err_msg);
// sqlite3_close(conn);
// return NULL;
}
sleep(2);
}
}
if (0<failed_tries && failed_tries <= 2) { //het mag =2, want als het =2 en de db faalt dan wordt het eerst geincrementeert naar 3
write_to_fifo("Connection to SQL server re-established. ", 5);
}
if(failed_tries>2) {
db_connection_failed_bool = 1;
sqlite3_close(conn);
write_to_fifo("Connection to SQL server lost. ", 6);
break;
}
if (res != NULL) {
sqlite3_step(res);
sqlite3_finalize(res);
res = NULL;
}
}
return NULL;
}
If you want to keep the code pure, you could always pass the insert function an invalid file path or invalid file name. If you are trying to test the recovery loop, and still want it to remain pure, you can pass the invalid file path and have the recovery loop try to build the path. SQLite won’t build a database in a folder that doesn’t exist when using sqlite3_prepare_v2.
I am trying to program the logomatic by sparkfun, and yes I have used their forum with no responses, and having some issues. I am trying to send characters to the UART0 and I want the logomatic to respond with specific characters and not just an echo. For example, I send 'ID?' over the terminal (using RealTerm), and the logomatic sends back '1'. All it will so now is echo.
I am using c with programmers notepad with the WinARM toolchain. The following snippet is from the main.c file. I only included this, because I am fairly certain that this is where my problem lies
void Initialize(void)
{
rprintf_devopen(putc_serial0);
PINSEL0 = 0xCF351505;
PINSEL1 = 0x15441801;
IODIR0 |= 0x00000884;
IOSET0 = 0x00000080;
S0SPCR = 0x08; // SPI clk to be pclk/8
S0SPCR = 0x30; // master, msb, first clk edge, active high, no ints
}
Notice the rprintf_devopen function, below is from the rprintf.c file, and due to my mediocre skills, I do not understand this bit of code. If I comment out the rprintf_devopen in main, the chip never initializes correctly.
static int (*putcharfunc)(int c);
void rprintf_devopen( int(*put)(int) )
{
putcharfunc = put;
}
static void myputchar(unsigned char c)
{
if(c == '\n') putcharfunc('\r');
putcharfunc(c);
}
Now, below is from the serial.c file. So my thought was that I should be able to just call one of these putchar functions in main.c and that it would work, but it still just echoes.
int putchar_serial0 (int ch)
{
if (ch == '\n')
{
while (!(U0LSR & 0x20));
U0THR = CR; // output CR
}
while (!(U0LSR & 0x20));
return (U0THR = ch);
}
// Write character to Serial Port 0 without \n -> \r\n
int putc_serial0 (int ch)
{
while (!(U0LSR & 0x20));
return (U0THR = ch);
}
// Write character to Serial Port 1 without \n -> \r\n
int putc_serial1 (int ch)
{
while (!(U1LSR & 0x20));
return (U1THR = ch);
}
void putstring_serial0 (const char *string)
{
char ch;
while ((ch = *string))
{
putchar_serial0(ch);
string++;
}
}
I have tried calling the different putchar functions in main, also with the rprintf_devopen. Still just echoes. I have altered the putchar functions and still just echoes. I have tried just writing to the U0THR register in main.c and no luck. Keep in mind that I am still a student and my major is electrical engineering, so the only programming classes that I have taken are intro to c, and an intro to vhdl. I am more of a math and physics guy. I was working on this for an internship I was doing. The internship ended, but it just bugs me that I cannot figure this out. Honestly, working on this program taught me more that the c class that I took. Anyways, I appreciate any help that can be offered, and let me know if you want to see the entire code.
Below is an update to the question. This function is in main.c
static void UART0ISR(void)
{
char temp;
trig = 13; //This is where you set the trigger character in decimal, in this case a carriage return.
temp = U0RBR; //U0RBR is the receive buffer on the chip, refer to datasheet.
if(temp == query1[counter1]) //This segment looks for the characters "ID?" from the U0RBR
{ //query1 is defined at the top of the program
counter1++;
if(counter1 >= 3)
{
flag1 = 1; //This keeps track of whether or not query1 was found
counter1 = 0;
stat(1,ON);
delay_ms(50);
stat(1,OFF);
RX_in = 0;
temp = 0;
//rprintf("\n\rtransmission works\n");
putc_serial1(49);
}
}
if(temp == query2[counter2] && flag1 == 1) //This segment looks for "protov?" from the U0RBR, but only after query1 has been found
{
counter2++;
if(counter2 >= 7)
{
flag2 = 1; //This keeps track of whether or not query2 was found
counter2 = 0;
stat(1,ON);
delay_ms(50);
stat(1,OFF);
RX_in = 0;
temp = 0;
putc_serial1(49);
}
}
if(temp == stop[counter3]) //This if segment looks for certain characters in the receive buffer to stop logging
{
counter3++;
if(counter3 >= 2)
{
flagstop = 1; //This flagstop keeps track of whether or not stop was found. When the stop characters are found,
flag1 = 0; //the query1 and query2 flags will be reset. So, in order to log again these queries must be sent again
flag2 = 0; //this may seem obvious, but deserves mention.
counter3 = 0;
stat(1,ON);
delay_ms(500);
stat(1,OFF);
RX_in = 0;
temp = 0;
}
flagstop = 0; //Reset the stop flag in order to wait once again for the query 1&2
}
if(RX_in == 0)
{
memset (RX_array1, 0, 512); // This clears the RX_array to make way for new data
memset (RX_array2, 0, 512);
}
if(RX_in < 512 && flag1 == 1 && flag2 == 1) //We cannot log data until we see both flags 1 & 2 and after we see these flags,
{ //we must then see the trigger character "carriage return"
RX_array1[RX_in] = temp;
RX_in++;
if(temp == trig)
{
RX_array1[RX_in] = 10; // delimiters
log_array1 = 1;
RX_in = 0;
}
}
else if(RX_in >= 512 && flag1 == 1 && flag2 == 1) //This else if is here in case the RX_in is greater than 512 because the RX_arrays are defined to
{ //be of size 512. If this happens we don't want to lose data, so we must put the overflow into another register.
RX_array2[RX_in - 512] = temp;
RX_in++;
RX_array1[512] = 10; // delimiters
RX_array1[512 + 1] = 13;
log_array1 = 1;
if(RX_in == 1024 || temp == trig)
{
RX_array2[RX_in - 512] = 10; // delimiters
log_array2 = 1;
RX_in = 0;
}
}
temp = U0IIR; // have to read this to clear the interrupt
VICVectAddr = 0;
}
as mentioned in the titled, my function doesn't end well. I am trying to do the following :
" Implement, with the DC method, a function which has this interface :
Returns the majority element of the given sequence if one such exists
PARAMETERS
sequence Valid pointer to an array of elements
sequenceLength Size of the array
*
RETURN
element A pointer to one element corresponding to the majority
element or NULL if no such element exists
const Element getMajElDC(const Element* const * sequence, size_t sequenceLength); "
Actually, I just tried to implement this solution : http://www.ece.northwestern.edu/~dda902/336/hw4-sol.pdf
And here's my way to do it :
const Element* getMajElDC(const Element* const * sequence, size_t,sequenceLength){
printf("1\n");
const Element* element_tmp_right;
const Element* element_tmp_left;
int occurence_left = 0;
int occurence_right = 0;
if (sequenceLength == 1)
return sequence[1];
int mid = (int)sequenceLength/2;
element_tmp_left = getMajElDC(sequence,mid);
if (sequenceLength%2 == 0)
element_tmp_right = getMajElDC(&sequence[mid],mid);
element_tmp_right = getMajElDC(&sequence[mid],mid+1);
if (element_tmp_left == NULL && element_tmp_right != NULL)
return element_tmp_right;
if (element_tmp_right == NULL && element_tmp_left != NULL)
return element_tmp_left;
if (element_tmp_right == NULL && element_tmp_left == NULL)
return NULL;
if (areEqual(element_tmp_left,element_tmp_right))
return element_tmp_left;
for (int i=0;i<sequenceLength;i++){
if( areEqual(sequence[i],element_tmp_left))
occurence_left++;
if (areEqual(sequence[i],element_tmp_right))
occurence_right++;
}
if (occurence_left > mid+1)
return element_tmp_left;
else if (occurence_left > mid+1)
return element_tmp_left;
else
return NULL;
}
When I try to run it in codeblocks, the .exe just stopworking. Just like if the function was endless. That's why I placed a printf in the beginning : I wanted to see how many times the " 1 " would appear in the application windows and it appears so many times that everything goes crazy.
I tried to look into the base case of the recursion, but nothing seems wrong with it...
I am truly lost my poor knowledge of C, does anyone see where the problem is ?
Ps : the areEqual() function is just a given function, here's its implementation but there is nothing special with it :
bool areEqual(const Element* a, const Element* b)
{
return a->value == b->value;
}
with
struct element_t
{
int value;
};
typedef struct element_t Element;
To end my question, I tell you in advance that I'm sorry if a crucial information is missing : It is the first time I use this website, please be indulgent !
You have to use debugger it will show you immediately where the problem is.
BTW look closer this code:
if (sequenceLength == 1)
return sequence[1];
int mid = (int)sequenceLength/2;
element_tmp_left = getMajElDC(sequence,mid);
if (sequenceLength%2 == 0)
element_tmp_right = getMajElDC(&sequence[mid],mid);
element_tmp_right = getMajElDC(&sequence[mid],mid+1);
You close the recursion when sequenceLength == 1, but if getMajElDC has been called with sequenceLength=0 it will never return.
Consider to modify:
if (sequenceLength == 1)
return sequence[1];
to:
if (sequenceLength <= 1)
return sequence[1];
consider this code snippet:
int mid = (int)sequenceLength/2;
element_tmp_left = getMajElDC(sequence,mid);
if (sequenceLength%2 == 0)
element_tmp_right = getMajElDC(&sequence[mid],mid);
element_tmp_right = getMajElDC(&sequence[mid],mid+1);
notice that the third call to getMajElDC is always called regardless of the value of sequenceLength. I suspect that you wanted to write this:
if (sequenceLength%2 == 0)
element_tmp_right = getMajElDC(&sequence[mid],mid);
else
element_tmp_right = getMajElDC(&sequence[mid],mid+1);