WebM is a digital multimedia container file format promoted by the open-source WebM Project. It comprises a subset of the Matroska multimedia container format.
Note: This document does not yet make reference to VP9-related conditions. It will be updated once implementation details are settled.
| Container Format Name | WebM |
| Filename Extension | .webm |
| MIME-type | video/webm |
| Audio-only MIME-type | audio/webm |
| Video Codec Name | VP8 |
| Audio Codec Name | Vorbis |
canPlayType('video/webm')
SHOULD return maybecanPlayType('audio/webm')
SHOULD return maybecanPlayType('video/webm; codecs="vp8, vorbis"')
SHOULD return
probablycanPlayType('video/webm; codecs="vp8.0, vorbis"')
SHOULD return
probablycanPlayType('audio/webm; codecs="vorbis"')
SHOULD return
probablyOne of the major goals is to allow content creators to have advanced playback capabilities, such as fast seeking and fast start using only an HTTP server. To achieve this, the WebM file format guidelines below should be followed when creating content.
These guidelines are currently for file streaming over an HTTP connection, and indicate the areas where WebM is strict, relative to the more permissive Matroska specification.
DocType
element SHOULD be “webm”.CodecPrivate
data for VP8.<video>
in the near future. WebM intends
to follow that guidance. Ref:
WebVTT.DocReadTypeVersion
SHOULD follow the Matroska specification.DocReadTypeVersion
of 2.Muxers should treat all guidelines marked SHOULD in this section as MUST. This will foster consistency across WebM files in the real world.
SeekHead
element.Cues
element.Cues
element.Cues
element SHOULD contain only video key frames, to
decrease the size of the file header.Cues
element be before any
clusters, so that the client can seek to a point in the data
that has not yet been downloaded in a single seek operation.
Ref: a tool
that will put the Cues
at the front.TimecodeScale
element SHOULD be set to a default of
1.000.000 nanoseconds.DisplayUnit
element.SimpleBlock
element.When enabled, the VP8 encoder will at its discretion inject a new frame — the alternate reference (AR) — into the output prior to the frame that depends on it. There will be at MOST 1 frame added between I/P-frames. The dependent frame (D) will always be a P-frame. The AR will be marked with the invisible flag by the codec SDK. This frame MUST be decoded before D, but will produce no output on its own.
The encoder will currently set the AR’s timestamp as close as possible to the previous frame while attempting to provide a timestamp that is strictly increasing. In cases where the time base given to the encoder at configure time is not granular enough to allow for this the AR will share the same timestamp as D, but SHOULD be treated as having no duration.
Ideally the AR’s timestamp should be as close as possible to frame D-1 to allow the decoder as much time as possible to decode AR before needing to display D.
| Input | F0 | F1 | |
| Output | I/P | AR | D |
| PTS | 0 | 1 | 2 |
| Input | I/P | AR | D |
| Output | F0 | F1 | |
| PTS | 0 | 2 |
Cues
element.Cues
element.Cues
element is not at the beginning of the file its
retrival should be deferred to allow playback to start as soon as
possible.The contents of the WebVTT file is stored as its own WebM track. The information that would appear as attributes of the HTML5 track tag can be embedded in WebM Track element as follows:
The TrackType sub-element value is 0x11 for WebVTT SUBTITLES and CAPTIONS, and 0x21 for WebVTT DESCRIPTIONS, and METADATA.
The label attribute is stored as the Name sub-element.
The srclang attribute is stored as the Language sub-element.
Per the convention (see the Matroska Codec Specifications) used for flavors of a particular video or audio codec, the CodecID for a WebVTT track is “D_WEBVTT/kind“, where kind is one of SUBTITLES, CAPTIONS, DESCRIPTIONS, or METADATA.
The WebVTT cues are stored as the data portion of Block elements in the track, per the formatting described below. All WebVTT data stored within a WebM Block MUST be encoded as UTF-8. The timestamp of the WebM block and its duration are synthesized from the start and end times specified on the timestamp of the WebVTT cue. A BlockGroup element (not a SimpleBlock) MUST be used to contain the Block element, in order to also use a BlockDuration element, which is necessary to losslessly encode the original timestamp of the WebVTT cue.
If the WebVTT cue includes a WebVTT cue identifier then the WebVTT cue identifier is written to the WebM Block followed by a WebVTT line terminator. If the WebVTT cue does not have a WebVTT cue identifier then a WebVTT line terminator is written to the WebM Block. The empty line is used to distinguish that there was no WebVTT cue identifier in the original WebVTT cue.
The WebVTT cue timings is not written to the WebM Block. The start and end time of the WebVTT cue is synthesized from the start time and duration of the WebM Block.
If the WebVTT cue includes a WebVTT cue settings then the WebVTT cue settings is written to the WebM Block followed by a WebVTT line terminator. If the WebVTT cue does not have a WebVTT cue settings then a WebVTT line terminator is written to the WebM Block.
The cue payload is then written to the WebM Block.
Note that no WebVTT data is stored in the CodecPrivate element of the WebM Track header. All WebVTT cues are stored as Block elements for the track.
The timestamps for WebVTT cues can overlap in time. This is how roll-up captions work: multiple cues are rendered simultaneously, and when the top cue expires, the other cues move up and a new cue appears at the bottom. The WebM block timestamps must therefore be allowed to be monotonically increasing (a requirement already needed for the WebM container to support VP8 alt-ref frames), and the duration for a block MUST be allowed to overlap the start time of the next block.
WebVTT chapter cues are used for navigation and so they are handled differently, because they must all be together and immediately available. For this reason, WebVTT chapter cues should not be embedded the same as for timed cues (a representation that would vitiate their use for navigation); instead they should be converted to Matroska chapters (see the Matroska Chapter Specifications) and embedded that way. Matroska chapters are a superset of WebVTT chapter cues and therefore the conversion is lossless.
At initial release, WebM supports a subset of the Matroska specification. Support for additional Matroska functionality will be under consideration as the project matures.
Following is a more detailed description of the currently supported elements, and the features still being evaluated.
| Element Name | Description | |
|---|---|---|
| Supported | EBML | Set the EBML characteristics of the data to follow. Each EBML document has to start with this. |
| Supported | EBMLVersion | The version of EBML parser used to create the file. |
| Supported | EBMLReadVersion | The minimum EBML version a parser has to support to read this file. |
| Supported | EBMLMaxIDLength | The maximum length of the IDs you’ll find in this file (4 or less in Matroska). |
| Supported | EBMLMaxSizeLength | The maximum length of the sizes you’ll find in this file (8 or less in Matroska). This does not override the element size indicated at the beginning of an element. Elements that have an indicated size which is larger than what is allowed by EBMLMaxSizeLength shall be considered invalid. |
| Supported | DocType | A string that describes the type of document that follows this EBML header (‘webm’ in our case). |
| Supported | DocTypeVersion | The version of DocType interpreter used to create the file. |
| Supported | DocTypeReadVersion | The minimum DocType version an interpreter has to support to read this file. |
| Element Name | Description | |
|---|---|---|
| Unsupported | CRC-32 | The CRC is computed on all the data of the Master element it’s in, regardless of its position. It’s recommended to put the CRC value at the beggining of the Master element for easier reading. All level 1 elements should include a CRC-32. |
| Supported | Void | Used to void damaged data, to avoid unexpected behaviors when using damaged data. The content is discarded. Also used to reserve space in a sub-element for later use. |
| Signature Start | ||
| Unsupported | SignatureSlot | Contain signature of some (coming) elements in the stream. |
| Unsupported | SignatureAlgo | Signature algorithm used (1=RSA, 2=elliptic). |
| Unsupported | SignatureHash | Hash algorithm used (1=SHA1-160, 2=MD5). |
| Unsupported | SignaturePublicKey | The public key to use with the algorithm (in the case of a PKI-based signature). |
| Unsupported | Signature | The signature of the data (until a new. |
| Unsupported | SignatureElements | Contains elements that will be used to compute the signature. |
| Unsupported | SignatureElementList | A list consists of a number of consecutive elements that represent one case where data is used in signature. Ex: Cluster |
| Unsupported | SignedElement | An element ID whose data will be used to compute the signature. |
| Signature End |
| Element Name | Description | |
|---|---|---|
| Supported | Segment | This element contains all other top-level (level 1) elements. Typically a Matroska file is composed of 1 segment. |
| Element Name | Description | |
|---|---|---|
| Supported | SeekHead | Contains the position of other level 1 elements. |
| Supported | Seek | Contains a single seek entry to an EBML element. |
| Supported | SeekID | The binary ID corresponding to the element name. |
| Supported | SeekPosition | The position of the element in the segment in octets (0 = first level 1 element). |
| Element Name | Description | |
|---|---|---|
| Supported | Info | Contains miscellaneous general information and statistics on the file. |
| Unsupported | SegmentUID | A randomly generated unique ID to identify the current segment between many others (128 bits). |
| Unsupported | SegmentFilename | A filename corresponding to this segment. |
| Unsupported | PrevUID | A unique ID to identify the previous chained segment (128 bits). |
| Unsupported | PrevFilename | An escaped filename corresponding to the previous segment. |
| Unsupported | NextUID | A unique ID to identify the next chained segment (128 bits). |
| Unsupported | NextFilename | An escaped filename corresponding to the next segment. |
| Unsupported | SegmentFamily | A randomly generated unique ID that all segments related to each other MUST use (128 bits). |
| Unsupported | ChapterTranslate | A tuple of corresponding ID used by chapter codecs to represent this segment. |
| Unsupported | ChapterTranslateEditionUID | Specify an edition UID on which this correspondance applies. When not specified, it means for all editions found in the segment. |
| Unsupported | ChapterTranslateCodec | The chapter codec using this ID (0: Matroska Script, 1: DVD-menu). |
| Unsupported | ChapterTranslateID | The binary value used to represent this segment in the chapter codec data. The format depends on the ChapProcessCodecID used. |
| Supported | TimecodeScale | Timecode scale in nanoseconds (1.000.000 means all timecodes in the segment are expressed in milliseconds). |
| Supported | Duration | Duration of the segment (based on TimecodeScale). |
| Supported | DateUTC | Date of the origin of timecode (value 0), i.e. production date. |
| Supported | Title | General name of the segment. |
| Supported | MuxingApp | Muxing application or library (“libmatroska-0.4.3”). |
| Supported | WritingApp | Writing application (“mkvmerge-0.3.3”). |
| Element Name | Description | |
|---|---|---|
| Supported | Cluster | The lower level element containing the (monolithic) Block structure. |
| Supported | Timecode | Absolute timecode of the cluster (based on TimecodeScale). |
| Unsupported | SilentTracks | The list of tracks that are not used in that part of the stream. It is useful when using overlay tracks on seeking. Then you should decide what track to use. |
| Unsupported | SilentTrackNumber | One of the track number that are not used from now on in the stream. It could change later if not specified as silent in a further Cluster. |
| Unsupported | Position | Position of the Cluster in the segment (0 in live broadcast streams). It might help to resynchronise offset on damaged streams. |
| Supported | PrevSize | Size of the previous Cluster, in octets. Can be useful for backward playing. |
| Supported | BlockGroup | Basic container of information containing a single Block or BlockVirtual, and information specific to that Block/VirtualBlock. |
| Supported | Block | Block containing the actual data to be rendered and a timecode relative to the Cluster Timecode. |
| Unsupported | BlockVirtual | A Block with no data. It MUST be stored in the stream at the place the real Block should be in display order. |
| Unsupported | BlockAdditions | Contain additional blocks to complete the main one. An EBML parser that has no knowledge of the Block structure could still see and use/skip these data. |
| Unsupported | BlockMore | Contain the BlockAdditional and some parameters. |
| Unsupported | BlockAddID | An ID to identify the BlockAdditional level. |
| Unsupported | BlockAdditional | Interpreted by the codec as it wishes (using the BlockAddID). |
| Supported | BlockDuration | The duration of the Block (based on TimecodeScale). This element is mandatory when DefaultDuration is set for the track. When not written and with no DefaultDuration, the value is assumed to be the difference between the timecode of this Block and the timecode of the next Block in “display” order (not coding order). This element can be useful at the end of a Track (as there is not other Block available), or when there is a break in a track like for subtitle tracks. |
| Unsupported | ReferencePriority | This frame is referenced and has the specified cache priority. In cache only a frame of the same or higher priority can replace this frame. A value of 0 means the frame is not referenced. |
| Supported | ReferenceBlock | Timecode of another frame used as a reference (ie: B or P frame). The timecode is relative to the block it’s attached to. |
| Unsupported | ReferenceVirtual | Relative position of the data that should be in position of the virtual block. |
| Unsupported | CodecState | The new codec state to use. Data interpretation is private to the codec. This information should always be referenced by a seek entry. |
| Unsupported | Slices | Contains slices description. |
| Unsupported | TimeSlice | Contains extra time information about the data contained in the Block. While there are a few files in the wild with this element, it is no longer in use and has been deprecated. Being able to interpret this element is not required for playback. |
| Supported | LaceNumber | The reverse number of the frame in the lace (0 is the last frame, 1 is the next to last, etc). While there are a few files in the wild with this element, it is no longer in use and has been deprecated. Being able to interpret this element is not required for playback. |
| Unsupported | FrameNumber | The number of the frame to generate from this lace with this delay (allow you to generate many frames from the same Block/Frame). |
| Unsupported | BlockAdditionID | The ID of the BlockAdditional element (0 is the main Block). |
| Unsupported | Delay | The (scaled) delay to apply to the element. |
| Unsupported | Duration | The (scaled) duration to apply to the element. |
| Supported | SimpleBlock | Similar to Block but without all the extra information, mostly used to reduced overhead when no extra feature is needed. |
| Unsupported | EncryptedBlock | Similar to SimpleBlock but the data inside the Block are Transformed (encrypt and/or signed). |
| Element Name | Description | |
|---|---|---|
| Supported | Tracks | A top-level block of information with many tracks described. |
| Supported | TrackEntry | Describes a track with all elements. |
| Supported | TrackNumber | The track number as used in the Block Header (using more than 127 tracks is not encouraged, though the design allows an unlimited number). |
| Supported | TrackUID | A unique ID to identify the Track. This should be kept the same when making a direct stream copy of the Track to another file. |
| Supported | TrackType | A set of track types coded on 8 bits (1: video, 2: audio, 3: complex, 0x10: logo, 0x11: subtitle, 0x12: buttons, 0x20: control). |
| Supported | FlagEnabled | Set if the track is used. |
| Supported | FlagDefault | Set if that track (audio, video or subs) SHOULD be used if no language found matches the user preference. |
| Supported | FlagForced | Set if that track MUST be used during playback. There can be many forced track for a kind (audio, video or subs), the player should select the one which language matches the user preference or the default + forced track. Overlay MAY happen between a forced and non-forced track of the same kind. |
| Supported | FlagLacing | Set if the track may contain blocks using lacing. |
| Unsupported | MinCache | The minimum number of frames a player should be able to cache during playback. If set to 0, the reference pseudo-cache system is not used. |
| Unsupported | MaxCache | The maximum cache size required to store referenced frames in and the current frame. 0 means no cache is needed. |
| Supported | DefaultDuration | Number of nanoseconds (i.e. not scaled) per frame. |
| Unsupported | TrackTimecodeScale | The scale to apply on this track to work at normal speed in relation with other tracks (mostly used to adjust video speed when the audio length differs). |
| Unsupported | TrackOffset | A value to add to the Block’s Timecode. This can be used to adjust the playback offset of a track. |
| Unsupported | MaxBlockAdditionID | The maximum value of BlockAddID. A value 0 means there is no BlockAdditions for this track. |
| Supported | Name | A human-readable track name. |
| Supported | Language | Specifies the language of the track in the Matroska languages form. |
| Supported | CodecID | An ID corresponding to the codec, see the codec page for more info. |
| Supported | CodecPrivate | Private data only known to the codec. |
| Supported | CodecName | A human-readable string specifying the codec. |
| Unsupported | AttachmentLink | The UID of an attachment that is used by this codec. |
| Unsupported | CodecSettings | A string describing the encoding setting used. |
| Unsupported | CodecInfoURL | A URL to find information about the codec used. |
| Unsupported | CodecDownloadURL | A URL to download about the codec used. |
| Unsupported | CodecDecodeAll | The codec can decode potentially damaged data. |
| Unsupported | TrackOverlay | Specify that this track is an overlay track for the Track specified (in the u-integer). That means when this track has a gap (see SilentTracks) the overlay track should be used instead. The order of multiple TrackOverlay matters, the first one is the one that should be used. If not found it should be the second, etc. |
| Unsupported | TrackTranslate | The track identification for the given Chapter Codec. |
| Unsupported | TrackTranslateEditionUID | Specify an edition UID on which this translation applies. When not specified, it means for all editions found in the segment. |
| Unsupported | TrackTranslateCodec | The chapter codec using this ID (0: Matroska Script, 1: DVD-menu). |
| Unsupported | TrackTranslateTrackID | The binary value used to represent this track in the chapter codec data. The format depends on the ChapProcessCodecID used. |
| Video Start | ||
| Supported | Video | Video settings. |
| Supported | FlagInterlaced | Set if the video is interlaced. |
| Supported | StereoMode | Stereo-3D video mode. Supported Modes: 0: mono, 1: side by side (left eye is first), 2: top-bottom (right eye is first), 3: top-bottom (left eye is first), 11: side by side (right eye is first) Unsupported Modes: 4: checkboard (right is first), 5: checkboard (left is first), 6: row interleaved (right is first), 7: row interleaved (left is first), 8: column interleaved (right is first), 9: column interleaved (left is first), 10: anaglyph (cyan/red) |
| Supported | PixelWidth | Width of the encoded video frames in pixels. |
| Supported | PixelHeight | Height of the encoded video frames in pixels. |
| Supported | PixelCropBottom | The number of video pixels to remove at the bottom of the image (for HDTV content). |
| Supported | PixelCropTop | The number of video pixels to remove at the top of the image. |
| Supported | PixelCropLeft | The number of video pixels to remove on the left of the image. |
| Supported | PixelCropRight | The number of video pixels to remove on the right of the image. |
| Supported | DisplayWidth | Width of the video frames to display. |
| Supported | DisplayHeight | Height of the video frames to display. |
| Supported | DisplayUnit | Type of the unit for DisplayWidth/Height (0: pixels, 1: centimeters, 2: inches). Pixels only supported. |
| Supported | AspectRatioType | Specify the possible modifications to the aspect ratio (0: free resizing, 1: keep aspect ratio, 2: fixed). |
| Unsupported | ColourSpace | Same value as in AVI (32 bits). |
| Unsupported | GammaValue | Gamma Value. |
| Supported | FrameRate | Number of frames per second. Informational only. |
| Video End | ||
| Audio Start | ||
| Supported | Audio | Audio settings. |
| Supported | SamplingFrequency | Sampling frequency in Hz. |
| Supported | OutputSamplingFrequency | Real output sampling frequency in Hz (used for SBR techniques). |
| Supported | Channels | Numbers of channels in the track. |
| Unsupported | ChannelPositions | Table of horizontal angles for each successive channel, see appendix. |
| Supported | BitDepth | Bits per sample, mostly used for PCM. |
| Audio End | ||
| Content Encoding Start | ||
| Unsupported | ContentEncodings | Settings for several content encoding mechanisms like compression or encryption. |
| Unsupported | ContentEncoding | Settings for one content encoding like compression or encryption. |
| Unsupported | ContentEncodingOrder | Tells when this modification was used during encoding/muxing starting with 0 and counting upwards. The decoder/demuxer has to start with the highest order number it finds and work its way down. This value has to be unique over all ContentEncodingOrder elements in the segment. |
| Unsupported | ContentEncodingScope | A bit field that describes which elements have been modified in this way. Values (big endian) can be OR’ed. Possible values: 1 - all frame contents; 2 - the track’s private data; 4 - the next ContentEncoding (next ContentEncodingOrder. Either the data inside ContentCompression and/or ContentEncryption) |
| Unsupported | ContentEncodingType | A value describing what kind of transformation has been done. Possible values: 0 - compression; 1 - encryption. |
| Unsupported | ContentCompression | Settings describing the compression used. Must be present if the value of ContentEncodingType is 0 and absent otherwise. Each block MUST be decompressable even if no previous block is available in order not to prevent seeking. |
| Unsupported | ContentCompAlgo | The compression algorithm used. Algorithms that have been specified so far are: 0 - zlib; 1 - bzlib; 2 - lzo1x; 3 - Header Stripping. |
| Unsupported | ContentCompSettings | Settings that might be needed by the decompressor. For Header Stripping (ContentCompAlgo=3), the bytes that were removed from the beggining of each frame of the track. |
| Unsupported | ContentEncryption | Settings describing the encryption used. Must be present if the value of ContentEncodingType is 1 and absent otherwise. |
| Unsupported | ContentEncAlgo | The encryption algorithm used. The value ‘0’ means that the contents have not been encrypted but only signed. Predefined values: 1 - DES; 2 - 3DES; 3 - Twofish; 4 - Blowfish; 5 - AES. |
| Unsupported | ContentEncKeyID | For public key algorithms this is the ID of the public key the the data was encrypted with. |
| Unsupported | ContentSignature | A cryptographic signature of the contents. |
| Unsupported | ContentSigKeyID | This is the ID of the private key the data was signed with. |
| Unsupported | ContentSigAlgo | The algorithm used for the signature. A value of ‘0’ means that the contents have not been signed but only encrypted. Predefined values: 1 - RSA |
| Unsupported | ContentSigHashAlgo | The hash algorithm used for the signature. A value of ‘0’ means that the contents have not been signed but only encrypted. Predefined values: 1 - SHA1-160; 2 - MD5. |
| Content Encoding End |
| Element Name | Description | |
|---|---|---|
| Supported | Cues | A top-level element to speed seeking access. All entries are local to the segment. |
| Supported | CuePoint | Contains all information relative to a seek point in the segment. |
| Supported | CueTime | Absolute timecode according to the segment time base. |
| Supported | CueTrackPositions | Contain positions for different tracks corresponding to the timecode. |
| Supported | CueTrack | The track for which a position is given. |
| Supported | CueClusterPosition | The position of the Cluster containing the required Block. |
| Supported | CueBlockNumber | Number of the Block in the specified Cluster. |
| Unsupported | CueCodecState | The position of the Codec State corresponding to this Cue element. 0 means that the data is taken from the initial Track Entry. |
| Unsupported | CueReference | The Clusters containing the required referenced Blocks. |
| Unsupported | CueRefTime | Timecode of the referenced Block. |
| Unsupported | CueRefCluster | Position of the Cluster containing the referenced Block. |
| Unsupported | CueRefNumber | Number of the referenced Block of Track X in the specified Cluster. |
| Unsupported | CueRefCodecState | The position of the Codec State corresponding to this referenced element. 0 means that the data is taken from the initial Track Entry. |
| Element Name | Description | |
|---|---|---|
| Unsupported | Attachments | Contain attached files. |
| Unsupported | AttachedFile | An attached file. |
| Unsupported | FileDescription | A human-friendly name for the attached file. |
| Unsupported | FileName | Filename of the attached file. |
| Unsupported | FileMimeType | MIME type of the file. |
| Unsupported | FileData | The data of the file. |
| Unsupported | FileUID | Unique ID representing the file, as random as possible. |
| Unsupported | FileReferral | A binary value that a track/codec can refer to when the attachment is needed. |
| Element Name | Description | |
|---|---|---|
| Unsupported | Chapters | A system to define basic menus and partition data. For more detailed information, look at the Chapters Explanation. |
| Unsupported | EditionEntry | Contains all information about a segment edition. |
| Unsupported | EditionUID | A unique ID to identify the edition. It’s useful for tagging an edition. |
| Unsupported | EditionFlagHidden | If an edition is hidden (1), it should not be available to the user interface (but still to Control Tracks). |
| Unsupported | EditionFlagDefault | If a flag is set (1) the edition should be used as the default one. |
| Unsupported | EditionFlagOrdered | Specify if the chapters can be defined multiple times and the order to play them is enforced. |
| Unsupported | ChapterAtom | Contains the atom information to use as the chapter atom (apply to all tracks). |
| Unsupported | ChapterUID | A unique ID to identify the Chapter. |
| Unsupported | ChapterTimeStart | Timecode of the start of Chapter (not scaled). |
| Unsupported | ChapterTimeEnd | Timecode of the end of Chapter (timecode excluded, not scaled). |
| Unsupported | ChapterFlagHidden | If a chapter is hidden (1), it should not be available to the user interface (but still to Control Tracks). |
| Unsupported | ChapterFlagEnabled | Specify wether the chapter is enabled. It can be enabled/disabled by a Control Track. When disabled, the movie should skip all the content between the TimeStart and TimeEnd of this chapter. |
| Unsupported | ChapterSegmentUID | A segment to play in place of this chapter. Edition ChapterSegmentEditionUID should be used for this segment, otherwise no edition is used. |
| Unsupported | ChapterSegmentEditionUID | The edition to play from the segment linked in ChapterSegmentUID. |
| Unsupported | ChapterPhysicalEquiv | Specify the physical equivalent of this ChapterAtom like “DVD” (60) or “SIDE” (50), see complete list of values. |
| Unsupported | ChapterTrack | List of tracks on which the chapter applies. If this element is not present, all tracks apply |
| Unsupported | ChapterTrackNumber | UID of the Track to apply this chapter too. In the absense of a control track, choosing this chapter will select the listed Tracks and deselect unlisted tracks. Absense of this element indicates that the Chapter should be applied to any currently used Tracks. |
| Unsupported | ChapterDisplay | Contains all possible strings to use for the chapter display. |
| Unsupported | ChapString | Contains the string to use as the chapter atom. |
| Unsupported | ChapLanguage | The languages corresponding to the string, in the bibliographic ISO-639-2 form. |
| Unsupported | ChapCountry | The countries corresponding to the string, same 2 octets as in Internet domains. |
| Unsupported | ChapProcess | Contains all the commands associated to the Atom. |
| Unsupported | ChapProcessCodecID | Contains the type of the codec used for the processing. A value of 0 means native Matroska processing (to be defined), a value of 1 means the DVD command set is used. More codec IDs can be added later. |
| Unsupported | ChapProcessPrivate | Some optional data attached to the ChapProcessCodecID information. For ChapProcessCodecID = 1, it is the “DVD level” equivalent. |
| Unsupported | ChapProcessCommand | Contains all the commands associated to the Atom. |
| Unsupported | ChapProcessTime | Defines when the process command should be handled (0: during the whole chapter, 1: before starting playback, 2: after playback of the chapter). |
| Unsupported | ChapProcessData | Contains the command information. The data should be interpreted depending on the ChapProcessCodecID value. For ChapProcessCodecID = 1, the data correspond to the binary DVD cell pre/post commands. |
| Element Name | Description | |
|---|---|---|
| Supported | Tags | Element containing elements specific to Tracks/Chapters. A list of valid tags can be found here. |
| Supported | Tag | Element containing elements specific to Tracks/Chapters. |
| Supported | Targets | Contain all UIDs where the specified meta data apply. It is void to describe everything in the segment. |
| Supported | TargetTypeValue | A number to indicate the logical level of the target (see TargetType). |
| Supported | TargetType | An informational string that can be used to display the logical level of the target like “ALBUM”, “TRACK”, “MOVIE”, “CHAPTER”, etc (see TargetType). |
| Supported | TrackUID | This value SHOULD be 0 , meaning the tags apply to all tracks in the Segment. |
| Unsupported | EditionUID | A unique ID to identify the EditionEntry(s) the tags belong to. If the value is 0 at this level, the tags apply to all editions in the Segment. |
| Unsupported | ChapterUID | A unique ID to identify the Chapter(s) the tags belong to. If the value is 0 at this level, the tags apply to all chapters in the Segment. |
| Unsupported | AttachmentUID | A unique ID to identify the Attachment(s) the tags belong to. If the value is 0 at this level, the tags apply to all the attachments in the Segment. |
| Supported | SimpleTag | Contains general information about the target. |
| Supported | TagName | The name of the Tag that is going to be stored. |
| Supported | TagLanguage | Specifies the language of the tag specified, in the Matroska languages form. |
| Supported | TagDefault | Indication to know if this is the default/original language to use for the given tag. |
| Supported | TagString | The value of the Tag. |
| Supported | TagBinary | The values of the Tag if it is binary. Note that this cannot be used in the same SimpleTag as TagString. |
See the Matroska Tag Specifications.
Work in-progress. See the wiki.


| I l@ve RuBoard |
10.4 Handling Multiple ClientsThe echo client and server programs shown previously serve to illustrate socket fundamentals. But the server model suffers from a fairly major flaw: if multiple clients try to connect to the server, and it takes a long time to process a given clients' request, the server will fail. More accurately, if the cost of handling a given request prevents the server from returning to the code that checks for new clients in a timely manner, it won't be able to keep up with all the requests, and some clients will eventually be denied connections. In real-world client/server programs, it's far more typical to code a server so as to avoid blocking new requests while handling a current client's request. Perhaps the easiest way to do so is to service each client's request in parallel -- in a new process, in a new thread, or by manually switching (multiplexing) between clients in an event loop. This isn't a socket issue per se, and we've already learned how to start processes and threads in Chapter 3. But since these schemes are so typical of socket server programming, let's explore all three ways to handle client requests in parallel here. 10.4.1 Forking ServersThe script in Example 10-4 works like the original echo server, but instead forks a new process to handle each new client connection. Because the handleClient function runs in a new process, the dispatcher function can immediately resume its main loop, to detect and service a new incoming request. Example 10-4. PP2E\Internet\Sockets\fork-server.py######################################################### # Server side: open a socket on a port, listen for # a message from a client, and send an echo reply; # forks a process to handle each client connection; # child processes share parent's socket descriptors; # fork is less portable than threads--not yet on Windows; ######################################################### import os, time, sys from socket import * # get socket constructor and constants myHost = '' # server machine, '' means local host myPort = 50007 # listen on a non-reserved port number sockobj = socket(AF_INET, SOCK_STREAM) # make a TCP socket object sockobj.bind((myHost, myPort)) # bind it to server port number sockobj.listen(5) # allow 5 pending connects def now(): # current time on server return time.ctime(time.time()) activeChildren = [] def reapChildren(): # reap any dead child processes while activeChildren: # else may fill up system table pid,stat = os.waitpid(0, os.WNOHANG) # don't hang if no child exited if not pid: break activeChildren.remove(pid) def handleClient(connection): # child process: reply, exit time.sleep(5) # simulate a blocking activity while 1: # read, write a client socket data = connection.recv(1024) # till eof when socket closed if not data: break connection.send('Echo=>%s at %s' % (data, now())) connection.close() os._exit(0) def dispatcher(): # listen until process killed while 1: # wait for next connection, connection, address = sockobj.accept() # pass to process for service print 'Server connected by', address, print 'at', now() reapChildren() # clean up exited children now childPid = os.fork() # copy this process if childPid == 0: # if in child process: handle handleClient(connection) else: # else: go accept next connect activeChildren.append(childPid) # add to active child pid list dispatcher() <IP_ADDRESS> Running the forking serverParts of this script are a bit tricky, and most of its library calls work only on Unix-like platforms (not Windows). But before we get into too many details, let's start up our server and handle a few client requests. First off, notice that to simulate a long-running operation (e.g., database updates, other network traffic), this server adds a five-second time.sleep delay in its client handler function, handleClient. After the delay, the original echo reply action is performed. That means that when we run a server and clients this time, clients won't receive the echo reply until five seconds after they've sent their requests to the server. To help keep track of requests and replies, the server prints its system time each time a client connect request is received, and adds its system time to the reply. Clients print the reply time sent back from the server, not their own -- clocks on the server and client may differ radically, so to compare apples to apples, all times are server times. Because of the simulated delays, we also usually must start each client in its own console window on Windows (on some platforms, clients will hang in a blocked state while waiting for their reply). But the grander story here is that this script runs one main parent process on the server machine, which does nothing but watch for connections (in dispatcher), plus one child process per active client connection, running in parallel with both the main parent process and the other client processes (in handleClient). In principle, the server can handle any number of clients without bogging down. To test, let's start the server remotely in a Telnet window, and start three clients locally in three distinct console windows: [server telnet window] [lutz@starship uploads]$ uname -a Linux starship ... [lutz@starship uploads]$ python fork-server.py Server connected by ('<IP_ADDRESS>', 1063) at Sun Jun 18 19:37:49 2000 Server connected by ('<IP_ADDRESS>', 1064) at Sun Jun 18 19:37:49 2000 Server connected by ('<IP_ADDRESS>', 1067) at Sun Jun 18 19:37:50 2000 [client window 1] C:\...\PP2E\Internet\Sockets>python echo-client.py starship.python.net Client received: 'Echo=>Hello network world at Sun Jun 18 19:37:54 2000' [client window 2] C:\...\PP2E\Internet\Sockets>python echo-client.py starship.python.net Bruce Client received: 'Echo=>Bruce at Sun Jun 18 19:37:54 2000' [client window 3] C:\...\PP2E\Internet\Sockets>python echo-client.py starship.python.net The Meaning of Life Client received: 'Echo=>The at Sun Jun 18 19:37:55 2000' Client received: 'Echo=>Meaning at Sun Jun 18 19:37:56 2000' Client received: 'Echo=>of at Sun Jun 18 19:37:56 2000' Client received: 'Echo=>Life at Sun Jun 18 19:37:56 2000' Again, all times here are on the server machine. This may be a little confusing because there are four windows involved. In English, the test proceeds as follows:
In other words, all three clients are serviced at the same time, by forked processes, while the main parent process continues listening for new client requests. If clients were not handled in parallel like this, no client could connect until the currently connected client's five-second delay expired. In a more realistic application, that delay could be fatal if many clients were trying to connect at once -- the server would be stuck in the action we're simulating with time.sleep, and not get back to the main loop to accept new client requests. With process forks per request, all clients can be serviced in parallel. Notice that we're using the same client script here (echo-client.py), just a different server; clients simply send and receive data to a machine and port, and don't care how their requests are handled on the server. Also note that the server is running remotely on a Linux machine. (As we learned in Chapter 3, the fork call is not supported on Windows in Python at the time this book was written.) We can also run this test on a Linux server entirely, with two Telnet windows. It works about the same as when clients are started locally, in a DOS console window, but here "local" means a remote machine you're telneting to locally: [one telnet window] [lutz@starship uploads]$ python fork-server.py & [1] 3379 Server connected by ('<IP_ADDRESS>', 2928) at Sun Jun 18 22:44:50 2000 Server connected by ('<IP_ADDRESS>', 2929) at Sun Jun 18 22:45:08 2000 Server connected by ('<IP_ADDRESS>', 2930) at Sun Jun 18 22:45:50 2000 [another telnet window, same machine] [lutz@starship uploads]$ python echo-client.py Client received: 'Echo=>Hello network world at Sun Jun 18 22:44:55 2000' [lutz@starship uploads]$ python echo-client.py localhost niNiNI Client received: 'Echo=>niNiNI at Sun Jun 18 22:45:13 2000' [lutz@starship uploads]$ python echo-client.py starship.python.net Say no More! Client received: 'Echo=>Say at Sun Jun 18 22:45:55 2000' Client received: 'Echo=>no at Sun Jun 18 22:45:55 2000' Client received: 'Echo=>More! at Sun Jun 18 22:45:55 2000' Now let's move on to the tricky bits. This server script is fairly straightforward as forking code goes, but a few comments about some of the library tools it employs are in order. <IP_ADDRESS> Forking processesWe met os.fork in Chapter 3, but recall that forked processes are essentially a copy of the process that forks them, and so they inherit file and socket descriptors from their parent process. Because of that, the new child process that runs the handleClient function has access to the connection socket created in the parent process. Programs know they are in a forked child process if the fork call returns 0; otherwise, the original parent process gets back the new child's ID. <IP_ADDRESS> Exiting from childrenIn earlier fork examples, child processes usually call one of the exec variants to start a new program in the child process. Here, instead, the child process simply calls a function in the same program and exits with os._exit. It's imperative to call os._exit here -- if we did not, each child would live on after handleClient returns, and compete for accepting new client requests. In fact, without the exit call, we'd wind up with as many perpetual server processes as requests served -- remove the exit call and do a ps shell command after running a few clients, and you'll see what I mean. With the call, only the single parent process listens for new requests. os._exit is like sys.exit, but it exits the calling process immediately without cleanup actions. It's normally only used in child processes, and sys.exit is used everywhere else. <IP_ADDRESS> Killing the zombiesNote, however, that it's not quite enough to make sure that child processes exit and die. On systems like Linux, parents must also be sure to issue a wait system call to remove the entries for dead child processes from the system's process table. If we don't, the child processes will no longer run, but they will consume an entry in the system process table. For long-running servers, these bogus entries may become problematic. It's common to call such dead-but-listed child processes "zombies": they continue to use system resources even though they've already passed over to the great operating system beyond. To clean up after child processes are gone, this server keeps a list, activeChildren, of the process IDs of all child processes it spawns. Whenever a new incoming client request is received, the server runs its reapChildren to issue a wait for any dead children by issuing the standard Python os.waitpid(0,os.WNOHANG) call. The os.waitpid call attempts to wait for a child process to exit and returns its process ID and exit status. With a for its first argument, it waits for any child process. With the WNOHANG parameter for its second, it does nothing if no child process has exited (i.e., it does not block or pause the caller). The net effect is that this call simply asks the operating system for the process ID of any child that has exited. If any have, the process ID returned is removed both from the system process table and from this script's activeChildren list. To see why all this complexity is needed, comment out the reapChildren call in this script, run it on a server, and then run a few clients. On my Linux server, a ps -f full process listing command shows that all the dead child processes stay in the system process table (show as <defunct>): [lutz@starship uploads]$ ps -f UID PID PPID C STIME TTY TIME CMD lutz 3270 3264 0 22:33 pts/1 00:00:00 -bash lutz 3311 3270 0 22:37 pts/1 00:00:00 python fork-server.py lutz 3312 3311 0 22:37 pts/1 00:00:00 [python <defunct>] lutz 3313 3311 0 22:37 pts/1 00:00:00 [python <defunct>] lutz 3314 3311 0 22:37 pts/1 00:00:00 [python <defunct>] lutz 3316 3311 0 22:37 pts/1 00:00:00 [python <defunct>] lutz 3317 3311 0 22:37 pts/1 00:00:00 [python <defunct>] lutz 3318 3311 0 22:37 pts/1 00:00:00 [python <defunct>] lutz 3322 3270 0 22:38 pts/1 00:00:00 ps -f When the reapChildren command is reactivated, dead child zombie entries are cleaned up each time the server gets a new client connection request, by calling the Python os.waitpid function. A few zombies may accumulate if the server is heavily loaded, but will remain only until the next client connection is received: [lutz@starship uploads]$ ps -f UID PID PPID C STIME TTY TIME CMD lutz 3270 3264 0 22:33 pts/1 00:00:00 -bash lutz 3340 3270 0 22:41 pts/1 00:00:00 python fork-server.py lutz 3341 3340 0 22:41 pts/1 00:00:00 [python <defunct>] lutz 3342 3340 0 22:41 pts/1 00:00:00 [python <defunct>] lutz 3343 3340 0 22:41 pts/1 00:00:00 [python <defunct>] lutz 3344 3270 6 22:41 pts/1 00:00:00 ps -f [lutz@starship uploads]$ Server connected by ('<IP_ADDRESS>', 1170) at Sun Jun 18 22:41:43 2000 [lutz@starship uploads]$ ps -f UID PID PPID C STIME TTY TIME CMD lutz 3270 3264 0 22:33 pts/1 00:00:00 -bash lutz 3340 3270 0 22:41 pts/1 00:00:00 python fork-server.py lutz 3345 3340 0 22:41 pts/1 00:00:00 [python <defunct>] lutz 3346 3270 0 22:41 pts/1 00:00:00 ps -f If you type fast enough, you can actually see a child process morph from a real running program into a zombie. Here, for example, a child spawned to handle a new request (process ID 11785) changes to <defunct> on exit. Its process entry will be removed completely when the next request is received: [lutz@starship uploads]$ Server connected by ('<IP_ADDRESS>', 1106) at Mon Jun 19 22:34:39 2000 [lutz@starship uploads]$ ps -f UID PID PPID C STIME TTY TIME CMD lutz 11089 11088 0 21:13 pts/2 00:00:00 -bash lutz 11780 11089 0 22:34 pts/2 00:00:00 python fork-server.py lutz 11785 11780 0 22:34 pts/2 00:00:00 python fork-server.py lutz 11786 11089 0 22:34 pts/2 00:00:00 ps -f [lutz@starship uploads]$ ps -f UID PID PPID C STIME TTY TIME CMD lutz 11089 11088 0 21:13 pts/2 00:00:00 -bash lutz 11780 11089 0 22:34 pts/2 00:00:00 python fork-server.py lutz 11785 11780 0 22:34 pts/2 00:00:00 [python <defunct>] lutz 11787 11089 0 22:34 pts/2 00:00:00 ps -f <IP_ADDRESS> Preventing zombies with signal handlersOn some systems, it's also possible to clean up zombie child processes by resetting the signal handler for the SIGCHLD signal raised by the operating system when a child process exits. If a Python script assigns the SIG_IGN (ignore) action as the SIGCHLD signal handler, zombies will be removed automatically and immediately as child processes exit; the parent need not issue wait calls to clean up after them. Because of that, this scheme is a simpler alternative to manually reaping zombies (on platforms where it is supported). If you've already read Chapter 3, you know that Python's standard signal module lets scripts install handlers for signals -- software-generated events. If you haven't read that chapter, here is a brief bit of background to show how this pans out for zombies. The program in Example 10-5 installs a Python-coded signal handler function to respond to whatever signal number you type on the command line. Example 10-5. PP2E\Internet\Sockets\signal-demo.py########################################################## # Demo Python's signal module; pass signal number as a # command-line arg, use a "kill -N pid" shell command # to send this process a signal; e.g., on my linux # machine, SIGUSR1=10, SIGUSR2=12, SIGCHLD=17, and # SIGCHLD handler stays in effect even if not restored: # all other handlers restored by Python after caught, # but SIGCHLD is left to the platform's implementation; # signal works on Windows but defines only a few signal # types; signals are not very portable in general; ########################################################## import sys, signal, time def now(): return time.ctime(time.time()) def onSignal(signum, stackframe): # python signal handler print 'Got signal', signum, 'at', now() # most handlers stay in effect if signum == signal.SIGCHLD: # but sigchld handler is not print 'sigchld caught' #signal.signal(signal.SIGCHLD, onSignal) signum = int(sys.argv[1]) signal.signal(signum, onSignal) # install signal handler while 1: signal.pause() # sleep waiting for signals To run this script, simply put it in the background and send it signals by typing the kill -signal-number process-id shell command line. Process IDs are listed in the PID column of ps command results. Here is this script in action catching signal numbers 10 (reserved for general use) and 9 (the unavoidable terminate signal): [lutz@starship uploads]$ python signal-demo.py 10 & [1] 11297 [lutz@starship uploads]$ ps -f UID PID PPID C STIME TTY TIME CMD lutz 11089 11088 0 21:13 pts/2 00:00:00 -bash lutz 11297 11089 0 21:49 pts/2 00:00:00 python signal-demo.py 10 lutz 11298 11089 0 21:49 pts/2 00:00:00 ps -f [lutz@starship uploads]$ kill -10 11297 Got signal 10 at Mon Jun 19 21:49:27 2000 [lutz@starship uploads]$ kill -10 11297 Got signal 10 at Mon Jun 19 21:49:29 2000 [lutz@starship uploads]$ kill -10 11297 Got signal 10 at Mon Jun 19 21:49:32 2000 [lutz@starship uploads]$ kill -9 11297 [1]+ Killed python signal-demo.py 10 And here the script catches signal 17, which happens to be SIGCHLD on my Linux server. Signal numbers vary from machine to machine, so you should normally use their names, not their numbers.  The forking server variant shown in Example 10-6 uses this trick to manage its children. Example 10-6. PP2E\Internet\Sockets\fork-server-signal.py######################################################### # Same as fork-server.py, but use the Python signal # module to avoid keeping child zombie processes after # they terminate, not an explicit loop before each new # connection; SIG_IGN means ignore, and may not work with # SIG_CHLD child exit signal on all platforms; on Linux, # socket.accept cannot be interrupted with a signal; ######################################################### import os, time, sys, signal, signal from socket import * # get socket constructor and constants myHost = '' # server machine, '' means local host myPort = 50007 # listen on a non-reserved port number sockobj = socket(AF_INET, SOCK_STREAM) # make a TCP socket object sockobj.bind((myHost, myPort)) # bind it to server port number sockobj.listen(5) # up to 5 pending connects signal.signal(signal.SIGCHLD, signal.SIG_IGN) # avoid child zombie processes def now(): # time on server machine return time.ctime(time.time()) def handleClient(connection): # child process replies, exits time.sleep(5) # simulate a blocking activity while 1: # read, write a client socket data = connection.recv(1024) if not data: break connection.send('Echo=>%s at %s' % (data, now())) connection.close() os._exit(0) def dispatcher(): # listen until process killed while 1: # wait for next connection, connection, address = sockobj.accept() # pass to process for service print 'Server connected by', address, print 'at', now() childPid = os.fork() # copy this process if childPid == 0: # if in child process: handle handleClient(connection) # else: go accept next connect dispatcher() Where applicable, this technique is:
In fact, there is really only one line dedicated to handling zombies here: the signal.signal call near the top, to set the handler. Unfortunately, this version is also even less portable than using os.fork in the first place, because signals may work slightly different from platform to platform. For instance, some platforms may not allow SIG_IGN to be used as the SIGCHLD action at all. On Linux systems, though, this simpler forking server variant works like a charm: [lutz@starship uploads]$ Server connected by ('<IP_ADDRESS>', 1166) at Mon Jun 19 22:38:29 2000 [lutz@starship uploads]$ ps -f UID PID PPID C STIME TTY TIME CMD lutz 11089 11088 0 21:13 pts/2 00:00:00 -bash lutz 11827 11089 0 22:37 pts/2 00:00:00 python fork-server-signal.py lutz 11835 11827 0 22:38 pts/2 00:00:00 python fork-server-signal.py lutz 11836 11089 0 22:38 pts/2 00:00:00 ps -f [lutz@starship uploads]$ ps -f UID PID PPID C STIME TTY TIME CMD lutz 11089 11088 0 21:13 pts/2 00:00:00 -bash lutz 11827 11089 0 22:37 pts/2 00:00:00 python fork-server-signal.py lutz 11837 11089 0 22:38 pts/2 00:00:00 ps -f Notice that in this version, the child process's entry goes away as soon as it exits, even before a new client request is received; no "defunct" zombie ever appears. More dramatically, if we now start up the script we wrote earlier that spawns eight clients in parallel (testecho.py) to talk to this server, all appear on the server while running, but are removed immediately as they exit: [lutz@starship uploads]$ ps -f UID PID PPID C STIME TTY TIME CMD lutz 11089 11088 0 21:13 pts/2 00:00:00 -bash lutz 11827 11089 0 22:37 pts/2 00:00:00 python fork-server-signal.py lutz 11839 11827 0 22:39 pts/2 00:00:00 python fork-server-signal.py lutz 11840 11827 0 22:39 pts/2 00:00:00 python fork-server-signal.py lutz 11841 11827 0 22:39 pts/2 00:00:00 python fork-server-signal.py lutz 11842 11827 0 22:39 pts/2 00:00:00 python fork-server-signal.py lutz 11843 11827 0 22:39 pts/2 00:00:00 python fork-server-signal.py lutz 11844 11827 0 22:39 pts/2 00:00:00 python fork-server-signal.py lutz 11845 11827 0 22:39 pts/2 00:00:00 python fork-server-signal.py lutz 11846 11827 0 22:39 pts/2 00:00:00 python fork-server-signal.py lutz 11848 11089 0 22:39 pts/2 00:00:00 ps -f [lutz@starship uploads]$ ps -f UID PID PPID C STIME TTY TIME CMD lutz 11089 11088 0 21:13 pts/2 00:00:00 -bash lutz 11827 11089 0 22:37 pts/2 00:00:00 python fork-server-signal.py lutz 11849 11089 0 22:39 pts/2 00:00:00 ps -f 10.4.2 Threading ServersBut don't do that . The forking model just described works well on some platforms in general, but suffers from some potentially big limitations:
If you read Chapter 3, you know that the solution to all of these dilemmas is usually to use threads instead of processes. Threads run in parallel and share global (i.e., module and interpreter) memory, but they are usually less expensive to start, and work both on Unix-like machines and Microsoft Windows today. Furthermore, threads are simpler to program -- child threads die silently on exit, without leaving behind zombies to haunt the server. Example 10-7 is another mutation of the echo server that handles client request in parallel by running them in threads, rather than processes. Example 10-7. PP2E\Internet\Sockets\thread-server.py######################################################### # Server side: open a socket on a port, listen for # a message from a client, and send an echo reply; # echos lines until eof when client closes socket; # spawns a thread to handle each client connection; # threads share global memory space with main thread; # this is more portable than fork--not yet on Windows; ######################################################### import thread, time from socket import * # get socket constructor and constants myHost = '' # server machine, '' means local host myPort = 50007 # listen on a non-reserved port number sockobj = socket(AF_INET, SOCK_STREAM) # make a TCP socket object sockobj.bind((myHost, myPort)) # bind it to server port number sockobj.listen(5) # allow up to 5 pending connects def now(): return time.ctime(time.time()) # current time on the server def handleClient(connection): # in spawned thread: reply time.sleep(5) # simulate a blocking activity while 1: # read, write a client socket data = connection.recv(1024) if not data: break connection.send('Echo=>%s at %s' % (data, now())) connection.close() def dispatcher(): # listen until process killd while 1: # wait for next connection, connection, address = sockobj.accept() # pass to thread for service print 'Server connected by', address, print 'at', now() thread.start_new(handleClient, (connection,)) dispatcher() This dispatcher delegates each incoming client connection request to a newly spawned thread running the handleClient function. Because of that, this server can process multiple clients at once, and the main dispatcher loop can get quickly back to the top to check for newly arrived requests. The net effect is that new clients won't be denied service due to a busy server. Functionally, this version is similar to the fork solution (clients are handled in parallel), but it will work on any machine that supports threads, including Windows and Linux. Let's test it on both. First, start the server on a Linux machine and run clients on both Linux and Windows: [window 1: thread-based server process, server keeps accepting client connections while threads are servicing prior requests] [lutz@starship uploads]$ /usr/bin/python thread-server.py Server connected by ('<IP_ADDRESS>', 2934) at Sun Jun 18 22:52:52 2000 Server connected by ('<IP_ADDRESS>', 1179) at Sun Jun 18 22:53:31 2000 Server connected by ('<IP_ADDRESS>', 1182) at Sun Jun 18 22:53:35 2000 Server connected by ('<IP_ADDRESS>', 1185) at Sun Jun 18 22:53:37 2000 [window 2: client, but on same server machine] [lutz@starship uploads]$ python echo-client.py Client received: 'Echo=>Hello network world at Sun Jun 18 22:52:57 2000' [window 3: remote client, PC] C:\...\PP2E\Internet\Sockets>python echo-client.py starship.python.net Client received: 'Echo=>Hello network world at Sun Jun 18 22:53:36 2000' [window 4: client PC] C:\...\PP2E\Internet\Sockets>python echo-client.py starship.python.net Bruce Client received: 'Echo=>Bruce at Sun Jun 18 22:53:40 2000' [window 5: client PC] C:\...\PP2E\Internet\Sockets>python echo-client.py starship.python.net The Meaning of Life Client received: 'Echo=>The at Sun Jun 18 22:53:42 2000' Client received: 'Echo=>Meaning at Sun Jun 18 22:53:42 2000' Client received: 'Echo=>of at Sun Jun 18 22:53:42 2000' Client received: 'Echo=>Life at Sun Jun 18 22:53:42 2000' Because this server uses threads instead of forked processes, we can run it portably on both Linux and a Windows PC. Here it is at work again, running on the same local Windows PC as its clients; again, the main point to notice is that new clients are accepted while prior clients are being processed in parallel with other clients and the main thread (in the five-second sleep delay): [window 1: server, on local PC] C:\...\PP2E\Internet\Sockets>python thread-server.py Server connected by ('<IP_ADDRESS>', 1186) at Sun Jun 18 23:46:31 2000 Server connected by ('<IP_ADDRESS>', 1187) at Sun Jun 18 23:46:33 2000 Server connected by ('<IP_ADDRESS>', 1188) at Sun Jun 18 23:46:34 2000 [window 2: client, on local PC] C:\...\PP2E\Internet\Sockets>python echo-client.py Client received: 'Echo=>Hello network world at Sun Jun 18 23:46:36 2000' [window 3: client] C:\...\PP2E\Internet\Sockets>python echo-client.py localhost Brian Client received: 'Echo=>Brian at Sun Jun 18 23:46:38 2000' [window 4: client] C:\...\PP2E\Internet\Sockets>python echo-client.py localhost Bright side of Life Client received: 'Echo=>Bright at Sun Jun 18 23:46:39 2000' Client received: 'Echo=>side at Sun Jun 18 23:46:39 2000' Client received: 'Echo=>of at Sun Jun 18 23:46:39 2000' Client received: 'Echo=>Life at Sun Jun 18 23:46:39 2000' Recall that a thread silently exits when the function it is running returns; unlike the process fork version, we don't call anything like os._exit in the client handler function (and we shouldn't -- it may kill all threads in the process!). Because of this, the thread version is not only more portable, but is also simpler. 10.4.3 Doing It with Classes: Server FrameworksNow that I've shown you how to write forking and threading servers to process clients without blocking incoming requests, I should also tell you that there are standard tools in the Python library to make this process easier. In particular, the SocketServer module defines classes that implement all flavors of forking and threading servers that you are likely to be interested in. Simply create the desired kind of imported server object, passing in a handler object with a callback method of your own, as shown in Example 10-8. Example 10-8. PP2E\Internet\Sockets\class-server.py######################################################### # Server side: open a socket on a port, listen for # a message from a client, and send an echo reply; # this version uses the standard library module # SocketServer to do its work; SocketServer allows # us to make a simple TCPServer, a ThreadingTCPServer, # a ForkingTCPServer, and more, and routes each client # connect request to a new instance of a passed-in # request handler object's handle method; also supports # UDP and Unix domain sockets; see the library manual. ######################################################### import SocketServer, time # get socket server, handler objects myHost = '' # server machine, '' means local host myPort = 50007 # listen on a non-reserved port number def now(): return time.ctime(time.time()) class MyClientHandler(SocketServer.BaseRequestHandler): def handle(self): # on each client connect print self.client_address, now() # show this client's address time.sleep(5) # simulate a blocking activity while 1: # self.request is client socket data = self.request.recv(1024) # read, write a client socket if not data: break self.request.send('Echo=>%s at %s' % (data, now())) self.request.close() # make a threaded server, listen/handle clients forever myaddr = (myHost, myPort) server = SocketServer.ThreadingTCPServer(myaddr, MyClientHandler) server.serve_forever() This server works the same as the threading server we wrote by hand in the previous section, but instead focuses on service implementation (the customized handle method), not on threading details. It's run the same way, too -- here it is processing three clients started by hand, plus eight spawned by the testecho script shown in Example 10-3: [window1: server, serverHost='localhost' in echo-client.py] C:\...\PP2E\Internet\Sockets>python class-server.py ('<IP_ADDRESS>', 1189) Sun Jun 18 23:49:18 2000 ('<IP_ADDRESS>', 1190) Sun Jun 18 23:49:20 2000 ('<IP_ADDRESS>', 1191) Sun Jun 18 23:49:22 2000 ('<IP_ADDRESS>', 1192) Sun Jun 18 23:49:50 2000 ('<IP_ADDRESS>', 1193) Sun Jun 18 23:49:50 2000 ('<IP_ADDRESS>', 1194) Sun Jun 18 23:49:50 2000 ('<IP_ADDRESS>', 1195) Sun Jun 18 23:49:50 2000 ('<IP_ADDRESS>', 1196) Sun Jun 18 23:49:50 2000 ('<IP_ADDRESS>', 1197) Sun Jun 18 23:49:50 2000 ('<IP_ADDRESS>', 1198) Sun Jun 18 23:49:50 2000 ('<IP_ADDRESS>', 1199) Sun Jun 18 23:49:50 2000 [window2: client] C:\...\PP2E\Internet\Sockets>python echo-client.py Client received: 'Echo=>Hello network world at Sun Jun 18 23:49:23 2000' [window3: client] C:\...\PP2E\Internet\Sockets>python echo-client.py localhost Robin Client received: 'Echo=>Robin at Sun Jun 18 23:49:25 2000' [window4: client] C:\...\PP2E\Internet\Sockets>python echo-client.py localhost Brave Sir Robin Client received: 'Echo=>Brave at Sun Jun 18 23:49:27 2000' Client received: 'Echo=>Sir at Sun Jun 18 23:49:27 2000' Client received: 'Echo=>Robin at Sun Jun 18 23:49:27 2000' C:\...\PP2E\Internet\Sockets>python testecho.py [window4: contact remote server instead -- times skewed] C:\...\PP2E\Internet\Sockets>python echo-client.py starship.python.net Brave Sir Robin Client received: 'Echo=>Brave at Sun Jun 18 23:03:28 2000' Client received: 'Echo=>Sir at Sun Jun 18 23:03:28 2000' Client received: 'Echo=>Robin at Sun Jun 18 23:03:29 2000' To build a forking server instead, just use class name ForkingTCPServer when creating the server object. The SocketServer module is more powerful than shown by this example; it also supports synchronous (nonparallel) servers, UDP and Unix sockets, and so on. See Python's library manual for more details. Also see the end of Chapter 15 for more on Python server implementation tools.[6]
10.4.4 Multiplexing Servers with selectSo far we've seen how to handle multiple clients at once with both forked processes and spawned threads, and we've looked at a library class that encapsulates both schemes. Under both approaches, all client handlers seem to run in parallel with each other and with the main dispatch loop that continues watching for new incoming requests. Because all these tasks run in parallel (i.e., at the same time), the server doesn't get blocked when accepting new requests or when processing a long-running client handler. Technically, though, threads and processes don't really run in parallel, unless you're lucky enough to have a machine with arbitrarily many CPUs. Instead, your operating system performs a juggling act -- it divides the computer's processing power among all active tasks. It runs part of one, then part of another, and so on. All the tasks appear to run in parallel, but only because the operating system switches focus between tasks so fast that you don't usually notice. This process of switching between tasks is sometimes called time-slicing when done by an operating system; it is more generally known as multiplexing. When we spawn threads and processes, we rely on the operating system to juggle the active tasks, but there's no reason that a Python script can't do so as well. For instance, a script might divide tasks into multiple steps -- do a step of one task, then one of another, and so on, until all are completed. The script need only know how to divide its attention among the multiple active tasks to multiplex on its own. Servers can apply this technique to yield yet another way to handle multiple clients at once, a way that requires neither threads nor forks. By multiplexing client connections and the main dispatcher with the select system call, a single event loop can process clients and accept new ones in parallel (or at least close enough to avoid stalling). Such servers are sometimes call asynchronous, because they service clients in spurts, as each becomes ready to communicate. In asynchronous servers, a single main loop run in a single process and thread decides which clients should get a bit of attention each time through. Client requests and the main dispatcher are each given a small slice of the server's attention if they are ready to converse. Most of the magic behind this server structure is the operating system select call, available in Python's standard select module. Roughly, select is asked to monitor a list of input sources, output sources, and exceptional condition sources, and tells us which sources are ready for processing. It can be made to simply poll all the sources to see which are ready, wait for a maximum time period for sources to become ready, or wait indefinitely until one or more sources are ready for processing. However used, select lets us direct attention to sockets ready to communicate, so as to avoid blocking on calls to ones that are not. That is, when the sources passed to select are sockets, we can be sure that socket calls like accept, recv, and send will not block (pause) the server when applied to objects returned by select. Because of that, a single-loop server that uses select need not get stuck communicating with one client or waiting for new ones, while other clients are starved for the server's attention. <IP_ADDRESS> A select-based echo serverLet's see how all this translates into code. The script in Example 10-9 implements another echo server, one that can handle multiple clients without ever starting new processes or threads. Example 10-9. PP2E\Internet\Sockets\select-server.py################################################################# # Server: handle multiple clients in parallel with select. # use the select module to multiplex among a set of sockets: # main sockets which accept new client connections, and # input sockets connected to accepted clients; select can # take an optional 4th arg--0 to poll, n.m to wait n.m secs, # ommitted to wait till any socket is ready for processing. ################################################################# import sys, time from select import select from socket import socket, AF_INET, SOCK_STREAM def now(): return time.ctime(time.time()) myHost = '' # server machine, '' means local host myPort = 50007 # listen on a non-reserved port number if len(sys.argv) == 3: # allow host/port as cmdline args too myHost, myPort = sys.argv[1:] numPortSocks = 2 # number of ports for client connects # make main sockets for accepting new client requests mainsocks, readsocks, writesocks = [], [], [] for i in range(numPortSocks): portsock = socket(AF_INET, SOCK_STREAM) # make a TCP/IP spocket object portsock.bind((myHost, myPort)) # bind it to server port number portsock.listen(5) # listen, allow 5 pending connects mainsocks.append(portsock) # add to main list to identify readsocks.append(portsock) # add to select inputs list myPort = myPort + 1 # bind on consecutive ports # event loop: listen and multiplex until server process killed print 'select-server loop starting' while 1: #print readsocks readables, writeables, exceptions = select(readsocks, writesocks, []) for sockobj in readables: if sockobj in mainsocks: # for ready input sockets # port socket: accept new client newsock, address = sockobj.accept() # accept should not block print 'Connect:', address, id(newsock) # newsock is a new socket readsocks.append(newsock) # add to select list, wait else: # client socket: read next line data = sockobj.recv(1024) # recv should not block print '\tgot', data, 'on', id(sockobj) if not data: # if closed by the clients sockobj.close() # close here and remv from readsocks.remove(sockobj) # del list else reselected else: # this may block: should really select for writes too sockobj.send('Echo=>%s at %s' % (data, now())) The bulk of this script is the big while event loop at the end that calls select to find out which sockets are ready for processing (these include main port sockets on which clients can connect, and open client connections). It then loops over all such ready sockets, accepting connections on main port sockets, and reading and echoing input on any client sockets ready for input. Both the accept and recv calls in this code are guaranteed to not block the server process after select returns; because of that, this server can get quickly back to the top of the loop to process newly arrived client requests and already-connected clients' inputs. The net effect is that all new requests and clients are serviced in pseudo-parallel fashion. To make this process work, the server appends the connected socket for each client to the readables list passed to select, and simply waits for the socket to show up in the selected inputs list. For illustration purposes, this server also listens for new clients on more than one port -- on ports 50007 and 50008 in our examples. Because these main port sockets are also interrogated with select, connection requests on either port can be accepted without blocking either already-connected clients or new connection requests appearing on the other port. The select call returns whatever sockets in list readables are ready for processing -- both main port sockets and sockets connected to clients currently being processed. <IP_ADDRESS> Running the select serverLet's run this script locally to see how it does its stuff (the client and server can also be run on different machines, as in prior socket examples). First of all, we'll assume we've already started this server script in one window, and run a few clients to talk to it. The following code is the interaction in two such client windows running on Windows (MS-DOS consoles). The first client simply runs the echo-client script twice to contact the server, and the second also kicks off the testecho script to spawn eight echo-client programs running in parallel. As before, the server simply echoes back whatever text that clients send. Notice that the second client window really runs a script called echo-client-50008 so as to connect to the second port socket in the server; it's the same as echo-client, with a different port number (alas, the original script wasn't designed to input a port): [client window 1] C:\...\PP2E\Internet\Sockets>python echo-client.py Client received: 'Echo=>Hello network world at Sun Aug 13 22:52:01 2000' C:\...\PP2E\Internet\Sockets>python echo-client.py Client received: 'Echo=>Hello network world at Sun Aug 13 22:52:03 2000' [client window 2] C:\...\PP2E\Internet\Sockets>python echo-client-50008.py localhost Sir Lancelot Client received: 'Echo=>Sir at Sun Aug 13 22:52:57 2000' Client received: 'Echo=>Lancelot at Sun Aug 13 22:52:57 2000' C:\...\PP2E\Internet\Sockets>python testecho.py Now, in the next code section is the sort of interaction and output that shows up in the window where the server has been started. The first three connections come from echo-client runs; the rest is the result of the eight programs spawned by testecho in the second client window. Notice that for testecho, new client connections and client inputs are all multiplexed together. If you study the output closely, you'll see that they overlap in time, because all activity is dispatched by the single event loop in the server.[7] Also note that the sever gets an empty string when the client has closed its socket. We take care to close and delete these sockets at the server right away, or else they would be needlessly reselected again and again, each time through the main loop:
[server window] C:\...\PP2E\Internet\Sockets>python select-server.py select-server loop starting Connect: ('<IP_ADDRESS>', 1175) 7965520 got Hello network world on 7965520 got on 7965520 Connect: ('<IP_ADDRESS>', 1176) 7964288 got Hello network world on 7964288 got on 7964288 Connect: ('<IP_ADDRESS>', 1177) 7963920 got Sir on 7963920 got Lancelot on 7963920 got on 7963920 [testecho results] Connect: ('<IP_ADDRESS>', 1178) 7965216 got Hello network world on 7965216 got on 7965216 Connect: ('<IP_ADDRESS>', 1179) 7963968 Connect: ('<IP_ADDRESS>', 1180) 7965424 got Hello network world on 7963968 Connect: ('<IP_ADDRESS>', 1181) 7962976 got Hello network world on 7965424 got on 7963968 got Hello network world on 7962976 got on 7965424 got on 7962976 Connect: ('<IP_ADDRESS>', 1182) 7963648 got Hello network world on 7963648 got on 7963648 Connect: ('<IP_ADDRESS>', 1183) 7966640 got Hello network world on 7966640 got on 7966640 Connect: ('<IP_ADDRESS>', 1184) 7966496 got Hello network world on 7966496 got on 7966496 Connect: ('<IP_ADDRESS>', 1185) 7965888 got Hello network world on 7965888 got on 7965888 A subtle but crucial point: a time.sleep call to simulate a long-running task doesn't make sense in the server here -- because all clients are handled by the same single loop, sleeping would pause everything (and defeat the whole point of a multiplexing server). Here are a few additional notes before we move on:
10.4.5 Choosing a Server SchemeSo when should you use select to build a server instead of threads or forks? Needs vary per application, of course, but servers based on the select call are generally considered to perform very well when client transactions are relatively short. If they are not short, threads or forks may be a better way to split processing among multiple clients. Threads and forks are especially useful if clients require long-running processing above and beyond socket calls. It's important to remember that schemes based on select (and nonblocking sockets) are not completely immune to blocking. In the example earlier, for instance, the send call that echoes text back to a client might block, too, and hence stall the entire server. We could work around that blocking potential by using select to make sure that the output operation is ready before we attempt it (e.g., use the writesocks list and add another loop to send replies to ready output sockets), albeit at a noticeable cost in program clarity. In general, though, if we cannot split up the processing of a client's request in such a way that it can be multiplexed with other requests and not block the server's loop, select may not be the best way to construct the server. Moreover, select also seems more complex than spawning either processes or threads, because we need to manually transfer control among all tasks (for instance, compare the threaded and select versions of this server, even without write selects). As usual, though, the degree of that complexity may vary per application. |
| I l@ve RuBoard |


{% extends "layout.html" %} {% block page_title %} GOV.UK prototype kit {% endblock %} {% block content %} BETA This is a new service – your feedback will help us to improve it. Andrea Authoriser Casterbridge College UKPRN:12345678 Home page Contracts Funding claims Subcontractors Settings Sign out You need to agree the subcontractor declaration terms You must check the box before submiting Submit your subcontractor information Subcontractor Declaration Warwickshire College October 2017 PDF, 82KB By submiting you agree: with the subcontractor funding rules you have permission to submit Please check box before submitting I agree with the terms and conditions Submit Back {% endblock %}
BETA This is a new service – your feedback will help us to improve it.
PDF, 82KB
By submiting you agree:
Submit
Back


| Package | Description |
|---|---|
| mars | |
| mars.riscv.hardware.memory | |
| mars.riscv.instructions | |
| mars.riscv.instructions.ecalls |
| Constructor | Description |
|---|---|
ErrorMessage(ProgramStatement statement,
java.lang.String message) |
Constructor for ErrorMessage, to be used for runtime exceptions.
|
ProcessingException(ProgramStatement ps,
java.lang.String m) |
Constructor for ProcessingException to handle runtime exceptions
|
ProcessingException(ProgramStatement ps,
java.lang.String m,
int cause) |
Constructor for ProcessingException to handle runtime exceptions
|
ProcessingException(ProgramStatement ps,
AddressErrorException aee) |
Constructor for ProcessingException to handle address runtime exceptions
|
| Modifier and Type | Method | Description |
|---|---|---|
ProgramStatement |
Memory.getStatement(java.lang.Number address) |
Gets ProgramStatement from Text Segment.
|
ProgramStatement |
Memory.getStatementNoNotify(java.lang.Number address) |
Gets ProgramStatement from Text Segment without notifying observers.
|
(package private) ProgramStatement |
TextBlockTable.readProgramStatement(java.lang.Number address) |
| Modifier and Type | Method | Description |
|---|---|---|
void |
Memory.setStatement(java.lang.Number address,
ProgramStatement statement) |
Stores ProgramStatement in Text Segment.
|
(package private) void |
TextBlockTable.storeProgramStatement(java.lang.Number address,
ProgramStatement statement) |
| Modifier and Type | Method | Description |
|---|---|---|
void |
SimulationCode.simulate(ProgramStatement statement) |
Method to simulate the execution of a specific RISCV basic instruction.
|
| Modifier and Type | Method | Description |
|---|---|---|
abstract void |
AbstractEcall.simulate(ProgramStatement statement) |
Performs ecall function.
|
void |
Ecall.simulate(ProgramStatement statement) |
Performs ecall function.
|
void |
EcallClose.simulate(ProgramStatement statement) |
Performs syscall function to close file descriptor given in $a0.
|
void |
EcallExit.simulate(ProgramStatement statement) |
Performs ecall function to exit the RISCV program.
|
void |
EcallExit2.simulate(ProgramStatement statement) |
Performs ecall function to exit the RISCV program with return value given in a0.
|
void |
EcallOpen.simulate(ProgramStatement statement) |
Performs ecall function to open file name specified by a0.
|
void |
EcallPrintChar.simulate(ProgramStatement statement) |
Performs syscall function to print on the console the character stored in a0.
|
void |
EcallPrintDouble.simulate(ProgramStatement statement) |
Performs ecall function to print double whose bits are stored in f12 & f13.
|
void |
EcallPrintFloat.simulate(ProgramStatement statement) |
Performs ecall function to display float whose bits are stored in f12
|
void |
EcallPrintIntHex.simulate(ProgramStatement statement) |
Performs ecall function to print on the console the integer stored in a0, in hexadecimal format.
|
void |
EcallPrintIntUnsigned.simulate(ProgramStatement statement) |
Performs ecall function to print on the console the integer stored in a0.
|
void |
EcallPrintNumber.simulate(ProgramStatement statement) |
Performs ecall function to print on the console the integer stored in a0.
|
void |
EcallPrintNumberBinary.simulate(ProgramStatement statement) |
Performs ecall function to print on the console the integer stored in a0, in hexadecimal format.
|
void |
EcallPrintString.simulate(ProgramStatement statement) |
Performs ecall function to print string stored starting at address in a0.
|
void |
EcallRandDouble.simulate(ProgramStatement statement) |
System call to the random number generator.
|
void |
EcallRandFloat.simulate(ProgramStatement statement) |
System call to the random number generator.
|
void |
EcallRandInt.simulate(ProgramStatement statement) |
System call to the random number generator.
|
void |
EcallRandIntRange.simulate(ProgramStatement statement) |
System call to the random number generator, with an upper range specified.
|
void |
EcallRandSeed.simulate(ProgramStatement statement) |
Set the seed of the underlying Java pseudorandom number generator.
|
void |
EcallRead.simulate(ProgramStatement statement) |
Performs syscall function to read from file descriptor given in a0.
|
void |
EcallReadChar.simulate(ProgramStatement statement) |
Performs syscall function to read a character from input console into $a0
|
void |
EcallReadDouble.simulate(ProgramStatement statement) |
Performs syscall function to read the bits of input double into $f0 and $f1.
|
void |
EcallReadFloat.simulate(ProgramStatement statement) |
Performs syscall function to read the bits of input float into $f0
|
void |
EcallReadInt.simulate(ProgramStatement statement) |
Performs ecall function to read an integer from input console into a3
|
void |
EcallReadString.simulate(ProgramStatement statement) |
Performs ecall function to read console input string into buffer starting at address in $a0.
|
void |
EcallSbrk.simulate(ProgramStatement statement) |
Performs ecall function to allocate amount of heap memory specified in a0, putting address into $v0.
|
void |
EcallSleep.simulate(ProgramStatement statement) |
System call to cause the MARS Java thread to sleep for (at least) the specified number of milliseconds.
|
void |
EcallTime.simulate(ProgramStatement statement) |
Performs ecall function to place current system time into a0 (low order 32 bits)
and a1 (high order 32 bits) in 32 bits architecture; in 64 places only in a0.
|
void |
EcallWrite.simulate(ProgramStatement statement) |
Performs syscall function to write to file descriptor given in a0.
|


1 {{teamsService.getTeam('east', 1) | team: 'name'}}
16 {{teamsService.getTeam('east', 16) | team: 'name'}}
8 {{teamsService.getTeam('east', 8) | team: 'name'}}
9 {{teamsService.getTeam('east', 9) | team: 'name'}}
5 {{teamsService.getTeam('east', 5) | team: 'name'}}
12 {{teamsService.getTeam('east', 12) | team: 'name'}}
4 {{teamsService.getTeam('east', 4) | team: 'name'}}
13 {{teamsService.getTeam('east', 13) | team: 'name'}}
6 {{teamsService.getTeam('east', 6) | team: 'name'}}
11 {{teamsService.getTeam('east', 11) | team: 'name'}}
3 {{teamsService.getTeam('east', 3) | team: 'name'}}
14 {{teamsService.getTeam('east', 14) | team: 'name'}}
7 {{teamsService.getTeam('east', 7) | team: 'name'}}
10 {{teamsService.getTeam('east', 10) | team: 'name'}}
2 {{teamsService.getTeam('east', 2) | team: 'name'}}
15 {{teamsService.getTeam('east', 15) | team: 'name'}}
1 {{teamsService.getTeam('west', 1) | team: 'name'}}
16 {{teamsService.getTeam('west', 16) | team: 'name'}}
8 {{teamsService.getTeam('west', 8) | team: 'name'}}
9 {{teamsService.getTeam('west', 9) | team: 'name'}}
5 {{teamsService.getTeam('west', 5) | team: 'name'}}
12 {{teamsService.getTeam('west', 12) | team: 'name'}}
4 {{teamsService.getTeam('west', 4) | team: 'name'}}
13 {{teamsService.getTeam('west', 13) | team: 'name'}}
6 {{teamsService.getTeam('west', 6) | team: 'name'}}
11 {{teamsService.getTeam('west', 11) | team: 'name'}}
3 {{teamsService.getTeam('west', 3) | team: 'name'}}
14 {{teamsService.getTeam('west', 14) | team: 'name'}}
7 {{teamsService.getTeam('west', 7) | team: 'name'}}
10 {{teamsService.getTeam('west', 10) | team: 'name'}}
2 {{teamsService.getTeam('west', 2) | team: 'name'}}
15 {{teamsService.getTeam('west', 15) | team: 'name'}}
1 {{teamsService.getTeam('south', 1) | team: 'name'}}
16 {{teamsService.getTeam('south', 16) | team: 'name'}}
8 {{teamsService.getTeam('south', 8) | team: 'name'}}
9 {{teamsService.getTeam('south', 9) | team: 'name'}}
5 {{teamsService.getTeam('south', 5) | team: 'name'}}
12 {{teamsService.getTeam('south', 12) | team: 'name'}}
4 {{teamsService.getTeam('south', 4) | team: 'name'}}
13 {{teamsService.getTeam('south', 13) | team: 'name'}}
6 {{teamsService.getTeam('south', 6) | team: 'name'}}
11 {{teamsService.getTeam('south', 11) | team: 'name'}}
3 {{teamsService.getTeam('south', 3) | team: 'name'}}
14 {{teamsService.getTeam('south', 14) | team: 'name'}}
7 {{teamsService.getTeam('south', 7) | team: 'name'}}
10 {{teamsService.getTeam('south', 10) | team: 'name'}}
2 {{teamsService.getTeam('south', 2) | team: 'name'}}
15 {{teamsService.getTeam('south', 15) | team: 'name'}}
1 {{teamsService.getTeam('midwest', 1) | team: 'name'}}
16 {{teamsService.getTeam('midwest', 16) | team: 'name'}}
8 {{teamsService.getTeam('midwest', 8) | team: 'name'}}
9 {{teamsService.getTeam('midwest', 9) | team: 'name'}}
5 {{teamsService.getTeam('midwest', 5) | team: 'name'}}
12 {{teamsService.getTeam('midwest', 12) | team: 'name'}}
4 {{teamsService.getTeam('midwest', 4) | team: 'name'}}
13 {{teamsService.getTeam('midwest', 13) | team: 'name'}}
6 {{teamsService.getTeam('midwest', 6) | team: 'name'}}
11 {{teamsService.getTeam('midwest', 11) | team: 'name'}}
3 {{teamsService.getTeam('midwest', 3) | team: 'name'}}
14 {{teamsService.getTeam('midwest', 14) | team: 'name'}}
7 {{teamsService.getTeam('midwest', 7) | team: 'name'}}
10 {{teamsService.getTeam('midwest', 10) | team: 'name'}}
2 {{teamsService.getTeam('midwest', 2) | team: 'name'}}
15 {{teamsService.getTeam('midwest', 15) | team: 'name'}}


{% extends "mails/messages/activity_base.html" %} {% load i18n %} {% block message %}
{% blocktrans context 'email' %} Some details of the team activity you are a part of have changed: {% endblocktrans %}
{% blocktrans context 'email' %} Updated details below: {% endblocktrans %}
{{ team_name }}
"{{ title }}"
{% include 'mails/messages/partial/team_slot.html' %}{% blocktrans context 'email' %} Please view your team from the activity page to see the changes. {% endblocktrans %}
{% endblock %} {% block end_message %}
{% blocktrans context 'email' %} If you are unable to participate, please withdraw via the activity page so that others can take your place. {% endblocktrans %}
{% endblock %}


final
or abstract
.
Utility classes have all fields and methods declared as static
.
Making them final
prevents them from being accidentally subclassed.
Example:
public class UtilityClass {
public static void foo() {}
}
After the quick-fix is applied:
public final class UtilityClass {
public static void foo() {}
}


// direct equivalent of PersonClass
let
PersonType2
=
(
function
()
{
"use strict"
;
const
PersonType2
=
function
(
name
)
{
// make sure the function was called with new
if
(
typeof
new
.
target
===
"undefined"
)
{
throw
new
Error
(
"Constructor must be called with new."
);
}
this
.
name
=
name
;
}
Object
.
defineProperty
(
PersonType2
.
prototype
,
"sayName"
,
{
value
:
function
()
{
// make sure the method wasn't called with new
if
(
typeof
new
.
target
!==
"undefined"
)
{
throw
new
Error
(
"Method cannot be called with new."
);
}
console
.
log
(
this
.
name
);
},
enumerable
:
false
,
writable
:
true
,
configurable
:
true
});
return
PersonType2
;
}());


A wrapper built around the libLBFGS optimization library by Naoaki Okazaki. The lbfgs package implements both the Limited-memory Broyden-Fletcher-Goldfarb-Shanno (L-BFGS) and the Orthant-Wise Quasi-Newton Limited-Memory (OWL-QN) optimization algorithms. The L-BFGS algorithm solves the problem of minimizing an objective, given its gradient, by iteratively computing approximations of the inverse Hessian matrix. The OWL-QN algorithm finds the optimum of an objective plus the L1-norm of the problem's parameters. The package offers a fast and memory-efficient implementation of these optimization routines, which is particularly suited for high-dimensional problems.
| Version: | 1.2.1 |
| Imports: | Rcpp (≥ 0.11.2) |
| LinkingTo: | Rcpp |
| Published: | 2014-08-31 |
| Author: | Antonio Coppola [aut, cre, cph], Brandon Stewart [aut, cph], Naoaki Okazaki [aut, cph], David Ardia [ctb, cph], Dirk Eddelbuettel [ctb, cph], Katharine Mullen [ctb, cph], Jorge Nocedal [ctb, cph] |
| Maintainer: | Antonio Coppola <acoppola at college.harvard.edu> |
| License: | GPL-2 | GPL-3 [expanded from: GPL (≥ 2)] |
| NeedsCompilation: | yes |
| Materials: | README |
| In views: | Optimization |
| CRAN checks: | lbfgs results |
| Reference manual: | lbfgs.pdf |
| Vignettes: |
An R Package for Limited-memory BFGS Optimization |
| Package source: | lbfgs_1.2.1.tar.gz |
| Windows binaries: | r-devel: lbfgs_1.2.1.zip, r-release: lbfgs_1.2.1.zip, r-oldrel: lbfgs_1.2.1.zip |
| OS X binaries: | r-release: lbfgs_1.2.1.tgz, r-oldrel: lbfgs_1.2.1.tgz |
| Reverse imports: | GauPro, nlmixr, splitfngr |
| Reverse suggests: | optimx, PlackettLuce, regsem |
Please use the canonical form https://CRAN.R-project.org/package=lbfgs to link to this page.


GPA for this term
Total GPA
Enter a subject degree
Enter a subject credit
Add subject
Degree
Hours
Calculate GPA
Your GPA is:


DOCTOR DOLITTLE (1998) A Film Review by Ted Prigge Copyright 1999 Ted Prigge
Director: Betty Thomas Writers: Nat Mauldin and Larry Levin (based on the novel by Hugh Lofting) Starring: Eddie Murphy, Ossie Davis, Kristen Wilson, Oliver Platt, Richard Schiff, Jeffrey Tambor, Kyla Pratt, Ramon-Simone, Peter Boyle, Norm MacDonald, Chris Rock, Albert Brooks, Reni Santoni, John Leguizamo, Julie Kavner, Gary Shandling, Ellen DeGeneres, Brian Doyle-Murphy, Jenna Elfman, Gilbert Gottfried, Paul Reubens, Jonathan Lipnicki
I just can't believe there was actually a bit of controversy surrounding this film. Though aimed specifically at children (and those of childish minds), this film was awarded a "PG-13" rating for basically toilet humor, and it still grossed well over one hundred million. But upon its release, many critics were almost brutal in their dislike for the film. Nathaniel R. Atcheson, for instance, completely flew off the handle and said that this film made him want to vomit. "Feces are never funny," he proclaimed, as he completely dismissed toilet humor as an adequate artform, especially not as entertainment for kids. Roger Ebert rebuked that (though not directly). In his review, he claimed that toilet humor is not at all a bad thing, and in fact is part of the grounds for developing a sense of humor. I agree. There are no rules to comedy, and in fact anything can work as humor - that's the point of it: laughing at the shit life drops on us, so to speak. In fact, if I had not been taught at a very young age to laugh at flatuation, I would have never survived the way Elementary School and Junior High chose to torment me because of the pronunication of my last name (and they didn't even know what a "prig" was).
Ebert awarded the film a 3-star recommendation because of this. I won't even come close to taking it that far. Yes, I agree that toilet humor is a valid type of comedy, as I agree that anything and everything can be a valid type of comedy. But that doesn't mean this new adaptation of "Dr. Dolittle" is actually funny, just because it was attacked for its application of toilet humor. In fact, I think I may have grimaced once, if not twice, during the entire length of this film.  There's one thing wrong with them: they're not funny. You've heard a bad joke, right?  Well, think of an entire 90 minutes of jokes exactly like that, and you have the newly enhanced "Dr. Dolittle," which has nothing to do with the original Rex Harrison musical classic except that for namesake and its very basic skin-and-bones gimmick (that a man can hear animals talk).
The fact that this is a loose remake is not a problem, though: I don't care what they do with a remake, even if they decided to remake "Citizen Kane" starring Carrot Top; as long as they just made it work. This one doesn't, and it's not even in the plotting. This one deals with a John Dolittle (Eddie Murphy) who, as a kid, could hear animals talk, notably his dog/best friend (voiced by Ellen Degeneres), but lost the ability when his father (Ossie Davis) took the dog away. He's grown up to be a successful doctor, with a pretty wife (Kristen Wilson), and two nice daughters (Kyla Pratt and "The Cosby Show"'s Ramon-Simone), and has since forgotten all about his childhood ability. One day, for no real reason, animals start talking to him, first by a dog named Lucky (voiced by Norm MacDonald), who is almost hit by him when driving, and then by numerous others.
This begins to tax on his sanity, and when no one believes him, and he's making unbelievably awkward decisions to accomodate his ability (such as helping all the animals like the world's greatest veteranarian so they'll just leave him alone - yeah, that's your cure, John), he winds up in a nuthouse. Meanwhile, his hospital staff is merging with another one (in the form of Peter Boyle) and his two head assistants are divided into the conservative nice guy (underrated character actor Richard Schiff) and greedy-as-balls pseudo-villain (the great Oliver Platt), so there's a bit of forced let's-take-up-some-screen-time conflict going on other than the animals/sanity bit.
The most humorous thing about this film is the celebrities who play the animals, but not really because of the writing involved. I more or less was mildly amused throughout the film as I distracted myself from the boredom I had succumb to by playing "Guess Whose Voice That Is?"  John Leguiziamo shows up as a rat. Julie Kavner and Gary Shandling make a cameo as a pair of bickering pigeons. And (my favorite) Albert Brooks stars as a suicidal tiger. Not that their scenes are actually gut-bursting or anything. Brooks, especially, isn't given anything very interesting to talk about, even when it has the potential to be the funniest thing about the movie (and it probably is anyway). Instead, his subplot is played nearly straight, and since the idea of a sucidal tiger can probably only be played as comedy, his subplot comes off as disturbingly, well, Live-Action-Disney-esque. Never would I have thought that a side story involving a suicidal tiger would be the cherry on the top of a dramatic arc, but then again, I can be easily surprised.
The handling of the animals should have worked, though, as the foundation of the comedy in this film. There are many opportunities for jokes, and it has the right fallacy: that the animals are exactly like humans personality-wise, but have bitchings about their own kind of lives. Nothing they say is particularly humorous, though, and with Murphy playing the straight man (and nicely, I should add - though this film doesn't require old school Eddie Murphy tactics, it does show great modesty on his behalf...or, at the very least, insecurity to take a big comic risk after the result of his early-to-mid 90s career), there's really nothing to keep interest. The result is that the film is a big fat bore, and after about a half hour or so of unfunny funniness, I began checking my watch repeatedly, wondering how long I had left until I could watch something with a little more class. Say, "Dumb and Dumber."
MY RATING (out of 4): **
Homepage at: http://www.geocities.com/Hollywood/Hills/8335/
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


procedure SetPoints(Points: TArrayOfFloatPoint); override;
SetPoints can be called to set all points at once.


Grilled cod with coco de paimpol beans recipe
by Angela HartnettThis fish recipe makes a delicious dinner for four. Grilled cod is served with coco de paimpol beans and buttered, toasted breadcrumbs.
Prep time: 10 minutes | Cooking time: 45 minutes
SERVES
Four
INGREDIENTS
- Olive oil, for frying and greasing
- 1 carrot, diced
- 1 onion, diced
- 1 stick of celery, diced
- 2 garlic cloves, crushed
- 50g pancetta, chopped
- 300g fresh coco beans
- 4 x 150g cod fillets, skin on [I cut one filleted piece into 150g portions]
- 1 tbsp chopped parsley
- 50g butter
- 100g panko breadcrumbs
- ½ tsp chopped thyme leaves
- Zest of 1 lemon
METHOD
- Add a touch of olive oil to a pan and sweat the diced vegetables with the garlic for five minutes until they start to get soft but not coloured. Add the pancetta and cook for a further two minutes then remove from the heat and tie the contents of the pan into a muslin cloth. Leave to one side.
- Place the coco beans in a clean pan and cover with cold water. Add the muslin bundle and bring to a boil. Turn down to a simmer and cook until the beans are soft but not mushy, about 30 minutes.
- Grease a baking tray with oil and place the cod pieces skin-side down. Grill for five to eight minutes until cooked through. The best way to tell is to gently push the thin handle of a kitchen spoon through the flesh of one of the fillets; if the flesh shows no resistance, it is cooked.
- Open the muslin cloth and add everything to the beans in the pan. There should still be enough liquid to form a nice ragou. Keep warm and stir through the parsley.
- Melt the butter in a pan and stir through the breadcrumbs and thyme. Toast until golden brown. Stir in the lemon zest.
- Dived the coco beans between warm dishes and place cod fillets on top. Finish with the toasted breadcrumbs.


About Elder renter
YOU can help the retired elderly when they need a job. This great website allows you to rent any of these kind and handy elderly men they are great for cooking and car repairs they also have much knowledge to share with you.How? you may ask well its simple Click the catalog button above and it will redirect you to our large colection of elders.you can rent up to two at once.Maximum rent time 8 hours. For cooking and small car repairs ONLY.Why you may ask well why not how many times have you wanted to help the elderly Well now you can call now and you get two hours for the price of one thats right you heard me 2 hours for the price of one what a deal with but wait theres more for only seven easy payments of 9999.99 you enter in a raffle to win 50000 dollars


Please note: Beginning July 1, 2017, information on Contracts over $10,000 for ACOA is only available on Canada's Open Government Portal
Please select a reporting period: