Writing a file larger than 2Gb - c++

I write a file storing all the raw data I read from two external sensors and I realized that program stops writing data when the file gets 2Gb, the program continuous working but it does not write anything more in the file.
I am using the next code (it is one threads that waits the signal and writes in the file):
while(1)
{
//Lock, Wait the signal and unlock
pthread_mutex_lock(&mutex_WriteOFIMUandGPS);
pthread_cond_wait(&cond_WriteOFIMUandGPS, &mutex_WriteOFIMUandGPS);
X_CopySnapshot = X_Snapshot;
Y_CopySnapshot = Y_Snapshot;
Z_CopySnapshot = Z_Snapshot;
Vx_CopySnapshot = Vx_Snapshot;
Vy_CopySnapshot = Vy_Snapshot;
Vz_CopySnapshot = Vz_Snapshot;
HPL_CopySnapshot = HPL_Snapshot;
HDOP_CopySnapshot = HDOP_Snapshot;
StdPosX_CopySnapshot = StdPosX_Snapshot;
StdPosY_CopySnapshot = StdPosY_Snapshot;
StdPosZ_CopySnapshot = StdPosZ_Snapshot;
pthread_mutex_unlock(&mutex_WriteOFIMUandGPS);
//Get Time and Date
now = time(0);
localtm = localtime(&now);
//Get millis
gettimeofday(&tp, NULL);
ms = round(tp.tv_usec / 1000);
sprintf(buf,"%03d",(int)ms);
//Empty strings
DateTime = "";
text.clear();
text.str(string());
//Store Data and Time information in a string
text << localtm->tm_year+1900 << "/";
text << (((localtm->tm_mon+1)<10) ? "0" : "") << localtm->tm_mon+1 << "/";
text << ((localtm->tm_mday<10)? "0" : "") << localtm->tm_mday << ",";
text << ((localtm->tm_hour<10)? "0" : "") << localtm->tm_hour << ":";
text << ((localtm->tm_min<10)? "0" : "") << localtm->tm_min << ":";
text << ((localtm->tm_sec<10)? "0" : "") << localtm->tm_sec << "."<< buf;
DateTime = text.str();
//Save data
fprintf(fid,"%s,"
"2,6,0," // Alg_ID,SolStatus,EGNOSStatus,
"%12.3f,%12.3f,%12.3f," // XyzUKF[0],XyzUKF[1],XyzUKF[2],
"%8.8f,%8.8f,%8.8f,%7.18f," // V_UKF[0],V_UKF[1],V_UKF[2],HPL,
"0,0,%5.2f,nan,nan,nan,nan," // NumSat,NumSatEx,HDOP,PDC1,PDC2,PDC3,PDC4,
"%7.2f,%7.2f,%7.2f," // StdPos[0],StdPos[1],StdPos[2]
"0,0,0," // StdVel[0],StdVel[1],StdVel[2],
"1,0," // TypePositioning[0],TechUsedPos,
"0,0,0,0,0," // Observables
"0,0,0,0,0," // Observables
"0,0," // VPL,VDOP
"0," // TechRec
"0,0,0,0,0," // Observables
"0,0,0,0,0\n", // Observables
DateTime.c_str(),
X_CopySnapshot, Y_CopySnapshot, Z_CopySnapshot,
Vx_CopySnapshot, Vy_CopySnapshot, Vz_CopySnapshot,HPL_CopySnapshot,
HDOP_CopySnapshot,
StdPosX_CopySnapshot, StdPosY_CopySnapshot, StdPosZ_CopySnapshot);
}
I do not know if there is any way to write files larger than 2Gb and how I should achieve it.
Many thanks for your help.

As you state that you use linux: man 2 open:
O_LARGEFILE
(LFS) Allow files whose sizes cannot be represented in an off_t (but can be represented
in an off64_t) to be opened. The _LARGEFILE64_SOURCE macro must be defined (before
including any header files) in order to obtain this definition. Setting the _FILE_OFF-
SET_BITS feature test macro to 64 (rather than using O_LARGEFILE) is the preferred
method of accessing large files on 32-bit systems (see feature_test_macros(7)).
Otherwise, file operations are limited to 2GiB.

Related

Building an OSC message with a for loop in C++/oscpack for lidar

Ok, so I'm decent with many programming languages, C++ isn't one of them. This task would take me 5 minutes in pretty much anything else, but after many tries, I'm hoping for some guidance.
My application is reading data from an RPLidar A3, and packaging up the data into OSC to be forwarded to other applications that work with the data and convert it into trackable blobs as a generic tracking system for people in a space. ( It currently looks like this )
I'm doing this via a TINY modification to their example viewer app using the oscpack library.
The sensor returns 2 values: an angle (Float) and a distance in mm (integer)
The sdk gets all the values from a spin and then you iterate through them with a loop. I have it working fine where it sends the value pairs out as it gets them "ie lidar1/ angle distance" out a UDP socket. It looks like this:
UdpTransmitSocket transmitSocket(IpEndpointName(ADDRESS, PORT));
char lidbuffer[OUTPUT_BUFFER_SIZE];
for (int pos = 0; pos < (int)count; ++pos) {
scanDot dot;
if (!buffer[pos].dist_mm_q2) continue;
dot.quality = buffer[pos].quality;
dot.angle = buffer[pos].angle_z_q14 * 90.f / 16384.f;
dot.dist = buffer[pos].dist_mm_q2 /4.0f;
_scan_data.push_back(dot);
osc::OutboundPacketStream p(lidbuffer, OUTPUT_BUFFER_SIZE);
p << osc::BeginMessage(SENDPREFIX)
<< dot.angle << (int)dot.dist << osc::EndMessage;
transmitSocket.Send(p.Data(), p.Size());
}
It works, but as I've move to a higher resolution sensor, I'm having issues with dropped data, so I would like to build the data into a single message or a bundle. As a reference, each revolution of the sensor is about 800 angle/distance pairs.
This is what I thought would work, based on the oscpack example It compiles, but crashes on opening:
As a big message:
UdpTransmitSocket transmitSocket(IpEndpointName(ADDRESS, PORT));
char lidbuffer[OUTPUT_BUFFER_SIZE];
//make a new message
osc::OutboundPacketStream p(lidbuffer, OUTPUT_BUFFER_SIZE);
p << osc::BeginMessage(SENDPREFIX);
for (int pos = 0; pos < (int)count; ++pos) {
scanDot dot;
if (!buffer[pos].dist_mm_q2) continue;
dot.quality = buffer[pos].quality;
dot.angle = buffer[pos].angle_z_q14 * 90.f / 16384.f;
dot.dist = buffer[pos].dist_mm_q2 /4.0f;
_scan_data.push_back(dot);
//add more data into the message
p << dot.angle << (int)dot.dist;
}
//send the message
p << osc::EndMessage;
transmitSocket.Send(p.Data(), p.Size());
As a bundle
UdpTransmitSocket transmitSocket(IpEndpointName(ADDRESS, PORT));
char lidbuffer[OUTPUT_BUFFER_SIZE];
osc::OutboundPacketStream p(lidbuffer, OUTPUT_BUFFER_SIZE);
//make a bundle
p << osc::BeginBundleImmediate;
for (int pos = 0; pos < (int)count; ++pos) {
scanDot dot;
if (!buffer[pos].dist_mm_q2) continue;
dot.quality = buffer[pos].quality;
dot.angle = buffer[pos].angle_z_q14 * 90.f / 16384.f;
dot.dist = buffer[pos].dist_mm_q2 /4.0f;
_scan_data.push_back(dot);
//add a message to the bundle
p << osc::BeginMessage(SENDPREFIX) << dot.angle << (int)dot.dist << osc::EndMessage;;
}
//send the bundle
p << osc::EndBundle;
transmitSocket.Send(p.Data(), p.Size());
Both compile but crash.
I've read several things, but << assignment methods aren't getting through and I'm guessing it is something really simple.
Caveats:
I know people have written wrappers for this driver code in many other languages, but I would like to stick with this one if possible
I would like to keep it as OSC/UDP
Any guidance is appreciated

CppUnitTestFramework: Test Method Fails, Stack Trace Lists Line Number at the End of Method, Debug Test Passes

I know, I know - that question title is very much all over the place. However, I am not sure what could be an issue here that is causing what I am witnessing.
I have the following method in class Project that is being unit tested:
bool Project::DetermineID(std::string configFile, std::string& ID)
{
std::ifstream config;
config.open(configFile);
if (!config.is_open()) {
WARNING << "Failed to open the configuration file for processing ID at: " << configFile;
return false;
}
std::string line = "";
ID = "";
bool isConfigurationSection = false;
bool isConfiguration = false;
std::string tempID = "";
while (std::getline(config, line))
{
std::transform(line.begin(), line.end(), line.begin(), ::toupper); // transform the line to all capital letters
boost::trim(line);
if ((line.find("IDENTIFICATIONS") != std::string::npos) && (!isConfigurationSection)) {
// remove the "IDENTIFICATIONS" part from the current line we're working with
std::size_t idStartPos = line.find("IDENTIFICATIONS");
line = line.substr(idStartPos + strlen("IDENTIFICATIONS"), line.length() - idStartPos - strlen("IDENTIFICATIONS"));
boost::trim(line);
isConfigurationSection = true;
}
if ((line.find('{') != std::string::npos) && isConfigurationSection) {
std::size_t bracketPos = line.find('{');
// we are working within the ids configuration section
// determine if this is the first character of the line, or if there is an ID that precedes the {
if (bracketPos == 0) {
// is the first char
// remove the bracket and keep processing
line = line.substr(1, line.length() - 1);
boost::trim(line);
}
else {
// the text before { is a temp ID
tempID = line.substr(0, bracketPos - 1);
isConfiguration = true;
line = line.substr(bracketPos, line.length() - bracketPos);
boost::trim(line);
}
}
if ((line.find("PORT") != std::string::npos) && isConfiguration) {
std::size_t indexOfEqualSign = line.find('=');
if (indexOfEqualSign == std::string::npos) {
WARNING << "Unable to determine the port # assigned to " << tempID;
}
else {
std::string portString = "";
portString = line.substr(indexOfEqualSign + 1, line.length() - indexOfEqualSign - 1);
boost::trim(portString);
// confirm that the obtained port string is not an empty value
if (portString.empty()) {
WARNING << "Failed to obtain the \"Port\" value that is set to " << tempID;
}
else {
// attempt to convert the string to int
int workingPortNum = 0;
try {
workingPortNum = std::stoi(portString);
}
catch (...) {
WARNING << "Failed to convert the obtained \"Port\" value that is set to " << tempID;
}
if (workingPortNum != 0) {
// check if this port # is the same port # we are publishing data on
if (workingPortNum == this->port) {
ID = tempID;
break;
}
}
}
}
}
}
config.close();
if (ID.empty())
return false;
else
return true;
}
The goal of this method is to parse any text file for the ID portion, based on matching the port # that the application is publishing data to.
Format of the file is like this:
Idenntifications {
ID {
port = 1001
}
}
In a separate Visual Studio project that unit tests various methods, including this Project::DetermineID method.
#define STRINGIFY(x) #x
#define EXPAND(x) STRINGIFY(x)
TEST_CLASS(ProjectUnitTests) {
Project* parser;
std::string projectDirectory;
TEST_METHOD_INITIALIZE(ProjectUnitTestInitialization) {
projectDirectory = EXPAND(UNITTESTPRJ);
projectDirectory.erase(0, 1);
projectDirectory.erase(projectDirectory.size() - 2);
parser = Project::getClass(); // singleton method getter/initializer
}
// Other test methods are present and pass/fail accordingly
TEST_METHOD(DetermineID) {
std::string ID = "";
bool x = parser ->DetermineAdapterID(projectDirectory + "normal.cfg", ID);
Assert::IsTrue(x);
}
};
Now, when I run the tests, DetermineID fails and the stack trace states:
DetermineID
Source: Project Tests.cpp line 86
Duration: 2 sec
Message:
Assert failed
Stack Trace:
ProjectUnitTests::DetermineID() line 91
Now, in my test .cpp file, TEST_METHOD(DetermineID) { is present on line 86. But that method's } is located on line 91, as the stack trace indicates.
And, when debugging, the unit test passes, because the return of x in the TEST_METHOD is true.
Only when running the test individually or running all tests does that test method fail.
Some notes that may be relevant:
This is a single-threaded application with no tasks scheduled (no race condition to worry about supposedly)
There is another method in the Project class that also processes a file with an std::ifstream same as this method does
That method has its own test method that has been written and passes without any problems
The test method also access the "normal.cfg" file
Yes, this->port has an assigned value
Thus, my questions are:
Why does the stack trace reference the closing bracket for the test method instead of the single Assert within the method that is supposedly failing?
How to get the unit test to pass when it is ran? (Since it currently only plasses during debugging where I can confirm that x is true).
If the issue is a race condition where perhaps the other test method is accessing the "normal.cfg" file, why does the test method fail even when the method is individually ran?
Any support/assistance here is very much appreciated. Thank you!

Keep Lua state in a C++ environment to limit context switches

I'm having fun coding simple OpenGL demos and I recently decided to use Lua with my C++ engine in order to change the rendering dynamically without having to recompile on and on my project. Thus I can tweak more easily the rendering algorithm. But I know that my current rendering update functions are probably far from being efficient.
For the moment, I'm transfering a matrix from C++ to Lua, modifying it in a Lua script and sending it back to my C++ rendering engine. But I'm reloading the Lua script each time I get an update call from the C++ engine, and I'm losing all of the variable context. That means I'm always starting from scratch and my rendering is far from being smooth. I include some code sample below to explain what I'm doing. I am currently learning Lua with C++ embedding, so I know I still don't have the best practices.
update.lua
function transform(m)
amplitude = 1.5
frequency = 500
phase = 0.0
r = {}
for i = 1, #m do
r[i] = {}
for j = 1, #m[i] do
if (i % 2) then
r[i][j] = amplitude * math.sin(m[i][j] + phase)
else
r[i][j] = -amplitude * math.sin(m[i][j] + phase)
end
phase = phase + 0.001
end
end
return r
end
-- called by c++
function update()
m = pull()
r = transform(m)
push(r)
end
matrix.cpp
// pull matrix from lua point of view
static int pull(lua_State * _L)
{
_push(_L, &_m);
return 1;
}
// push matrix from lua point of view
static int push(lua_State * _L)
{
// get number of arguments
int n = lua_gettop(_L);
if(1 == n) {
_pull(_L, 1, &_m);
}
return 1;
}
void matrix::load_file(char * file, char * function)
{
int status;
// load the file containing the script we are going to run
status = luaL_loadfile(_L, file);
switch (status) {
case LUA_OK:
break;
case LUA_ERRFILE:
std::cout << "LUA_ERRFILE: " << lua_error(_L) << std::endl;
break;
case LUA_ERRSYNTAX:
std::cout << "LUA_ERRSYNTAX: " << lua_error(_L) << std::endl;
break;
default:
std::cout << lua_error(_L) << std::endl;
}
lua_getglobal(_L, function);
status = lua_pcall(_L, 1, 1, 0);
if (status != LUA_OK) {
std::cout << "error running file" << lua_error(_L) << std::endl;
}
}
void matrix::update()
{
load_file("lua/update.lua", "update");
}
I'm thinking of passing some arguments when calling the update() function, but I'm wondering if the C++ to Lua then back to C++ approach is correct and efficient. Especially considering the fact that I might transfer and modify huge matrix in Lua. I probably lack some embedded Lua knowledge to keep context while loading a script. Do you have some general advice on how I would improve my code ? I know that my current approach is overly complicated.
A quick fix would be to only load the file if it has been modified since the last frame:
static time_t last_modified = 0;
struct stat sbuf;
stat(file, &sbuf);
if (sbuf.st_mtime > last_modified) {
last_modified = sbuf.st_mtime;
status = luaL_loadfile(_L, file);
// etc
}
// Now call the function
lua_getglobal(_L, function);
status = lua_pcall(_L, 1, 1, 0);
OK, loading the chunk of the update() function into a global variable and having a global parameter table in the Lua script is the way to go. I achieved this using the following guidelines, and I will post the detailed steps below. Basically, loading the script entirely first ensures that all global variables are stored in the C++ context. Then storing the wanted function as an index allows us to run it again, while keeping the global variables in the script evolving on their own.
Step 1
First call luaL_loadfile once at init
Step 2
Run the script once using lua_pcall(_L, 0, 0, 0);
This ensures that the global variables, which are used as parameters in the Lua script are in memory.
Step 3
Store the Lua function. I managed to do it with the following C++ code:
void matrix::store(char * function)
{
lua_newtable(_L); // create table for functions
_idx = luaL_ref(_L, LUA_REGISTRYINDEX); // store said table in pseudo-registry
lua_rawgeti(_L, LUA_REGISTRYINDEX, _idx); // retrieve table for functions
lua_getglobal(_L, function); // retrieve function to store
if (lua_isfunction(_L, -1)) {
_f = luaL_ref(_L, -2); // store a function in the function table
}
else {
lua_pop(_L, 1);
std::cout << "can't find " << function << std::endl;
}
// table is two places up the current stack counter
lua_pop(_L, 1); // we are done with the function table, so pop it
std::cout << "idx: " << _idx << ", function: " << _f << std::endl;
}
Step 4
Call the stored function again when rendering using the following C++ function:
void matrix::run()
{
int status;
if (_f == -1) {
std::cout << "invalid function index " << _f << std::endl;
}
else {
lua_rawgeti(_L, LUA_REGISTRYINDEX, _idx); // retrieve function table
lua_rawgeti(_L, -1, _f); // retrieve function
//use function
status = lua_pcall(_L, 0, 0, 0); // 0 arguments, 0 results
if (status != LUA_OK) {
std::cout << "error running function" << lua_error(_L) << std::endl;
}
//don't forget to pop the function table from the stack
lua_pop(_L, 1);
}
}
Step 5 (optional)
If we set all the Lua parameters in a global table, we can retrieve them dynamically in C++ using the following piece of code:
void matrix::get_params(char * p)
{
lua_getglobal(_L, p);
lua_pushnil(_L);
int i = 0;
while(lua_next(_L,-2))
{
const char * key = lua_tostring(_L,-2);
double value = lua_tonumber(_L,-1);
lua_pop(_L,1);
std::cout << key << " = " << value << std::endl;
_h[i].key.assign(key);
_h[i].value = value;
i++;
}
lua_pop(_L, 1);
}
Where _his a simple dynamic structure defined as such:
typedef struct {
std::string key;
float value;
} hash;
I only use float, so this simple structure is convenient enough for my needs, and allows me to add lots of variables in my Lua script without bothering with a structure definition in C++. This way I can add as many parameters in my Lua table and do the maths when updating.
Step 6
Tweak the Lua script forever ! Et voila:
p = {
amplitude = 1.5,
frequency = 500,
phase = 0.0
}
function transform(m)
r = {}
for i = 1, #m do
r[i] = {}
for j = 1, #m[i] do
if (i % 2) then
r[i][j] = p.amplitude * math.sin(m[i][j] + p.phase)
else
r[i][j] = -p.amplitude * math.sin(m[i][j] + p.phase)
end
p.phase = p.phase + 0.001
end
end
return r
end
-- called by c++
function update()
m = pull()
r = transform(m)
push(r)
end
This solution fits my needs, but seems very complicated and inefficient. But it was a fine hacking session anyway.

calculate the message delivery ratio

I am trying to calculate the message delivery ratio using TraCIDemo.
In sendBeacon I am incrementing messageDeliverySend every time I send a message and in processBeacon I increment the messageDeliveryReceive parameter based on the sending node.
In processBeacon I do a string compare with node[0], but I want to check this parameter dynamically. How do I do the dynamic check part for this code?
My scenario will be if there are multiple nodes transmitting to node[1] for example I want to record values only from node[0].
void ROAMER::sendBeacon(ROAMERBeacon * beacon, double delay) {
ROAMER_EV << "Sending beacon: address = " << beacon->getAddress()
<< ", position = " << beacon->getPosition() << endl;
IPv4ControlInfo * networkProtocolControlInfo = new IPv4ControlInfo();
networkProtocolControlInfo->setProtocol(IP_PROT_MANET);
networkProtocolControlInfo->setTimeToLive(255);
networkProtocolControlInfo->setDestAddr(IPv4Address::LL_MANET_ROUTERS);
networkProtocolControlInfo->setSrcAddr(getSelfAddress().get4());
messageDeliverySend++;
delayTime = simTime();
UDPPacket * udpPacket = new UDPPacket(beacon->getName());
udpPacket->encapsulate(beacon);
udpPacket->setSourcePort(ROAMER_UDP_PORT);
udpPacket->setDestinationPort(ROAMER_UDP_PORT);
udpPacket->setControlInfo(networkProtocolControlInfo);
sendUDPPacket(udpPacket, delay);
}
void ROAMER::processBeacon(ROAMERBeacon * beacon) {
if(strcmp(beacon->getSenderAddress(),"node[0]") == 0){
messageDeliveryReceive++;
}
}
void ROAMER::finish(){
messageDeliveryRatio = messageDeliveryReceive/messageDeliverySend;
recordScalar("Message Delivery Ratio",messageDeliveryVecRatio);
}

how to pass data from terminal to a program?

i am using a GPS reciever that will print GPS message contiuously in terminal using a C++ program like this
Latitude:13.3 Longitude:80.25
Latitude:13.4 Longitude:80.27
Latitude:13.5 Longitude:80.28
I want to take this data inside my c++ program (QT Application)
Below is my full program code
void QgsGpsPlotPluginGui::on_buttonBox_accepted()
{
QString myPluginsDir = "usr/lib/qgis/plugins";
QgsProviderRegistry::instance(myPluginsDir);
QgsVectorLayer * mypLayer = new QgsVectorLayer("/home/mit/Documents/Dwl/GIS DataBase/india_placename.shp","GPS","ogr");
QgsSingleSymbolRenderer *mypRenderer = new
QgsSingleSymbolRenderer(mypLayer->geometryType());
QList <QgsMapCanvasLayer> myLayerSet;
mypLayer->setRenderer(mypRenderer);
if (mypLayer->isValid())
{
qDebug("Layer is valid");
}
else
{
qDebug("Layer is NOT valid");
}
// Add the Vector Layer to the Layer Registry
QgsMapLayerRegistry::instance()->addMapLayer(mypLayer, TRUE);
// Add the Layer to the Layer Set
myLayerSet.append(QgsMapCanvasLayer(mypLayer, TRUE));
QgsMapCanvas * mypMapCanvas = new QgsMapCanvas(0, 0);
mypMapCanvas->setExtent(mypLayer->extent());
mypMapCanvas->enableAntiAliasing(true);
mypMapCanvas->setCanvasColor(QColor(255, 255, 255));
mypMapCanvas->freeze(false);
QgsFeature * mFeature = new QgsFeature();
QgsGeometry * geom = QgsGeometry::fromPoint(*p);
QGis::GeometryType geometryType=QGis::Point;
QgsRubberBand * mrub = new QgsRubberBand (mypMapCanvas,geometryType);
QgsPoint * p = new QgsPoint();
double latitude =13.3;
double longitude = 80.25;
p->setX(latitude);
p->setY(longitude);
mrub->setToGeometry(geom,mypLayer);
mrub->show()
}
In the above code i have manually entered the value for Latitude and Longitude like this,
double latitude =13.3;
double longitude = 80.25;
p->setX(latitude);
p->setY(longitude);
but i need to get these value from terminal.
Both program are written in c++ but they belong to different framework.
I assume that your library doesn't have an API you can use.
Then one fairly straight forward way to integrate them would be to use pipes.
You can quickly do something like
gps_program | qt_program
And now you get the coordinates via stdin.
The more complex way to set it up is using exec and fork. You create pipe objects, then fork and run using exec the gps_programon one of the branches. This you can do entirely in your code without depending on bash or something like it. You still have to parse the data coming from the pipe the same way.
Just create a pipe:
#include <cstdio>
#include <iostream>
#define WWRITER 0
#if WWRITER
int main() {
while (true) {
std::cout << "Latitude:13.3 Longitude:80.25";
}
return 0;
}
#else
int main() {
FILE* fp = popen("Debug/Writer", "r");
if(fp == 0) perror(0);
else {
const std::size_t LatitudeLength = 9;
const std::size_t LongitudeLength = 10;
char latitude_name[LatitudeLength+1];
char longitude_name[LongitudeLength+1];
double latitude;
double longitude;
while(fscanf(fp, "%9s%lf%10s%lf",
latitude_name,
&latitude,
longitude_name,
&longitude) == 4)
{
std::cout << "Values: " << latitude << ", " << longitude << std::endl;
}
pclose(fp);
}
return 0;
}
#endif
Note: The example runs endlessly.
+1 to Sorin's answer, makes this nice and easy passing stdout to stdin :) but assuming you are running in linux / cigwin?
But if you have access to both program codes then a nicer solution is to use UdpSockets (or maybe Tcp, but Udp is simpler) and pass the data between programs in this way... not sure how big/long-term your solution needs to be but if you want to integrate them in a "long-term" and more maintainable way this would be a better approach.