Пример #1
0
void Agent::streamData (ostream &          out,
                        std::set<string> & aFilter,
                        bool               current,
                        unsigned int       aInterval,
                        uint64_t           start,
                        unsigned int       count,
                        unsigned int       aHeartbeat
                        )
{
    // Create header
    string boundary = md5(intToString(time(NULL)));

    ofstream log;

    if ( mLogStreamData )
    {
        string filename = "Stream_" + getCurrentTime(LOCAL) + "_"
                          + int64ToString((uint64_t) dlib::get_thread_id( )) + ".log";
        log.open(filename.c_str( ));
    }

    out << "HTTP/1.1 200 OK\r\n"
           "Date: " << getCurrentTime(HUM_READ) << "\r\n"
                                                   "Server: MTConnectAgent\r\n"
                                                   "Expires: -1\r\n"
                                                   "Connection: close\r\n"
                                                   "Cache-Control: private, max-age=0\r\n"
                                                   "Content-Type: multipart/x-mixed-replace;boundary=" << boundary << "\r\n"
                                                                                                                      "Transfer-Encoding: chunked\r\n\r\n";

    // This object will automatically clean up all the observer from the
    // signalers in an exception proof manor.
    ChangeObserver observer;

    // Add observers
    std::set<string>::iterator iter;

    for ( iter = aFilter.begin( ); iter != aFilter.end( ); ++iter )
    {
        mDataItemMap[*iter]->addObserver(&observer);
    }

    uint64_t interMicros = aInterval * 1000;
    uint64_t firstSeq    = getFirstSequence( );

    if ( start < firstSeq )
    {
        start = firstSeq;
    }

    try
    {
        // Loop until the user closes the connection
        timestamper ts;

        while ( out.good( ) )
        {
            // Remember when we started this grab...
            uint64_t last = ts.get_timestamp( );

            // Fetch sample data now resets the observer while holding the sequence
            // mutex to make sure that a new event will be recorded in the observer
            // when it returns.
            string   content;
            uint64_t end;
            bool     endOfBuffer = false;

            if ( current )
            {
                content = fetchCurrentData(aFilter, NO_START);
            }
            else
            {
                // Check if we're falling too far behind. If we are, generate an
                // MTConnectError and return.
                if ( start < getFirstSequence( ) )
                {
                    sLogger << LWARN << "Client fell too far behind, disconnecting";
                    throw ParameterError("OUT_OF_RANGE", "Client can't keep up with event stream, disconnecting");
                }
                else
                {
                    // end and endOfBuffer are set during the fetch sample data while the
                    // mutex is held. This removed the race to check if we are at the end of
                    // the bufffer and setting the next start to the last sequence number
                    // sent.
                    content = fetchSampleData(aFilter, start, count, end,
                                              endOfBuffer, &observer);
                }

                if ( mLogStreamData )
                {
                    log << content << endl;
                }
            }

            ostringstream str;

            // Make sure we're terminated with a <cr><nl>
            content.append("\r\n");
            out.setf(ios::dec, ios::basefield);
            str << "--" + boundary << "\r\n"
                                      "Content-type: text/xml\r\n"
                                      "Content-length: " << content.length( ) << "\r\n\r\n"
                << content;

            string chunk = str.str( );
            out.setf(ios::hex, ios::basefield);
            out << chunk.length( ) << "\r\n";
            out << chunk << "\r\n";
            out.flush( );

            // Wait for up to frequency ms for something to arrive... Don't wait if
            // we are not at the end of the buffer. Just put the next set after aInterval
            // has elapsed. Check also if in the intervening time between the last fetch
            // and now. If so, we just spin through and wait the next interval.

            // Even if we are at the end of the buffer, or within range. If we are filtering,
            // we will need to make sure we are not spinning when there are no valid events
            // to be reported. we will waste cycles spinning on the end of the buffer when
            // we should be in a heartbeat wait as well.
            if ( current || !endOfBuffer )
            {
                // If this is not a current, move the start to the end. This is only significant
                // if we are not at the end of the buffer and we are scanning through the event
                // buffer.
                if ( !current )
                {
                    start = end;
                }

                // Measure the delta time between the point you last fetched data to now.
                uint64 delta = ts.get_timestamp( ) - last;

                if ( delta < interMicros )
                {
                    // Sleep the remainder
                    dlib::sleep(( interMicros - delta ) / 1000);
                }
            }
            else if ( observer.wait(aHeartbeat) )
            {
                // Make sure the observer was signaled!
                if ( !observer.wasSignaled( ) )
                {
                    sLogger << LERROR << "Agent::streamData: Observer returned true from wait, but observer was not signaled. Closing connection...";
                    throw ParameterError("INTERNAL_ERROR", "Event observer failed");
                }

                // Get the sequence # signaled in the observer when the earliest event arrived.
                // This will allow the next set of data to be pulled. Any later events will have
                // greater sequence numbers, so this should not cause a problem. Also, signaled
                // sequence numbers can only decrease, never increase.
                start = observer.getSequence( );

                // Now wait the remainder if we triggered before the timer was up.
                uint64 delta = ts.get_timestamp( ) - last;

                if ( delta < interMicros )
                {
                    // Sleep the remainder
                    dlib::sleep(( interMicros - delta ) / 1000);
                }
            }
            else
            {
                // If nothing came out during the last wait, we may have still have advanced
                // the sequence number. We should reset the start to something closer to the
                // current sequence. If we lock the sequence lock, we can check if the observer
                // was signaled between the time the wait timed out and the mutex was locked.
                // Otherwise, nothing has arrived and we set to the next sequence number to
                // the next sequence number to be allocated and continue.
                dlib::auto_mutex lock(*mSequenceLock);

                if ( observer.wasSignaled( ) )
                {
                    start = observer.getSequence( );
                }
                else
                {
                    start = mSequence;
                }
            }
        }
    }
    catch ( ParameterError & aError )
    {
        sLogger << LINFO << "Caught a parameter error.";

        if ( out.good( ) )
        {
            string content = printError(aError.mCode, aError.mMessage);
            out << "--" + boundary << "\n"
                                      "Content-type: text/xml\n"
                                      "Content-length: " << content.length( ) << "\n\n"
                << content;

            out.flush( );
        }
    }
    catch ( ... )
    {
        sLogger << LWARN << "Error occurred during streaming data";

        if ( out.good( ) )
        {
            string content = printError("INTERNAL_ERROR", "Unknown error occurred during streaming");
            out << "--" + boundary << "\n"
                                      "Content-type: text/xml\n"
                                      "Content-length: " << content.length( ) << "\n\n"
                << content;

            out.flush( );
        }
    }

    out.setstate(ios::badbit);

    // Observer is auto removed from signalers
}
Пример #2
0
boolean RasterCode::GConstDecls(ostream& out) {
    out << "(Raster*, Graphic* gr = nil);\n";
    out << "    virtual Graphic* Copy();\n";
    return out.good();
}
Пример #3
0
boolean RasterCode::Definition (ostream& out) {
    boolean ok = true;

    const char* sfile;
    IRasterComp* rastercomp = GetIRasterComp();
    RasterComp* target = (RasterComp*) rastercomp->GetTarget();
    RasterRect* raster = target->GetRasterRect();

    SubclassNameVar* cnamer = rastercomp->GetCClassNameVar();
    SubclassNameVar* gnamer = rastercomp->GetGClassNameVar();
    MemberNameVar* mnamer = rastercomp->GetMemberNameVar();

    const char* mname = mnamer->GetName();
    const char* cname = cnamer->GetName();
    const char* gname = gnamer->GetName();

    if (_emitInstanceDecls || _emitGraphicState) {
	ok = ok && GraphicCodeView::Definition(out);

    } else if (_emitInstanceInits) {
        static int raster_id;

        char substName[CHARBUFSIZE];
        sfile = target->GetFileName();
        Catalog* catalog = unidraw->GetCatalog();

        if (sfile == nil) {
            sprintf(substName, "raster%d.ps", raster_id++);
            sfile = substName;
        }
        if (!catalog->Exists(sfile)) {
            char orig[CHARBUFSIZE];
            const char* name = catalog->GetName(rastercomp->GetRoot());
            char* dir = GetDirName(name);
            char* index = strrchr(sfile, '/');
            if (index == nil) {
                strcpy(orig, sfile);
            } else {
                strcpy(orig, &index[1]);
            }
            strcpy(substName, dir);
            strcat(substName, orig);
            sfile = substName;
            if (!catalog->Exists(sfile)) {
                catalog->Save(target, sfile);
            }
        }
        out << "    {\n";
        out << "        RasterComp* " << mname << "_comp = (RasterComp*) ";
        out << "ImportCmd::Import(\"" << sfile << "\");\n"; 
        out << "        Raster* " << mname << "_raster = ";
        out << mname << "_comp->GetRasterRect()->GetOriginal();\n";
        if (_emitGraphicComp) {
           out << "        " << mname << "_gr";
        } else {
            out << "        " << mname;
        }
        out << " = new " << gname << "(" << mname << "_raster, ";
        out << mname << "_comp->GetGraphic());\n";
        out << "        delete " << mname << "_comp;\n";

        ok = WriteGraphicInits(raster, out);
        if (_emitGraphicComp) {
            out << "        " << mname << " = new " << cname << "(";
            out << mname << "_gr, \"" << sfile << "\");\n";
            out << "        " << mname << "->Update();\n";
        }
        out << "    }\n";

    } else if (_emitExpHeader) {
        ok = ok && GraphicCodeView::Definition(out);

        if (strcmp(gname, _classname) == 0) {
            if (!_namelist->Search("raster")) {
                _namelist->Append("raster");
                out << "#include <InterViews/raster.h> \n";
            }
        }
    } else {
        ok = ok && GraphicCodeView::Definition(out);
    }
    return ok && out.good();
}
Пример #4
0
boolean TextEditCode::Definition (ostream& out) {
    boolean ok = true;
    if (
	_emitProperty || _emitInstanceDecls || 
        _emitClassHeaders || _emitHeaders || _emitForward
    ) {
        return CodeView::Definition(out);

    } else if (_emitExpHeader) {
	InteractorComp* icomp = GetIntComp();
	MemberNameVar* mnamer = icomp->GetMemberNameVar();
        SubclassNameVar* snamer = icomp->GetClassNameVar();
        if (!snamer->IsSubclass()) {
            if (
                _scope && mnamer->GetExport()&&!_namelist->Search("texteditor")
            ) {
                _namelist->Append("texteditor");
                out << "#include <InterViews/texteditor.h>\n";
                out << "#include <InterViews/textbuffer.h>\n";
            }
        } else {
            ok = ok && CodeView::Definition(out);
        }
    } else if (_emitCorehHeader) {
	InteractorComp* icomp = GetIntComp();
        SubclassNameVar* snamer = icomp->GetClassNameVar();
        const char* subclass = snamer->GetName();
        if (snamer->IsSubclass() && strcmp(subclass, _classname) == 0) {
            if (!_namelist->Search("texteditor")) {
                _namelist->Append("texteditor");
                out << "#include <InterViews/texteditor.h>\n";
            }
        }
    } else if (_emitInstanceInits) {
        InteractorComp* icomp = GetIntComp();
        const char* mname = icomp->GetMemberNameVar()->GetName();

        if (!_instancelist->Find((void*) mname)) {
            _instancelist->Append(new UList((void*)mname));

            TextEditComp* tc = GetTextEditComp();
            int rows, cols;
    
            BeginInstantiate(out);
            StrBrowserGraphic* graphic = tc->GetStrBrowserGraphic();
            graphic->GetRowsCols(rows, cols);

            out << "(";
            InstanceName(out);
            out << rows << ", " << cols << ", " << 4 << ", Reversed" << ");\n";
	    out << "    " << mname;
	    out << "->Edit(new TextBuffer(new char[256], 0, 256))";
            EndInstantiate(out);
        }

    } else if (
	_emitFunctionDecls || _emitFunctionInits || 
	_emitBSDecls || _emitBSInits 
    ) {
        return true;

    } else if (
        _emitCoreDecls || _emitCoreInits || _emitClassDecls || _emitClassInits
    ) {
	ok = ok && CodeView::Definition(out);
        
    } else if (_emitMain) {
	ok = ok && CodeView::Definition(out);
        
    }

    return out.good() && ok;
}
Пример #5
0
boolean TextEditCode::ConstDecls(ostream& out) {
    out << "(const char*, int r, int c, int t, int h);\n";
    return out.good();
}
Пример #6
0
int FixedLengthBuffer::write(ostream& stream) const{
		int recAddr = stream.tellp();
		stream.write(this->buffer, this->bufferSize);
		if(!stream.good()) return -1;
		return recAddr;
}
Пример #7
0
boolean ScrollerCode::ConstDecls(ostream& out) {
    out << "(const char*, Interactor* i);\n";
    return out.good();
}
Пример #8
0
boolean ScrollerCode::Definition (ostream& out) {
    boolean ok = true;
    if (
	_emitProperty || _emitInstanceDecls || 
        _emitForward || _emitClassHeaders || _emitHeaders
    ) {
        return CodeView::Definition(out);

    } else if (_emitExpHeader) {
	InteractorComp* icomp = GetIntComp();
	MemberNameVar* mnamer = icomp->GetMemberNameVar();
        SubclassNameVar* snamer = icomp->GetClassNameVar();
        if (!snamer->IsSubclass()) {
            if (
                _scope && mnamer->GetExport() && !_namelist->Search("scroller")
            ) {
                _namelist->Append("scroller");
                out << "#include <InterViews/scroller.h>\n";
            }
        } else {
            ok = ok && CodeView::Definition(out);
        }

    } else if (_emitCorehHeader) {
	InteractorComp* icomp = GetIntComp();
        SubclassNameVar* snamer = icomp->GetClassNameVar();
        const char* subclass = snamer->GetName();
        if (snamer->IsSubclass() && strcmp(subclass, _classname) == 0) {
            if (!_namelist->Search("scroller")) {
                _namelist->Append("scroller");
                out << "#include <InterViews/scroller.h>\n";
            }
        }
    } else if (_emitInstanceInits) {
        InteractorComp* icomp = GetIntComp();
        InteractorComp* ctarget = nil;
        const char* mname = icomp->GetMemberNameVar()->GetName();
	MemberNameVar* mnamer = (MemberNameVar*) icomp->GetState(
	    "AdjusteeVar"
	);
        const char* scrollee = mnamer->GetName();

	if (*scrollee == '\0') {
            if (_err_count < 10) {
                strcat(_errbuf, mname);
                strcat(_errbuf, " has undefined scrolling target.\n");
                _err_count++;
            } 
	    return false;

        } else if (!Search(mnamer, ctarget)) {
            if (_err_count < 10) {
                strcat(_errbuf, mname);
                strcat(
                    _errbuf, "'s scrolling target is not in the same hierarchy.\n"
                );
                _err_count++;
            } 
	    return false;

        } else if (ctarget != nil && !icomp->IsRelatableTo(ctarget)) {
            if (_err_count < 10) {
                strcat(_errbuf, mname);
                strcat(
                    _errbuf, 
                    "'s adjusting target is not subclassed nor adjustable.\n"
                );
                _err_count++;
            }
	    return false;
        }
	if (_instancelist->Find((void*) scrollee)) {
            if (!_instancelist->Find((void*) mname)) {
                _instancelist->Append(new UList((void*)mname));

        	scrollee = (*scrollee == '\0') ? "nil" : scrollee;

        	BeginInstantiate(out);
        	out << "(";
        	InstanceName(out);
        	out << scrollee << ")";
        	EndInstantiate(out);
		_icomplete = true;
            }
	} else {
	    _icomplete = false;
	}

    } else if (
	_emitBSDecls || _emitBSInits || 
	_emitFunctionDecls || _emitFunctionInits
    ) {
        return true;

    } else if (
        _emitCoreDecls || _emitCoreInits || _emitClassDecls || _emitClassInits
    ) {
	ok = ok && CodeView::Definition(out);
        
    } else if (_emitMain) {
	ok = ok && CodeView::Definition(out);
        
    }
    return out.good() && ok;
}