I've created a MySQL User defined function to open a unix domain type socket.
My problem is that if I call my function directly like so:
SELECT socketOpen("/path/to/file", "message");
It always executes in <10ms. So that is nice. But since I don't want to manually call this function everytime, I've created a stored procedure which does an insert into database and then calls this function.
The problem I'm facing is that the stored procedure usually takes <10ms, but somestimes takes over 1s. Even 5s. I don't understand how this happens. Is there a caching problem or something ?
Below is the code is use, stripped of error checking for clarity:
char *socketOpen(UDF_INIT *initid __attribute__((unused)),
UDF_ARGS *args, char *result, unsigned long *length,
char *is_null, char *error __attribute__((unused)))
{
int sockfd, portno, n, servlen;
struct sockaddr_un serv_addr;
struct hostent *server;
char socket_path[100];
char message[100];
memcpy(socket_path,args->args[0],args->lengths[0]);
socket_path[args->lengths[0]] = 0;
memcpy(message,args->args[1],args->lengths[1]);
message[args->lengths[1]] = 0;
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sun_family = AF_UNIX;
strcpy(serv_addr.sun_path, args->args[0]);
servlen=strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);
connect(sockfd,(struct sockaddr *) &serv_addr, servlen);
n = write(sockfd, message, strlen(message));
bzero(message,100);
n = read(sockfd, message, 100);
close(sockfd);
strcpy(result, message);
*length = strlen(message);
return result;
}
I would appreciate your insight into this problem. Thank you.
Since I've got no replies and I've fixed the problem I would like to share my solution to the problem.
The cause of the problem was quite different than I ancipated.
The machine of running the above code was Raspberry pi, which slowness I did not take into account. As it turns out most of the delay was caused by the UPDATE statement in the procedure. As soon as I changed the table ENGINE to MyISAM everything went smooth from then on.
Altough while testing the code there was sometimes still a slight delay. I've fixed that with making the socket non-blocking. That means that if something will go wrong the socket will never be opened, but I figure that is better than blocking indefinetely.
Related
I am new to programming and I am trying to read a page (64Bytes) from an SPI Eeprom and I got it working when reading to an array[67] (3 transmitted Bytes to start the read process via SPI + 64 Bytes data).
I am using IAR Workbench working on a STM32L475.
When I try to use pointers it does not work, probably a stupid no brainer of a beginners mistake, but I appreciate some help to solve this.
I am using a union like this (I know I am wasting mem but for the test it is like this):
//Production Data union
union Production_Data_union
{
struct
{
uint8_t Dummy_Array[3];
char Xxxx_Sn[16];
char Yyyy_Sn[16];
char Prod_Date[8];
char Firmware_Ver[8];
};
uint8_t Eeprom_Page0_Buffer[67];
};
union Production_Data_union Prod_Data;
uint8_t *Eeprom_Page0_Ptr;
uint8_t Read_Cmd[3] = {0x03, 0x00, 0x00};
uint8_t Buff[67];
uint8_t Eeprom_Page_Size = 64;
void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No);
My Main looks like this:
Eeprom_Page0_Ptr = (uint8_t*)&Prod_Data.Eeprom_Page0_Buffer;
Eeprom_Page_Read(Eeprom_Page0_Ptr, 0);
The Eeprom_Page_Read function:
void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No)
{
uint16_t Address;
Address = Page_No * Eeprom_Page_Size;
Read_Cmd[2] = Address & 0xFF;
Read_Cmd[1] = (Address >> 8) & 0xFF;
//Send READ command to Eeprom
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
if(HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)Read_Cmd, (uint8_t *)&Data, (Eeprom_Page_Size +3), 5000) != HAL_OK)
{
Error_Handler();
}
printf("Prod_Data:\n - Xxxx SN %s\n - Yyyy SN %s\n - Prod date %s - Firmware %s\n - Cmd - %d - %d - %d\n",
Prod_Data.Xxxx_Sn,
Prod_Data.Yyyy_Sn,
Prod_Data.Prod_Date,
Prod_Data.Firmware_Ver,
Read_Cmd[0],
Read_Cmd[1],
Read_Cmd[2]);
//Wait for SPI transfer to complete
while (HAL_SPI_GetState(&hspi3) != HAL_SPI_STATE_READY)
{
}
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
Read_E2prom = 0;
}
I know the content of the Eeprom is ok and I can read it if I replace “&Data” with “Buff” (Array[67]) in the HAL_SPI_TransmitReceive(...) call.
Pointer value is the start address of the structure (0x20000090).
So addressing a.s.o. should be ok but the struct is empty when using a pointer.
I am mostly interested in why this does not work and a fix to this, not so much in comments like "why don't you do it like this instead, I want to learn what I have done wrong cause this approach, I believe, should work.
Please remember that I AM NEW at programming so please explain "for Dummies".
I am not sure why that is ?
The function HAL_SPI_TransmitReceive wants a pointer to know where to store the data it receives. It essentially wants an address of where to go place the bytes. In your case, according to line
void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No){...}
Data is already a pointer, because it's denoted with a *. This means that Datais a pointer pointing to some uint8_t number/array somewhere. That somewhere is where you want your SPI to write to.
When you added the & you basically gave the SPI the pointer to the pointer of where you want to write. So the SPI is writing the received data over the pointer, instead of at where the pointer points?
If that doesn't make sense then ask me again. It's a hard thing to explain.
Update:
This is as I understand it, not a pointer but an array?
The compiler only see's it as an pointer. In your case the pointer happen to point to an array, but it could have been to anywhere (almost) in memory. I implore you to rather think in terms of a pointer pointing to the first element of an array (*ptr==array[0]), and not in terms of an array.
Is it somehow implicit so the compiler knows what I want to do so it just accepts and compiles correctly?
I'm not sure if the compiler should compile successfully or not. But you should not rely on that. It's happens often where one could send pointers of pointers around (**ptr), so the compiler is just going to assume you know what you are doing. So you must take great care of how you work with your pointers.
Ok, after trying to solve this for a day or so, I finally found the mistake, it should not be &Data but just Data so it must look like this:
if(HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)Read_Cmd, (uint8_t *)Data, (Eeprom_Page_Size +3), 5000) != HAL_OK)
{
/* Transfer error in transmission process */
Error_Handler();
}
I am not sure why that is ?
I do realise that this problem is pretty common, but I have spent around 4 days so far, trying to fix it on my own, using all the smart advice I found on the Internet and - unfortunately - I've failed.
I managed to make openCV2.4.6 work with my VisualStudio 2012, or at least that's what I assumed after I was able to stream a video from my webcam with this example:
#include "stdafx.h"
#include "opencv2/opencv.hpp"
int main( int argc, const char** argv )
{
CvCapture* capture;
IplImage* newImg;
while (true)
{
capture = cvCaptureFromCAM(-1);
newImg = cvQueryFrame( capture );
cvNamedWindow("Window1", CV_WINDOW_AUTOSIZE);
cvShowImage("Window1", newImg);
int c = cvWaitKey(10);
if( (char)c == 27 ) { exit(0); }
}
cvReleaseImage(&newImg);
return 0;
}
Everything worked fine, so I decided to play around with it and I made an attempt to use a simple image processing operation such as converting rgb to grayscale. I modified my code to following:
#include "stdafx.h"
#include "opencv2/opencv.hpp"
int main( int argc, const char** argv )
{
CvCapture* capture;
IplImage* img1;
IplImage* img2;
while (true)
{
capture = cvCaptureFromCAM(-1);
img1 = cvQueryFrame( capture );
img2 = cvCreateImage(cvGetSize(img1),IPL_DEPTH_8U,1);
cvCvtColor(img1,img2,CV_RGB2GRAY);
cvNamedWindow("Window1", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Window2", CV_WINDOW_AUTOSIZE);
cvShowImage("Window1", img1);
cvNamedWindow("Window2", CV_WINDOW_AUTOSIZE);
int c = cvWaitKey(10);
if( (char)c == 27 ) { exit(0); }
}
cvReleaseImage(&img1);
cvReleaseImage(&img2);
return 0;
}
And that's the place where the nightmare started. I keep getting the
Unhandled exception at at 0x000007FEFD57AA7D in opencvbegginer.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000000030F920.
I did some research and tried few solutions, such as exchanging opencv_core246.lib to opencv_core246d.lib, etc. For a second I hoped it might work, but the reality punched me again with msvcp100d.dll missing. I tried to update all redistributable packages, but it didn't change the fact I keep getting this error. I tried to find out how to fix it another way and I found some forum on which they tell to go to C/C++ properties and change the Runtime Library to MTd, so... I tried this as well, but - as you can notice by now - it didn't work.
At this current moment I just ran out of ideas on how to fix this, so I would be really grateful for any help.
Cheers
PS. Important thing to add: when I got the unhandled exception, opencv 'spoke to me', saying
OpenCV Error: Bad argument in
unknown function, file ......\scr\opencv\modules\core\src\array.cpp,
line 1238
However, I already assumed way back then that I'm just not clever enough with my idiot-resistant code and I tried few other pieces of code that were written by competent people - unfortunately, I keep getting exactly the same error (the rest is the same as well, after I change the things mentioned above).
If img1 == NULL, then it crashes on cvGetSize(img1). Try enclosing the code after cvQueryFrame in an if (img1 != NULL).
However, if it returns NULL for every frame, it means there is something wrong with your camera/drivers/way you capture the frames.
You should also move the cvNamedWindow outside of the loop, since there is no need for it to be recreated for every frame.
I'm new to using the gwan server(link) and for that matter programming in c. I wanted to know what was the easiest way to use mysql in a c script for the gwan server?
I've experimented with dbi.c as used here and the project page can be found here, but also found that there is a c API for mysql itself which you can find here.
Anyone have experience using either or both? What are some of the pros/cons? Are there other libraries that make connecting to mysql easy for a noob like myself?
Any help appreciated.
Thanks!
[EDIT]
Also is libdbi thread safe? it appears to not be.
[EDIT 2]
It appears that the mysql lib itself is the easy way to go unless you think might be switching database types later as libdbi appears to be able to have different drivers which is nice for abstraction.
Relating to GWAN for me if i had any "mysql code" in the main function of a handler it appeared to be unsafe and caused random errors intermittently, but if i put the "mysql code" in the init function and put any data i need in a kv store accessed off of one of the global pointers the random errors went away completely. (I was using libdbi i assume it would be the same for the mysql api)
Hope this helps
I always prefer using the native c api...
#pragma link "/usr/lib/libmysqlclient.so"
#include "gwan.h"
#include <mysql/mysql.h>
int
main (int argc, char **argv)
{
MYSQL_RES *result;
MYSQL_ROW row;
MYSQL conn, *conn_h;
conn_h = mysql_init (&conn);
if (!conn_h)
{
return 200;
}
if (!mysql_real_connect (conn_h, "localhost", ctx->usr, ctx->psw, NULL, 0, NULL, 0))
{
mysql_close (conn_h);
return 200;
}
mysql_select_db (conn_h, "");
char *query = "";
if (mysql_query (conn_h, query))
{
mysql_close (conn_h);
return 200;
}
result = mysql_store_result (conn_h);
if (!result)
{
mysql_close (conn_h);
return 200;
}
if (mysql_num_rows (result) == 0)
{
return 200;
}
while ((row = mysql_fetch_row (result)))
{
/* do something with row[i] */
}
mysql_free_result (result);
mysql_close (conn_h);
return 200; // Ok
}
Keep in mind you need to initialize the mysql library if you plan to spawn threads (this code is not thread safe).
Hope this help you someway.
I'm trying to use the librtmp library and it worked pretty well to pull a stream. But now I am trying to publish a stream and for that I believe I have to use the RTMP_Write function.
What I am trying to accomplish here is a simple c++ program that will read from a file and try to push the stream to a crtmp server. The connection and stream creation is ok, but I'm quite puzzled by the use of RTMP_Write.
Here is what I did:
int Upload(RTMP * rtmp, FILE * file){
int nRead = 0;
unsigned int nWrite = 0;
int diff = 0;
int bufferSize = 64 * 1024;
int byteSum = 0;
int count = 0;
char * buffer;
buffer = (char *) malloc(bufferSize);
do{
nRead = fread(buffer+diff,1,bufferSize-diff,file);
if(nRead != bufferSize){
if(feof(file)){
RTMP_LogPrintf("End of file reached!\n");
break;
}else if(ferror(file)){
RTMP_LogPrintf("Error reading from file stream detected\n");
break;
}
}
count += 1;
byteSum += nRead;
RTMP_LogPrintf("Read %d from file, Sum: %d, Count: %d\n",nRead,byteSum,count);
nWrite = RTMP_Write(rtmp,buffer,nRead);
if(nWrite != nRead){
diff = nRead - nWrite;
memcpy(buffer,(const void*)(buffer+bufferSize-diff),diff);
}
}while(!RTMP_ctrlC && RTMP_IsConnected(rtmp) && !RTMP_IsTimedout(rtmp));
free(buffer);
return RD_SUCCESS;
}
In this Upload function I am receiving the already initiallized RTMP structure and a pointer to an open file.
This actually works and I can see some video being displayed, but it soon gets lost and stops sending packages. I managed to understand that it happens whenever the buffer that I setup (and which I randomly required to be 64k, no special reason for that) happens to split the flv tag (http://osflash.org/flv#flv_format) of a new package.
For that I modified the RTMP_Write function and told it to verify if it will be able to decode the whole flv tag (packet type, body size, timestamp, etc..) and if it will not, then it should just return the amount of useful bytes left in the buffer.
if(s2 - 11 <= 0){
rest = size - s2;
return rest;
}
The code above takes notice of this, and if the value returned by RTMP_Write is not the amount of bytes it was supposed to send, then it knows that value is the amount of useful bytes left in the buffer. I then copy these bytes to the beginning of the buffer and read more from the file.
But I keep getting problems with it, so I was wondering: what is the correct use of this function anyway? is there a specific buffer value that I should be using? (don't think so) or is it buggy by itself?
What's the difference in the outcome between call by reference and copy/restore?
Background: I'm currently studying distributed systems. Concerning the passing of reference parameters for remote procedure calls, the book states that: "the call by reference has been replaced by copy/restore. Although this is not always identical, it is good enough". I understand how call by reference and copy/restore work in principle, but I fail to see where a difference in the result may be?
Examples taken from here.
Main code:
#include <stdio.h>
int a;
int main() {
a = 3;
f( 4, &a );
printf("%d\n", a);
return 0;
}
Call by Value:
f(int x, int &y){
// x will be 3 as passed argument
x += a;
// now a is added to x so x will be 6
// but now nothing is done with x anymore
a += 2*y;
// a is still 3 so the result is 11
}
Value is passed in and has no effect on the value of the variable passed in.
Call by Reference:
f(int x, int &y){
// x will be 3 as passed argument
x += a;
// now a is added to x so x will be 6
// but because & is used x is the same as a
// meaning if you change x it will change a
a += 2*y;
// a is now 6 so the result is 14
}
Reference is passed in. Effectively the variable in the function is the same as the one outside.
Call with Copy/Restore:
int a;
void unsafe(int x) {
x= 2; //a is still 1
a= 0; //a is now 0
}//function ends so the value of x is now stored in a -> value of a is now 2
int main() {
a= 1;
unsafe(a); //when this ends the value of a will be 2
printf("%d\n", a); //prints 2
}
Value is passed in and has no effect on the value of the variable passed in UNTIL the end of the function, at which point the FINAL value of the function variable is stored in the passed in variable.
The basic difference between call by reference and copy/restore then is that changes made to the function variable will not show up in the passed in variable until after the end of the function while call by reference changes will be seen immediately.
Call by Copy/Restore is a special case of call-by-reference where the provided reference is unique to the caller. The final result on the referenced values will not be saved until the end of the function.
This type of calling is useful when a method in RPC called by reference. The actual data is sent to the server side and the final result will send to the client. This will reduce the traffic, since the server will not update the reference each time.
Call By Reference:
In call-by-reference, we pass a pointer to the called function. Any changes that happens to the data pointed by that pointer will be reflected immediately.
Suppose if there are numerous changes to be made to that data, while it wouldn’t incur much cost locally, it’ll be expensive in terms of network cost as for each change data will have to be copied back to the client.
C Code:
void addTwo(int *arr, int n){
for(int i=0;i<n;i++){
arr[i]+=2; //change is happening in the original data as well
}
}
int main(){
int arr[100]={1,2,3,...}; // assuming it to be initialised
addTwo(arr,100);
}
Call By Copy/Restore:
In call-by-copy/restore, the idea is that when the function is called with the reference to the data, only the final result of the changes made to the data is copied back to the original data(when the function is about to return) without making any changes to the original data during the function call, requiring only one transfer back to the client.
In the C code below, the data pointed by arr is copied in the function and stored back to arr after all the changes to the local data are finalised.
C Code:
void addTwo(int *arr, int n){
// copy data locally
larr = (int*)malloc(n*sizeof(int));
for(int i=0;i<n;i++){
larr[i]=arr[i];
}
for(int i=0;i<n;i++){
// change is happening to the local variable larr
larr[i]+=2;
}
//copy all the changes made to the local variable back to the original data
for(int i=0;i<n;i++){
arr[i]=larr[i];
}
}
int main(){
int arr[100]={1,2,3,...}; // assuming it to be initialised
addTwo(arr,100);
}
Note: Code shown above doesn’t represent actual RPC implementation, just an illustration of the concepts. In real RPC, complete data is passed in the message instead of pointers(addresses).