<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Je t'embrasse</title>
	<atom:link href="http://www.jjinno.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jjinno.com</link>
	<description>Salutations from Silicon Valley, California</description>
	<lastBuildDate>Thu, 22 Mar 2012 17:02:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>std::list iterate + erase</title>
		<link>http://www.jjinno.com/2012/01/20/stdlist-iterate-erase/</link>
		<comments>http://www.jjinno.com/2012/01/20/stdlist-iterate-erase/#comments</comments>
		<pubDate>Sat, 21 Jan 2012 00:38:33 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C/C++]]></category>

		<guid isPermaLink="false">http://www.jjinno.com/?p=328</guid>
		<description><![CDATA[I had an interesting problem the other day where I needed to iterate over an std::list, removing invalid items from that list. The only problem was that the list is a list of pointers, each pointing to allocated values that must be freed. Here is what I started with: As you can see, the problem [...]]]></description>
			<content:encoded><![CDATA[<p>I had an interesting problem the other day where I needed to iterate over an std::list, removing invalid items from that list. The only problem was that the list is a list of pointers, each pointing to allocated values that must be freed.</p>
<p>Here is what I started with:</p>
<pre class="brush: cpp; title: ; notranslate">#include &lt;stdio.h&gt;
#include &lt;list&gt;
using std::list;

struct COORD { int x,y; };

int i,j;
struct COORD *c;
list&lt;struct COORD *&gt; coordList;
list&lt;struct COORD *&gt;::iterator it1;

/* Prep the list */
for (i=0, j=0; i&lt;10, j&lt;10; i++, j++) {
    c = (struct COORD *)malloc(sizeof(struct COORD));
    c-&gt;x = i; c-&gt;y = j;
    coordList.push_back(c);
}

/* Display while erasing all - for loop */
for (it1=coordList.begin(); it1!=coordList.end(); it1++) {
    c = (*it1);
    printf(&quot;A: (%d,%d)\n&quot;, c-&gt;x, c-&gt;y);
    coordList.erase(it1); /* segfault */
    free(c);
}</pre>
<p>As you can see, the problem with this is in the .erase() call. As soon as the item is taken out of the list, "it" still points to that item. Even if you get lucky once or twice, eventually "it1" will point to a value outside of the bounds of coordList.begin() and coordList.end(). At this point, you will continue, because it1!=coordList.end()... and you will segfault when you try to erase the now-invalid iterator.</p>
<p>The fix is to not auto-increment the iterator.</p>
<pre class="brush: cpp; title: ; notranslate">/* Display while erasing all - for loop */
for (it=coordList.begin(); it!=coordList.end(); ) {
    c = (*it);
    printf(&quot;A: (%d,%d)\n&quot;, c-&gt;x, c-&gt;y);
    coordList.erase(it++);
    free(c);
}</pre>
<p>Note that by removing the increment step from the loop argument, we have to do the increment ourselves.</p>
<p>Of course, you could also use the power of the .erase() method, which states that the return value is:</p>
<blockquote><p>A bidirectional iterator pointing to the new location of the element that followed the last element erased by the function call, which is the list end if the operation erased the last element in the sequence.</p></blockquote>
<p>Because of that we can do something a bit fancier:</p>
<pre class="brush: cpp; title: ; notranslate">/* Display while erasing some - for loop #2 */
for (it=coordList.begin(); it!=coordList.end(); ) {
    c = (*it);
    printf(&quot;B: (%d,%d)\n&quot;, c-&gt;x, c-&gt;y);
    it = coordList.erase(it);
    free(c);
}</pre>
<p>See how we set the iterator value to the next available one by using the return value of the .erase() method. This is a relatively elegant solution, but that also is because we are always updating the iterator through use of the .erase() method.  If we had to limit the erase, only deleting odd values (for example), we would have to remember to increment that iterator (otherwise the loop would stay pointing at the same list element forever).</p>
<pre class="brush: cpp; title: ; notranslate">/* Display while erasing some - for loop #3 */
for (it=coordList.begin(); it!=coordList.end(); ) {
    c = (*it);

    if ((c-&gt;x % 2) == 1) {
        printf(&quot;C: (%d,%d)\n&quot;, c-&gt;x, c-&gt;y);
        it = coordList.erase(it);
        free(c);
    }
    else {
        ++it;
    }
}</pre>
<p>That's it. My trial-and-error wisdom, passed on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jjinno.com/2012/01/20/stdlist-iterate-erase/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Traversing a file in C</title>
		<link>http://www.jjinno.com/2011/12/24/traversing-a-file-in-c/</link>
		<comments>http://www.jjinno.com/2011/12/24/traversing-a-file-in-c/#comments</comments>
		<pubDate>Sun, 25 Dec 2011 07:11:49 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C/C++]]></category>

		<guid isPermaLink="false">http://www.jjinno.com/?p=323</guid>
		<description><![CDATA[I can not begin to tell you how useful the following code has been in my endeavors to do complicated forward-backward grep-esque searching. Along with the regular-expression matching that I have put together previously, this will round off pretty much everything you need to do your own fancy-grepping. The code below is based upon the [...]]]></description>
			<content:encoded><![CDATA[<p>I can not begin to tell you how useful the following code has been in my endeavors to do complicated forward-backward grep-esque searching.  Along with the regular-expression matching that I have put together previously, this will round off pretty much everything you need to do your own fancy-grepping.</p>
<p>The code below is based upon the fgetc() and fgets() functions.  The first two, rgetc() and rgets() are essentially the reverse of the original functions. They read from the file, but instead of moving the file-pointer forward, they move it back. Thus, you could start at end-of-file, and traverse all the way back to beginning-of-file.</p>
<pre class="brush: cpp; title: ; notranslate">
int
rgetc(FILE *stream)
{
  if (fseek(stream, -2, SEEK_CUR) == -1) return EOF;
  return fgetc(stream);
}

int
rgets(char *s, int size, FILE *stream)
{
  int n=0;
  int c;

  while (1) {
    if ((c = rgetc(stream)) == EOF) {
      /* if we are too close to BOF to rgetc() */
      if ((ftell(stream) &lt;= 2) &amp;&amp; (n+1 == 2)) {
        rewind(stream);
        n=2;
      }
      /* otherwise EOF == ERROR */
      else return EINVAL;
    }
    if (c == '\n') n++;
    if (n == 2) break;
  }

  if (fgets(s, size, stream) == NULL) return EINVAL;
  return 0;
}
</pre>
<p>Finally, there is always the time in which what you really want is to read without moving the file-pointer at all. This way, you get a character/line into a buffer, but you still have the same character/line pointed to at the end as you did at the beginning. (Very useful when you need to double-parse a line)</p>
<pre class="brush: cpp; title: ; notranslate">
int
tgetc(FILE *stream)
{
  if (fseek(stream, -1, SEEK_CUR) == -1) return EOF;
  return fgetc(stream);
}

int
tgets(char *s, int size, FILE *stream)
{
  int n=0;
  int c;

  while (1) {
    if ((c = rgetc(stream)) == EOF) {
      /* if we are too close to BOF to rgetc() */
      if ((ftell(stream) &lt;= 2) &amp;&amp; (n+1 == 2)) {
        rewind(stream);
        n=2;
      }
      /* otherwise EOF == ERROR */
      else return EINVAL;
    }
    if (c == '\n') n++;
    if (n == 1) break;
  }

  /* Look for a newline, otherwise EOF */
  if (fgets(s, size, stream) == NULL) return EINVAL;
  if (strstr(s, &quot;\n&quot;) == NULL) return EOF;
  return 0;
}
</pre>
<p>Trust me, if you want to grep through logs, going forward till X, backward from there till Y, find Z &#038; re-grep entire file for Z, and then locate the 3rd occurrence of the word "ERROR" also associated with Z... anyway, you get the point. Grep is useless. My functions RULE!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jjinno.com/2011/12/24/traversing-a-file-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C/C++ Regular Expressions</title>
		<link>http://www.jjinno.com/2011/11/18/cc-regular-expressions/</link>
		<comments>http://www.jjinno.com/2011/11/18/cc-regular-expressions/#comments</comments>
		<pubDate>Fri, 18 Nov 2011 22:11:36 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C/C++]]></category>

		<guid isPermaLink="false">http://www.jjinno.com/?p=313</guid>
		<description><![CDATA[I had to do some regular-expression matching the other day (a bit of a grep-esque application) The basic idea behind the "match" function is to provide a case-insensitive means of telling whether the "string" matches the "pattern". This is why I made this particular function a boolean. I find that this becomes much more powerful [...]]]></description>
			<content:encoded><![CDATA[<p>I had to do some regular-expression matching the other day (a bit of a grep-esque application)</p>
<pre class="brush: cpp; title: ; notranslate">#include &lt;stdio.h&gt;
#include &lt;regex.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;</pre>
<p>The basic idea behind the "match" function is to provide a case-insensitive means of telling whether the "string" matches the "pattern". This is why I made this particular function a boolean.  I find that this becomes much more powerful when used with a tokenizer, such that specific tokens are matched. (For example log-grepping for a specific user-level or process name)</p>
<pre class="brush: cpp; title: ; notranslate">bool
match(const char *string, const char *pattern)
{
  int status;
  char msg[1024];
  regex_t re;

  if(regcomp(&amp;re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE) != 0) {
    regerror(status, &amp;re, msg, 1024);
    fprintf(stderr, &quot;Error analyzing regular expression '%s': %s.\n&quot;,
            pattern, msg);
    return false;
  }

  status = regexec(&amp;re, string, (size_t)0, NULL, 0);
  regfree(&amp;re);

  if (status == REG_NOMATCH) return false;
  else if (status != 0) {
    regerror(status, &amp;re, msg, 1024);
    fprintf(stderr, &quot;Error analyzing regular expression '%s': %s.\n&quot;,
            pattern, msg);
    return false;
  }

  return true;
}</pre>
<p>Of course, sometimes matching does not go far enough (or in the previous example, sometimes your tokens are not always aligned). Which is why I created the regular-expression version of strstr().  This does exactly what you think, and searches for the regex "pattern" inside of "string".  The only difference is that if it is found, we want to return the substring. Likewise if not found, we return NULL.</p>
<pre class="brush: cpp; title: ; notranslate">char *
reSubstring(const char *string, const char *pattern)
{
  int        status, size, i;
  char       msg[1024];
  regex_t    re;
  regmatch_t pmatch[1];
  char       *p_buf;

  if(regcomp(&amp;re, pattern, REG_EXTENDED|REG_ICASE) != 0) {
    regerror(status, &amp;re, msg, 1024);
    fprintf(stderr, &quot;Error analyzing regular expression '%s': %s.\n&quot;,
            pattern, msg);
    return NULL;
  }

  status = regexec(&amp;re, string, (size_t)1, pmatch, 0);
  regfree(&amp;re);

  if (status == REG_NOMATCH) return NULL;
  else if (status != 0) {
    regerror(status, &amp;re, msg, 1024);
    fprintf(stderr, &quot;Error analyzing regular expression '%s': %s.\n&quot;,
            pattern, msg);
    return NULL;
  }

  size = (pmatch[0].rm_eo - pmatch[0].rm_so) + 1;
  p_buf = (char *)malloc(size);
  memset(p_buf, 0, size);

  for (i=pmatch[0].rm_so; i&lt;pmatch[0].rm_eo; i++)
    p_buf[i-pmatch[0].rm_so] = string[i];

  return p_buf;
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.jjinno.com/2011/11/18/cc-regular-expressions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pythons getoutput() ported to C/C++</title>
		<link>http://www.jjinno.com/2011/09/14/pythons-getcommandoutput-ported-to-cc/</link>
		<comments>http://www.jjinno.com/2011/09/14/pythons-getcommandoutput-ported-to-cc/#comments</comments>
		<pubDate>Wed, 14 Sep 2011 20:36:58 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C/C++]]></category>

		<guid isPermaLink="false">http://www.jjinno.com/?p=305</guid>
		<description><![CDATA[I ran into an issue the other day where, being an avid Python programmer, I was trying my best in C/C++ to mimic the command-output-capturing capabilities of Python. In an effort to produce a C/C++ version of the Python commands.getoutput() function, I ended up with the following: Although it does require a bit more information [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into an issue the other day where, being an avid Python programmer, I was trying my best in C/C++ to mimic the command-output-capturing capabilities of Python.<br />
In an effort to produce a C/C++ version of the Python commands.getoutput() function, I ended up with the following:</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;sys/wait.h&gt;

int
command_output(const char *cmd, char *output, int readlen)
{
    FILE *fp;
    int retval=0;
    memset(output, 0, readlen);

    /* return error if pipe error */
    if ( !(fp = (FILE*)popen(cmd, &quot;r&quot;)) ) return 1;

    if (fread(output, readlen, 1, fp) != 1) {
        retval = pclose(fp);
        if (WIFEXITED(retval)) return 0;
        /* Command did not execute correctly, or was killed */
        return 2;
    }

    /* guarantee NULL termination */
    output[readlen - 1] = '&#92;&#48;';
    pclose(fp);
    return 0;
}</pre>
<p>Although it does require a bit more information than the Python equivalent, it is extremely handy to have in one's toolbox.  Especially when interactions are forced between your C/C++ internals, and preexisting applications.  Note that this code operates with the same permissions as the application, thus cannot execute anything that the application does not have permission to execute.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jjinno.com/2011/09/14/pythons-getcommandoutput-ported-to-cc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>commands to subprocess transition</title>
		<link>http://www.jjinno.com/2011/05/20/commands-to-subprocess-transition/</link>
		<comments>http://www.jjinno.com/2011/05/20/commands-to-subprocess-transition/#comments</comments>
		<pubDate>Fri, 20 May 2011 22:47:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.jjinno.com/?p=300</guid>
		<description><![CDATA[The Python Documentation goes a long way in describing how to transition old code, but for some reason, fails to mention how to transition the legacy "commands.getoutput()" and "commands.getstatusoutput()" functionality into the new Python 2.6+ model of using the subprocess module. Here is the code required (direct pull/modification of original 2.5 commands module code):]]></description>
			<content:encoded><![CDATA[<p>The Python Documentation goes a long way in describing how to transition old code, but for some reason, fails to mention how to transition the legacy "commands.getoutput()" and "commands.getstatusoutput()" functionality into the new Python 2.6+ model of using the subprocess module.</p>
<p>Here is the code required (direct pull/modification of original 2.5 commands module code):</p>
<pre class="brush: python; title: ; notranslate">
# Get the output from a shell command into a string.
# The exit status is ignored; a trailing newline is stripped.
# Assume the command will work with '{ ... ; } 2&gt;&amp;1' around it..
def getoutput(cmd):
    return getstatusoutput(cmd)[1]

# Ditto but preserving the exit status.
# Returns a pair (sts, output)
def getstatusoutput(cmd):
    import subprocess, os
    p = subprocess.Popen('{ ' + cmd + '; } 2&gt;&amp;1',
                         shell=True, stdout=subprocess.PIPE)
    sts = os.waitpid(p.pid, 0)[1]
    text = p.stdout.read()
    p.stdout.close()
    if text[-1:] == '\n': text = text[:-1]
    return sts, text
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.jjinno.com/2011/05/20/commands-to-subprocess-transition/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pretty-Print for Python Dict/List/Tuple</title>
		<link>http://www.jjinno.com/2011/04/13/pretty-print-for-python-dictlisttuple/</link>
		<comments>http://www.jjinno.com/2011/04/13/pretty-print-for-python-dictlisttuple/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 00:43:27 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.jjinno.com/?p=284</guid>
		<description><![CDATA[I wrote this a while ago to give me a better view into complex nested structures Dict-of-List-of-Dict, etc. The benefit here is that these functions can be wrapped as a Python module, and imported to all your projects for debug. Enjoy.]]></description>
			<content:encoded><![CDATA[<p>I wrote this a while ago to give me a better view into complex nested structures Dict-of-List-of-Dict, etc.<br />
The benefit here is that these functions can be wrapped as a Python module, and imported to all your projects for debug.</p>
<p>Enjoy.</p>
<pre class="brush: python; title: ; notranslate">import sys

def newline():
    sys.stdout.write('\n')
    sys.stdout.flush()

def __type_quote(this):
    if type(this) == type(1): return str(this)
    else: return &quot;'&quot;+str(this)+&quot;'&quot;

def __has_children(parent):
    answer = False
    valid = [type([1,2]), type((1,2)), type({1:2})]
    if type(parent) == type([1,2]):
        for each in parent:
            if type(each) in valid: answer = True
    elif type(parent) == type((1,2)):
        answer = __has_children(list(parent))
    elif type(parent) == type({1:2}):
        for (key, value) in parent.items():
            if type(value) in valid: answer = True
    return answer

def __print_list(list, n=0, shrink=False, opener=&quot;[&quot;, closer=&quot;]&quot;):
    assert type(list) == type([])
    sp = &quot;&quot;.join([&quot; &quot;]*n)
    valid = [type([1,2]), type((1,2)), type({1:2})]

    # find the max index (for spacing of the format string)
    size = len(list)
    fstring = &quot;%s  %-&quot;+str(size)+&quot;s: &quot;

    # start printing stuff
    sys.stdout.write(opener)
    sys.stdout.flush()
    list.sort()
    for index in range(len(list)):
        newline()
        sys.stdout.write(fstring%(sp, index))
        sys.stdout.flush()
        this = list[index]
        if not __has_children(this) and type(this) in valid:
            if type(this) == type([1,2]) and len(this) &gt; 10 and shrink == True:
                sys.stdout.write(&quot;['%s', ... ,'%s']&quot;%(this[0], this[-1]))
                sys.stdout.flush()
            else:
                sys.stdout.write(str(this))
                sys.stdout.flush()
        elif type(this) == type([1,2]): __print_list(this, n+4+size)
        elif type(this) == type({1:2}): __print_dict(this, n+4+size)
        elif type(this) == type((1,2)): __print_tuple(this, n+4+size)
        else:
            sys.stdout.write(str(this))
            sys.stdout.flush()
    if len(list) &gt; 0:
        newline()
        sys.stdout.write(&quot;%s%s&quot;%(sp, closer))
    else: sys.stdout.write(&quot;%s&quot;%closer)
    sys.stdout.flush()

def __print_dict(dict, n=0, shrink=False):
    assert type(dict) == type({1:2})
    sp = &quot;&quot;.join([&quot; &quot;]*n)
    valid = [type([1,2]), type((1,2)), type({1:2})]

    # find the max key-size (for spacing of the format string)
    size = 0
    for key in dict.keys():
        if len(str(key)) &gt; size: size = len(str(key))
    fstring = &quot;%s  %-&quot;+str(size)+&quot;s: &quot;

    # start printing stuff
    sys.stdout.write(&quot;{&quot;)
    sys.stdout.flush()
    keys = dict.keys()
    keys.sort()
    for key in keys:
        newline()
        sys.stdout.write(fstring%(sp, key))
        sys.stdout.flush()
        this = dict[key]
        if not __has_children(this) and type(this) in valid:
            if type(this) == type([1,2]) and len(this) &gt; 10 and shrink == True:
                sys.stdout.write(&quot;[%s, ... ,%s]&quot;%(__type_quote(this[0]),
                                                  __type_quote(this[-1])))
                sys.stdout.flush()
            else:
                sys.stdout.write(str(this))
                sys.stdout.flush()
        elif type(this) == type([1,2]): __print_list(this, n+4+size)
        elif type(this) == type({1:2}): __print_dict(this, n+4+size)
        elif type(this) == type((1,2)): __print_tuple(this, n+4+size)
        else:
            sys.stdout.write(__type_quote(this))
            sys.stdout.flush()
    if len(dict.keys()) &gt; 0:
        newline()
        sys.stdout.write(&quot;%s}&quot;%sp)
    else: sys.stdout.write(&quot;}&quot;)
    sys.stdout.flush()

def __print_tuple(tup, n=0, shrink=False):
    assert type(tup) == type((1,2))
    __print_list(list(tup), n, shrink, opener=&quot;(&quot;, closer=&quot;)&quot;)

def print_dict(d):
    __print_dict(d, shrink=True)
    newline()

def print_list(l):
    __print_list(l, shrink=True)
    newline()

def print_tuple(t):
    __print_tuple(t, shrink=True)
    newline()
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.jjinno.com/2011/04/13/pretty-print-for-python-dictlisttuple/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parallel DHCP Clients</title>
		<link>http://www.jjinno.com/2011/02/23/parallel-dhcp-clients/</link>
		<comments>http://www.jjinno.com/2011/02/23/parallel-dhcp-clients/#comments</comments>
		<pubDate>Wed, 23 Feb 2011 18:59:25 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.jjinno.com/?p=152</guid>
		<description><![CDATA[There (as of 4.1.1-P1) is a bug in DHCP (at least the public release from the ISC) that can cause multiple DHCP client instances to accidentally generate the same "random" XIDs (transaction ID) and therefore mangle communications when operating in parallel. The problem is that they seed their randomness using "current time in seconds" + [...]]]></description>
			<content:encoded><![CDATA[<p>There (as of 4.1.1-P1) is a bug in DHCP (at least the public release from the ISC) that can cause multiple DHCP client instances to accidentally generate the same "random" XIDs (transaction ID) and therefore mangle communications when operating in parallel.  The problem is that they seed their randomness using "current time in seconds" + "some seed".  And as you quickly note, launching processes in parallel almost guarantees more than one process per second...</p>
<pre class="brush: cpp; title: ; notranslate">srandom(seed + cur_time);</pre>
<p>The fix, as I filed under [ISC-Bugs #21497] (thanks to <a href="https://lists.isc.org/pipermail/dhcp-users/2010-June/011512.html">Jeff Haran</a> for the idea) was simple...  Just add getpid().</p>
<pre class="brush: cpp; title: ; notranslate">srandom(seed + (unsigned)cur_time + (unsigned)getpid());</pre>
<p>Of course, fixing this 1 issue brought 2 more to the surface. Read on to see what I mean.</p>
<ol style="list-style: decimal outside">
<li style="list-style-type: decimal; text-indent: -20px; padding-left: 20px;">
<p>At least in Linux, there is a notion of "Primary" and "Secondary" addresses. (Aliases being one kind of secondary address) The problem is that with removal of any Primary address (which happens in several different DHCP client state changes) all Secondary addresses are lost.  This plays out very badly if any of the secondary addresses are controlled by a separate instance of a DHCP client state machine. Not to mention that if you lose state on a running DHCP client (like removing its address from under it), you may have to wait for a lease renewal to reactivate the state machine.</p>
</li>
<li style="list-style-type: decimal; text-indent: -20px; padding-left: 20px;">
<p>Which brings up the next issue, which is the lack of shared state between parallel instances of DHCP clients.  Seems unnecessary until you realize that because there isn't any shared state, the Primary address is not guaranteed to arrive first.  This also seems of little consequence until you realize that any Secondary addresses, assigned before the Primary, are obliterated (another loss of state) in the setting of the Primary address. Oops?</p>
</li>
</ol>
<p>Now, after about 3 weeks of working on this issue, I think I discovered a solution to the Primary/Secondary problem.  Hey, 50% isn't too bad.<br />
The fix is to set a kernel networking flag called "promote_secondaries", although you will note that this is only for IPv4.</p>
<pre class="brush: cpp; title: ; notranslate">echo 1 &gt;/proc/sys/net/ipv4/conf/all/promote_secondaries</pre>
<p>It is just that simple.  Now as soon as you remove a Primary address, the next Secondary address will take its place.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jjinno.com/2011/02/23/parallel-dhcp-clients/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Christopsomo (Greek Christmas Bread)</title>
		<link>http://www.jjinno.com/2010/12/26/christopsomo-greek-christmas-bread/</link>
		<comments>http://www.jjinno.com/2010/12/26/christopsomo-greek-christmas-bread/#comments</comments>
		<pubDate>Sun, 26 Dec 2010 17:27:55 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.jjinno.com/?p=208</guid>
		<description><![CDATA[This recipe comes from my mother, via the "Sunset Cook Book of Breads" (1984). Ingredients: 2 Tbps Active Dry Yeast 1/2 Cup Warm Water 1/2 Cup Scalded &#038; Cooled Milk 1 Cup Butter 4 Eggs, beaten 3/4 Cup Granulated Sugar 2 teaspoons crushed Anise seed 1 teaspoon salt 7 Cups all-purpose flour Directions: Mix yeast [...]]]></description>
			<content:encoded><![CDATA[<p>This recipe comes from my mother, via the "Sunset Cook Book of Breads" (1984).</p>
<p><a class="tt-flickr tt-flickr-Medium" title="Ready for Last Rise" href="http://www.flickr.com/photos/jinno/5293829760/in/photostream/"><img class="alignleft" style="border: 2px solid grey;" src="http://farm6.static.flickr.com/5242/5293829760_98118a3da4.jpg" alt="Ready for Last Rise" width="270" height="180" /></a><br />
<strong>Ingredients:</strong><br />
2 Tbps Active Dry Yeast<br />
1/2 Cup Warm Water<br />
1/2 Cup Scalded &#038; Cooled Milk<br />
1 Cup Butter<br />
4 Eggs, beaten<br />
3/4 Cup Granulated Sugar<br />
2 teaspoons crushed Anise seed<br />
1 teaspoon salt<br />
7 Cups all-purpose flour</p>
<p>
<strong>Directions:</strong><br />
Mix yeast with warm water &#038; set aside for about 5 minutes. Mix together yeast mixture, milk, butter, eggs, salt, sugar, and anise thoroughly before adding flour.  Gradually add flour one cup at a time mixing/massaging the flour in evenly.  </p>
<p>Kneed the dough until the elasticity of it pushes back, and the dough is smooth.  Roll into a ball in a large greased bowl, making sure to get the surface of the dough covered in the oil/grease.  Set aside to rise (for the first time) in a warm/moist location. (Or if you are lazy like me, put it in an empty oven, with some almost-boiling water in a adjacent pan)</p>
<p><a class="tt-flickr tt-flickr-Medium" title="Ready to Eat" href="http://www.flickr.com/photos/jinno/5294943626/in/photostream/"><img class="alignright" style="border: 2px solid grey;" src="http://farm6.static.flickr.com/5122/5294943626_2427cc7620.jpg" alt="Ready to Eat" width="180" height="270" /></a>When the dough has doubled in size (1-2 hours) punch it down &#038; divide it up into 2 even halves.  Additionally cut off about 1 Cup worth of dough from each, and set aside (will be used later to decorate).  Kneed each half into a smooth round, and place on a flat baking sheet.  Shape the 1 Cup of dough into two equal-length ropes, cutting down each end of the ropes to create the traditional Greek cross shape.  Finally, garnish the holes with walnuts or candied cherries, and wipe the top with an egg-white to add shine.</p>
<p>Once shaped, let rise again (the last time) until almost double in size. At this point, place in a 350-degree oven for about 45 minutes. (If you are me, and have risen the bread IN the oven, no worries, just turn on the oven to 350, and add 10 minutes for it to preheat WITH the bread already in there)</p>
<p><strong>Alternatives:</strong><br />
You can make this same recipe into a single large loaf, but it is a bit unwieldy, and relatively hard to find a non-pizza pan for.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jjinno.com/2010/12/26/christopsomo-greek-christmas-bread/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An academic approach to &#8216;import&#8217;</title>
		<link>http://www.jjinno.com/2010/06/20/an-academic-approach-to-import/</link>
		<comments>http://www.jjinno.com/2010/06/20/an-academic-approach-to-import/#comments</comments>
		<pubDate>Sun, 20 Jun 2010 21:29:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.jjinno.com/?p=119</guid>
		<description><![CDATA[As they say, Python is a language that does not force you to do things. Instead, it assumes the programmer to be a consenting adult who, knowingly or unknowingly has the power to bend and mold existing paradigms to fit whatever task is at hand. While this easy-peasy mindset sometimes can be an absolute asset, [...]]]></description>
			<content:encoded><![CDATA[<p>As they say, Python is a language that does not force you to do things.  Instead, it assumes the programmer to be a consenting adult who, knowingly or unknowingly has the power to bend and mold existing paradigms to fit whatever task is at hand.  While this easy-peasy mindset sometimes can be an absolute asset, it will inevitably (hopefully not more than once) lead you down the winding path of destruction.  Personally I feel that nothing in Python is quite as capable at dragging people down like the "import" statement.</p>
<p><strong>Standard Imports:</strong></p>
<pre class="brush: python; title: ; notranslate">import os
from os.path import isfile as isFile
from time import *</pre>
<p>Hopefully this is not the first time you've heard this, but you should avoid the asterisk on imports.  Unless you own the import (like a file with a bunch of common functions in it) then you can never be sure that a function defined within the import has not just blown away a function with the same name in your application.</p>
<p><strong>User-specific Imports:</strong><br />
But what about the following... (Linux only I believe)</p>
<pre class="brush: python; title: ; notranslate">import os
import sys
sys.path.append(os.path.join(os.environ['HOME'], 'scripts'))
import userScript</pre>
<p>This can be really helpful to provide some user-specific functionality.  Basically the username determines the home directory, and the home directory then provides you with a specific subdirectory of Python scripts.  If you log in as "root" you will get one set of functionality, whereas if you log in as "user" you will get a different set of functionality.</p>
<p>Watch out though, as environmental variables are very inaccurate.  Anybody and anything can change these variables, and can leave you depending on incorrect or invalid values.  One of the easiest ways to see this is by having a proper-daemon C/C++ application that calls a Python script.  When you log on as any user and execute the binary, you will see the expected results.  If you (via socket or RPC or whatever) call it remotely, the user defaults to the system, which unfortunately does not have certain environmental variables (like a "HOME" directory)... in other words, remote call = failure.</p>
<p><strong>Application-relative (not path-relative) Imports:</strong><br />
Here is another one that I have seen, but have rarely used.  Similarly to  the previous condition, it requires appending to the system path, but this time we are working with a relative directory.</p>
<pre class="brush: python; title: ; notranslate">import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import someClass</pre>
<p>There are two special things happening here.  First, we are extracting the direct relative path to the file containing this code.  If we were to run this through the interpreter, we would get an error because there is no "__file__". Second, because "__file__" is always the relative path to the Python file, it doesn't matter where you execute from, absolute path or not, you will always be referring to ".." from the Python file.  This is EXTREMELY useful if you need to create an application that can be run via both relative and absolute path.</p>
<p><strong>Path-agnostic Import Best Practices:</strong><br />
Although I have given multiple examples of how to get the system path to not care where you are executing from, I have for the most part found that the best practice with import paths is to use a configuration file.  Why did I just complicate the import process even more?  Well, lets take a look at the code:</p>
<pre class="brush: python; title: ; notranslate">import os
import sys
lines = open(os.path.join(os.path.dirname(__file__), &quot;config.cfg&quot;)).splitlines()
paths = [line.split(&quot;=&quot;)[1] for line in lines if &quot;path&quot; is line.split(&quot;=&quot;)[0]]
for path in paths: sys.path.append(path)
import customModule</pre>
<p>The benefit here is that now when you want to swap out "customModule" with a different version for testing, you dont need to move any directories, or rename any imports.  All you do is change the config file.  And yes, I did go a little overboard here, and allow you to add as many paths to the system path list as you want.  The other big benefit here is that since you are always specifying an absolute path in the configuration file, you are always guaranteed that the import will succeed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jjinno.com/2010/06/20/an-academic-approach-to-import/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using a Property to get a Class name into an Attribute</title>
		<link>http://www.jjinno.com/2010/05/28/using-a-python-property-to-get-a-class-name-into-an-attribute/</link>
		<comments>http://www.jjinno.com/2010/05/28/using-a-python-property-to-get-a-class-name-into-an-attribute/#comments</comments>
		<pubDate>Fri, 28 May 2010 22:57:45 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.jjinno.com/?p=148</guid>
		<description><![CDATA[For one reason or another, I found myself in a slight predicament. I needed to get the name of my class into an attribute. Thanks to Google + KyLev I managed to procure a workable solution:]]></description>
			<content:encoded><![CDATA[<p>For one reason or another, I found myself in a slight predicament.  I needed to get the name of my class into an attribute.</p>
<p>Thanks to Google + <a href="http://www.kylev.com/2004/10/13/fun-with-python-properties/">KyLev</a> I managed to procure a workable solution:</p>
<pre class="brush: python; title: ; notranslate">class Problem(object):
    moduleIndex = 0
    def __init__(self):
        self.__class__.moduleIndex = self.__class__.moduleIndex + 1

class Solution(object):
    moduleIndex = 0
    moduleName = property(fget=lambda self: self.__class__.__name__)
    def __init__(self):
        self.__class__.moduleIndex = self.__class__.moduleIndex + 1
        print &quot;[%s] %s&quot;%(self.moduleIndex, self.moduleName)

if __name__ == &quot;__main__&quot;: t = Solution()
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.jjinno.com/2010/05/28/using-a-python-property-to-get-a-class-name-into-an-attribute/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

