<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.apertium.org/w/index.php?action=history&amp;feed=atom&amp;title=Apertium-apy%2FTranslation</id>
	<title>Apertium-apy/Translation - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.apertium.org/w/index.php?action=history&amp;feed=atom&amp;title=Apertium-apy%2FTranslation"/>
	<link rel="alternate" type="text/html" href="https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;action=history"/>
	<updated>2026-04-19T10:01:16Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.34.1</generator>
	<entry>
		<id>https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=50841&amp;oldid=prev</id>
		<title>Unhammer: /* servlet.py */</title>
		<link rel="alternate" type="text/html" href="https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=50841&amp;oldid=prev"/>
		<updated>2014-11-06T09:38:41Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;servlet.py&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;Revision as of 09:38, 6 November 2014&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 9:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 9:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;==servlet.py==&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;==servlet.py==&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;div&gt;When you start servlet, you choose the number of processes with the -j switch. Each process has its own dict of pipelines and pipeline_locks. So in one servlet process, there might be an TranslateHandler.pipelines[(&quot;eng&quot;,&quot;kaz&quot;)]=(fd_in, fd_out) and a corresponding TranslateHandler.pipeline_locks[(&quot;eng&quot;,&quot;kaz&quot;)]=&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;threading&lt;/del&gt;.&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;Rlock&lt;/del&gt;() (this is the pipeline and translock, respectively, sent to translate.py&#039;s translate() function). &lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;When you start servlet, you choose the number of processes with the -j switch. Each process has its own dict of pipelines and pipeline_locks. So in one servlet process, there might be an TranslateHandler.pipelines[(&quot;eng&quot;,&quot;kaz&quot;)]=(fd_in, fd_out) and a corresponding TranslateHandler.pipeline_locks[(&quot;eng&quot;,&quot;kaz&quot;)]=&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;toro&lt;/ins&gt;.&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;Lock&lt;/ins&gt;() (this is the pipeline and translock, respectively, sent to translate.py&#039;s translate() function). &lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;When TranslateHandler.get is called, it first ensures e.g. eng-kaz is started if it does flushing (the function &amp;lt;code&amp;gt;startPipeline()&amp;lt;/code&amp;gt;), the first and last process of the pipeline will be assigned to self.pipelines[(&quot;eng&quot;,&quot;kaz&quot;)] when the pipeline is started. Non-flushing pairs get the value None.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;When TranslateHandler.get is called, it first ensures e.g. eng-kaz is started if it does flushing (the function &amp;lt;code&amp;gt;startPipeline()&amp;lt;/code&amp;gt;), the first and last process of the pipeline will be assigned to self.pipelines[(&quot;eng&quot;,&quot;kaz&quot;)] when the pipeline is started. Non-flushing pairs get the value None.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Unhammer</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=50840&amp;oldid=prev</id>
		<title>Unhammer: /* servlet.py */</title>
		<link rel="alternate" type="text/html" href="https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=50840&amp;oldid=prev"/>
		<updated>2014-11-06T09:38:29Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;servlet.py&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;Revision as of 09:38, 6 November 2014&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 9:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 9:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;==servlet.py==&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;==servlet.py==&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;div&gt;When you start servlet, you choose the number of processes with the -j switch. Each process has its own dict of pipelines and pipeline_locks. So in one servlet process, there might be an TranslateHandler.&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;pielines&lt;/del&gt;[(&quot;eng&quot;,&quot;kaz&quot;)]=(fd_in, fd_out) and a corresponding TranslateHandler.&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;pieline_locks&lt;/del&gt;[(&quot;eng&quot;,&quot;kaz&quot;)]=threading.Rlock() (this is the pipeline and translock, respectively, sent to translate.py&#039;s translate() function). &lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;When you start servlet, you choose the number of processes with the -j switch. Each process has its own dict of pipelines and pipeline_locks. So in one servlet process, there might be an TranslateHandler.&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;pipelines&lt;/ins&gt;[(&quot;eng&quot;,&quot;kaz&quot;)]=(fd_in, fd_out) and a corresponding TranslateHandler.&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;pipeline_locks&lt;/ins&gt;[(&quot;eng&quot;,&quot;kaz&quot;)]=threading.Rlock() (this is the pipeline and translock, respectively, sent to translate.py&#039;s translate() function). &lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;div&gt;When TranslateHandler.get is called, it first ensures e.g. eng-kaz is started (the function &amp;lt;code&amp;gt;&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;runPipeline&lt;/del&gt;()&amp;lt;/code&amp;gt;), the first and last process of the pipeline will be assigned to self.pipelines[(&quot;eng&quot;,&quot;kaz&quot;)] when the pipeline is started.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;When TranslateHandler.get is called, it first ensures e.g. eng-kaz is started&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt; if it does flushing&lt;/ins&gt; (the function &amp;lt;code&amp;gt;&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;startPipeline&lt;/ins&gt;()&amp;lt;/code&amp;gt;), the first and last process of the pipeline will be assigned to self.pipelines[(&quot;eng&quot;,&quot;kaz&quot;)] when the pipeline is started&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;. Non-flushing pairs get the value None&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;a class=&quot;mw-diff-movedpara-right&quot; title=&quot;Paragraph was moved. Click to jump to old location.&quot; href=&quot;#movedpara_7_2_lhs&quot;&gt;&amp;#x26AB;&lt;/a&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;&lt;a name=&quot;movedpara_5_0_rhs&quot;&gt;&lt;/a&gt;&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;Then&lt;/ins&gt; &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;it starts the&lt;/ins&gt; translation&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;,&lt;/ins&gt; &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;which,&lt;/ins&gt; &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;like TranslateHandler.get, is&lt;/ins&gt; a &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;coroutine. Thus we can have several calls to get which get queued up by the&lt;/ins&gt; &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;ioloop&lt;/ins&gt;, but each pipeline has a lock (per servlet process). We can at most start one pipeline&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt; per pair&lt;/ins&gt; per servlet process, and requests for the same pipeline have to wait for their turn (which is not too long due to translateSplitting, see above), but we can handle several translation requests for different pipelines in parallell.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;div&gt;Then it starts the translation in a separate thread, using &amp;lt;code&amp;gt;start_worker()&amp;lt;/code&amp;gt; from ThreadableMixin pattern described at http://umumble.com/blogs/server_side_optimization/66/ with the callback &amp;lt;code&amp;gt;handleTranslation()&amp;lt;/code&amp;gt;  – this pattern just ensures the servlet process doesn&#039;t block when waiting for translation results.&lt;/div&gt;&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-added&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-added&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-added&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;a class=&quot;mw-diff-movedpara-left&quot; title=&quot;Paragraph was moved. Click to jump to new location.&quot; href=&quot;#movedpara_5_0_rhs&quot;&gt;&amp;#x26AB;&lt;/a&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;div&gt;&lt;a name=&quot;movedpara_7_2_lhs&quot;&gt;&lt;/a&gt;&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;So&lt;/del&gt; &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;each&lt;/del&gt; translation &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;request&lt;/del&gt; &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;gets&lt;/del&gt; a &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;separate&lt;/del&gt; &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;thread&lt;/del&gt;, but each pipeline has a lock (per servlet process). We can at most start one pipeline per servlet process, and requests for the same pipeline have to wait for their turn (which is not too long due to translateSplitting, see above), but we can handle several translation requests for different pipelines in parallell&lt;del class=&quot;diffchange diffchange-inline&quot;&gt; since they all spawn off new threads&lt;/del&gt;.&lt;/div&gt;&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-added&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Unhammer</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=50839&amp;oldid=prev</id>
		<title>Unhammer: /* translate.py */</title>
		<link rel="alternate" type="text/html" href="https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=50839&amp;oldid=prev"/>
		<updated>2014-11-06T09:33:26Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;translate.py&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;Revision as of 09:33, 6 November 2014&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 2:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 2:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;==translate.py==&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;==translate.py==&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;div&gt;The function translate() is the main entry point to translation. It expects a text string, a lock&lt;del class=&quot;diffchange diffchange-inline&quot;&gt; (threading.Rlock)&lt;/del&gt; and a pipeline (a pair of input/output file descriptors). The lock is there to make sure only one process can do translation on a certain pipeline at any one time. Each pipeline should have its own &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;Rlock&lt;/del&gt;.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;The function translate() is the main entry point to translation. It expects a text string, a lock and a pipeline (a pair of input/output file descriptors&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;) or a command (for pairs that can&#039;t NUL flush&lt;/ins&gt;). The lock is there to make sure only one process can do translation on a certain pipeline at any one time. Each pipeline should have its own &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;lock&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;div&gt;The function translateNULFlush() first deformats the text, then sends that into the input fd, then reads the output fd until it sees a NUL byte. Then it reformats and returns. It&#039;s wrapped in &quot;with &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;translock&lt;/del&gt;&quot; so we make sure we don&#039;t read translations based on other people&#039;s input …&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;The function translateNULFlush() first deformats the text, then sends that into the input fd, then reads the output fd until it sees a NUL byte. Then it reformats and returns. It&#039;s wrapped in &quot;with &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;lock&lt;/ins&gt;&quot; so we make sure we don&#039;t read translations based on other people&#039;s input …&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;We could have defined translate() as just &amp;lt;code&amp;gt;return translateNULFlush(toTranslate, translock, pipeline)&amp;lt;/code&amp;gt;, but then what if someone sends in a huge text? We&#039;d lock up that pipeline for too long, and everyone else would have to wait. &amp;lt;smaller&amp;gt;Also, we&#039;d fill up the FIFO buffers: since we don&#039;t read the output of translation until we&#039;ve sent in all the input, we would be trying to push in more data into the input file descriptor, but the buffer would be full and the program would hang until someone read off the output file descriptor.&amp;lt;/smaller&amp;gt; So to solve that, we split the input text up into chunks, and send one chunk at a time into translateNULflush. So translate() calls translateSplitting() once which calls translateNULFlush() a bunch of times (or only once for very short texts).&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;We could have defined translate() as just &amp;lt;code&amp;gt;return translateNULFlush(toTranslate, translock, pipeline)&amp;lt;/code&amp;gt;, but then what if someone sends in a huge text? We&#039;d lock up that pipeline for too long, and everyone else would have to wait. &amp;lt;smaller&amp;gt;Also, we&#039;d fill up the FIFO buffers: since we don&#039;t read the output of translation until we&#039;ve sent in all the input, we would be trying to push in more data into the input file descriptor, but the buffer would be full and the program would hang until someone read off the output file descriptor.&amp;lt;/smaller&amp;gt; So to solve that, we split the input text up into chunks, and send one chunk at a time into translateNULflush. So translate() calls translateSplitting() once which calls translateNULFlush() a bunch of times (or only once for very short texts).&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-added&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;==servlet.py==&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;==servlet.py==&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Unhammer</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=48285&amp;oldid=prev</id>
		<title>Unhammer: /* servlet.py */</title>
		<link rel="alternate" type="text/html" href="https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=48285&amp;oldid=prev"/>
		<updated>2014-04-25T16:10:34Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;servlet.py&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;Revision as of 16:10, 25 April 2014&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 12:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 12:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;When you start servlet, you choose the number of processes with the -j switch. Each process has its own dict of pipelines and pipeline_locks. So in one servlet process, there might be an TranslateHandler.pielines[(&quot;eng&quot;,&quot;kaz&quot;)]=(fd_in, fd_out) and a corresponding TranslateHandler.pieline_locks[(&quot;eng&quot;,&quot;kaz&quot;)]=threading.Rlock() (this is the pipeline and translock, respectively, sent to translate.py&#039;s translate() function). &lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;When you start servlet, you choose the number of processes with the -j switch. Each process has its own dict of pipelines and pipeline_locks. So in one servlet process, there might be an TranslateHandler.pielines[(&quot;eng&quot;,&quot;kaz&quot;)]=(fd_in, fd_out) and a corresponding TranslateHandler.pieline_locks[(&quot;eng&quot;,&quot;kaz&quot;)]=threading.Rlock() (this is the pipeline and translock, respectively, sent to translate.py&#039;s translate() function). &lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;div&gt;When TranslateHandler.get is called, it first ensures e.g. eng-kaz is started (the function runPipeline()), the first and last process of the pipeline will be assigned to self.pipelines[(&quot;eng&quot;,&quot;kaz&quot;)] when the pipeline is started.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;When TranslateHandler.get is called, it first ensures e.g. eng-kaz is started (the function &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;&amp;lt;code&amp;gt;&lt;/ins&gt;runPipeline()&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;&amp;lt;/code&amp;gt;&lt;/ins&gt;), the first and last process of the pipeline will be assigned to self.pipelines[(&quot;eng&quot;,&quot;kaz&quot;)] when the pipeline is started.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;div&gt;Then it starts the translation in a separate thread, using &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;the&lt;/del&gt; ThreadableMixin pattern described at http://umumble.com/blogs/server_side_optimization/66/ – this just ensures the servlet process doesn&#039;t block when waiting for translation results.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;Then it starts the translation in a separate thread, using &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;&amp;lt;code&amp;gt;start_worker()&amp;lt;/code&amp;gt; from&lt;/ins&gt; ThreadableMixin pattern described at http://umumble.com/blogs/server_side_optimization/66/&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt; with the callback &amp;lt;code&amp;gt;handleTranslation()&amp;lt;/code&amp;gt; &lt;/ins&gt; – this&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt; pattern&lt;/ins&gt; just ensures the servlet process doesn&#039;t block when waiting for translation results.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;So each translation request gets a separate thread, but each pipeline has a lock (per servlet process). We can at most start one pipeline per servlet process, and requests for the same pipeline have to wait for their turn (which is not too long due to translateSplitting, see above), but we can handle several translation requests for different pipelines in parallell since they all spawn off new threads.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Unhammer</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=48283&amp;oldid=prev</id>
		<title>Unhammer: /* servlet.py */</title>
		<link rel="alternate" type="text/html" href="https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=48283&amp;oldid=prev"/>
		<updated>2014-04-25T16:00:11Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;servlet.py&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;Revision as of 16:00, 25 April 2014&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 13:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 13:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;When TranslateHandler.get is called, it first ensures e.g. eng-kaz is started (the function runPipeline()), the first and last process of the pipeline will be assigned to self.pipelines[(&quot;eng&quot;,&quot;kaz&quot;)] when the pipeline is started.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;When TranslateHandler.get is called, it first ensures e.g. eng-kaz is started (the function runPipeline()), the first and last process of the pipeline will be assigned to self.pipelines[(&quot;eng&quot;,&quot;kaz&quot;)] when the pipeline is started.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;Then it starts the translation in a separate thread, using the ThreadableMixin pattern described at http://umumble.com/blogs/server_side_optimization/66/ – this just ensures the servlet process doesn&#039;t block when waiting for translation results.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Unhammer</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=48282&amp;oldid=prev</id>
		<title>Unhammer: /* translate.py */</title>
		<link rel="alternate" type="text/html" href="https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=48282&amp;oldid=prev"/>
		<updated>2014-04-25T15:57:14Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;translate.py&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;Revision as of 15:57, 25 April 2014&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 7:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 7:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;We could have defined translate() as just &amp;lt;code&amp;gt;return translateNULFlush(toTranslate, translock, pipeline)&amp;lt;/code&amp;gt;, but then what if someone sends in a huge text? We&#039;d lock up that pipeline for too long, and everyone else would have to wait. &amp;lt;smaller&amp;gt;Also, we&#039;d fill up the FIFO buffers: since we don&#039;t read the output of translation until we&#039;ve sent in all the input, we would be trying to push in more data into the input file descriptor, but the buffer would be full and the program would hang until someone read off the output file descriptor.&amp;lt;/smaller&amp;gt; So to solve that, we split the input text up into chunks, and send one chunk at a time into translateNULflush. So translate() calls translateSplitting() once which calls translateNULFlush() a bunch of times (or only once for very short texts).&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;We could have defined translate() as just &amp;lt;code&amp;gt;return translateNULFlush(toTranslate, translock, pipeline)&amp;lt;/code&amp;gt;, but then what if someone sends in a huge text? We&#039;d lock up that pipeline for too long, and everyone else would have to wait. &amp;lt;smaller&amp;gt;Also, we&#039;d fill up the FIFO buffers: since we don&#039;t read the output of translation until we&#039;ve sent in all the input, we would be trying to push in more data into the input file descriptor, but the buffer would be full and the program would hang until someone read off the output file descriptor.&amp;lt;/smaller&amp;gt; So to solve that, we split the input text up into chunks, and send one chunk at a time into translateNULflush. So translate() calls translateSplitting() once which calls translateNULFlush() a bunch of times (or only once for very short texts).&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;==servlet.py==&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;When you start servlet, you choose the number of processes with the -j switch. Each process has its own dict of pipelines and pipeline_locks. So in one servlet process, there might be an TranslateHandler.pielines[(&quot;eng&quot;,&quot;kaz&quot;)]=(fd_in, fd_out) and a corresponding TranslateHandler.pieline_locks[(&quot;eng&quot;,&quot;kaz&quot;)]=threading.Rlock() (this is the pipeline and translock, respectively, sent to translate.py&#039;s translate() function). &lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-addedline diff-side-added&quot;&gt;&lt;div&gt;When TranslateHandler.get is called, it first ensures e.g. eng-kaz is started (the function runPipeline()), the first and last process of the pipeline will be assigned to self.pipelines[(&quot;eng&quot;,&quot;kaz&quot;)] when the pipeline is started.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Unhammer</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=48280&amp;oldid=prev</id>
		<title>Unhammer: Created page with &quot;How translation currently works in APY:  ==translate.py== The function translate() is the main entry point to translation. It expects a text string, a lock (threading.Rlock) a...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.apertium.org/w/index.php?title=Apertium-apy/Translation&amp;diff=48280&amp;oldid=prev"/>
		<updated>2014-04-25T15:16:34Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;How translation currently works in APY:  ==translate.py== The function translate() is the main entry point to translation. It expects a text string, a lock (threading.Rlock) a...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;How translation currently works in APY:&lt;br /&gt;
&lt;br /&gt;
==translate.py==&lt;br /&gt;
The function translate() is the main entry point to translation. It expects a text string, a lock (threading.Rlock) and a pipeline (a pair of input/output file descriptors). The lock is there to make sure only one process can do translation on a certain pipeline at any one time. Each pipeline should have its own Rlock.&lt;br /&gt;
&lt;br /&gt;
The function translateNULFlush() first deformats the text, then sends that into the input fd, then reads the output fd until it sees a NUL byte. Then it reformats and returns. It&amp;#039;s wrapped in &amp;quot;with translock&amp;quot; so we make sure we don&amp;#039;t read translations based on other people&amp;#039;s input …&lt;br /&gt;
&lt;br /&gt;
We could have defined translate() as just &amp;lt;code&amp;gt;return translateNULFlush(toTranslate, translock, pipeline)&amp;lt;/code&amp;gt;, but then what if someone sends in a huge text? We&amp;#039;d lock up that pipeline for too long, and everyone else would have to wait. &amp;lt;smaller&amp;gt;Also, we&amp;#039;d fill up the FIFO buffers: since we don&amp;#039;t read the output of translation until we&amp;#039;ve sent in all the input, we would be trying to push in more data into the input file descriptor, but the buffer would be full and the program would hang until someone read off the output file descriptor.&amp;lt;/smaller&amp;gt; So to solve that, we split the input text up into chunks, and send one chunk at a time into translateNULflush. So translate() calls translateSplitting() once which calls translateNULFlush() a bunch of times (or only once for very short texts).&lt;/div&gt;</summary>
		<author><name>Unhammer</name></author>
		
	</entry>
</feed>