I am trying to do a routine Init_buffer (which create a new buffer to new a new client). So far I only discovered this way (in pseudo-code):
//Globally
BufferClass buffer1('some_random_size');
BufferClass buffer2('some_random_size');
BufferClass buffer3('some_random_size');
(...)
//Binary data (chunck) from Nodejs Server
void buffering_mem(char* chunk, int size_chunk, int close_file,
int client, int total_size) {
if(client == 0) {
buffer1.write(chunk,size_chunk);
}
else if(client == 1) {
buffer2.write(chunk, size_chunk);
}
(...)
}
Now I want to do the whole process without the repetition of code. Any ideas?
You could read up on how to use a std::vector.
Something a bit like this:
std::vector<BufferClass> buffers(3, BufferClass(1024));
void buffering_mem(char* chunk, int size_chunk, int close_file
, int client, int total_size)
{
if(client >= buffers.size())
throw std::range_error("out of range client: " + std::to_string(client));
buffers[client].write(chunk, size_chunk);
}
Related
I'm attempting to execute various functions sequentially n number of times, only moving forward if previous function did not return false (error) otherwise I reset and start all over again.
An example of a sequence would be :
Turn module ON : module.power(true), 3 attempts
Wait for a signal : module.signal(), 10 attempts
Send a message : module.sendSMS('test'), 3 attempts
Turn module OFF : module.power(false), 1 attempt
Each of those actions are done the same way, only changing the DEBUG text and the function to launch :
DEBUG_PRINT("Powering ON"); // This line changes
uint8_t attempts = 0;
uint8_t max_attempts = 3; // max_attempts changes
while(!module.power(true) && attempts < max_attempts){ // This line changes
attempts++;
DEBUG_PRINT(".");
if(attempts == max_attempts) {
DEBUG_PRINTLN(" - Failed.");
soft_reset(); // Start all over again
}
delay(100);
}
DEBUG_PRINTLN(" - Success");
wdt_reset(); // Reset watchdog timer, ready for next action
Is there an elegant way I can put this process in a function I could call to execute the required functions this particular way, for example something like :
void try_this_action(description, function, n_attempts)
Which would make actions 1-4 above like :
try_this_action("Powering ON", module.power(true), 3);
try_this_action("Waiting for signal", module.signal(), 10);
try_this_action("Sending SMS", module.sendSMS('test'), 3);
try_this_action("Powering OFF", module.power(false), 1);
A difficulty I have is that the functions called have different syntax (some take parameters, some other don't...). Is there a more elegant modulable way of doing this besides copy/paste the chunck of code everywhere I need it ?
A difficulty I have is that the functions called have different syntax
(some take parameters, some other don't...).
That is indeed an issue. Along with it you have the possibility of variation in actual function arguments for the same function.
Is there a more elegant
modulable way of doing this besides copy/paste the chunck of code
everywhere I need it ?
I think you could make a variadic function that uses specific knowledge of the functions to dispatch in order to deal with the differing function signatures and actual arguments. I'm doubtful that I would consider the result more elegant, though.
I would be inclined to approach this job via a macro, instead:
// desc: a descriptive string, evaluated once
// action: an expression to (re)try until it evaluates to true in boolean context
// attempts: the maximum number of times the action will be evaluated, itself evaluated once
#define try_this_action(desc, action, attempts) do { \
int _attempts = (attempts); \
DEBUG_PRINT(desc); \
while(_attempts && !(action)) { \
_attempts -= 1; \
DEBUG_PRINT("."); \
delay(100); \
} \
if (_attempts) { \
DEBUG_PRINTLN(" - Success"); \
} else { \
DEBUG_PRINTLN(" - Failed."); \
soft_reset(); \
} \
wdt_reset(); \
} while (0)
Usage would be just as you described:
try_this_action("Powering ON", module.power(true), 3);
etc.. Although the effect is as if you did insert the code for each action in each spot, using a macro such as this would yield code that is much easier to read, and that is not lexically repetitive. Thus, for example, if you ever need to change the the steps for trying actions, you can do it once for all by modifying the macro.
You need to make the function pointers all have the same signature. I would use something like this;
typedef int(*try_func)(void *arg);
And have a try_this_action(...) signature similar to the following;
void try_this_action(char * msg, int max_trys, try_func func, void *arg)
You would then implement your actions similar to this;
int power(void *pv)
{
int *p = pv;
int on_off = *p;
static int try = 0;
if (on_off && try++)
return 1;
return 0;
}
int signal(void *pv)
{
static int try = 0;
if (try++ > 6)
return 1;
return 0;
}
And call them like this;
int main(int c, char *v[])
{
int on_off = 1;
try_this_action("Powering ON", 3, power, &on_off);
try_this_action("Signaling", 10, signal, 0);
}
Functions of different arity may be abstracted with a generic signature (think about main). Instead of each giving each their own unique arguments, you simply supply them all with:
An argument count.
A vector of pointers to the arguments.
This is how your operating system treats all programs it runs anyways. I've given a very basic example below which you can inspect.
#include <stdio.h>
#include <stdlib.h>
/* Define total function count */
#define MAX_FUNC 2
/* Generic function signature */
typedef void (*func)(int, void **, const char *);
/* Function pointer array (NULL - initialized) */
func functions[MAX_FUNC];
/* Example function #1 */
void printName (int argc, void **argv, const char *desc) {
fprintf(stdout, "Running: %s\n", desc);
if (argc != 1 || argv == NULL) {
fprintf(stderr, "Err in %s!\n", desc);
return;
}
const char *name = (const char *)(argv[0]);
fprintf(stdout, "Name: %s\n", name);
}
/* Example function #2 */
void printMax (int argc, void **argv, const char *desc) {
fprintf(stdout, "Running: %s\n", desc);
if (argc != 2 || argv == NULL) {
fprintf(stderr, "Err in %s!\n", desc);
return;
}
int *a = (int *)(argv[0]), *b = (int *)(argv[1]);
fprintf(stdout, "Max: %d\n", (*a > *b) ? *a : *b);
}
int main (void) {
functions[0] = printName; // Set function #0
functions[1] = printMax; // Set function #1
int f_arg_count[2] = {1, 2}; // Function 0 takes 1 argument, function 1 takes 2.
const char *descs[2] = {"printName", "printMax"};
const char *name = "Natasi"; // Args of function 0
int a = 2, b = 3; // Args of function 1
int *args[2] = {&a, &b}; // Args of function 1 in an array.
void **f_args[2] = {(void **)(&name),
(void **)(&args)}; // All function args.
// Invoke all functions.
for (int i = 0; i < MAX_FUNC; i++) {
func f = functions[i];
const char *desc = descs[i];
int n = f_arg_count[i];
void **args = f_args[i];
f(n, args, desc);
}
return EXIT_SUCCESS;
}
You can use a variadic function, declaring in the parameter list first those parameters that are always present, then the variable part.
In following code we define a type for action functions, void returning having as parameter an argument list:
typedef void (*action)(va_list);
Then define the generic action routine that prepare for the action execution:
void try_this_action(char *szActionName, int trials, action fn_action, ...)
{
va_list args;
va_start(args, fn_action); //Init the argument list
DEBUG_PRINT(szActionName); // This line changes
uint8_t attempts = 0;
uint8_t max_attempts = trials; // max_attempts changes
//Here we call our function through the pointer passed as argument
while (!fn_action(args) && attempts < max_attempts)
{ // This line changes
attempts++;
DEBUG_PRINT(".");
if (attempts == max_attempts)
{
DEBUG_PRINTLN(" - Failed.");
soft_reset(); // Start all over again
}
delay(100);
}
DEBUG_PRINTLN(" - Success");
wdt_reset(); // Reset watchdog timer, ready for next action
va_end(args);
}
Each function must be coded to use an argument list:
int power(va_list args)
{
//First recover all our arguments using the va_arg macro
bool cond = va_arg(args, bool);
if (cond == true)
{
... //do something
return true;
}
return false;
}
The usage will be:
try_this_action("Powering ON", 3, module.power, true);
try_this_action("Waiting for signal", 10, module.signal);
try_this_action("Sending SMS", 3, module.sendSMS, "test");
try_this_action("Powering OFF", 1, module.power, false);
If you need more info on variadic functions and usage of stdarg.h macros google the net. Start from here https://en.cppreference.com/w/c/variadic.
It could be coded also as a macro implementation, as the excellent proposal in the John Bollinger answer, but in that case you must consider that each macro usage will instantiate the whole code, that could be eventually even better for speed (avoiding a function call), but could be not suitable on systems with limited memory (embedded), or where you need reference to the function try_this_action (inexistent).
this code is make queues for the the operating system
I used structures to implement my processes
and used arr_processes to handle all of this processes
and new_processes array to sort this processes according to its arrival time
but when i run this code on visual studio 2010
it produces this run time error
Run-Time Check Failure #2 - Stack around the variable arr_processes was corrupted!
this is the code
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int id;
int arr_time;
int serv_time;
int deadline;
} process;
void print_process(process n);
int main()
{
process arr_processes[8];
process new_processes[8];
process real_processes[3];
process ready_processes[5];
process tmp_process[1];
int length_ready;
int i,length,j;
int length_real;
arr_processes[0].id=1;
arr_processes[0].arr_time=12;
arr_processes[0].serv_time=4;
arr_processes[0].deadline=0;
arr_processes[1].id=2;
arr_processes[1].arr_time=10;
arr_processes[1].serv_time=5;
arr_processes[1].deadline=0;
arr_processes[2].id=3;
arr_processes[2].arr_time=9;
arr_processes[2].serv_time=2;
arr_processes[2].deadline=0;
arr_processes[3].id=4;
arr_processes[3].arr_time=8;
arr_processes[3].serv_time=4;
arr_processes[3].deadline=10;
arr_processes[4].id=5;
arr_processes[4].arr_time=5;
arr_processes[4].serv_time=2;
arr_processes[4].deadline=8;
arr_processes[5].id=6;
arr_processes[5].arr_time=3;
arr_processes[5].serv_time=3;
arr_processes[5].deadline=0;
arr_processes[6].id=7;
arr_processes[6].arr_time=2;
arr_processes[6].serv_time=3;
arr_processes[6].deadline=0;
arr_processes[7].id=8;
arr_processes[7].arr_time=1;
arr_processes[7].serv_time=1;
arr_processes[7].deadline=28;
length=sizeof(arr_processes)/sizeof(arr_processes[0]);
printf("\t length of the processes=%i\n\n",length);
printf("\t The Original processes \n\n");
for(i=0;i<8;i++)
print_process(arr_processes[i]);
// now we want to sort the processes according to their arrival time
for(i=0;i<8;i++)
{
new_processes[i]=arr_processes[i];
}
for(i=0;i<length;i++)
{
for(j=0;j<length-i;j++)
{
if((new_processes[j].arr_time)>(new_processes[j+1].arr_time))
{
tmp_process[0]=new_processes[j];
new_processes[j]=new_processes[j+1];
new_processes[j+1]=tmp_process[0];
}
}
}
printf("\t The New processes \n\n");
for(i=0;i<8;i++)
print_process(new_processes[i]); // the new queue
ready_processes[0]=arr_processes[0];
ready_processes[1]=arr_processes[1];
ready_processes[2]=arr_processes[2];
ready_processes[3]=arr_processes[5];
ready_processes[4]=arr_processes[6];
length_ready=sizeof(ready_processes)/sizeof(ready_processes[0]);
// now we want to design the ready queue
for(i=0;i<length_ready;i++)
{
for(j=0;j<length_ready-i;j++)
{
if((ready_processes[j].arr_time)>ready_processes[j+1].arr_time)
{
tmp_process[0]=ready_processes[j];
ready_processes[j]=ready_processes[j+1];
ready_processes[j+1]=tmp_process[0];
}
}
}
printf("\t The ready processes \n\n");
for(i=0;i<length_ready;i++)
print_process(ready_processes[i]); // the ready queue
// now we want to design the ready real queue for the shortest deadline first
// we donnot need to check for the new proesses at each instant of time
//but we need to check for the service time from now
real_processes[0]=arr_processes[3];
real_processes[1]=arr_processes[4];
real_processes[2]=arr_processes[7];
length_real=sizeof(real_processes)/sizeof(real_processes[0]);
for(i=0;i<length_real;i++)
{
for(j=0;j<length_real-i;j++)
{
if((real_processes[j].deadline)>real_processes[j+1].deadline)
{
tmp_process[0]=real_processes[j];
real_processes[j]=real_processes[j+1];
real_processes[j+1]=tmp_process[0];
}
}
}
printf("\t The real processes \n\n");
for(i=0;i<length_real;i++)
print_process(real_processes[i]); // the ready real queue
// removed real process
process removed_real;
removed_real.id=0;
removed_real.arr_time=0;
removed_real.serv_time=0;
removed_real.deadline=0;
process running_process;
running_process.id=0;
running_process.arr_time=0;
running_process.serv_time=0;
running_process.deadline=0;
int counter=0;
int start_time;
while(counter<=28)
{
printf("when time = %i\n\n",counter);
// printf("\t The real processes when the counter=%i \n\n",counter);
// for(i=0;i<length_real;i++)
// print_process(real_processes[i]); // the ready real queue
// first we must check for the real processes
for(i=0;i<length_real;i++)
{
if((counter==real_processes[i].arr_time)
&&((real_processes[i].deadline)-counter)>=(real_processes[i].serv_time))
{
running_process=real_processes[i];
printf("The non zero deadline process is:%i\n",running_process.id);
real_processes[i]=removed_real;
start_time=counter; // real process
while(counter!=(start_time+running_process.serv_time))
{
printf("At time = %i,The Running Process is...\n",counter);
print_process(running_process);
counter++;
}
}
}
counter++;
}
return 0;
}
void print_process(process n)
{
if(n.deadline!=0)
printf("ID=%i\narr_time=%i\nserv_time=%i\ndeadline=%i\n\n\n",n.id,n.arr_time,n.serv_time,n.deadline);
else if(n.deadline==0)
printf("ID=%i\narr_time=%i\nserv_time=%i\n\n\n",n.id,n.arr_time,n.serv_time);
}
As you run out of index, here is a sort example:
for(i=0; i<length - 1; i++)
{
for(j=i + 1;j<length;j++)
{
if((new_processes[j].arr_time)>(new_processes[i].arr_time))
{
tmp_process[0]=new_processes[j];
new_processes[j]=new_processes[i] ;
new_processes[i]=tmp_process[0] ;
}
}
}
Or, you can use standard function:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
Define a comparison function:
int compare_by_arr_time(const void* a, const void* b)
{
int a_int = ((const process*)a)->arr_time;
int b_int = ((const process*)b)->arr_time;
return a_int - b_int; // or b_int - a_int
}
And use it as follows:
qsort(new_processes,
sizeof(new_processes)/sizeof(new_processes[0]),
sizeof(new_processes[0]),
compare_by_arr_time);
You get these kinds of errors when you go out of the bounds of an array.
for(i=0;i<length;i++)
{
for(j=0;j<length-i;j++)
{
if((new_processes[j].arr_time)>(new_processes[j+1].arr_time))
{
tmp_process[0]=new_processes[j];
new_processes[j]=new_processes[j+1] ;
new_processes[j+1]=tmp_process[0] ;
}
}
}
In the first iteration, i = 0, j = 0 and j must be less than 8 - i, which is 8.
Notice the expression j+1. This expression will return values in the range of [1 ... 9] during the first iteration of the outer-most loop, and thus, you will be going out of the bounds your new_processes array.
There's your problem.
edit: This problem may also be present in the for loops that follow the first one.
Hi I have try to read Stream from the server with this code
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, wchar_t &Key)
{
//TMemoryStream *TMS = new TMemoryStream;
TStringStream *TSS = new TStringStream;
AnsiString A,B;
TStream *TS;
INT64 Len;
try
{
if (Key == VK_RETURN)
{
Beep(0,0);
if(Edit1->Text == "mystream")
{
TCPClient1->IOHandler->WriteLn("mystream");
Len = StrToInt(TCPClient1->IOHandler->ReadLn());
TCPClient1->IOHandler->ReadStream(TS,Len,false);
TSS->CopyFrom(TS,0);
RichEdit1->Lines->Text = TSS->DataString;
Edit1->Clear();
}
else
{
TCPClient1->IOHandler->WriteLn(Edit1->Text);
A = TCPClient1->IOHandler->ReadLn();
RichEdit1->Lines->Add(A);
Edit1->Clear();
}
}
}
__finally
{
TSS->Free();
}
}
and every times client try to read stream from the server, compiler says.
First chance exception at $75D89617. Exception class EAccessViolation with message 'Access violation at address 500682B3 in module 'rtl140.bpl'. Read of address 00000018'. Process Project1.exe (6056)
How to handle this?
You are not instantiating your TStream object before calling ReadStream(). Your TS variable is completely uninitialized. ReadStream() does not create the TStream object for you, only writes to it, so you have to create the TStream yourself beforehand.
Given the code you have shown, you can replace the TStream completely by using the ReadString() method instead:
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, wchar_t &Key)
{
if (Key == VK_RETURN)
{
Beep(0,0);
if (Edit1->Text == "mystream")
{
TCPClient1->IOHandler->WriteLn("mystream");
int Len = StrToInt(TCPClient1->IOHandler->ReadLn());
RichEdit1->Lines->Text = TCPClient1->IOHandler->ReadString(Len);
}
else
{
TCPClient1->IOHandler->WriteLn(Edit1->Text);
String A = TCPClient1->IOHandler->ReadLn();
RichEdit1->Lines->Add(A);
}
Edit1->Clear();
}
}
Working with Rasterbar libtorrent I dont want the downloaded data to sit on my hard drive rather a pipe or variable or something Soft so I can redirect it to somewhere else, Mysql, or even trash if it is not what I want, is there anyway of doing this in preferably python binding if not in C++ using Libtorrent?
EDIT:--> I like to point out this is a libtorrent question not a Linux file handling or Python file handling question. I need to tell libtorrent to instead of save the file traditionally in a normal file save it to my python pipe or variable or etc.
You can do this by implementing your own storage class to use with libtorrent. Unfortunately this is not possible to do in python, but you can do it in c++. The documentation for it is a bit scarce and can be found here.
Here's a simple example of how to do this by storing all the data in RAM:
struct temp_storage : storage_interface
{
temp_storage(file_storage const& fs) : m_files(fs) {}
virtual bool initialize(bool allocate_files) { return false; }
virtual bool has_any_file() { return false; }
virtual int read(char* buf, int slot, int offset, int size)
{
std::map<int, std::vector<char> >::const_iterator i = m_file_data.find(slot);
if (i == m_file_data.end()) return 0;
int available = i->second.size() - offset;
if (available <= 0) return 0;
if (available > size) available = size;
memcpy(buf, &i->second[offset], available);
return available;
}
virtual int write(const char* buf, int slot, int offset, int size)
{
std::vector<char>& data = m_file_data[slot];
if (data.size() < offset + size) data.resize(offset + size);
std::memcpy(&data[offset], buf, size);
return size;
}
virtual bool rename_file(int file, std::string const& new_name) { assert(false); return false; }
virtual bool move_storage(std::string const& save_path) { return false; }
virtual bool verify_resume_data(lazy_entry const& rd, error_code& error) { return false; }
virtual bool write_resume_data(entry& rd) const { return false; }
virtual bool move_slot(int src_slot, int dst_slot) { assert(false); return false; }
virtual bool swap_slots(int slot1, int slot2) { assert(false); return false; }
virtual bool swap_slots3(int slot1, int slot2, int slot3) { assert(false); return false; }
virtual size_type physical_offset(int slot, int offset) { return slot * m_files.piece_length() + offset; };
virtual sha1_hash hash_for_slot(int slot, partial_hash& ph, int piece_size)
{
int left = piece_size - ph.offset;
TORRENT_ASSERT(left >= 0);
if (left > 0)
{
std::vector<char>& data = m_file_data[slot];
// if there are padding files, those blocks will be considered
// completed even though they haven't been written to the storage.
// in this case, just extend the piece buffer to its full size
// and fill it with zeroes.
if (data.size() < piece_size) data.resize(piece_size, 0);
ph.h.update(&data[ph.offset], left);
}
return ph.h.final();
}
virtual bool release_files() { return false; }
virtual bool delete_files() { return false; }
std::map<int, std::vector<char> > m_file_data;
file_storage m_files;
};
You'd also need a constructor function to pass in through the add_torrent_params struct when adding a torrent:
storage_interface* temp_storage_constructor(
file_storage const& fs, file_storage const* mapped
, std::string const& path, file_pool& fp
, std::vector<boost::uint8_t> const& prio)
{
return new temp_storage(fs);
}
From this point it should be fairly straight forward to store it in a MySQL database or any other back-end.
If you're on Linux, you could torrent into a tmpfs mount; this will avoid writing to disk. That said, this obviously means you're storing large files in RAM; make sure you have enough memory to deal with this.
Note also that most Linux distributions have a tmpfs mount at /dev/shm, so you could simply point libtorrent to a file there.
I've implemented a torrent client in Go just for this purpose. I wanted to able to handle and control the data directly, for use in writing torrentfs, and to have storage backends to S3 and various databases.
It would be trivial to plug in an in-memory storage backend to this client.
Try giving the library a cStringIO "file handle" instead of a real file handle. That works for most python libraries.
I want to implement port-forwarding using intel-upnp.
I got XML data like:
Device found at location: http://192.168.10.1:49152/gatedesc.xml
service urn:schemas-upnp-org:service:WANIPConnection:1
controlurl /upnp/control/WANIPConn1
eventsuburl : /upnp/control/WANIPConn1
scpdurl : /gateconnSCPD.xml
And now, I want to make upnp-action. But, I don't know how to make it.
If you know some code snippet or helpful URL in C, please tell me.
char actionxml[250];
IXML_Document *action = NULL;
strcpy(actionxml, "<u:GetConnectionTypeInfo xmlns:u=\"urn:schemas-upnp- org:service:WANCommonInterfaceConfig:1\">");
action = ixmlParseBuffer(actionxml);
int ret = UpnpSendActionAsync( g_handle,
"http:192.168.10.1:49152/upnp/control/WANCommonIFC1",
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",
NULL,
action,
upnp_callback,
NULL);
I know this is an old question, but it can be kept for reference. You can take a look at the sample code in the libupnp library here: https://github.com/mrjimenez/pupnp/blob/master/upnp/sample/common/tv_ctrlpt.c
The relevant code is in the function TvCtrlPointSendAction():
int TvCtrlPointSendAction(
int service,
int devnum,
const char *actionname,
const char **param_name,
char **param_val,
int param_count)
{
struct TvDeviceNode *devnode;
IXML_Document *actionNode = NULL;
int rc = TV_SUCCESS;
int param;
ithread_mutex_lock(&DeviceListMutex);
rc = TvCtrlPointGetDevice(devnum, &devnode);
if (TV_SUCCESS == rc) {
if (0 == param_count) {
actionNode =
UpnpMakeAction(actionname, TvServiceType[service],
0, NULL);
} else {
for (param = 0; param < param_count; param++) {
if (UpnpAddToAction
(&actionNode, actionname,
TvServiceType[service], param_name[param],
param_val[param]) != UPNP_E_SUCCESS) {
SampleUtil_Print
("ERROR: TvCtrlPointSendAction: Trying to add action param\n");
/*return -1; // TBD - BAD! leaves mutex locked */
}
}
}
rc = UpnpSendActionAsync(ctrlpt_handle,
devnode->device.
TvService[service].ControlURL,
TvServiceType[service], NULL,
actionNode,
TvCtrlPointCallbackEventHandler, NULL);
if (rc != UPNP_E_SUCCESS) {
SampleUtil_Print("Error in UpnpSendActionAsync -- %d\n",
rc);
rc = TV_ERROR;
}
}
ithread_mutex_unlock(&DeviceListMutex);
if (actionNode)
ixmlDocument_free(actionNode);
return rc;
}
The explanation is that you should create the action with UpnpMakeAction() if you have no parameters or UpnpAddToAction() if you have parameters to create your action, and then send it either synchronously or asynchronously.