|
From: Jonathan L. <jon...@ee...> - 2008-12-10 23:14:21
|
Hmm. The advantage of lastPingTime is that you learn whether or not
you've tried to contact a neighbor and they haven't responded. Then
you can use that knowledge to determine whether or not to toss them.
Maybe I'm not understanding your suggestion then.
-jonathan
On Dec 10, 2008, at 12:51 PM, Eric Chan-Tin wrote:
> That's a good idea. Here is a little twist on it.
>
> Put a "weight" on each neighbor, based on the lastUpdateTime. So if
> currentTime - neighbor's lastUpdateTime, then the weight is higher.
> Then in getNeighborToPing, neighbor's with higher weight have a
> higher probability of getting picked than neighbor's with lower
> weight.
>
> The weight could be ( (currentTime - lastUpdateTime) / 15 minutes).
> It's not 10 minutes so as to avoid a probability of 1 if the
> lastUpdateTime was the previous performMaintenance. This should also
> avoid the problem of always pinging the oldest neighbor since it's
> about probability (weight).
>
> It seems a little bit less complicated than having lastPingTime and
> MIN_UPDATE_TIME.
>
> -Eric
>
> On Dec 10 2008, Jonathan Ledlie wrote:
>
>>
>> This is an interesting situation. Let's think about the goal.
>> The goal is to keep pinging the same nodes as long as they are
>> alive, and to replace a node soon after it dies, keeping the total
>> number of up neighbors at approximately MAX_NEIGHBORS.
>>
>> How about the following:
>> - when you pick a neighbor to ping, you set a time on that event
>> (in a new per-neighbor timestamp LastPingTime)
>> - when you first insert a neighbor, set this timestamp to 0.
>> - when you loop in performMaintenance, remove nodes whose
>> LastPingTime - LastUpdateTime > threshold (like 10 minutes)
>>
>> - when picking a node, pick the guy with the oldest LastPingTime
>> (not sure about this one -- I don't like situations where you pick
>> the absolute *oldest* because then we could get in a situation
>> where an old guy sits there, waiting to be kicked out, and we keep
>> picking him to be pinged; I'd prefer to pick randomly, or random
>> older guys).
>> - a simple way around this is to simply have a self-adjusting
>> threshold: so, we walk through the nodes, and everyone whose
>> LastPingTime is older than MIN_UPDATE_TIME_TO_PING ago (a relative
>> time) get added to a set; we pick a guy randomly from the set to
>> ping. If the set is empty, we increase MIN_UPDATE_TIME_TO_PING,
>> and wait for the next time the function is called. If the set is
>> too large (relative to a fraction of MAX_NEIGHBORS), we decrease it.
>>
>> We still might get some churn from lost UDP packets. You might
>> also give nodes a second chance to be pinged by including
>> LastPingTime - LastUpdateTime > 1 minute in the set. Note that
>> increases and decreases in MIN_UPDATE_TIME_TO_PING shouldn't be
>> affected by the number of nodes that fall into this category.
>>
>> We still probably need a way for new potential neighbors to be
>> rejected if our current set of neighbors is fine. Because I still
>> want addNeigbor to really add the neighbor, how about putting a
>> check before calling that to see if we need more neighbors.
>>
>> What thinks?
>>
>> -jonathan
>>
>> On Dec 9, 2008, at 11:37 PM, ext Eric Chan-Tin wrote:
>>
>>> Peter,
>>>
>>> Thanks. That fixed it.
>>>
>>> However, here is another problem I found while deploying Pyxida and
>>> running them for a while.
>>>
>>> In performMaintenance(), I loop through every neighbor and if
>>> (neighbor.getLastUpdateTime() < current_time - 10 minutes), then I
>>> remove that neighbor.
>>
>>
>>>
>>>
>>> In NCManager, I call getNeighborToPing, which randomly picks one
>>> of the
>>> neighbors (32 in this case). Pinging is performed every 10
>>> seconds, so
>>> in 10 minutes, you can ping 60 nodes. However, if a neighbor A is
>>> not
>>> among those 60 nodes, it will get kicked out in
>>> performMaintenance(),
>>> although A is still alive (it just hasn't been contacted yet).
>>>
>>> There are some possible options.
>>>
>>> 1) Increase the timeout period from 10 minutes to ?? minutes. This
>>> doesn't quite work because say in Azureus, the number of neighbors
>>> is
>>> 512, so the timeout needs to be increased even more... It could be a
>>> function of MAX_NEIGHBORS...
>>>
>>> 2) When Pyxida replies to a ping request, it will update the
>>> neighbor's
>>> lastUpdateTime. This does not quite work either because it assumes a
>>> symmetric relationship which is most likely not the case.
>>>
>>> 3) Introduce some more logic to Pyxida so it remembers what nodes it
>>> contacted and does not send, say, more than 2 requests in 10
>>> minutes to
>>> the same node. This solution isn't that great either.
>>>
>>> Let me know what you guys think. I am currently leaning towards
>>> option
>>> 1) but make the timeout period a function of MAX_NEIGHBORS,
>>> although I
>>> haven't quite found the perfect function yet.
>>>
>>> Here are some preliminary results. I compared the number of
>>> neighbors
>>> which are the same at each reported time (10 minutes). Before the
>>> fix,
>>> more than 50% of the neighbors changed within 10 minutes. After
>>> the fix,
>>> only about 30% of the neighbors changed within 10 minutes. It is
>>> more
>>> stable but I think 30% is still quite a big number.
>>>
>>> Sorry for the long email :)
>>>
>>> -Eric
>>>
>>> Peter Pietzuch wrote:
>>>> Hi,
>>>>
>>>> Eric Chan-Tin wrote:
>>>>> for (RemoteState<T> neighbor : neighbors) { //this is line 1029
>>>>> if (neighbor.getLastUpdateTime() < (curr_time -
>>>>> MAINTENANCE_PERIOD)) {
>>>>> neighbors.remove(neighbor);
>>>>> }
>>>>> }
>>>>
>>>> IIRC you can't modify a collection while iterating over it using
>>>> the
>>>> above for loop. Instead you have to use a proper
>>>> Iterator<RemoteState<T>> and use it's remove method.
>>>>
>>>> Cheers,
>>>> Peter
>>>>
>>>>> Jonathan Ledlie wrote:
>>>>>> On Nov 3, 2008, at 3:46 PM, Eric Chan-Tin wrote:
>>>>>>
>>>>>>> Jonathan,
>>>>>>>
>>>>>>> I can insert some code to fix this and it doesn't look too
>>>>>>> hard but I do
>>>>>>> have some concerns.
>>>>>>>
>>>>>>>> I don't remember observing this behavior in our PL
>>>>>>>> deployment, but that could have been because we had the ping
>>>>>>>> time set
>>>>>>>> to 1-2 minutes, IIRC.
>>>>>>> The default ping time was set to 10 seconds + some Gaussian
>>>>>>> distribution,
>>>>>>> so that's what I used, but changing the ping time to 1 minute
>>>>>>> or more
>>>>>>> will
>>>>>>> result in the same effect except it will take longer for the
>>>>>>> "cycle" to
>>>>>>> occur.
>>>>>>>
>>>>>>> What I have in mind was the following:
>>>>>>>
>>>>>>> 1) In NCClient.addNeighbor() would be changed to (in pseudocode)
>>>>>>> protected boolean addNeighbor(RemoteState<T> guy) {
>>>>>>> boolean added = false;
>>>>>>> //if neighbors.size() >= MAX_NEIGHBORS
>>>>>>> //Check last update time of each neighbor in
>>>>>>> neighbors
>>>>>>> //neighbor.getLastUpdateTime()
>>>>>>> //if any of them is older than some number
>>>>>>> TIMEOUT,
>>>>>>> remove the oldest one, then add "guy" to neighbors
>>>>>>> //else don't add "guy" to neighbors
>>>>>>> //else add "guy" to neighbors
>>>>>>> }
>>>>>>>
>>>>>> IMO this shouldn't be the behavior of this function because it
>>>>>> is called
>>>>>> "addNeighbor." Instead what could happen is that part of the
>>>>>> performMaintenance() function could remove old neighbors.
>>>>>>
>>>>>>> 2) In NCManager, getGossipNode() would just pick a random
>>>>>>> node from
>>>>>>> localNC.primaryNC.getNeighbors() to send a request to every
>>>>>>> 10 seconds.
>>>>>>>
>>>>>>> 3) Pyxida will still keep track of all GossipNodes in the
>>>>>>> network. It
>>>>>>> could
>>>>>>> also (say every 10 minutes) check its NCClient.neighbors list
>>>>>>> and see if
>>>>>>> any neighbor is older than TIMEOUT, remove it, then pick a
>>>>>>> random
>>>>>>> GossipNode to send a ping request.
>>>>>>>
>>>>>>> The main problem with this scheme is that one Pyxida node
>>>>>>> would most
>>>>>>> likely
>>>>>>> stay with the same set of neighbors all the time. Its
>>>>>>> coordinates
>>>>>>> would be
>>>>>>> greatly affected by those 32 nodes (I am assuming
>>>>>>> MAX_NEIGHBORS = 32).
>>>>>>>
>>>>>> Instead of (2), why not have the getNeighborToPing function
>>>>>> determine
>>>>>> the behavior? If it returns a node, then ping it. If it
>>>>>> returns null,
>>>>>> then have the NCManager pick some other node to use? If things
>>>>>> are
>>>>>> hunky-dory, getNeighborToPing() would return a node (a current
>>>>>> member of
>>>>>> the neighbor set), if we're short on neighbors, then it would
>>>>>> return
>>>>>> null. The periodic maintenance would have already tossed old
>>>>>> nodes, so
>>>>>> this would be self-sustaining.
>>>>>>
>>>>>> The "problem" you mention is fairly central to network
>>>>>> coordinates in
>>>>>> general. Sure the coordinates will be a little better the more
>>>>>> neighbors you have. But in a very large system talking to
>>>>>> everybody
>>>>>> isn't feasible. Peter and I have a graph in one of the
>>>>>> workshop papers
>>>>>> which shows the effect of increasing the number of neighbors
>>>>>>
>>>>>>> I don't think the network would be partitioned, but it could
>>>>>>> happen. For
>>>>>>> example, the boostrap nodes have each other in their
>>>>>>> neighbors list.
>>>>>>> Every
>>>>>>> new node bootstrapping to the network would contact those
>>>>>>> bootstrapping
>>>>>>> nodes first and add them to their neighbors. So every Pyxida
>>>>>>> node could
>>>>>>> have as its neighbors the "Bootstrap nodes", which would make
>>>>>>> Pyxida
>>>>>>> become
>>>>>>> a centralized system.
>>>>>>>
>>>>>> As long as the initial bootstrap list is large enough, I think
>>>>>> you are
>>>>>> right, that partitions won't be a problem.
>>>>>>
>>>>>>> One last thing: When Pyxida receives a ping request from a
>>>>>>> node, it does
>>>>>>> not update its coordinates. Is there any particular reason
>>>>>>> for that?
>>>>>>> Is it
>>>>>>> because Pyxida will not be able to calculate the RTT?
>>>>>>>
>>>>>> Yes.
>>>>>>
>>>>>>> Also, there is no "gossiping" of other nodes' coordinates,
>>>>>>> right? So if A
>>>>>>> has B in its neighbors list, it will from time to time tell
>>>>>>> other nodes
>>>>>>> about B's coordinates. I realize this has a lot of
>>>>>>> complications but the
>>>>>>> original Vivaldi paper was very fuzzy about this point and
>>>>>>> the previous
>>>>>>> point that it seems it is up to the implementors to decide
>>>>>>> what to do.
>>>>>>>
>>>>>> I don't think we are doing this. It could be useful in certain
>>>>>> circumstance (e.g., picking potential new neighbors), but
>>>>>> we're not, IIRC.
>>>>>>
>>>>>>> I will have to think some more about this as there are a lot
>>>>>>> of nasty
>>>>>>> little side effects that could happen, but these are my
>>>>>>> thoughts.
>>>>>>>
>>>>>>> Thanks,
>>>>>>>
>>>>>>> -Eric
>>>>>>>
>>>>>> Sounds good.
>>>>>>
>>>>>> -jonathan
>>>>>>
>>>>>>> On Nov 3 2008, Jonathan Ledlie wrote:
>>>>>>>
>>>>>>>> Eric,
>>>>>>>>
>>>>>>>> Based on a look at the code just now, I see where you are
>>>>>>>> coming from:
>>>>>>>> with these params on PL, there isn't anything stopping the
>>>>>>>> neighbor
>>>>>>>> list from circulating pretty quickly through all nodes. In the
>>>>>>>> Azureus implementation, the guys fed to the alg (fed to
>>>>>>>> processSample)
>>>>>>>> weren't changing much because they were coming from the
>>>>>>>> routing finger
>>>>>>>> tables. I don't remember observing this behavior in our PL
>>>>>>>> deployment, but that could have been because we had the ping
>>>>>>>> time set
>>>>>>>> to 1-2 minutes, IIRC.
>>>>>>>>
>>>>>>>> Do you want to insert some code that will fix this?
>>>>>>>> Basically we want
>>>>>>>> to only add a new neighbor if our oldest neighbor should be
>>>>>>>> tossed (or
>>>>>>>> if we haven't reached MAX_NEIGHBORS). It's probably best
>>>>>>>> from a
>>>>>>>> clarity standpoint if addNeighbor does continue to actually
>>>>>>>> add the
>>>>>>>> neighbor in all cases. Probably the best thing to do is to
>>>>>>>> have
>>>>>>>> NCClient drop old neighbors internally and have NCManager
>>>>>>>> ask it which
>>>>>>>> nodes should be pinged via getNeighborToPing. So NCClient
>>>>>>>> would
>>>>>>>> continue to have the same behavior on processSample (it would
>>>>>>>> not
>>>>>>>> reject new information) and NCManager and NCClient would
>>>>>>>> cooperate to
>>>>>>>> measure RTTs to current neighbors. We do want to make sure,
>>>>>>>> however,
>>>>>>>> that the gossip set stays large enough so that partitions
>>>>>>>> don't occur.
>>>>>>>>
>>>>>>>> Do you want to be added to the SourceForge Pyxida developers
>>>>>>>> to make
>>>>>>>> this change? (Please test it out carefully first.)
>>>>>>>>
>>>>>>>> -jonathan
>>>>>>>>
>>>>>>>> On Oct 30, 2008, at 11:32 AM, ext Eric Chan-Tin wrote:
>>>>>>>>
>>>>>>>>> Jonathan,
>>>>>>>>>
>>>>>>>>> From what I saw, eventually, you learn about all the nodes
>>>>>>>>> in the
>>>>>>>>> network. Every 10 seconds, Pyxida picks a random "Gossip"
>>>>>>>>> node from
>>>>>>>>> its
>>>>>>>>> list and sends a request. The Gossip node will reply back
>>>>>>>>> with an
>>>>>>>>> "upNeighbor", that is, a "Gossip" node that is "up" or with
>>>>>>>>> 10%
>>>>>>>>> probability, a node that is "pending". Since naturally, all
>>>>>>>>> the nodes
>>>>>>>>> bootstrap off the same set of nodes, every node will
>>>>>>>>> eventually know
>>>>>>>>> of
>>>>>>>>> every other node.
>>>>>>>>>
>>>>>>>>> Pyxida might not be rotating through everybody continuously
>>>>>>>>> (although
>>>>>>>>> eventually, since it knows everybody, it will have added
>>>>>>>>> everybody to
>>>>>>>>> its Neighbors list at some point), but could be removing a
>>>>>>>>> node that
>>>>>>>>> is
>>>>>>>>> "alive". So, if MAX_NEIGHBORS = 32, let's call them A_1,
>>>>>>>>> A_2, ...,
>>>>>>>>> A_32.
>>>>>>>>> Pyxida picks a random Gossip node B, sends it a request and
>>>>>>>>> B replies
>>>>>>>>> back. Pyxida will add B to its Neighbors list, see that size
>>>>>>>>> of
>>>>>>>>> Neighbors > MAX_NEIGHBORS, kick A_1 out. Then from those 32
>>>>>>>>> neighbors
>>>>>>>>> A_2, ...., A_32, B, it will calculate the force, and apply
>>>>>>>>> it to the
>>>>>>>>> current system coordinates. Thus, if every 10 seconds,
>>>>>>>>> Pyxida picks a
>>>>>>>>> different set of nodes C, D, E, etc... it would keep
>>>>>>>>> kicking nodes out
>>>>>>>>> of the neighbors list.
>>>>>>>>>
>>>>>>>>> It's the "kicking A_1 out" part that seemed a bit
>>>>>>>>> confusing. Churn
>>>>>>>>> is a
>>>>>>>>> good reason but you don't check that A_1 might still be
>>>>>>>>> alive or maybe
>>>>>>>>> A_1 was just added. I have been printing the neighbors list
>>>>>>>>> every 10
>>>>>>>>> minutes, and they are completely different between those 10
>>>>>>>>> minutes.
>>>>>>>>>
>>>>>>>>> One possible problem might be that I am choosing the value of
>>>>>>>>> MAX_NEIGHBORS to be too small. Originally it was set to 512
>>>>>>>>> (which was
>>>>>>>>> meant for Azureus). Since I am using Planetlab where there
>>>>>>>>> are about
>>>>>>>>> 400-500 "stable" nodes, I changed the value to 32. But I
>>>>>>>>> don't think
>>>>>>>>> that should be a problem since log(n) = log(512) = 9.
>>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>>
>>>>>>>>> -Eric
>>>>>>>>>
>>>>>>>>> Jonathan Ledlie wrote:
>>>>>>>>>> Eric,
>>>>>>>>>>
>>>>>>>>>> Glad to hear it. Let Peter and me know if you publish
>>>>>>>>>> anything using
>>>>>>>>>> Pyxida and we can put it on the web page.
>>>>>>>>>>
>>>>>>>>>> "Gossip" nodes are for learning about the network.
>>>>>>>>>> "Neighbors" are
>>>>>>>>>> for
>>>>>>>>>> constructing the coordinate.
>>>>>>>>>>
>>>>>>>>>> So, IIRC, the gossip process learns about nodes that may
>>>>>>>>>> or may not
>>>>>>>>>> be
>>>>>>>>>> applied to the neighbor list. That is, we may eventually
>>>>>>>>>> learn
>>>>>>>>>> about a
>>>>>>>>>> large portion of the network, via gossiping, but should
>>>>>>>>>> only be using
>>>>>>>>>> MAX_NEIGHBORS at any given time for coordinate
>>>>>>>>>> computation. The
>>>>>>>>>> reason
>>>>>>>>>> we don't want to use a fixed set of neighbors for coordinate
>>>>>>>>>> computation
>>>>>>>>>> is because nodes may come and go from the system.
>>>>>>>>>> However, it should
>>>>>>>>>> not be the case that we just rotate through everybody,
>>>>>>>>>> because
>>>>>>>>>> then, as
>>>>>>>>>> you note, we'd be computing against everyone's coordinate/
>>>>>>>>>> latency,
>>>>>>>>>> and
>>>>>>>>>> this is counter to the point of network coordinates. With
>>>>>>>>>> this
>>>>>>>>>> gradual
>>>>>>>>>> transience as a desirable quality in mind, I am pretty sure
>>>>>>>>>> we
>>>>>>>>>> maintain
>>>>>>>>>> neighbors in a fairly fixed manner. Does this not seem to
>>>>>>>>>> be the
>>>>>>>>>> case
>>>>>>>>>> to you?
>>>>>>>>>>
>>>>>>>>>> -jonathan
>>>>>>>>>>
>>>>>>>>>> On Oct 29, 2008, at 9:20 PM, Eric Chan-Tin wrote:
>>>>>>>>>>
>>>>>>>>>>> Hi Jonathan and Peter,
>>>>>>>>>>>
>>>>>>>>>>> First of all, just wanted to say that Pyxida has been
>>>>>>>>>>> working
>>>>>>>>>>> great on
>>>>>>>>>>> Planetlab for the past 4 months or so. Getting good data and
>>>>>>>>>>> experiments
>>>>>>>>>>> going well.
>>>>>>>>>>>
>>>>>>>>>>> However, I do have one question/comment.
>>>>>>>>>>>
>>>>>>>>>>> Every Pyxida node contains a list of Neighbors (in
>>>>>>>>>>> NCClient) and a
>>>>>>>>>>> list
>>>>>>>>>>> of Gossip nodes (they are called neighbors in NCManager
>>>>>>>>>>> but I will
>>>>>>>>>>> call
>>>>>>>>>>> them gossip for now so as not to confuse with the 'real'
>>>>>>>>>>> neighbors
>>>>>>>>>>> in
>>>>>>>>>>> NCClient). Every 10 seconds, Pyxida will pick a random
>>>>>>>>>>> node (call
>>>>>>>>>>> it A)
>>>>>>>>>>> from Gossip and send a gossip request (basically asking
>>>>>>>>>>> for rtt,
>>>>>>>>>>> coordinate, error). But Gossip contains all the nodes in the
>>>>>>>>>>> network.
>>>>>>>>>>> The comment in the code said that was to avoid Pyxida
>>>>>>>>>>> becoming
>>>>>>>>>>> lonely
>>>>>>>>>>> and no-one to gossip with, which makes sense.
>>>>>>>>>>>
>>>>>>>>>>> Once A responds, Pyxida will add A to its Neighbors (if
>>>>>>>>>>> Neighbors
>>>>>>>>>>> does
>>>>>>>>>>> not contain A) and remove the first element from the
>>>>>>>>>>> Neighbors list.
>>>>>>>>>>> This seems a little bit odd. Was there any particular
>>>>>>>>>>> reasoning
>>>>>>>>>>> behind
>>>>>>>>>>> this? Because it would seem like you're getting the
>>>>>>>>>>> coordinate from
>>>>>>>>>>> every node in the network eventually.
>>>>>>>>>>>
>>>>>>>>>>> Thanks a lot,
>>>>>>>>>>>
>>>>>>>>>>> -Eric
>>>>>>>>>>>
>>>>>>>>>>> Jonathan Ledlie wrote:
>>>>>>>>>>>> Your inclination is correct. See forwarded message.
>>>>>>>>>>>>
>>>>>>>>>>>> -jonathan
>>>>>>>>>>>>
>>>>>>>>>>>> On Apr 9, 2008, at 1:53 PM, ext Eric Chan-Tin wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> Thank you for the clarification.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I've been reading through your published papers and
>>>>>>>>>>>>> code and I
>>>>>>>>>>>>> must
>>>>>>>>>>>>> say I learned a lot about how Pyxida works :)
>>>>>>>>>>>>>
>>>>>>>>>>>>> I still have a quick and easy (hopefully) question.
>>>>>>>>>>>>> Each Pyxida
>>>>>>>>>>>>> node
>>>>>>>>>>>>> has a small amount of neighbors and learn about other
>>>>>>>>>>>>> nodes
>>>>>>>>>>>>> through
>>>>>>>>>>>>> other nodes. I am running on about 200 machines, and it
>>>>>>>>>>>>> seems
>>>>>>>>>>>>> like all
>>>>>>>>>>>>> the Pyxida nodes are adding each other to their
>>>>>>>>>>>>> upNeighbors set.
>>>>>>>>>>>>> NCClient.java has the MAX_NEIGHBORS set to 512.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I wanted to make sure that I am not misreading the code,
>>>>>>>>>>>>> but
>>>>>>>>>>>>> shouldn't
>>>>>>>>>>>>> each Pyxida node keep a small number of neighbors in its
>>>>>>>>>>>>> upNeighbors
>>>>>>>>>>>>> set. Else, it will be a lot of updates to send a
>>>>>>>>>>>>> gossipMessage
>>>>>>>>>>>>> to all
>>>>>>>>>>>>> 200 neighbors, and it also means that a Pyxida node has
>>>>>>>>>>>>> the whole
>>>>>>>>>>>>> network in its upNeighbors set - that seems wrong. I am
>>>>>>>>>>>>> inclined
>>>>>>>>>>>>> to
>>>>>>>>>>>>> change the value of MAX_NEIGHBORS but wanted to make
>>>>>>>>>>>>> sure that my
>>>>>>>>>>>>> understanding is correct first.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Thank you,
>>>>>>>>>>>>>
>>>>>>>>>>>>> Eric
>>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -------------------------------------------------------------------------
>>>>>>>>>>>
>>>>>>>>>>> This SF.Net email is sponsored by the Moblin Your Move
>>>>>>>>>>> Developer's
>>>>>>>>>>> challenge Build the coolest Linux based applications with
>>>>>>>>>>> Moblin
>>>>>>>>>>> SDK &
>>>>>>>>>>> win great prizes Grand prize is a trip for two to an Open
>>>>>>>>>>> Source
>>>>>>>>>>> event
>>>>>>>>>>> anywhere in the world
>>>>>>>>>>> http://moblin-contest.org/redirect.php?banner_id=100&url=/
>>>>>>>>>>> _______________________________________________ Pyxida-
>>>>>>>>>>> users mailing
>>>>>>>>>>> list Pyx...@li...
>>>>>>>>>>> https://lists.sourceforge.net/lists/listinfo/pyxida-users
>>>>>>>
>>>>>>> ------------------------------------------------------------------------- This
>>>>>>> SF.Net email is sponsored by the Moblin Your Move Developer's
>>>>>>> challenge Build the coolest Linux based applications with
>>>>>>> Moblin SDK & win great prizes Grand prize is a trip for two to
>>>>>>> an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/
>>>>>>> _______________________________________________ Pyxida-users
>>>>>>> mailing list Pyx...@li... https://lists.sourceforge.net/lists/listinfo/pyxida-users
>>>>>
>>>>> ------------------------------------------------------------------------------ SF
>>>>> .Net email is Sponsored by MIX09, March 18-20, 2009 in Las
>>>>> Vegas, Nevada. The future of the web can't happen without you.
>>>>> Join us at MIX09 to help pave the way to the Next Web now. Learn
>>>>> more and register at http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/
>>>>> _______________________________________________ Pyxida-users
>>>>> mailing list Pyx...@li... https://lists.sourceforge.net/lists/listinfo/pyxida-users
>>>>
>>>>
>>
|