![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /******************************************************************************* 00002 * This file is part of openWNS (open Wireless Network Simulator) 00003 * _____________________________________________________________________________ 00004 * 00005 * Copyright (C) 2004-2007 00006 * Chair of Communication Networks (ComNets) 00007 * Kopernikusstr. 5, D-52074 Aachen, Germany 00008 * phone: ++49-241-80-27910, 00009 * fax: ++49-241-80-22242 00010 * email: info@openwns.org 00011 * www: http://www.openwns.org 00012 * _____________________________________________________________________________ 00013 * 00014 * openWNS is free software; you can redistribute it and/or modify it under the 00015 * terms of the GNU Lesser General Public License version 2 as published by the 00016 * Free Software Foundation; 00017 * 00018 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00019 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00020 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00021 * details. 00022 * 00023 * You should have received a copy of the GNU Lesser General Public License 00024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00025 * 00026 ******************************************************************************/ 00027 00028 #include <WNS/scheduler/queue/detail/InnerQueue.hpp> 00029 00030 #include <WNS/scheduler/queue/ISegmentationCommand.hpp> 00031 #include <WNS/ldk/CommandTypeSpecifier.hpp> 00032 00033 #include <WNS/simulator/ISimulator.hpp> 00034 #include <WNS/ldk/probe/TickTack.hpp> 00035 00036 00037 using namespace wns::scheduler::queue::detail; 00038 00039 InnerQueue::InnerQueue(): 00040 nettoBits_(0), 00041 sequenceNumber_(0), 00042 frontSegmentSentBits_(0) 00043 { 00044 } 00045 00046 Bit 00047 InnerQueue::queuedNettoBits() const 00048 { 00049 return nettoBits_; 00050 } 00051 00052 Bit 00053 InnerQueue::queuedBruttoBits(Bit fixedHeaderSize, Bit extensionHeaderSize, bool byteAlignHeader) const 00054 { 00055 if (queuedNettoBits() == 0) 00056 { 00057 return 0; 00058 } 00059 else 00060 { 00061 Bit headerSize = fixedHeaderSize + (pduQueue_.size() - 1) * extensionHeaderSize; 00062 if (byteAlignHeader) 00063 { 00064 headerSize += headerSize % 8; 00065 } 00066 return headerSize + queuedNettoBits(); 00067 } 00068 } 00069 00070 int 00071 InnerQueue::queuedCompounds() const 00072 { 00073 return pduQueue_.size(); 00074 } 00075 00076 bool 00077 InnerQueue::empty() const 00078 { 00079 return pduQueue_.empty(); 00080 } 00081 00082 void 00083 InnerQueue::put(const wns::ldk::CompoundPtr& compound) 00084 { 00085 pduQueue_.push(compound); 00086 00087 nettoBits_ += compound->getLengthInBits(); 00088 } 00089 00090 wns::ldk::CompoundPtr 00091 InnerQueue::retrieve(Bit requestedBits, Bit fixedHeaderSize, Bit extensionHeaderSize, 00092 bool usePadding, bool byteAlignHeader, wns::ldk::CommandReaderInterface* reader, 00093 const wns::probe::bus::ContextCollectorPtr& probeCC, 00094 wns::ldk::CommandReaderInterface* probeCmdReader) 00095 { 00096 if (requestedBits <= fixedHeaderSize) 00097 { 00098 throw RequestBelowMinimumSize(requestedBits, fixedHeaderSize); 00099 } 00100 00101 if (pduQueue_.size() <= 0) 00102 { 00103 throw RetrieveException("Queue is empty"); 00104 } 00105 00106 wns::ldk::CompoundPtr pdu(pduQueue_.front()->copy()); 00107 00108 assure(reader != NULL, "No valid segmentHeaderReader given!"); 00109 00110 reader->activateCommand(pdu->getCommandPool()); 00111 00112 ISegmentationCommand* header = reader->readCommand<ISegmentationCommand>(pdu->getCommandPool()); 00113 00114 header->increaseHeaderSize(fixedHeaderSize); 00115 00116 header->setSequenceNumber(sequenceNumber_); 00117 sequenceNumber_ += 1; 00118 00119 (frontSegmentSentBits_ == 0) ? header->setBeginFlag():header->clearBeginFlag(); 00120 00121 while (header->totalSize() < requestedBits) 00122 { 00123 wns::ldk::CompoundPtr c = pduQueue_.front(); 00124 Bit length = c->getLengthInBits() - frontSegmentSentBits_; // netto 00125 Bit capacity = requestedBits - header->totalSize(); // netto 00126 if (capacity >= length) 00127 { 00128 // fits in completely 00129 header->addSDU(c->copy()); 00130 header->increaseDataSize(length); 00131 probe(c, probeCC, probeCmdReader); 00132 pduQueue_.pop(); 00133 frontSegmentSentBits_ = 0; 00134 nettoBits_ -= length; 00135 00136 Bit headerPadding = 0; 00137 if ( byteAlignHeader ) 00138 { 00139 headerPadding = (header->headerSize() + extensionHeaderSize) % 8; 00140 } 00141 00142 if ( (header->totalSize() + extensionHeaderSize + headerPadding < requestedBits) && 00143 (pduQueue_.size() > 0)) 00144 { 00145 header->increaseHeaderSize(extensionHeaderSize); 00146 } 00147 else 00148 { 00149 break; 00150 } 00151 } 00152 else 00153 { 00154 Bit headerPadding = 0; 00155 if ( byteAlignHeader ) 00156 { 00157 headerPadding = header->headerSize() % 8; 00158 } 00159 // only a fraction fits in 00160 header->addSDU(c->copy()); 00161 header->increaseDataSize(capacity - headerPadding); 00162 header->increaseHeaderSize(headerPadding); 00163 frontSegmentSentBits_ += capacity - headerPadding; 00164 nettoBits_ -= capacity - headerPadding; 00165 assure(frontSegmentSentBits_ < pduQueue_.front()->getLengthInBits(), "frontSegmentSentBits_ is larger than the front PDU size!"); 00166 } 00167 } 00168 00169 // remaining bits: 00170 if (pduQueue_.size()==0) 00171 { 00172 nettoBits_ = 0; 00173 } 00174 00175 // Is the last segment in the PDU a fragment? Then clear end flag 00176 (frontSegmentSentBits_ == 0) ? header->setEndFlag():header->clearEndFlag(); 00177 00178 if (byteAlignHeader) 00179 { 00180 header->increaseHeaderSize(header->headerSize() % 8); 00181 } 00182 00183 // Rest is padding (optional) 00184 if (usePadding) { 00185 header->increasePaddingSize(requestedBits - header->totalSize()); 00186 } 00187 00188 assure(header->totalSize()<=requestedBits,"pdulength="<<header->totalSize()<<" > bits="<<requestedBits); 00189 return pdu; 00190 } 00191 00192 std::queue<wns::ldk::CompoundPtr> 00193 InnerQueue::getQueueCopy() 00194 { 00195 return pduQueue_; 00196 } 00197 00198 void 00199 InnerQueue::probe(const wns::ldk::CompoundPtr& compound, 00200 const wns::probe::bus::ContextCollectorPtr& probeCC, 00201 wns::ldk::CommandReaderInterface* cmdReader) 00202 { 00203 assure(compound != wns::ldk::CompoundPtr(), "No valid compound"); 00204 00205 if(cmdReader == NULL || 00206 probeCC == wns::probe::bus::ContextCollectorPtr()) 00207 return; 00208 00209 wns::ldk::probe::TickTackCommand* cmd; 00210 cmd = cmdReader->readCommand<wns::ldk::probe::TickTackCommand>(compound->getCommandPool()); 00211 assure(cmd != NULL, "Cannot get TickTackCommand to probe delay"); 00212 00213 wns::simulator::Time now = wns::simulator::getEventScheduler()->getTime(); 00214 probeCC->put(compound, now - cmd->magic.tickTime); 00215 } 00216 00217
1.5.5