void snlKnotVector::truncate ( knot param, bool keepLast ) { // Truncate knot vector. // --------------------- // param: Parameter to truncate at. // keepLast: Keep last section of knot vector, discard first part. // // Notes: Truncates at last of knots valued at param. // Assumes degree knots are present at param. unsigned start, end; if ( keepLast ) { start = findSpan ( param ); start = getPreviousSpan ( start ) + 1; // Go to start of knots if more than one at param. end = vectorSize - 1; } else { start = 0; end = findSpan ( param ); } // Generate new knot vector and populate. unsigned newSize = end - start + 2; // Add one point for correct clamping. knot* newKnots = new knot [ newSize ]; unsigned copyFrom = start; if ( keepLast ) { for ( unsigned index = 1; index < newSize; index ++, copyFrom ++ ) newKnots [ index ] = knots [ copyFrom ]; newKnots [ 0 ] = param; } else { for ( unsigned index = 0; index < newSize - 1; index ++, copyFrom ++ ) newKnots [ index ] = knots [ copyFrom ]; newKnots [ newSize - 1 ] = param; } delete[] knots; knots = newKnots; vectorSize = newSize; }
void snlKnotVector::insertKnot ( knot param, int numTimes ) { // Insert new knot into vector. // ---------------------------- // param: knot to insert. // numTimes: Number of times to insert knot into vector. unsigned index; if ( ! knots ) return; unsigned span = findSpan ( param ); knot* newKnots = new knot [ vectorSize + numTimes ]; // Copy up to insertion point. for ( index = 0; index <= span; index ++ ) newKnots [ index ] = knots [ index ]; // Add in new knot. for ( int count = 0; count < numTimes; count ++ ) newKnots [ span + count + 1 ] = param; // Copy rest of old knots to new vector. for ( index = span + numTimes + 1; index < vectorSize + numTimes; index ++ ) newKnots [ index ] = knots [ index - numTimes ]; delete[] knots; knots = newKnots; vectorSize += numTimes; }
static Vertex InterpolateNurbs(Curve *Curve, double u, int derivee) { double Nb[1000]; int span = findSpan(u, Curve->degre, List_Nbr(Curve->Control_Points), Curve->k); basisFuns(u, span, Curve->degre, Curve->k, Nb); Vertex p; p.Pos.X = p.Pos.Y = p.Pos.Z = p.w = p.lc = 0.0; for(int i = Curve->degre; i >= 0; --i) { Vertex *v; List_Read(Curve->Control_Points, span - Curve->degre + i, &v); p.Pos.X += Nb[i] * v->Pos.X; p.Pos.Y += Nb[i] * v->Pos.Y; p.Pos.Z += Nb[i] * v->Pos.Z; p.w += Nb[i] * v->w; p.lc += Nb[i] * v->lc; } return p; }
int snlKnotVector::findMultiplicity ( knot param ) const { // Find the knot multiplicity at a particular knot value. // ------------------------------------------------------ // param: Parameter to evaluate. // // Returns: Number of knots found. // Find span parameter belongs to. unsigned span = findSpan ( param ); // Find value of knot associated with span. knot spanKnotVal = val ( span ); // Return multiplicity. if ( param == spanKnotVal ) return findMultiplicity ( span ); return 0; }
/*! Compute the nonvanishing basis functions at \f$ u \f$. All the basis functions are stored in an array such as : N = \f$ N_{i,0}(u) \f$, \f$ N_{i-1,1}(u) \f$, \f$ N_{i,1}(u) \f$, ... , \f$ N_{i-k,k}(u) \f$, ..., \f$ N_{i,k}(u) \f$, ... , \f$ N_{i-p,p}(u) \f$, ... , \f$ N_{i,p}(u) \f$ where i the number of the knot interval in which \f$ u \f$ lies. \param u : A real number which is between the extrimities of the knot vector \return An array containing the nonvanishing basis functions at \f$ u \f$. The size of the array is \f$ p +1 \f$. */ vpBasisFunction* vpBSpline::computeBasisFuns(double u) { unsigned int i = findSpan(u); return computeBasisFuns(u, i, p ,knots); }
/*! Find the knot interval in which the parameter \f$ u \f$ lies. Indeed \f$ u \in [u_i, u_{i+1}[ \f$ Example : The knot vector is the following \f$ U = \{0, 0 , 1 , 2 ,3 , 3\} \f$ with \f$ p \f$ is equal to 1. - For \f$ u \f$ equal to 0.5 the method will retun 1. - For \f$ u \f$ equal to 2.5 the method will retun 3. - For \f$ u \f$ equal to 3 the method will retun 3. \param u : The knot whose knot interval is seeked. \return the number of the knot interval in which \f$ u \f$ lies. */ unsigned int vpBSpline::findSpan(double u) { return findSpan( u, p, knots); }
basis* snlKnotVector::evalBasisDeriv ( knot param, int deriv ) { // Evaluate basis functions and their derivatives. // ----------------------------------------------- // // param: Parameter to process at. // deriv: Which derivative to process to. // // Returns: Two dimensional array of basis and basis derivative values. // // Notes: The calling function is responsible for deleting the returned array // using delete[]. The size of the array is [ deriv + 1 ] [ deg + 1 ]. basis* right = new basis [ deg + 1 ]; basis* left = new basis [ deg + 1 ]; basis saved, temp; basis* derivSaved = new basis [ deriv ]; unsigned index, level; int count; basis* bVals = new basis [ ( deriv + 1 ) * ( deg + 1 ) ]; unsigned spanIndex = findSpan ( param ); unsigned overFlow; // Just in case deriv is bigger than degree. if ( deriv > deg ) { overFlow = deriv - deg; deriv = deg; } else overFlow = 0; bVals [ 0 ] = 1.0; for ( level = 1; level <= (unsigned) deg; level ++ ) { left [ level ] = param - knots [ spanIndex + 1 - level ]; right [ level ] = knots [ spanIndex + level ] - param; saved = 0.0; for ( count = 0; count < deriv; count ++ ) derivSaved [ count ] = 0.0; for ( index = 0; index < level; index ++ ) { temp = bVals [ index ] / ( right [ index + 1 ] + left [ level - index ] ); bVals [ index ] = saved + right [ index + 1 ] * temp; saved = left [ level - index ] * temp; // Process first order derivatives as needed. if ( level > (unsigned) ( deg - deriv ) ) { bVals [ index + ( ( deg - level + 1 ) * ( deg + 1 ) ) ] = level * ( derivSaved [ 0 ] - temp ); derivSaved [ 0 ] = temp; } // Process other order derivatives. for ( count = deg - level + 2; count <= deriv; count ++ ) { temp = bVals [ index + ( count * ( deg + 1 ) ) ] / ( right [ index + 1 ] + left [ level - index ] ); bVals [ index + ( count * ( deg + 1 ) ) ] = level * ( derivSaved [ count - 1 ] - temp ); derivSaved [ count - 1 ] = temp; } } bVals [ level ] = saved; // Add last first order derivative at this level. if ( level > (unsigned) ( deg - deriv ) ) bVals [ level + ( ( deg - level + 1 ) * ( deg + 1 ) ) ] = level * derivSaved [ 0 ]; // Add last other order derivatives at this level. for ( count = deg - level + 2; count <= deriv; count ++ ) bVals [ index + ( count * ( deg + 1 ) ) ] = level * derivSaved [ count - 1 ]; } if ( overFlow ) { for ( index = ( deriv + 1 ) * ( deg + 1 ); index < ( deriv + overFlow + 1 ) * ( deg + 1 ); index ++ ) bVals [ index ] = 0.0; } delete[] left; delete[] right; delete[] derivSaved; return bVals; }
basis* snlKnotVector::evalBasis ( knot param ) { // Evaluate Basis Functions // ------------------------ // param: Paramater value to process at. // // Returns: Array of basis function values, evaluated at param. // // Notes: The calling function owns the returned array and is responsible for // deleting it using delete[]. The size of the array is always deg + 1. basis* bVals = new basis [ deg + 1 ]; if ( param == knots [ 0 ] && kvType == open ) { // First basis function value is 1 the rest are zero. bVals [ 0 ] = 1.0; for ( int index = 1; index < deg + 1; index ++ ) bVals [ index ] = 0.0; return bVals; } if ( param == knots [ vectorSize - 1 ] && kvType == open ) { // Last basis function value is 1 the rest are zero. bVals [ deg ] = 1.0; for ( int index = 0; index < deg; index ++ ) bVals [ index ] = 0.0; return bVals; } unsigned spanIndex = findSpan ( param ); basis* right = new basis [ deg + 1 ]; basis* left = new basis [ deg + 1 ]; basis saved, temp; unsigned index, level; bVals [ 0 ] = 1.0; for ( level = 1; level <= (unsigned) deg; level ++ ) { left [ level ] = param - knots [ spanIndex + 1 - level ]; right [ level ] = knots [ spanIndex + level ] - param; saved = 0.0; for ( index = 0; index < level; index ++ ) { temp = bVals [ index ] / ( right [ index + 1 ] + left [ level - index ] ); bVals [ index ] = saved + right [ index + 1 ] * temp; saved = left [ level - index ] * temp; } bVals [ level ] = saved; } delete[] right; delete[] left; return bVals; }
void NURBSCurve<Real>::refine(Array1D_Real & insknts, Array1D_Vector3 & Qw, Array1D_Real & Ubar ) { // Input Array1D_Real X = insknts; Array1D_Vector3 Pw = this->mCtrlPoint; Array1D_Real U = GetKnotVector(); int s = insknts.size(); int order = this->GetDegree() + 1; int p = order - 1; int n = Pw.size() - 1; int r = X.size() - 1; int m = n+p+1; // Output Qw.resize ( n+s+1, Vector3(0,0,0) ); Ubar.resize ( m+s+1, 0 ); int a = findSpan(n,p,X[0],U); int b = findSpan(n,p,X[r],U) + 1; int j = 0; for(j=0 ; j<=a-p; j++) Qw[j] = Pw[j]; for(j=b-1; j<=n ; j++) Qw[j+r+1] = Pw[j]; for(j=0 ; j<=a ; j++) Ubar[j] = U[j]; for(j=b+p; j<=m ; j++) Ubar[j+r+1] = U[j]; int i = b+p-1; int k = b+p+r; Real alfa = 0; for (int j=r; j>=0; j--) { while (X[j] <= U[i] && i > a) { Qw[k-p-1] = Pw[i-p-1]; Ubar[k] = U[i]; k = k - 1; i = i - 1; } Qw[k-p-1] = Qw[k-p]; for (int l=1; l<=p; l++) { int ind = k-p+l; alfa = Ubar[k+l] - X[j]; if (fabs(alfa) == 0.0) { Qw[ind-1] = Qw[ind]; } else { alfa = alfa / (Ubar[k+l] - U[i-p+l]); Qw[ind-1] = alfa * Qw[ind-1] + (1.0 - alfa) * Qw[ind]; } } Ubar[k] = X[j]; k = k - 1; } }
int NURBSCurve<Real>::findSpan(Real u) { return findSpan(this->mCtrlPoint.size() - 1, GetDegree(), u, GetKnotVector() ); }
/*! Method which enables to compute a NURBS curve approximating a set of data points. The data points are approximated thanks to a least square method. The result of the method is composed by a knot vector, a set of control points and a set of associated weights. \param l_crossingPoints : The list of data points which have to be interpolated. \param l_p : Degree of the NURBS basis functions. \param l_n : The desired number of control points. l_n must be under or equal to the number of data points. \param l_knots : The knot vector. \param l_controlPoints : the list of control points. \param l_weights : the list of weights. */ void vpNurbs::globalCurveApprox(std::vector<vpImagePoint> &l_crossingPoints, unsigned int l_p, unsigned int l_n, std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints, std::vector<double> &l_weights) { l_knots.clear(); l_controlPoints.clear(); l_weights.clear(); unsigned int m = (unsigned int)l_crossingPoints.size()-1; double d = 0; for(unsigned int k=1; k<=m; k++) d = d + distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1); //Compute ubar std::vector<double> ubar; ubar.push_back(0.0); for(unsigned int k=1; k<m; k++) ubar.push_back(ubar[k-1]+distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1)/d); ubar.push_back(1.0); //Compute the knot vector for(unsigned int k = 0; k <= l_p; k++) l_knots.push_back(0.0); d = (double)(m+1)/(double)(l_n-l_p+1); for(unsigned int j = 1; j <= l_n-l_p; j++) { double i = floor(j*d); double alpha = j*d-i; l_knots.push_back((1.0-alpha)*ubar[(unsigned int)i-1]+alpha*ubar[(unsigned int)i]); } for(unsigned int k = 0; k <= l_p ; k++) l_knots.push_back(1.0); //Compute Rk std::vector<vpImagePoint> Rk; vpBasisFunction* N; for(unsigned int k = 1; k <= m-1; k++) { unsigned int span = findSpan(ubar[k], l_p, l_knots); if (span == l_p && span == l_n) { N = computeBasisFuns(ubar[k], span, l_p, l_knots); vpImagePoint pt(l_crossingPoints[k].get_i()-N[0].value*l_crossingPoints[0].get_i()-N[l_p].value*l_crossingPoints[m].get_i(), l_crossingPoints[k].get_j()-N[0].value*l_crossingPoints[0].get_j()-N[l_p].value*l_crossingPoints[m].get_j()); Rk.push_back(pt); delete[] N; } else if (span == l_p) { N = computeBasisFuns(ubar[k], span, l_p, l_knots); vpImagePoint pt(l_crossingPoints[k].get_i()-N[0].value*l_crossingPoints[0].get_i(), l_crossingPoints[k].get_j()-N[0].value*l_crossingPoints[0].get_j()); Rk.push_back(pt); delete[] N; } else if (span == l_n) { N = computeBasisFuns(ubar[k], span, l_p, l_knots); vpImagePoint pt(l_crossingPoints[k].get_i()-N[l_p].value*l_crossingPoints[m].get_i(), l_crossingPoints[k].get_j()-N[l_p].value*l_crossingPoints[m].get_j()); Rk.push_back(pt); delete[] N; } else { Rk.push_back(l_crossingPoints[k]); } } vpMatrix A(m-1,l_n-1); //Compute A for(unsigned int i = 1; i <= m-1; i++) { unsigned int span = findSpan(ubar[i], l_p, l_knots); N = computeBasisFuns(ubar[i], span, l_p, l_knots); for (unsigned int k = 0; k <= l_p; k++) { if (N[k].i > 0 && N[k].i < l_n) A[i-1][N[k].i-1] = N[k].value; } delete[] N; } vpColVector Ri(l_n-1); vpColVector Rj(l_n-1); vpColVector Rw(l_n-1); for (unsigned int i = 0; i < l_n-1; i++) { double sum =0; for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]*Rk[k].get_i(); Ri[i] = sum; sum = 0; for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]*Rk[k].get_j(); Rj[i] = sum; sum = 0; for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]; //The crossing points weigths are equal to 1. Rw[i] = sum; } vpMatrix AtA = A.AtA(); vpMatrix AtAinv; AtA.pseudoInverse(AtAinv); vpColVector Pi = AtAinv*Ri; vpColVector Pj = AtAinv*Rj; vpColVector Pw = AtAinv*Rw; vpImagePoint pt; l_controlPoints.push_back(l_crossingPoints[0]); l_weights.push_back(1.0); for (unsigned int k = 0; k < l_n-1; k++) { pt.set_ij(Pi[k],Pj[k]); l_controlPoints.push_back(pt); l_weights.push_back(Pw[k]); } l_controlPoints.push_back(l_crossingPoints[m]); l_weights.push_back(1.0); }
/*! Method which enables to compute a NURBS curve passing through a set of data points. The result of the method is composed by a knot vector, a set of control points and a set of associated weights. \param l_crossingPoints : The list of data points which have to be interpolated. \param l_p : Degree of the NURBS basis functions. This value need to be > 0. \param l_knots : The knot vector \param l_controlPoints : the list of control points. \param l_weights : the list of weights. */ void vpNurbs::globalCurveInterp(std::vector<vpImagePoint> &l_crossingPoints, unsigned int l_p, std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints, std::vector<double> &l_weights) { if (l_p == 0) { //vpERROR_TRACE("Bad degree of the NURBS basis functions"); throw(vpException(vpException::badValue, "Bad degree of the NURBS basis functions")) ; } l_knots.clear(); l_controlPoints.clear(); l_weights.clear(); unsigned int n = (unsigned int)l_crossingPoints.size()-1; unsigned int m = n+l_p+1; double d = 0; for(unsigned int k=1; k<=n; k++) d = d + distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1); //Compute ubar std::vector<double> ubar; ubar.push_back(0.0); for(unsigned int k=1; k<n; k++) ubar.push_back(ubar[k-1]+distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1)/d); ubar.push_back(1.0); //Compute the knot vector for(unsigned int k = 0; k <= l_p; k++) l_knots.push_back(0.0); double sum = 0; for(unsigned int k = 1; k <= l_p; k++) sum = sum + ubar[k]; //Centripetal method for(unsigned int k = 1; k <= n-l_p; k++) { l_knots.push_back(sum/l_p); sum = sum - ubar[k-1] + ubar[l_p+k-1]; } for(unsigned int k = m-l_p; k <= m; k++) l_knots.push_back(1.0); vpMatrix A(n+1,n+1); vpBasisFunction* N; for(unsigned int i = 0; i <= n; i++) { unsigned int span = findSpan(ubar[i], l_p, l_knots); N = computeBasisFuns(ubar[i], span, l_p, l_knots); for (unsigned int k = 0; k <= l_p; k++) A[i][span-l_p+k] = N[k].value; delete[] N; } //vpMatrix Ainv = A.inverseByLU(); vpMatrix Ainv; A.pseudoInverse(Ainv); vpColVector Qi(n+1); vpColVector Qj(n+1); vpColVector Qw(n+1); for (unsigned int k = 0; k <= n; k++) { Qi[k] = l_crossingPoints[k].get_i(); Qj[k] = l_crossingPoints[k].get_j(); } Qw = 1; vpColVector Pi = Ainv*Qi; vpColVector Pj = Ainv*Qj; vpColVector Pw = Ainv*Qw; vpImagePoint pt; for (unsigned int k = 0; k <= n; k++) { pt.set_ij(Pi[k],Pj[k]); l_controlPoints.push_back(pt); l_weights.push_back(Pw[k]); } }
/*! Insert \f$ l_r \f$ knots in the knot vector. Of course the knot vector changes. But The list of control points and the list of the associated weights change too. \param l_x : Several real numbers which are between the extrimities of the knot vector and which have to be inserted. \param l_r : Number of knot in the array \f$ l_x \f$. \param l_p : Degree of the NURBS basis functions. \param l_knots : The knot vector \param l_controlPoints : the list of control points. \param l_weights : the list of weights. */ void vpNurbs::refineKnotVectCurve(double* l_x, unsigned int l_r, unsigned int l_p, std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints, std::vector<double> &l_weights) { unsigned int a = findSpan(l_x[0], l_p, l_knots); unsigned int b = findSpan(l_x[l_r], l_p, l_knots); b++; unsigned int n = (unsigned int)l_controlPoints.size(); unsigned int m = (unsigned int)l_knots.size(); for (unsigned int j = 0; j < n; j++) { l_controlPoints[j].set_ij(l_controlPoints[j].get_i()*l_weights[j],l_controlPoints[j].get_j()*l_weights[j]); } std::vector<double> l_knots_tmp(l_knots); std::vector<vpImagePoint> l_controlPoints_tmp(l_controlPoints); std::vector<double> l_weights_tmp(l_weights); vpImagePoint pt; double w = 0; for (unsigned int j = 0; j <= l_r; j++) { l_controlPoints.push_back(pt); l_weights.push_back(w); l_knots.push_back(w); } for(unsigned int j = b+l_p; j <= m-1; j++) l_knots[j+l_r+1] = l_knots_tmp[j]; for (unsigned int j = b-1; j <= n-1; j++) { l_controlPoints[j+l_r+1] = l_controlPoints_tmp[j]; l_weights[j+l_r+1] = l_weights_tmp[j]; } unsigned int i = b+l_p-1; unsigned int k = b+l_p+l_r; { unsigned int j = l_r + 1; do{ j--; while(l_x[j] <= l_knots[i] && i > a) { l_controlPoints[k-l_p-1] = l_controlPoints_tmp[i-l_p-1]; l_weights[k-l_p-1] = l_weights_tmp[i-l_p-1]; l_knots[k] = l_knots_tmp[i]; k--; i--; } l_controlPoints[k-l_p-1] = l_controlPoints[k-l_p]; l_weights[k-l_p-1] = l_weights[k-l_p]; for (unsigned int l = 1; l <= l_p; l++) { unsigned int ind = k-l_p+l; double alpha = l_knots[k+l] - l_x[j]; //if (vpMath::abs(alpha) == 0.0) if (std::fabs(alpha) <= std::numeric_limits<double>::epsilon()) { l_controlPoints[ind-1] = l_controlPoints[ind]; l_weights[ind-1] = l_weights[ind]; } else { alpha = alpha/(l_knots[k+l]-l_knots_tmp[i-l_p+l]); l_controlPoints[ind-1].set_i( alpha * l_controlPoints[ind-1].get_i() + (1.0-alpha) * l_controlPoints[ind].get_i()); l_controlPoints[ind-1].set_j( alpha * l_controlPoints[ind-1].get_j() + (1.0-alpha) * l_controlPoints[ind].get_j()); l_weights[ind-1] = alpha * l_weights[ind-1] + (1.0-alpha) * l_weights[ind]; } } l_knots[k] = l_x[j]; k--; }while(j != 0); } for (unsigned int j = 0; j < n; j++) { l_controlPoints[j].set_ij(l_controlPoints[j].get_i()/l_weights[j],l_controlPoints[j].get_j()/l_weights[j]); } }
/*! Insert \f$ r \f$ times a knot in the \f$ k \f$ th interval of the knot vector. The inserted knot \f$ u \f$ has multiplicity \f$ s \f$. Of course the knot vector changes. But The list of control points and the list of the associated weights change too. \param u : A real number which is between the extrimities of the knot vector and which has to be inserted. \param s : Multiplicity of \f$ l_u \f$ \param r : Number of times \f$ l_u \f$ has to be inserted. */ void vpNurbs::curveKnotIns(double u, unsigned int s, unsigned int r) { unsigned int i = findSpan(u); curveKnotIns(u, i, s, r, p, knots, controlPoints, weights); }
/*! Compute the kth derivatives of \f$ C(u) \f$ for \f$ k = 0, ... , l_{der} \f$. To see how the derivatives are computed refers to the Nurbs book. \param u : A real number which is between the extrimities of the knot vector \param der : The last derivative to be computed. \return an array of size l_der+1 containing the coordinates \f$ C^{(k)}(u) \f$ for \f$ k = 0, ... , der \f$. The kth derivative is in the kth cell of the array. */ vpImagePoint* vpNurbs::computeCurveDersPoint(double u, unsigned int der) { unsigned int i = findSpan(u); return computeCurveDersPoint(u, i, p, der, knots, controlPoints, weights); }
int pmqlso(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10) { char *mqName = (char *) a1; uvast remoteEngineId = a2 != 0 ? strtouvast((char *) a2) : 0; #else int main(int argc, char *argv[]) { char *mqName = argc > 1 ? argv[1] : NULL; uvast remoteEngineId = argc > 2 ? strtouvast(argv[2]) : 0; #endif Sdr sdr; LtpVspan *vspan; PsmAddress vspanElt; struct mq_attr mqAttributes = { 0, PMQLSA_MAXMSG, PMQLSA_MSGSIZE, 0 }; mqd_t mq; int running; int segmentLength; char *segment; if (remoteEngineId == 0 || mqName == NULL) { puts("Usage: pmqlso <message queue name> <remote engine ID>"); return 0; } /* Note that ltpadmin must be run before the first * invocation of ltplso, to initialize the LTP database * (as necessary) and dynamic database. */ if (ltpInit(0) < 0) { putErrmsg("pmqlso can't initialize LTP.", NULL); return 1; } sdr = getIonsdr(); CHKERR(sdr_begin_xn(sdr)); /* Just to lock memory. */ findSpan(remoteEngineId, &vspan, &vspanElt); if (vspanElt == 0) { sdr_exit_xn(sdr); putErrmsg("No such engine in database.", itoa(remoteEngineId)); return 1; } if (vspan->lsoPid > 0 && vspan->lsoPid != sm_TaskIdSelf()) { sdr_exit_xn(sdr); putErrmsg("LSO task is already started for this span.", itoa(vspan->lsoPid)); return 1; } /* All command-line arguments are now validated. */ sdr_exit_xn(sdr); mq = mq_open(mqName, O_RDWR | O_CREAT, 0777, &mqAttributes); if (mq == (mqd_t) -1) { putSysErrmsg("pmqlso can't open message queue", mqName); return 1; } oK(_pmqlsoSemaphore(&vspan->segSemaphore)); isignal(SIGTERM, interruptThread); /* Can now begin transmitting to remote engine. */ writeMemo("[i] pmqlso is running."); running = 1; while (running && !(sm_SemEnded(_pmqlsoSemaphore(NULL)))) { segmentLength = ltpDequeueOutboundSegment(vspan, &segment); if (segmentLength < 0) { running = 0; /* Terminate LSO. */ continue; } if (segmentLength == 0) /* Interrupted. */ { continue; } if (segmentLength > PMQLSA_MSGSIZE) { putErrmsg("Segment is too big for PMQ LSO.", itoa(segmentLength)); running = 0; /* Terminate LSO. */ continue; } if (sendSegmentByPMQ(mq, segment, segmentLength) < 0) { putSysErrmsg("pmqlso failed sending segment", mqName); running = 0; /* Terminate LSO. */ continue; } /* Make sure other tasks have a chance to run. */ sm_TaskYield(); } mq_close(mq); writeErrmsgMemos(); writeMemo("[i] pmqlso duct has ended."); ionDetach(); return 0; }