virtual int svc () { //int i =0; ACE_Message_Block *mblk; int len = 0; while(!fin.eof()) { fin.getline(file_buf, LineSize); len = ACE_OS::strlen( file_buf ); ACE_NEW_RETURN (mblk, ACE_Message_Block (len+200), 0); if (file_buf[len-1] == '\r') { len = len - 1; } mblk->copy (file_buf, len+1 ); // 通过put_next函数,将消息传递给下一个过滤器 put_next (mblk); } ACE_NEW_RETURN(mblk, ACE_Message_Block (0, ACE_Message_Block::MB_STOP), 0); put_next (mblk); fin.close(); ACE_DEBUG ((LM_DEBUG, "read svc return .\n")); return 0; }
virtual int put (ACE_Message_Block *mblk, ACE_Time_Value *) { if (mblk->msg_type () != ACE_Message_Block::MB_STOP) { size_t fmt_len (ACE_OS::sprintf (mblk->wr_ptr ()-1, "%s", "attention please!\r\n" )); mblk->wr_ptr (fmt_len); } //ACE_DEBUG ((LM_DEBUG, "suffix:%@.%s\n",mblk,mblk->base())); return put_next (mblk); }
virtual int put (ACE_Message_Block *mblk, ACE_Time_Value *) { for (ACE_Message_Block *temp = mblk; temp != 0; temp = temp->cont ()) { if (temp->msg_type () != ACE_Message_Block::MB_STOP) { format_data(temp); } } return put_next (mblk); }
virtual int svc () { int stop = 0; for (ACE_Message_Block *mb; !stop && getq (mb) != -1; ) { if (mb->msg_type () == ACE_Message_Block::MB_STOP) { stop = 1; } else { ACE_DEBUG ((LM_DEBUG, "%s",mb->base())); } put_next (mb); } return 0; }
void RPG_Net_Protocol_Module_IRCSplitter::handleDataMessage(RPG_Net_Protocol_Message*& message_inout, bool& passMessageDownstream_out) { RPG_TRACE(ACE_TEXT("RPG_Net_Protocol_Module_IRCSplitter::handleDataMessage")); // init return value(s), default behavior is to pass all messages along... // --> we don't want that ! passMessageDownstream_out = false; // sanity check(s) ACE_ASSERT(message_inout); ACE_ASSERT(myIsInitialized); // perhaps we already have part of this message ? if (myCurrentBuffer) myCurrentBuffer->cont(message_inout); // chain the buffer myCurrentBuffer = message_inout; // scan the bytestream for frame bounds "\r\n" // do we know where to start ? if (myCurrentMessage == NULL) myCurrentMessage = myCurrentBuffer; // start scanning at offset 0... // *NOTE*: the scanner checks sequences of >= 2 bytes (.*\r\n) // --> make sure we have a minimum amount of data... // --> more sanity check(s) if (myCurrentMessage->total_length() < RPG_NET_PROTOCOL_IRC_FRAME_BOUNDARY_SIZE) return; // don't have enough data, cannot proceed if (myCurrentBuffer->length() < RPG_NET_PROTOCOL_IRC_FRAME_BOUNDARY_SIZE) { // *sigh*: OK, so this CAN actually happen... // case1: if we have anything OTHER than '\n', there's nothing to do // --> wait for more data // case2: if we have an '\n' we have to check the trailing character // of the PRECEDING buffer: // - if it's an '\r' --> voilà, we've found a frame boundary // - else --> wait for more data if (((*myCurrentBuffer->rd_ptr()) == '\n') && (myCurrentMessage != myCurrentBuffer)) { ACE_Message_Block* preceding_buffer = myCurrentMessage; for (; preceding_buffer->cont() != myCurrentBuffer; preceding_buffer = preceding_buffer->cont()); if (*(preceding_buffer->rd_ptr() + (preceding_buffer->length() - 1)) == '\r') { // OK, we have all of it ! if (myCrunchMessages) { myCurrentMessage->crunch(); } // end IF // --> push it downstream... if (put_next(myCurrentMessage, NULL) == -1) { ACE_DEBUG((LM_ERROR, ACE_TEXT("failed to ACE_Task::put_next(): \"%m\", continuing\n"))); // clean up myCurrentMessage->release(); } // end IF // bye bye... myCurrentMessageLength = 0; myCurrentMessage = NULL; myCurrentBuffer = NULL; return; } // end IF } // end IF return; // don't have enough data, cannot proceed } // end IF // OK, init scanner... // *WARNING*: cannot use yy_scan_buffer(), as flex modifies the data... :-( // // *NOTE*: in order to accomodate flex, the buffer needs two trailing // // '\0' characters... // // --> make sure it has this capacity // if (myCurrentBuffer->space() < RPG_NET_PROTOCOL_FLEX_BUFFER_BOUNDARY_SIZE) // { // // *sigh*: (try to) resize it then... // if (myCurrentBuffer->size(myCurrentBuffer->size() + RPG_NET_PROTOCOL_FLEX_BUFFER_BOUNDARY_SIZE)) // { // ACE_DEBUG((LM_ERROR, // ACE_TEXT("failed to ACE_Message_Block::size(%u), aborting\n"), // (myCurrentBuffer->size() + RPG_NET_PROTOCOL_FLEX_BUFFER_BOUNDARY_SIZE))); // // // what else can we do ? // return; // } // end IF // myCurrentBufferIsResized = true; // // // *WARNING*: beyond this point, make sure we resize the buffer back // // to its original length... // // *NOTE*: this is safe, as realloc() just crops the trailing bytes again... // } // end IF // // for (int i = 0; // // i < RPG_NET_PROTOCOL_FLEX_BUFFER_BOUNDARY_SIZE; // // i++) // // *(myCurrentBuffer->wr_ptr() + i) = YY_END_OF_BUFFER_CHAR; // *(myCurrentBuffer->wr_ptr()) = '\0'; // *(myCurrentBuffer->wr_ptr() + 1) = '\0'; // // if (!scan_begin(myCurrentBuffer->rd_ptr(), // myCurrentBuffer->length() + RPG_NET_PROTOCOL_FLEX_BUFFER_BOUNDARY_SIZE)) if (!scan_begin(myCurrentBuffer->rd_ptr(), myCurrentBuffer->length())) { ACE_DEBUG((LM_ERROR, ACE_TEXT("failed to scan_begin(%@, %u), aborting\n"), myCurrentBuffer->rd_ptr(), myCurrentBuffer->length())); // // clean up // if (myCurrentBufferIsResized) // { // if (myCurrentBuffer->size(myCurrentBuffer->size() - RPG_NET_PROTOCOL_FLEX_BUFFER_BOUNDARY_SIZE)) // ACE_DEBUG((LM_ERROR, // ACE_TEXT("failed to ACE_Message_Block::size(%u), continuing\n"), // (myCurrentBuffer->size() - RPG_NET_PROTOCOL_FLEX_BUFFER_BOUNDARY_SIZE))); // myCurrentBufferIsResized = false; // } // end IF // what else can we do ? return; } // end IF // // debug info // ACE_DEBUG((LM_DEBUG, // ACE_TEXT("[%u]: scanning %u byte(s)\n\"%s\"\n"), // myCurrentBuffer->getID(), // myCurrentBuffer->length(), // std::string(myCurrentBuffer->rd_ptr(), myCurrentBuffer->length()).c_str())); // scan it ! myCurrentNumFrames = 0; bool finished_scanning = false; int scanned_bytes = 0; int scanned_chunk = 0; // while (myCurrentMessageLength = myScanner.yylex()) do { scanned_chunk = RPG_Net_Protocol_IRCBisect_lex(myScannerContext); // scanned_chunk = IRCBisectlex(myScannerContext); switch (scanned_chunk) { case 0: { // --> finished scanning this buffer finished_scanning = true; // no (more) frame boundaries found // remember how much data was scanned so far... myCurrentMessageLength += scanned_bytes; break; } case -1: { // found a frame border scanned_bytes bytes into the buffer // *NOTE*: if scanned_bytes == 0, then it's the corner // case where the current buffer starts with either: // - a '\n' // - a "\r\n" // *NOTE*: in EITHER case, a new frame has been found... if ((scanned_bytes == 0) && (*myCurrentBuffer->rd_ptr() == '\n')) { scanned_bytes = 1; myCurrentMessageLength += RPG_NET_PROTOCOL_IRC_FRAME_BOUNDARY_SIZE; } // end IF else { scanned_bytes += RPG_NET_PROTOCOL_IRC_FRAME_BOUNDARY_SIZE; myCurrentMessageLength += scanned_bytes; } // end IF // ACE_DEBUG((LM_DEBUG, // ACE_TEXT("buffer (ID: %u, length: %u): frame boundary [#%u] @ offset %u\n\"%s\"\n"), // myCurrentBuffer->getID(), // myCurrentMessageLength, // myCurrentNumFrames, // (scanned_bytes + (myCurrentBuffer->rd_ptr() - myCurrentBuffer->base())), // std::string(myCurrentBuffer->rd_ptr(), scanned_bytes).c_str())); RPG_Net_Protocol_Message* message = myCurrentMessage; if (myCurrentMessageLength < myCurrentMessage->total_length()) { // more data to scan... // *NOTE*: copy ctor shallow-copies the current data block myCurrentMessage = dynamic_cast<RPG_Net_Protocol_Message*>(myCurrentBuffer->duplicate()); ACE_ASSERT(myCurrentMessage); // adjust wr_ptr (point to one-past-the-end of the current message) myCurrentBuffer->wr_ptr(myCurrentBuffer->rd_ptr() + scanned_bytes); ACE_ASSERT(myCurrentMessageLength == message->total_length()); // adjust rd_ptr (point to the beginning of the next message) myCurrentMessage->rd_ptr(scanned_bytes); } // end IF else { // NO more data to scan... ACE_ASSERT(myCurrentMessageLength == myCurrentMessage->total_length()); // set new message head myCurrentMessage = NULL; } // end ELSE if (myCrunchMessages) { message->crunch(); } // end IF // ACE_DEBUG((LM_DEBUG, // ACE_TEXT("processing message (ID: %u - %u byte(s))...\n"), // message->getID(), // message->total_length())); // --> push it downstream... if (put_next(message, NULL) == -1) { ACE_DEBUG((LM_ERROR, ACE_TEXT("failed to ACE_Task::put_next(): \"%m\", continuing\n"))); // clean up message->release(); } // end IF // set new current buffer myCurrentBuffer = myCurrentMessage; // reset state myCurrentMessageLength = 0; scanned_bytes = 0; // ...continue scanning ! break; } default: { // scanned one/some character(s)... scanned_bytes += scanned_chunk; break; } } // end SWITCH } while (!finished_scanning); // clean up scan_end(); // // *NOTE*: that even if we've sent some frames downstream in the meantime, // // we're still referencing the same buffer we resized earlier - it's always // // the new "head" message... // if (myCurrentBufferIsResized) // { // if (myCurrentBuffer->size(myCurrentBuffer->size() - RPG_NET_PROTOCOL_FLEX_BUFFER_BOUNDARY_SIZE)) // ACE_DEBUG((LM_ERROR, // ACE_TEXT("failed to ACE_Message_Block::size(%u), continuing\n"), // (myCurrentBuffer->size() - RPG_NET_PROTOCOL_FLEX_BUFFER_BOUNDARY_SIZE))); // myCurrentBufferIsResized = false; // } // end IF // ACE_DEBUG((LM_DEBUG, // ACE_TEXT("found %u frame bound(s)...\n"), // myCurrentNumFrames)); }
virtual int svc () { const size_t FileReadSize = 8 * 1024; ACE_Message_Block mblk (FileReadSize); for (;; mblk.crunch ()) { // Read as much as will fit in the message block. ssize_t bytes_read = logfile_.recv (mblk.wr_ptr (), mblk.space ()); if (bytes_read <= 0) break; mblk.wr_ptr (static_cast<size_t> (bytes_read)); // We have a bunch of data from the log file. The data is // arranged like so: // hostname\0 // CDR-encoded log record // So, first we scan for the end of the host name, then // initialize another ACE_Message_Block aligned for CDR // demarshaling and copy the remainder of the block into it. We // can't use duplicate() because we need to be sure the data // pointer is aligned properly for CDR demarshaling. If at any // point, there's not enough data left in the message block to // extract what's needed, crunch the block to move all remaining // data to the beginning and read more from the file. for (;;) { size_t name_len = ACE_OS::strnlen (mblk.rd_ptr (), mblk.length ()); if (name_len == mblk.length ()) break; char *name_p = mblk.rd_ptr (); ACE_Message_Block *rec, *head, *temp; ACE_NEW_RETURN (head, ACE_Message_Block (name_len, MB_CLIENT), 0); head->copy (name_p, name_len); mblk.rd_ptr (name_len + 1); // Skip nul also size_t need = mblk.length () + ACE_CDR::MAX_ALIGNMENT; ACE_NEW_RETURN (rec, ACE_Message_Block (need), 0); ACE_CDR::mb_align (rec); rec->copy (mblk.rd_ptr (), mblk.length ()); // Now rec contains the remaining data we've read so far from // the file. Create an ACE_InputCDR to start demarshaling the // log record, header first to find the length, then the data. // Since the ACE_InputCDR constructor increases the reference count // on rec, we release it upon return to prevent leaks. // The cdr 'read' methods return 0 on failure, 1 on success. ACE_InputCDR cdr (rec); rec->release (); ACE_CDR::Boolean byte_order; if (!cdr.read_boolean (byte_order)) { head->release (); rec->release (); break; } cdr.reset_byte_order (byte_order); // Now read the length of the record. From there, we'll know // if rec contains the complete record or not. ACE_CDR::ULong length; if (!cdr.read_ulong (length)) { head->release (); mblk.rd_ptr (name_p); break; } if (length > cdr.length ()) { head->release (); mblk.rd_ptr (name_p); break; } // The complete record is in rec... grab all the fields into // separate, chained message blocks. ACE_NEW_RETURN (temp, ACE_Message_Block (length, MB_TEXT), 0); ACE_NEW_RETURN (temp, ACE_Message_Block (2 * sizeof (ACE_CDR::Long), MB_TIME, temp), 0); ACE_NEW_RETURN (temp, ACE_Message_Block (sizeof (ACE_CDR::Long), MB_PID, temp), 0); ACE_NEW_RETURN (temp, ACE_Message_Block (sizeof (ACE_CDR::Long), MB_TYPE, temp), 0); head->cont (temp); // Extract the type ACE_CDR::Long *lp; lp = reinterpret_cast<ACE_CDR::Long*> (temp->wr_ptr ()); cdr >> *lp; temp->wr_ptr (sizeof (ACE_CDR::Long)); temp = temp->cont (); // Extract the pid lp = reinterpret_cast<ACE_CDR::Long*> (temp->wr_ptr ()); cdr >> *lp; temp->wr_ptr (sizeof (ACE_CDR::Long)); temp = temp->cont (); // Extract the timestamp (2 Longs) lp = reinterpret_cast<ACE_CDR::Long*> (temp->wr_ptr ()); cdr >> *lp; ++lp; cdr >> *lp; temp->wr_ptr (2 * sizeof (ACE_CDR::Long)); temp = temp->cont (); // Demarshal the length of the message text, then demarshal // the text into the block. ACE_CDR::ULong text_len; cdr >> text_len; cdr.read_char_array (temp->wr_ptr (), text_len); temp->wr_ptr (text_len); // Forward the whole lot to the next module. if (put_next (head) == -1) break; // Move the file-content block's read pointer up past whatever // was just processed. Although the mblk's rd_ptr has not been // moved, cdr's has. Therefore, use its length() to determine // how much is left. mblk.rd_ptr (mblk.length () - cdr.length ()); } } // Now that the file is done, send a block down the stream to tell // the other modules to stop. ACE_Message_Block *stop; ACE_NEW_RETURN (stop, ACE_Message_Block (0, ACE_Message_Block::MB_STOP), 0); put_next (stop); return 0; }
int Task::svc (void) { // This is the function that our service threads run once they are spawned. ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::svc () -- once per servicing thread\n", d_nameOfTask)); // First, we wait until all of our peer service threads have arrived // at this point also. d_barrier.wait (); ACE_Message_Block *messageBlock; while (1) { // And now we loop almost infinitely. // getq () will block until a Message_Block is available to be read, // or an error occurs. if ( this->getq (messageBlock, 0) == -1) { ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Task::svc () getq"), -1); } if (messageBlock->msg_type () == ACE_Message_Block::MB_HANGUP) { // If the Message_Block is of type MB_HANGUP, then we're being asked // to shut down nicely. ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::svc () -- HANGUP block received\n", d_nameOfTask)); // So, we duplicate the Block, and put it back into the Message_Queue, // in case there are some more peer service threads still running. if (this->putq (messageBlock->duplicate ()) == -1) { ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Task::svc () putq"), -1); } // We release our copy of the Block. messageBlock->release (); // And we break out of the nearly infinitely loop, and // head towards close () ourselves. break; } // If we're here, then we've received a Message_Block that was // not informing us to quit, so we're assuming it's a valid // meaningful Block. ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::svc () -- Normal block received\n", d_nameOfTask)); // We grab the read-pointer from the Block, and display it through a DEBUG statement. ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::svc () -- %s\n", d_nameOfTask, messageBlock->rd_ptr () )); // We pretend that this takes to time to process the Block. // If you're on a fast machine, you might have to raise this // value to actually witness different threads handling // blocks for each Task. ACE_OS::sleep (ACE_Time_Value (0, 250)); // Since we're part of a Stream, we duplicate the Block, and // send it on to the next Task. if (put_next (messageBlock->duplicate ()) == -1) { ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Task::svc () put_next"), -1); } // And then we release our copy of it. messageBlock->release (); } return 0; }