All of the interesting technological, artistic or just plain fun subjects I'd investigate if I had an infinite number of lifetimes. In other words, a dumping ground...

Wednesday, 31 October 2007

haacked blog

http://haacked.com/

Tuesday, 30 October 2007

Null bytes to fool virus detection

http://blog.didierstevens.com/2007/10/23/a000n0000-0000o000l00d00-0i000e000-00t0r0000i0000c000k/

When I found a malicious script riddled with 0×00 bytes, SANS handler Bojan
Zdrnja explained to me that this was an old trick. When rendering an HTML
page, Internet Explorer will ignore all zero-bytes (bytes with value zero,
0×00). Malware authors use this to obscure their scripts. But this old
trick still packs a punch.

Virus Total

http://www.virustotal.com/
Virustotal is a service that analyzes suspicious files and facilitates the
quick detection of viruses, worms, trojans, and all kinds of malware
detected by antivirus engines.

Hash functions

http://burtleburtle.net/bob/hash/doobs.html

Code and analysis of different hash functions.

Hashes looked at: Additive, Rotating, One-at-a-Time, Bernstein, FNV,
Pearson, CRC, Generalized, Universal, Zobrist, Paul Hsieh's, My Hash,
lookup3.c, MD4

Thursday, 25 October 2007

GIMP 2.4 preview

http://www.redhatmagazine.com/2007/10/23/gimp-24-preview/

by Nicu Buculei


Fedora 8 test releases have a surprise for all users interested in
graphics: a release candidate for the new GIMP 2.4, meaning the final
version will get the stable GIMP 2.41. This is exciting news, as the
previous major release, GIMP 2.2, is several years old, and a lot of new
features were added in the meantime.


In this article, we'll take a look at some of the most visible new
features, but beyond them, there are tons of less visible things: speedups,
a decrease in memory consumption, better importing and exporting, a better
print plugin, better EXIF support, changed scripting language for plugins,
zoomable preview for plugins, many bug fixes, and more.


If you'd like to see a more practical application of these tools, take a
look at my article on improving portraits with GIMP.


Note: You can click on any image in this article to see a larger version.

Fail2ban

http://www.fail2ban.org/wiki/index.php/Main_Page
Fail2ban scans log files like /var/log/pwdfail or /var/log/apache/error_log
and bans IP that makes too many password failures. It updates firewall
rules to reject the IP address.

Ohloh

Open source metrics and connecting people
http://www.ohloh.net/learn
Interesting site. Awesome design and pictures.

shipping container stacking strategy

(See attached file: shipping_issues_08.jpg)

Tuesday, 23 October 2007

python genetic programming

http://www.freenet.org.nz/python/pygene/doc/

Package pygene


pygene is a library for genetic algorithms in python


It aims to be very simple to use, and suitable for people new to genetic
algorithms.
Submodules
gamete: Implements gametes, which are the result of splitting an
organism's genome in two, and are used in the organism's sexual
reproduction
gene: Implements a collection of gene classes
organism: Implements classes for entire organisms
population: pygene/population.py - Represents a population of
organisms
prog: Implements genetic programming organisms
xmlio: xmlio.py


http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/199121

<code>
#
# genetic.py
#

import random

MAXIMIZE, MINIMIZE = 11, 22

class Individual(object):
alleles = (0,1)
length = 30
seperator = ''
optimization = MINIMIZE

def __init__(self, chromosome=None):
self.chromosome = chromosome or self._makechromosome()
self.score = None # set during evaluation

def _makechromosome(self):
"makes a chromosome from randomly selected alleles."
return [random.choice(self.alleles) for gene in range(self.length)]

def evaluate(self, optimum=None):
"this method MUST be overridden to evaluate individual fitness
score."
pass

def crossover(self, other):
"override this method to use your preferred crossover method."
return self._twopoint(other)

def mutate(self, gene):
"override this method to use your preferred mutation method."
self._pick(gene)

# sample mutation method
def _pick(self, gene):
"chooses a random allele to replace this gene's allele."
self.chromosome[gene] = random.choice(self.alleles)

# sample crossover method
def _twopoint(self, other):
"creates offspring via two-point crossover between mates."
left, right = self._pickpivots()
def mate(p0, p1):
chromosome = p0.chromosome[:]
chromosome[left:right] = p1.chromosome[left:right]
child = p0.__class__(chromosome)
child._repair(p0, p1)
return child
return mate(self, other), mate(other, self)

# some crossover helpers ...
def _repair(self, parent1, parent2):
"override this method, if necessary, to fix duplicated genes."
pass

def _pickpivots(self):
left = random.randrange(1, self.length-2)
right = random.randrange(left, self.length-1)
return left, right

#
# other methods
#

def __repr__(self):
"returns string representation of self"
return '<%s chromosome="%s" score=%s>' % \
(self.__class__.__name__,
self.seperator.join(map(str,self.chromosome)), self.score)

def __cmp__(self, other):
if self.optimization == MINIMIZE:
return cmp(self.score, other.score)
else: # MAXIMIZE
return cmp(other.score, self.score)

def copy(self):
twin = self.__class__(self.chromosome[:])
twin.score = self.score
return twin


class Environment(object):
def __init__(self, kind, population=None, size=100, maxgenerations=100,

crossover_rate=0.90, mutation_rate=0.01, optimum=None):
self.kind = kind
self.size = size
self.optimum = optimum
self.population = population or self._makepopulation()
for individual in self.population:
individual.evaluate(self.optimum)
self.crossover_rate = crossover_rate
self.mutation_rate = mutation_rate
self.maxgenerations = maxgenerations
self.generation = 0
self.report()

def _makepopulation(self):
return [self.kind() for individual in range(self.size)]

def run(self):
while not self._goal():
self.step()

def _goal(self):
return self.generation > self.maxgenerations or \
self.best.score == self.optimum

def step(self):
self.population.sort()
self._crossover()
self.generation += 1
self.report()

def _crossover(self):
next_population = [self.best.copy()]
while len(next_population) < self.size:
mate1 = self._select()
if random.random() < self.crossover_rate:
mate2 = self._select()
offspring = mate1.crossover(mate2)
else:
offspring = [mate1.copy()]
for individual in offspring:
self._mutate(individual)
individual.evaluate(self.optimum)
next_population.append(individual)
self.population = next_population[:self.size]

def _select(self):
"override this to use your preferred selection method"
return self._tournament()

def _mutate(self, individual):
for gene in range(individual.length):
if random.random() < self.mutation_rate:
individual.mutate(gene)

#
# sample selection method
#
def _tournament(self, size=8, choosebest=0.90):
competitors = [random.choice(self.population) for i in range(size)]
competitors.sort()
if random.random() < choosebest:
return competitors[0]
else:
return random.choice(competitors[1:])

def best():
doc = "individual with best fitness score in population."
def fget(self):
return self.population[0]
return locals()
best = property(**best())

def report(self):
print "="*70
print "generation: ", self.generation
print "best: ", self.best

---------------------------------------------------------------------
#
# onemax.py - useage example
#
# the fittest individual will have a chromosome consisting of 30 '1's
#

import genetic

class OneMax(genetic.Individual):
optimization = genetic.MAXIMIZE
def evaluate(self, optimum=None):
self.score = sum(self.chromosome)
def mutate(self, gene):
self.chromosome[gene] = not self.chromosome[gene] # bit flip

if __name__ == "__main__":
env = genetic.Environment(OneMax, maxgenerations=1000, optimum=30)
env.run()
</code>

travelling salesman problem

http://xiru.org/blog/python-genetic-algorithms

http://www.iwr.uni-heidelberg.de/groups/comopt/software/TSPLIB95/

TSPLIB is a library of sample instances for the TSP (and related problems)
from various sources and of various types.
Symmetric traveling salesman problem (TSP)
Given a set of n nodes and distances for each pair of nodes, find a
roundtrip of minimal total length visiting each node exactly once. The
distance from node i to node j is the same as from node j to node i.
-> TSP data
Best known solutions for symmetric TSPs


http://www.tsp.gatech.edu/world/countries.html


We list below 25 TSP instances taken from the World TSP. For these
instances, the cost of travel between cities is specified by the Eulidean
distance rounded to the nearest whole number (the TSPLIB EUC_2D-norm). The
TSPs range in size from 29 cities in Western Sahara to 71,009 cities in
China; they provide additional tests to complement the TSPLIB collection.
The TSPs were derived from data contained in the National Imagery and
Mapping Agency database of geographic feature names.

We will be most happy to report any improved tours or improved lower bounds
that you may find.  A summary of the current solution status for the
instances can be found here.

http://www.gcd.org/sengoku/docs/arob98.pdf

Arbitrage view in the US

http://www.arbitrageview.com/riskarb.htm

and books
http://www.arbitrageview.com/books.htm

Arbitrage

http://en.wikipedia.org/wiki/Arbitrage

Arbitrage

From Wikipedia, the free encyclopedia

In economics and finance, arbitrage is the practice of taking advantage of a price differential between two or more markets: a combination of matching deals are struck that capitalize upon the imbalance, the profit being the difference between the market prices. When used by academics, an arbitrage is a transaction that involves no negative cash flow at any probabilistic or temporal state and a positive cash flow in at least one state; in simple terms, a risk-free profit. A person who engages in arbitrage is called an arbitrageur. The term is mainly applied to trading in financial instruments , such as bonds, stocks, derivatives, commodities and currencies.

If the market prices do not allow for profitable arbitrage, the prices are said to constitute an arbitrage equilibrium or arbitrage-free market. An arbitrage equilibrium is a precondition for a general economic equilibrium. The assumption that there is no arbitrage is used in quantitative finance to calculate a unique risk neutral price for a derivatives.

Statistical arbitrage is an imbalance in expected values. A casino has a statistical arbitrage in almost every game of chance that it offers.

Contents

[hide]

Conditions for arbitrage

Arbitrage is possible when one of three conditions is met:

  1. The same asset does not trade at the same price on all markets ("the law of one price").
  2. Two assets with identical cash flows do not trade at the same price.
  3. An asset with a known price in the future does not today trade at its future price discounted at the risk-free interest rate (or, the asset does not have negligible costs of storage; as such, for example, this condition holds for grain but not for securities).

Arbitrage is not simply the act of buying a product in one market and selling it in another for a higher price at some later time. The transactions must occur simultaneously to avoid exposure to market risk, or the risk that prices may change on one market before both transactions are complete. In practical terms, this is generally only possible with securities and financial products which can be traded electronically.

In the most simple example, any good sold in one market should sell for the same price in another. Traders may, for example, find that the price of wheat is lower in agricultural regions than in cities, purchase the good, and transport it to another region to sell at a higher price. This type of price arbitrage is the most common, but this simple example ignores the cost of transport, storage, risk, and other factors. "True" arbitrage requires that there be no market risk involved. Where securities are traded on more than one exchange, arbitrage occurs by simultaneously buying in one and selling on the other.

See rational pricing, particularly arbitrage mechanics, for further discussion.

Examples

  • Suppose that the exchange rates (after taking out the fees for making the exchange) in London are £5 = $10 = ¥1000 and the exchange rates in Tokyo are ¥1000 = £6 = $12. Converting ¥1000 to $12 in Tokyo and converting that $12 into ¥1200 in London, for a profit of ¥200, would be arbitrage. In reality, this "triangle arbitrage" is so simple that it almost never occurs. But more complicated foreign exchange arbitrages, such as the spot-forward arbitrage (see interest rate parity) are much more common.
  • One example of arbitrage involves the New York Stock Exchange and the Chicago Mercantile Exchange. When the price of a stock on the NYSE and its corresponding futures contract on the CME are out of sync, one can buy the less expensive one and sell the more expensive. Because the differences between the prices are likely to be small (and not to last very long), this can only be done profitably with computers examining a large number of prices and automatically exercising a trade when the prices are far enough out of balance. The activity of other arbitrageurs can make this risky. Those with the fastest computers and the smartest mathematicians take advantage of series of small differentials that would not be profitable if taken individually.
  • Economists use the term "global labor arbitrage" to refer to the tendency of manufacturing jobs to flow towards whichever country has the lowest wages per unit output at present and has reached the minimum requisite level of political and economic development to support industrialization. At present, many such jobs appear to be flowing towards China, though some which require command in English are going to India and the Philippines.
  • Sports arbitrage - numerous internet bookmakers offer odds on the outcome of the same event. Any given bookmaker will weight their odds so that no one customer can cover all outcomes at a profit against their books. However, in order to remain competitive their margins are usually quite low. Different bookmakers may offer different odds on the same outcome of a given event; by taking the best odds offered by each bookmaker, a customer can under some circumstances cover all possible outcomes of the event and lock a small risk-free profit, known as a Dutch book. This profit would typically be between 1% and 5% but can be much higher. One problem with sports arbitrage is that bookmakers sometimes make mistakes and this can lead to an invocation of the 'palpable error' rule, which most bookmakers invoke when they have made a mistake by offering or posting incorrect odds. As bookmakers become more proficient, the odds of making an 'arb' usually last for less than an hour and typically only a few minutes. Furthermore, huge bets on one side of the market also alert the bookies to correct the market.
  • Exchange-traded fund arbitrage - Exchange Traded Funds allow authorized participants to exchange back and forth between shares in underlying securities held by the fund and shares in the fund itself, rather than allowing the buying and selling of shares in the ETF directly with the fund sponsor. ETFs trade in the open market, with prices set by market demand. An ETF may trade at a premium or discount to the value of the underlying assets. When a significant enough premium appears, an arbitrageur will buy the underlying securities, convert them to shares in the ETF, and sell them in the open market. When a discount appears, an arbitrageur will do the reverse. In this way, the arbitrageur makes a low-risk profit, while fulfilling a useful function in the ETF marketplace by keeping ETF prices in line with their underlying value.
  • Some types of hedge funds make use of a modified form of arbitrage to profit. Rather than exploiting price differences between identical assets, they will purchase and sell securities, assets and derivatives with similar characteristics, and hedge any significant differences between the two assets. Any difference between the hedged positions represents any remaining risk (such as basis risk) plus profit; the belief is that there remains some difference which, even after hedging most risk, represents pure profit. For example, a fund may see that there is a substantial difference between U.S. dollar debt and local currency debt of a foreign country, and enter into a series of matching trades (including currency swaps) to arbitrage the difference, while simultaneously entering into credit default swaps to protect against country risk and other types of specific risk.

Price convergence

Arbitrage has the effect of causing prices in different markets to converge. As a result of arbitrage, the currency exchange rates, the price of commodities, and the price of securities in different markets tend to converge to the same prices, in all markets, in each category. The speed at which prices converge is a measure of market efficiency. Arbitrage tends to reduce price discrimination by encouraging people to buy an item where the price is low and resell it where the price is high, as long as the buyers are not prohibited from reselling and the transaction costs of buying, holding and reselling are small relative to the difference in prices in the different markets.

Arbitrage moves different currencies toward purchasing power parity. As an example, assume that a car purchased in America is cheaper than the same car in Canada. Canadians would buy their cars across the border to exploit the arbitrage condition. At the same time, Americans would buy US cars, transport them across the border, and sell them in Canada. Canadians would have to buy American Dollars to buy the cars, and Americans would have to sell the Canadian dollars they received in exchange for the exported cars. Both actions would increase demand for US Dollars, and supply of Canadian Dollars, and as a result, there would be an appreciation of the US Dollar. Eventually, if unchecked, this would make US cars more expensive for all buyers, and Canadian cars cheaper, until there is no longer an incentive to buy cars in the US and sell them in Canada. More generally, international arbitrage opportunities in commodities, goods, securities and currencies, on a grand scale, tend to change exchange rates until the purchasing power is equal.

In reality, of course, one must consider taxes and the costs of travelling back and forth between the US and Canada. Also, the features built into the cars sold in the US are not exactly the same as the features built into the cars for sale in Canada, due, among other things, to the different emissions and other auto regulations in the two countries. In addition, our example assumes that no duties have to be paid on importing or exporting cars from the USA to Canada. Similarly, most assets exhibit (small) differences between countries, and transaction costs , taxes, and other costs provide an impediment to this kind of arbitrage.

Similarly, arbitrage affects the difference in interest rates paid on government bonds, issued by the various countries, given the expected depreciations in the currencies, relative to each other (see interest rate parity).

Risks

Arbitrage transactions in modern securities markets involve fairly low risks. Generally it is impossible to close two or three transactions at the same instant; therefore, there is the possibility that when one part of the deal is closed, a quick shift in prices makes it impossible to close the other at a profitable price. There is also counter-party risk, that the other party to one of the deals fails to deliver as agreed; though unlikely, this hazard is serious because of the large quantities one must trade in order to make a profit on small price differences. These risks become magnified when leverage or borrowed money is used.

Another risk occurs if the items being bought and sold are not identical and the arbitrage is conducted under the assumption that the prices of the items are correlated or predictable. In the extreme case this is risk arbitrage, described below. In comparison to the classical quick arbitrage transaction, such an operation can produce disastrous losses.

Competition in the marketplace can also create risks during arbitrage transactions. As an example, if one was trying to profit from a price discrepancy between IBM on the NYSE and IBM on the London Stock Exchange, they may purchase a large number of shares on the NYSE and find that they cannot simultaneously sell on the LSE. This leaves the arbitrageur in an unhedged risk position.

In the 1980s, risk arbitrage was common. In this form of speculation , one trades a security that is clearly undervalued or overvalued, when it is seen that the wrong valuation is about to be corrected by events. The standard example is the stock of a company, undervalued in the stock market, which is about to be the object of a takeover bid; the price of the takeover will more truly reflect the value of the company, giving a large profit to those who bought at the current price—if the merger goes through as predicted. Traditionally, arbitrage transactions in the securities markets involve high speed and low risk. At some moment a price difference exists, and the problem is to execute two or three balancing transactions while the difference persists (that is, before the other arbitrageurs act). When the transaction involves a delay of weeks or months, as above, it may entail considerable risk if borrowed money is used to magnify the reward through leverage. One way of reducing the risk is through the illegal use of inside information, and in fact risk arbitrage with regard to leveraged buyouts was associated with some of the famous financial scandals of the 1980s such as those involving Michael Milken and Ivan Boesky.

Types of arbitrage

Merger arbitrage

Also called risk arbitrage, merger arbitrage generally consists of buying the stock of a company that is the target of a takeover while shorting the stock of the acquiring company.

Usually the market price of the target company is less than the price offered by the acquiring company. The spread between these two prices depends mainly on the probability and the timing of the takeover being completed as well as the prevailing level of interest rates.

The bet in a merger arbitrage is that such a spread will eventually be zero, if and when the takeover is completed. The risk is that the deal "breaks" and the spread massively widens.

Municipal bond arbitrage

Also called municipal bond relative value arbitrage, municipal arbitrage, or just muni arb, this hedge fund strategy involves one of two approaches.

Generally, managers seek relative value opportunities by being both long and short municipal bonds with a duration-neutral book. The relative value trades may be between different issuers, different bonds issued by the same entity, or capital structure trades referencing the same asset (in the case of revenue bonds). Managers aim to capture the inefficiencies arising from the heavy participation of non-economic investors (i.e., high income "buy and hold" investors seeking tax-exempt income) as well as the "crossover buying" arising from corporations' or individuals' changing income tax situations (i.e., insurers switching their munis for corporates after a large loss as they can capture a higher after-tax yield by offsetting the taxable corporate income with underwriting losses). There are additional inefficiencies arising from the highly fragmented nature of the municipal bond market which has two million outstanding issues and 50,000 issuers in contrast to the Treasury market which has 400 issues and a single issuer.

Second, managers construct leveraged portfolios of AAA- or AA-rated tax-exempt municipal bonds with the duration risk hedged by shorting the appropriate ratio of taxable corporate bonds. These corporate equivalents are typically interest rate swaps referencing Libor [1] or BMA (short for Bond Market Association [2]). The arbitrage manifests itself in the form of a relatively cheap longer maturity municipal bond, which is a municipal bond that yields significantly more than 65% of a corresponding taxable corporate bond. The steeper slope of the municipal yield curve allows participants to collect more after-tax income from the municipal bond portfolio than is spent on the interest rate swap; the carry is greater than the hedge expense. Positive, tax-free carry from muni arb can reach into the double digits. The bet in this municipal bond arbitrage is that, over a longer period of time, two similar instruments--municipal bonds and interest rate swaps--will correlate with each other; they are both very high quality credits, have the same maturity and are denominated in U.S. dollars. Credit risk and duration risk are largely eliminated in this strategy. However, basis risk arises from use of an imperfect hedge, which results in significant, but range-bound principal volatility. The end goal is to limit this principal volatility, eliminating its relevance over time as the high, consistent, tax-free cash flow accumulates. Since the inefficiency is related to government tax policy, and hence is structural in nature, it has not been arbitraged away.

Convertible bond arbitrage

A convertible bond is a bond that an investor can return to the issuing company in exchange for a predetermined number of shares in the company.

A convertible bond can be thought of as a corporate bond with a stock call option attached to it.

The price of a convertible bond is sensitive to three major factors:

  • interest rate. When rates move higher, the bond part of a convertible bond tends to move lower, but the call option part of a convertible bond moves higher (and the aggregate tends to move lower).
  • stock price. When the price of the stock the bond is convertible into moves higher, the price of the bond tends to rise.
  • credit spread. If the creditworthiness of the issuer deteriorates (e.g. rating downgrade) and its credit spread widens, the bond price tends to move lower, but, in many cases, the call option part of the convertible bond moves higher (since credit spread correlates with volatility).

Given the complexity of the calculations involved and the convoluted structure that a convertible bond can have, an arbitrageur often relies on sophisticated quantitative models in order to identify bonds that are trading cheap versus their theoretical value.

Convertible arbitrage consists of buying a convertible bond and hedging two of the three factors in order to gain exposure to the third factor at a very attractive price.

For instance an arbitrageur would first buy a convertible bond, then sell fixed income securities or interest rate futures (to hedge the interest rate exposure) and buy some credit protection (to hedge the risk of credit deterioration). Eventually what he'd be left with is something similar to a call option on the underlying stock, acquired at a very low price. He could then make money either selling some of the more expensive options that are openly traded in the market or delta hedging his exposure to the underlying shares.

Depository receipts

A depository receipt is a security that is offered as a "tracking stock" on another foreign market. For instance a Chinese company wishing to raise more money may issue a depository receipt on the New York Stock Exchange, as the amount of capital on the local exchanges is limited. These securities, known as ADRs ( American Depositary Receipt) or GDRs ( Global Depositary Receipt) depending on where they are issued, are typically considered "foreign" and therefore trade at a lower value when first released. However, they are exchangeable into the original security (known as fungibility) and actually have the same value. In this case there is a spread between the perceived value and real value, which can be extracted. Since the ADR is trading at a value lower than what it is worth, one can purchase the ADR and expect to make money as its value converges on the original. However there is a chance that the original stock will fall in value too, so by shorting it you can hedge that risk.

Regulatory arbitrage

Regulatory arbitrage is where a regulated institution takes advantage of the difference between its real (or economic) risk and the regulatory position. For example, if a bank, operating under the Basel I accord, has to hold 8% capital against default risk, but the real risk of default is lower, it is profitable to securitise the loan, removing the low risk loan from its portfolio. On the other hand, if the real risk is higher than the regulatory risk then it is profitable to make that loan and hold on to it, provided it is priced appropriately.

This process can increase the overall riskiness of institutions under a risk insensitive regulatory regime, as described by Alan Greenspan in his October 1998 speech on The Role of Capital in Optimal Banking Supervision and Regulation .

In economics, regulatory arbitrage (sometimes, tax arbitrage) may be used to refer to situations when a company can choose a nominal place of business with a regulatory, legal or tax regime with lower costs. For example, an insurance company may choose to locate in Bermuda due to preferential tax rates and policies for insurance companies. This can occur particularly where the business transaction has no obvious physical location: in the case of many financial products, it may be unclear "where" the transaction occurs.

Telecom arbitrage

Telecom arbitrage companies like Action Telecom UK allow mobile phone users to make international calls for free through certain access numbers. The telecommunication arbitrage companies get paid an interconnect charge by the UK mobile networks and then buy international routes at a lower cost. The calls are seen as free by the UK contract mobile phone customers since they are using up their allocated monthly minutes rather than paying for additional calls. The end effect is telecom arbitrage. This is usually marketed as "free international calls". The profit margins are usually very small. However, with enough volume, enough money is made from the cost difference to turn a profit. This is very similar to Future Phone in the US.

The debacle of Long-Term Capital Management

Long-Term Capital Management (LTCM) lost 4.6 billion U.S. dollars in fixed income arbitrage in September 1998. LTCM had attempted to make money on the price difference between different bonds. For example, it would sell U.S. Treasury securities and buy Italian bond futures. The concept was that because Italian bond futures had a less liquid market, in the short term Italian bond futures would have a higher return than U.S. bonds, but in the long term, the prices would converge. Because the difference was small, a large amount of money had to be borrowed to make the buying and selling profitable.

The downfall in this system began on August 17, 1998, when Russia defaulted on its ruble debt and domestic dollar debt. Because the markets were already nervous due to the Asian financial crisis, investors began selling non-U.S. treasury debt and buying U.S. treasuries, which were considered a safe investment. As a result the return on U.S. treasuries began decreasing because there were many buyers, and the return on other bonds began to increase because there were many sellers. This caused the difference between the returns of U.S. treasuries and other bonds to increase, rather than to decrease as LTCM was expecting. Eventually this caused LTCM to fold, and their creditors had to arrange a bail-out. More controversially, officials of the Federal Reserve assisted in the negotiations that led to this bail-out, on the grounds that so many companies and deals were intertwined with LTCM that if LTCM actually failed, they would as well, causing a collapse in confidence in the economic system. Thus LTCM failed as a fixed income arbitrage fund, although it is unclear what sort of profit was realized by the banks that bailed LTCM out.

Etymology

"Arbitrage" is a French word and denotes a decision by an arbitrator or arbitration tribunal. (In modern French, "arbitre" usually means referee or umpire). In the sense used here it is first defined in 1704 by Mathieu de la Porte in his treatise "La science des négocians et teneurs de livres" as a consideration of different exchange rates to recognize the most profitable places of issuance and settlement for a bill of exchange ("[U]ne combinaison que l'on fait de plusieurs Changes, pour connoître quelle Place est plus avantageuse pour tirer et remettre"). See "Arbitrage" in Trésor de la Langue Française.

See also

References

External links


Pasha bulker

The ship "Pasha bulker" stranded on Nobby's Beach earlier this year. They
did eventually get it off.

(See attached file: pasha_bulker_ship_nobbys_beach.jpg)(See attached file:
pasha_bulker_ship_nobbys_beach2.jpg)

Postgres explain analyse

http://explain-analyze.info/

Try this page out when working with Postgresql.

Monday, 22 October 2007

Javascript library - jQuery

http://jquery.com/
jQuery is a new type of JavaScript library.


jQuery is a fast, concise, JavaScript Library that simplifies how you
traverse HTML documents, handle events, perform animations, and add Ajax
interactions to your web pages. jQuery is designed to change the way that
you write JavaScript.


"You start with 10 lines of jQuery that would have been 20 lines of
tedious DOM JavaScript. By the time you are done it's down to two or
three lines and it couldn't get any shorter unless it read your
mind." - Dave Methvin

What does jQuery code look like? The quick and dirty:


$("p.surprise").addClass("ohmy").show("slow");


Congratulations! You just ran a snippet of jQuery code. Wasn't that easy?
There's lots of example code throughout the documentation on this site. Be
sure to give all the code a test run, to see what happens.


The above code snippet looks for all paragraphs that have a class of
'surprise', adds the class 'ohmy' to them, then slowly reveals them. Click
the 'Run' button to see it in action!

Gantt project charting for Linux

http://ganttproject.biz/

GanttProject is a free and easy to use Gantt chart based project scheduling
and management tool. Our major features include:
Task hierarchy and dependencies
Gantt chart
Resource load chart
Generation of PERT chart
PDF and HTML reports
MS Project import/export
WebDAV based groupwork


(See attached file: ganttproject-house-building-sample.png)

Part image - save a partition

http://www.partimage.org/Main_Page

Welcome to Partimage homepage


Description: Partimage is a Linux utility which saves partitions having a
supported filesystem to an image file. Most Linux and Windows filesystems
are supported. The image file can be compressed with the gzip / bzip2
programs to save disk space, and they can be splitted into multiple files
to be copied on CDs / DVDs, ... Partitions can also be saved across the
network since version 0.6.0 using the partimage network support, or using
Samba / NFS. If you don't want to install Partimage, you can download and
burn SystemRescueCd. It's a livecd that allows to use Partimage immediately
even if your computer has no operating system installed (useful to restore
an image), and it allows to save an image on a DVD on the fly.


Partimage will only copy data from the used portions of the partition. For
speed and efficiency, free blocks are not written to the image file. This
is unlike the 'dd' command, which also copies empty blocks. Partimage also
works for large, very full partitions. For example, a full 1 GB partition
can be compressed with gzip down to 400MB.


This is very useful to save partitions to an image in some cases:
First you can restore your linux partition if there is a problem
(virus, file system errors, manipulation error). When you have a
problem, you just have to restore the partition, and after 10
minutes, you have the original partition. You can write the image to
a CD-R if you don't want the image to use hard-disk space.
This utility can be used to install many identical computers. For
example, if you buy 50 PCs, with the same hardware, and you want to
install the same linux systems on all 50 PCs, you will save a lot of
time. Indeed, you just have to install on the first PC and create an
image from it. For the 49 others, you can use the image file and
Partition Image's restore function.

Friday, 19 October 2007

Aircrack-ng & Airsnort & Kismet

http://en.wikipedia.org/wiki/Aircrack-ng
http://www.aircrack-ng.org/doku.php
http://en.wikipedia.org/wiki/AirSnort
http://en.wikipedia.org/wiki/Kismet_%28software%29

Aircrack is an 802.11 WEP and WPA-PSK keys cracking program that can
recover keys once enough data packets have been captured. It implements the
standard FMS attack along with some optimizations like KoreK attacks, thus
making the attack much faster compared to other WEP cracking tools. In
fact, aircrack is a set of tools for auditing wireless networks.

AirSnort is a Linux utility (using GTK+) for decrypting WEP encryption on
an 802.11b network. A Windows port also exists. Distributed under the GNU
General Public License,[1] AirSnort is free software.


Scott Fluhrer, Itsik Mantin and Adi Shamir (who was one of the inventors of
the RSA encryption algorithm) released a paper entitled Weaknesses in the
Key Scheduling Algorithm of RC4. Based on the security flaws described
therein, Blake Hegerle and Jeremy Bruestle wrote a tool that must only
gather roughly five to ten million encrypted packets from a wireless access
point before it can attempt to recover the wireless key. Depending on the
environment, this can take as little as a few minutes or more commonly a
few hours and possibly a few days.

Kismet is a network detector, packet sniffer, and intrusion detection
system for 802.11 wireless LANs. Kismet will work with any wireless card
which supports raw monitoring mode, and can sniff 802.11b, 802.11a and
802.11g traffic. The program runs under Linux, FreeBSD, NetBSD, OpenBSD,
and Mac OS X. The client can also run on Windows, although a drone is the
only compatible packet source.

Wednesday, 17 October 2007

GDB reference card

(See attached file: gdb-refcard-a4.pdf)

The Pedal-to-the-Metal, Totally Illegal, Cross-Country Sprint for Glory

http://www.wired.com/cars/coolwheels/magazine/15-11/ff_cannonballrun

And so the clock starts and the taillights flare, and they're off again, strapped down, fueled up, and bound on an outlaw enterprise with 2,795 miles of interstate and some 31,000 highway cops between them and the all-time speed record for crossing the American continent on four wheels.


bin packing

http://facebook.enomalylabs.com/treemap7.php

This widget has been developed by Khaz Sapenov, using "bin packing" algorithm.

In computational complexity theory, the bin packing problem is a combinatorial NP-hard problem. In it, objects of different volumes must be packed into a finite number of bins of capacity V in a way that minimizes the number of bins used.

There are many variations of this problem, such as 2D packing, linear packing, packing by weight, packing by cost, and so on. They have many applications, such as filling up containers, loading trucks with weight capacity, and creating file backup in removable media.

Since it is NP-hard, the most efficient known algorithms use heuristics to accomplish results which, though very good in most cases, may not be the optimal solution. For example, the first fit algorithm provides a fast but often nonoptimal solution, involving placing each item into the first bin in which it will fit. It requires O(n log n) time. The algorithm can be made much more effective by first sorting the list of elements into decreasing order (sometimes known as the first-fit decreasing algorithm), although this does not guarantee an optimal solution, and for longer lists may increase the running time of the algorithm.


Elastic compute clouds and internet storage

http://www.amazon.com/gp/browse.html?node=16427261

Amazon Simple Storage Service (Amazon S3)

Amazon S3 is storage for the Internet. It is designed to make web-scale computing easier for developers.

Amazon S3 provides a simple web services interface that can be used to store and retrieve any amount of data, at any time, from anywhere on the web. It gives any developer access to the same highly scalable, reliable, fast, inexpensive data storage infrastructure that Amazon uses to run its own global network of web sites. The service aims to maximize benefits of scale and to pass those benefits on to developers.

Pricing

Pay only for what you use. There is no minimum fee. Estimate your monthly bill using AWS Simple Monthly Calculator.

Storage
$0.15 per GB-Month of storage used

Data Transfer
$0.10 per GB - all data transfer in

$0.18 per GB - first 10 TB / month data transfer out
$0.16 per GB - next 40 TB / month data transfer out
$0.13 per GB - data transfer out / month over 50 TB

Data transfer "in" and "out" refers to transfer into and out of Amazon S3.
Data transferred between Amazon S3 and Amazon EC2 is free of charge

Requests
$0.01 per 1,000 PUT or LIST requests
$0.01 per 10,000 GET and all other requests*
* No charge for delete requests

http://nirvanix.com/platform.aspx

File System Scalability

File System Scalability The Nirvanix Internet Media File System™, the backbone of the Nirvanix SDS, was designed from the ground-up to eliminate scaling considerations when building new web services. It removes barriers for companies to offer Internet-scale media applications by eliminating all storage and bandwidth constraints from the application servers and into Nirvanix's SDS that scales to one pentillion files (a pentillion is 1 followed by 18 zeros). A pentillion files would be equal to 150 million files for every man, woman and child on the planet.

Service Pricing

The Nirvanix Storage Delivery Service in an on-demand solution where customers only pay for what they use. Our services are priced as follows:

Base Price*:
  • Storage Services: $0.18 (average GB stored/mo, based on daily average)
  • Transfer Services: $0.18 (total GB/mo uploaded/downloaded)
  • Media Processing Services: Will be priced as they become generally available
  • Credit card fee: $1 per month minimum fee
Customer Support:
  • Basic Support: FREE (unlimited e-mail, web forum, live chat)
  • Enhanced Support $160/mo (adds phone access, alerts, 2hr integration)
  • Premium Support $600/mo (adds priority routing, 24/7 access, 4hr integration)
  • More information
Service Level Agreement:
  • Standard: 99.9% uptime guarantee, allows for 45 min/mo of unplanned downtime, backed by service credits**.

http://www.amazon.com/b/ref=sc_fe_l_2/103-2370110-5651045?ie=UTF8&node=201590011&no=342430011&me=A36L942TSJ2AJA

Amazon Elastic Compute Cloud (Amazon EC2) - Beta

Amazon Elastic Compute Cloud (Amazon EC2) is a web service that provides resizable compute capacity in the cloud. It is designed to make web-scale computing easier for developers.

Just as Amazon Simple Storage Service (Amazon S3) enables storage in the cloud, Amazon EC2 enables "compute" in the cloud. Amazon EC2's simple web service interface allows you to obtain and configure capacity with minimal friction. It provides you with complete control of your computing resources and lets you run on Amazon's proven computing environment. Amazon EC2 reduces the time required to obtain and boot new server instances to minutes, allowing you to quickly scale capacity, both up and down, as your computing requirements change. Amazon EC2 changes the economics of computing by allowing you to pay only for capacity that you actually use.

Amazon EC2 Functionality

Amazon EC2 presents a true virtual computing environment, allowing you to use web service interfaces to requisition machines for use, load them with your custom application environment, manage your network's access permissions, and run your image using as many or few systems as you desire.

To use Amazon EC2, you simply:

  • Create an Amazon Machine Image (AMI) containing your applications, libraries, data and associated configuration settings. Or use our pre-configured, templated images to get up and running immediately.
  • Upload the AMI into Amazon S3. Amazon EC2 provides tools that make storing the AMI simple. Amazon S3 provides a safe, reliable and fast repository to store your images.
  • Use Amazon EC2 web service to configure security and network access.
  • Choose the type(s) of instance you want to run.
  • Start, terminate, and monitor as many instances of your AMI as needed, using the web service APIs.
  • Pay for the instance-hours and bandwidth that you actually consume.

Pricing

Pay only for what you use. There is no minimum fee. Estimate your monthly bill using AWS Simple Monthly Calculator.

Instances

$0.10 - Small Instance (Default)

    1.7 GB of memory, 1 EC2 Compute Unit (1 virtual core with 1 EC2 Compute Unit), 160 GB of instance storage, 32-bit platform

$0.40 - Large Instance

    7.5 GB of memory, 4 EC2 Compute Units (2 virtual cores with 2 EC2 Compute Units each), 850 GB of instance storage, 64-bit platform

$0.80 - Extra Large Instance

    15 GB of memory, 8 EC2 Compute Units (4 virtual cores with 2 EC2 Compute Units each), 1690 GB of instance storage, 64-bit platform

Pricing is per instance-hour consumed for each instance type. Partial instance-hours consumed are billed as full hours.

One EC2 Compute Unit provides the equivalent CPU capacity of a 1.0-1.2 GHz 2007 Opteron or 2007 Xeon processor. This is also the equivalent to an early-2006 1.7 GHz Xeon processor referenced in our original documentation. See Measuring Compute Resources for a complete description of an EC2 Compute Unit.

See Amazon EC2 Instance Types for details on available instance configurations.
 

Data Transfer

$0.10 per GB - all data transfer in

$0.18 per GB - first 10 TB / month data transfer out
$0.16 per GB - next 40 TB / month data transfer out
$0.13 per GB - data transfer out / month over 50 TB

Data transfer "in" and "out" refers to transfer into and out of Amazon EC2.

Data transferred within the Amazon EC2 environment, or between Amazon EC2 and Amazon S3, is free of charge (i.e., $0.00 per GB). All Amazon S3 storage and request charges will still apply.

Amazon S3 usage is billed separately from Amazon EC2; charges for each service will be billed at the end of the month.

http://www.amazon.com/Mechanical-Turk-AWS-home-page/b/ref=sc_fe_l_2/103-2370110-5651045?ie=UTF8&node=15879911&no=342430011&me=A36L942TSJ2AJA

Amazon Mechanical Turk (Amazon MTurk) - Beta

Amazon Mechanical Turk is a marketplace for work that requires human intelligence. The Mechanical Turk web service enables companies to programmatically access this marketplace and a diverse, on-demand workforce. Developers can leverage this service to build human intelligence directly into their applications.

While computing technology continues to improve, there are still many things that human beings can do much more effectively than computers, such as identifying objects in a photo or video, performing data de-duplication, transcribing audio recordings or researching data details. Traditionally, tasks like this have been accomplished by hiring a large temporary workforce (which is time consuming, expensive and difficult to scale) or have gone undone.

Mechanical Turk aims to make accessing human intelligence simple, scalable, and cost-effective. Businesses or developers needing tasks done (called Human Intelligence Tasks or "HITs") can use the robust Mechanical Turk APIs to access thousands of high quality, low cost, global, on-demand workers -- and then programmatically integrate the results of that work directly into their business processes and systems. Mechanical Turk enables developers and businesses to achieve their goals more quickly and at a lower cost than was previously possible.

http://www.amazon.com/Simple-Queue-Service-home-page/b/ref=sc_fe_l_2/103-2370110-5651045?ie=UTF8&node=13584001&no=342430011&me=A36L942TSJ2AJA

Amazon Simple Queue Service (Amazon SQS)

Amazon Simple Queue Service (Amazon SQS) offers a reliable, highly scalable hosted queue for storing messages as they travel between computers. By using Amazon SQS, developers can simply move data between distributed application components performing different tasks, without losing messages or requiring each component to be always available.

Amazon SQS works by exposing Amazon's web-scale messaging infrastructure as a web service. Any computer on the Internet can add or read messages without any installed software or special firewall configurations. Components of applications using Amazon SQS can run independently, and do not need to be on the same network, developed with the same technologies, or running at the same time.

Pricing

Pay only for what you use. There is no minimum fee. Estimate your monthly bill using AWS Simple Monthly Calculator.

Messages
$0.10 per 1,000 messages sent ($0.0001 per message sent)

Data Transfer
$0.10 per GB - all data transfer in

$0.18 per GB - first 10 TB / month data transfer out
$0.16 per GB - next 40 TB / month data transfer out
$0.13 per GB - data transfer out / month over 50 TB

Data transfer "in" and "out" refers to transfer into and out of Amazon SQS.


Monday, 15 October 2007

Books to buy - Code Complete, The Mythical Man-Month

Code Complete, Second Edition (Paperback)
by Steve McConnell (Author) "Developing computer software can be a
complicated process, and in the last 25 years, researchers have identified
numerous distinct activities that go into software development..."


The Mythical Man-Month: Essays on Software Engineering, 20th Anniversary
Edition by Frederick P. Brooks

Thursday, 11 October 2007

Harvard scientists predict the future of the past tense

http://www.sciencecodex.com/harvard_scientists_predict_the_future_of_the_past_tense

Posted On: October 10, 2007 - 4:00am


Verbs evolve and homogenize at a rate inversely proportional to their
prevalence in the English language, according to a formula developed by
Harvard University mathematicians who've invoked evolutionary principles to
study our language over the past 1,200 years, from "Beowulf" to "Canterbury
Tales" to "Harry Potter."


Writing this week in the journal Nature, Erez Lieberman, Jean-Baptiste
Michel, and colleagues in Harvard's Program for Evolutionary Dynamics, led
by Martin A. Nowak, conceive of linguistic development as an essentially
evolutionary scheme: Just as genes and organisms undergo natural selection,
words -- specifically, irregular verbs that do not take an "-ed" ending in
the past tense -- are subject to powerful pressure to "regularize" as the
language develops.


"Mathematical analysis of this linguistic evolution reveals that irregular
verb conjugations behave in an extremely regular way -- one that can yield
predictions and insights into the future stages of a verb's evolutionary
trajectory," says Lieberman, a graduate student in applied mathematics in
Harvard's School of Engineering and Applied Sciences and in the Harvard-MIT
Division of Health Sciences and Technology, and an affiliate of Harvard's
Program for Evolutionary Dynamics. "We measured something no one really
thought could be measured, and got a striking and beautiful result."


"We're really on the front lines of developing the mathematical tools to
study evolutionary dynamics," says Michel, a graduate student in systems
biology at Harvard Medical School and an affiliate of the Program for
Evolutionary Dynamics. "Before, language was considered too messy and
difficult a system for mathematical study, but now we're able to
successfully quantify an aspect of how language changes and develops."


Lieberman, Michel, and colleagues built upon previous study of seven
competing rules for verb conjugation in Old English, six of which have
gradually faded from use over time. They found that the one surviving rule,
which adds an "-ed" suffix to simple past and past participle forms,
contributes to the evolutionary decay of irregular English verbs according
to a specific mathematical function: It regularizes them at a rate that is
inversely proportional to the square root of their usage frequency.


In other words, a verb used 100 times less frequently will evolve 10 times
as fast.


To develop this formula, the researchers tracked the status of 177
irregular verbs in Old English through linguistic changes in Middle English
and then modern English. Of these 177 verbs that were irregular 1,200 years
ago, 145 stayed irregular in Middle English and just 98 remain irregular
today, following the regularization over the centuries of such verbs as
help, laugh, reach, walk, and work.


Lieberman and Michel's group computed the "half-lives" of the surviving
irregular verbs to predict how long they will take to regularize. The most
common ones, such as "be" and "think," have such long half-lives (38,800
years and 14,400 years, respectively) that they will effectively never
become regular. Irregular verbs with lower frequencies of use -- such as
"shrive" and "smite," with half-lives of 300 and 700 years, respectively --
are much more likely to succumb to regularization.


Lieberman, Michel, and their co-authors project that the next word to
regularize will likely be "wed."


"Now may be your last chance to be a 'newly wed'," they quip in the Nature
paper. "The married couples of the future can only hope for 'wedded'
bliss."


Extant irregular verbs represent the vestiges of long-abandoned rules of
conjugation; new verbs entering English, such as "google," are universally
regular. Although fewer than 3 percent of modern English verbs are
irregular, this number includes the 10 most common verbs: be, have, do, go,
say, can, will, see, take, and get. Lieberman, Michel, and colleagues
expect that some 15 of the 98 modern irregular verbs they studied --
although likely none of these top 10 -- will regularize in the next 500
years.


The group's Nature paper makes a quantitative, astonishingly precise
description of something linguists have suspected for a long time: The most
frequently used irregular verbs are repeated so often that they are
unlikely to ever go extinct.


"Irregular verbs are fossils that reveal how linguistic rules, and perhaps
social rules, are born and die," Michel says.


"If you apply the right mathematical structure to your data, you find that
the math also organizes your thinking about the entire process," says
Lieberman, whose unorthodox projects as a graduate student have ranged from
genomics to bioastronautics. "The data hasn't changed, but suddenly you're
able to make powerful predictions about the future."


Lieberman and Michel's co-authors on the Nature paper are Nowak, professor
of mathematics and of biology at Harvard and director of the Program for
Evolutionary Dynamics, and Harvard undergraduates Joe Jackson and Tina
Tang. Their work was sponsored by the John Templeton Foundation, the
National Science Foundation, and the National Institutes of Health.

Wednesday, 10 October 2007

ANT Censuses of the Internet Address Space

http://www.isi.edu/ant/address/

(See attached file: it.15.all.16-subnet_stats.3px-per-point.annotated.png)

based on http://www.xkcd.com/195/
(See attached file: map_of_the_internet.jpg)

Explaining how they did it:
(See attached file: address_space_2007_smaller.png)

Tuesday, 9 October 2007

Windows - Speeding up filesystems

http://msdn2.microsoft.com/en-us/library/ms940846.aspx
Disabling Last Access Time Stamps

If you are using an NTFS file system, you can increase the performance of EWF by disabling the last access date/time stamps.

To disable Last Access timestamps

  • Create the following registry key on your run-time image:

    Key Name: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem
    Name: NtfsDisableLastAccessUpdate
    Type: REG_DWORD
    Value: 1


http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/fsutil_behavior.mspx?mfr=true

Fsutil: behavior

Queries the current settings for generating 8.3 character-length file names, allowing extended characters in 8.3 character-length file names on NTFS volumes, updating the last access timestamp on NTFS volumes, how often quota events are written to the system log, and the size of the master file table (MFT) Zone. Enables or disables the use of 8.3 character-length file names, allowing extended characters in 8.3 character-length file names on NTFS volumes, and updating the last access timestamp on NTFS volumes. Enables you to change how often quota events are written to the system log and to change the amount of disk space reserved for the MFT Zone.



http://www.diskeeper.com/defrag.asp


Adobe Flex Builder for Linux Alpha

From lwn.net & http://weblog.infoworld.com/techwatch/archives/014192.html
Tech Watch reports on Adobe's release of Adobe Flex Builder for Linux. "Flex Builder is an IDE for building rich Internet applications that leverage Flex and Adobe's Flash Player. Flex Builder Linux Alpha offers most Flex Builder 3 features such as project creation, code coloring, code hints and Ajax bridge. The release requires Sun Java Runtime Environment 1.5.x and the Eclipse 3.3 platform. The alpha producte supports several Suse, Red Hat and Ubuntu Linux distributions and the Firefox browser. Plans call for expanding support to other browsers and Linux distributions, said Phil Costa, director of product management at Adobe."

New York Times - The Next Leap for Linux

http://www.nytimes.com/2007/10/04/technology/circuits/04basics.html?ex=1192161600&en=47d6bc2f2d559a0f&ei=5070&emc=eta1

Until recently, major PC makers shied away from Linux. Now the industry is watching as Dell is selling two Linux-equipped desktop models ($549 and $870, including a monitor) and a $774 notebook PC. ( Hewlett-Packard offers Linux systems to businesses, and Lenovo , the Chinese company that bought I.B.M.'s PC division, sells Linux machines in China and says it will soon offer Linux-based computers in the United States.)

The Ubuntu version of Linux runs the Dell computers. Because Dell does not have to pay a licensing fee for the operating system, the computers are $80 cheaper than PCs with Windows Vista Home Premium or $50 cheaper than the stripped-down Vista Basic edition.


Linkers documented

http://www.airs.com/blog/archives/38

I've been working on and off on a new linker. To my surprise, I've discovered in talking about this that some people, even some computer programmers, are unfamiliar with the details of the linking process. I've decided to write some notes about linkers, with the goal of producing an essay similar to my existing one about the GNU configure and build system.

As I only have the time to write one thing a day, I'm going to do this on my blog over time, and gather the final essay together later. I believe that I may be up to five readers, and I hope y'all will accept this digression into stuff that matters. I will return to random philosophizing and minding other people's business soon enough.

A Personal Introduction

Who am I to write about linkers?

I wrote my first linker back in 1988, for the AMOS operating system which ran on Alpha Micro systems. (If you don't understand the following description, don't worry; all will be explained below). I used a single global database to register all symbols. Object files were checked into the database after they had been compiled. The link process mainly required identifying the object file holding the main function. Other objects files were pulled in by reference. I reverse engineered the object file format, which was undocumented but quite simple. The goal of all this was speed, and indeed this linker was much faster than the system one, mainly because of the speed of the database.

I wrote my second linker in 1993 and 1994. This linker was designed and prototyped by Steve Chamberlain while we both worked at Cygnus Support (later Cygnus Solutions, later part of Red Hat). This was a complete reimplementation of the BFD based linker which Steve had written a couple of years before. The primary target was a.out and COFF. Again the goal was speed, especially compared to the original BFD based linker. On SunOS 4 this linker was almost as fast as running the cat program on the input .o files.

The linker I am now working, called gold, on will be my third. It is exclusively an ELF linker. Once again, the goal is speed, in this case being faster than my second linker. That linker has been significantly slowed down over the years by adding support for ELF and for shared libraries. This support was patched in rather than being designed in. Future plans for the new linker include support for incremental linking–which is another way of increasing speed.

There is an obvious pattern here: everybody wants linkers to be faster. This is because the job which a linker does is uninteresting. The linker is a speed bump for a developer, a process which takes a relatively long time but adds no real value. So why do we have linkers at all? That brings us to our next topic.

A Technical Introduction

What does a linker do?

It's simple: a linker converts object files into executables and shared libraries. Let's look at what that means. For cases where a linker is used, the software development process consists of writing program code in some language: e.g., C or C++ or Fortran (but typically not Java, as Java normally works differently, using a loader rather than a linker). A compiler translates this program code, which is human readable text, into into another form of human readable text known as assembly code. Assembly code is a readable form of the machine language which the computer can execute directly. An assembler is used to turn this assembly code into an object file. For completeness, I'll note that some compilers include an assembler internally, and produce an object file directly. Either way, this is where things get interesting.

In the old days, when dinosaurs roamed the data centers, many programs were complete in themselves. In those days there was generally no compiler–people wrote directly in assembly code–and the assembler actually generated an executable file which the machine could execute directly. As languages liked Fortran and Cobol started to appear, people began to think in terms of libraries of subroutines, which meant that there had to be some way to run the assembler at two different times, and combine the output into a single executable file. This required the assembler to generate a different type of output, which became known as an object file (I have no idea where this name came from). And a new program was required to combine different object files together into a single executable. This new program became known as the linker (the source of this name should be obvious).

Linkers still do the same job today. In the decades that followed, one new feature has been added: shared libraries.


5 Great (And Free) Games You’re Not Playing Now

Found on

http://gigaom.com/2007/10/07/5-great-and-free-games-youre-not-playing-now/

via http://del.icio.us/







Written by Jane Pinckard

Sunday, October 7, 2007 at 12:00 PM PT

The growth of casual gaming has spawned an unprecedented variety, and

quality, of free web-based games. And as the development quality gets ever

higher, it attracts more talent, bigger budgets, and more ambitious scopes.

Here are five terrific games from independent developers you might have

missed the first time around. All of these can be played in your browser,

with Flash. Go on, it's Sunday — waste a little time!





GrowCube: This and the other equally gorgeous puzzles on EyezMaze require

imagination, trial and error, and maybe even some note-taking. Patience

will be rewarded by lovely animations and transformations in the game

world. The unique gameplay requires you to think several steps ahead.





Tanks: It's simple, and addictive — shoot various types of missiles at the

enemy tank, judging angles and mass to score direct hits. The best part is

that it can be played multiplayer, for up to five players, or just play the

AI alone.





Warbears: Another puzzle game, with an utterly charming design and engaging

sense of humor. Aid the bears in their mission by choosing the order of

their actions — or watch as they hilariously meet failure.





Dai Pai Dong: Cooking Mama meets the classic Diner Dash — in Hong Kong! Try

to keep up with the picky customers' demands by cooking to order and

serving up beers. Warning: playing before lunch may make you hungry for

sauteed crab.





Sprout: The hand-drawn art sets this puzzle game apart, as does the

creatively told story of one lonely seedling far from where it sprouted. By

planting the seed and growing a new plant, with new properties, guide the

seedling home.





And one extra, Scrabulous on Facebook: It's simply Scrabble, online, with

friends, through Facebook, and that's simply it. And it is indeed fabulous

— as well as a great way to stay in noncommittal contact with friends. And

of course you already know about Desktop Tower Defense, right? Good.

Monday, 8 October 2007

Server logging visualisation using Ruby and OpenGL

From http://www.fudgie.org/



View real-time data and statistics from any logfile on any server you have
SSH access to, in an intuitive and entertaining way.


Here is the code:

#!/usr/bin/env ruby
# gl_tail.rb v0.01 - OpenGL visualization of your server traffic
# Copyright 2007 Erlend Simonsen
#
# Licensed under the GPLv2
#
# I know, horrible code and global variables, and what not. But, it works,
# and it's too fun to watch my servers traffic in real time to clean up
# everything before releasing it.
#
# Installation instructions (Ubuntu/Debian):
# sudo apt-get install libopengl-ruby rubygems
# sudo gem install -y net-ssh
#
# Installation instructions (Mac OS/X):
#
# sudo gem install -y ruby-opengl net-ssh
# (You might need option 2 or higher)
#
# Configuration:
# Modify $SERVERS, $BLOCKS & $PARSERS to your liking. Either include a
# :password for each of your servers, or make sure your ssh-keys are
# correctly set up.
#
# Running:
# ./gl_tail.rb
#
# Changelog:
# 06 Oct 2007 - v0.01 Initial release
# 07 Oct 2007 - v0.02 Postfix parser
# IIS parser (Tucker Sizemore )
#
# Further ideas:
# Get rid of GLUT.BitmapCharacter and use textured polygons instead
# Allow more indicators (pulsing color/size, cubes, teapots, etc)
# Clickable links
# Drag 'n drop organizing
# Hide/show blocks with keypresses
# Limit display to specific host
# Background IP lookups
# Geolocation on IPS
#

require 'rubygems'

require 'opengl'
if RUBY_PLATFORM == "i386-mswin32"
require 'glut_prev'
else
require 'glut'
end
#require 'cgi'
#require 'resolv'

require_gem 'net-ssh'


#################
### Configuration
###

ENV['__GL_SYNC_TO_VBLANK']="1"
$WINDOW_WIDTH = 1200
$WINDOW_HEIGHT = 760

# $MIN_BLOB_SIZE = 0.07
$MIN_BLOB_SIZE = 0.05
$MAX_BLOB_SIZE = 0.6

$SERVERS = [
# List of machines to log in to via SSH, and which files to tail for traffic data.
{:name => 'server1', :host => 'server1.example.com', :user => 'joeuser', :password => 'secret', :command => 'tail -f', :files => ['/var/log/apache/access_log'], :color => [0.6, 0.6, 1.0, 1.0], :parser => :apache },
{:name => 'server2', :host => 'login.mycoolsite.com', :user => 'otheruser', :password => 'othersecret', :port => 22222, :command => 'xtail', :files => ['/usr/local/www/apps/myapp/current/log/production.log'], :color => [0.1, 0.6, 0.6, 1.0], :parser => :rails },
{:name => 'mail', :host => 'mail.spamme.com', :user => 'otheruser', :password => 'othersecret', :command => 'tail -f', :files => ['/var/log/maillog'], :color => [0.8, 1.0, 0.0, 1.0], :parser => :postfix },
]

$BLOCKS = [
# Sections with different information to display on the screen
{ :name => 'info', :position => :left, :order => 0, :size => 10, :auto_clean => false, :show => :total },
{ :name => 'sites', :position => :left, :order => 1, :size => 10 },
{ :name => 'content', :position => :left, :order => 2, :size => 5, :show => :total, :color => [1.0, 0.8, 0.4, 1.0] },
{ :name => 'status', :position => :left, :order => 3, :size => 10, :color => [1.0, 0.8, 0.4, 1.0] },
{ :name => 'users', :position => :left, :order => 4, :size => 10 },
{ :name => 'smtp', :position => :left, :order => 5, :size => 5 },

{ :name => 'urls', :position => :right, :order => 0, :size => 15 },
{ :name => 'slow requests', :position => :right, :order => 1, :size => 5, :show => :average },
{ :name => 'referrers', :position => :right, :order => 2, :size => 10 },
{ :name => 'user agents', :position => :right, :order => 3, :size => 5, :color => [1.0, 1.0, 1.0, 1.0] },
{ :name => 'mail', :position => :right, :order => 4, :size => 5 },
]

$PARSERS = {
# Parser which handles access_logs in combined format from Apache
:apache => Proc.new { |server,line|
_, host, user, domain, date, url, status, size, referrer, useragent = /^([\d.]+) (\S+) (\S+) \[([^\]]+)\] \"(.+?)\" (\d+) ([\S]+) \"([^\"]+)\" \"([^\"]+)\"/.match(line).to_a

if host
method, url, http_version = url.split(" ")

url, parameters = url.split('?')

server.add_activity(:block => 'sites', :name => server.name, :size => size.to_i/1000000.0) # Size of activity based on size of request
server.add_activity(:block => 'urls', :name => url)
server.add_activity(:block => 'users', :name => host, :size => size.to_i/1000000.0)
server.add_activity(:block => 'referrers', :name => referrer) unless (referrer.include?(server.name) || referrer.include?(server.host))
server.add_activity(:block => 'user agents', :name => useragent, :type => 3)

if( url.include?('.gif') || url.include?('.jpg') || url.include?('.png') || url.include?('.ico'))
type = 'image'
elsif url.include?('.css')
type = 'css'
elsif url.include?('.js')
type = 'javascript'
elsif url.include?('.swf')
type = 'flash'
elsif( url.include?('.avi') || url.include?('.ogm') || url.include?('.flv') || url.include?('.mpg') )
type = 'movie'
elsif( url.include?('.mp3') || url.include?('.wav') || url.include?('.fla') || url.include?('.aac') || url.include?('.ogg'))
type = 'music'
else
type = 'page'
end
server.add_activity(:block => 'content', :name => type)
server.add_activity(:block => 'status', :name => status, :type => 3) # don't show a blob

# Events to pop up
server.add_event(:block => 'info', :name => "Logins", :message => "Login...", :update_stats => true, :color => [1.5, 1.0, 0.5, 1.0]) if method == "POST" && url.include?('login')
server.add_event(:block => 'info', :name => "Sales", :message => "$", :update_stats => true, :color => [1.5, 0.0, 0.0, 1.0]) if method == "POST" && url.include?('/checkout')
server.add_event(:block => 'info', :name => "Signups", :message => "New User...", :update_stats => true, :color => [1.0, 1.0, 1.0, 1.0]) if( method == "POST" && (url.include?('/signup') || url.include?('/users/create')))
end
},

:rails => Proc.new { |server,line|
#Completed in 0.02100 (47 reqs/sec) | Rendering: 0.01374 (65%) | DB: 0.00570 (27%) | 200 OK [http://example.com/whatever/whatever]
_, ms, url = /^Completed in ([\d.]+) .* \[([^\]]+)\]/.match(line).to_a


if url
_, host, url = /^http[s]?:\/\/([^\/]+)(.*)/.match(url).to_a

server.add_activity(:block => 'sites', :name => host, :size => ms.to_f) # Size of activity based on request time.
server.add_activity(:block => 'urls', :name => url, :size => ms.to_f)
server.add_activity(:block => 'slow requests', :name => url, :size => ms.to_f)

# Events to pop up
server.add_event(:block => 'info', :name => "Logins", :message => "Login...", :update_stats => true, :color => [0.5, 1.0, 0.5, 1.0]) if url.include?('/login')
server.add_event(:block => 'info', :name => "Sales", :message => "$", :update_stats => true, :color => [1.5, 0.0, 0.0, 1.0]) if url.include?('/checkout')
server.add_event(:block => 'info', :name => "Signups", :message => "New User...", :update_stats => true, :color => [1.0, 1.0, 1.0, 1.0]) if(url.include?('/signup') || url.include?('/users/create'))
elsif line.include?('Processing ')
#Processing TasksController#update_sheet_info (for 123.123.123.123 at 2007-10-05 22:34:33) [POST]
_, host = /^Processing .* \(for (\d+.\d+.\d+.\d+) at .*\).*$/.match(line).to_a
if host
server.add_activity(:block => 'users', :name => host)
end
elsif line.include?('Error (')
_, error, msg = /^([^ ]+Error) \((.*)\):/.match(line).to_a
if error
server.add_event(:block => 'info', :name => "Exceptions", :message => error, :update_stats => true, :color => [1.0, 0.0, 0.0, 1.0])
server.add_event(:block => 'info', :name => "Exceptions", :message => msg, :update_stats => false, :color => [1.0, 0.0, 0.0, 1.0])
end
end
},

:postfix => Proc.new { |server,line|

if line.include?(': connect from')
_, host, ip = /: connect from ([^\[]+)\[(\d+.\d+.\d+.\d+)\]/.match(line).to_a
if host
server.add_activity(:block => 'smtp', :name => host, :size => 0.03)
end
elsif line.include?(' from=<') _, from, size = /: from=<([^>]+)>, size=(\d+)/.match(line).to_a
if from
server.add_activity(:block => 'mail', :name => from, :size => size.to_f/100000.0)
end
elsif line.include?(' to=<') if line.include?('relay=local') # Incoming _, to, delay, status = /: to=<([^>]+)>, .*delay=([\d.]+).*status=([^ ]+)/.match(line).to_a
server.add_activity(:block => 'mail', :name => to, :size => delay.to_f/10.0, :type => 5, :color => [1.0, 0.0, 1.0, 1.0])
server.add_activity(:block => 'status', :name => 'received', :size => delay.to_f/10.0, :type => 3)
else
# Outgoing
_, to, relay_host, delay, status = /: to=<([^>]+)>, relay=([^\[,]+).*delay=([\d.]+).*status=([^ ]+)/.match(line).to_a
server.add_activity(:block => 'mail', :name => to, :size => delay.to_f/10.0)
server.add_activity(:block => 'smtp', :name => relay_host, :size => delay.to_f/10.0)
server.add_activity(:block => 'status', :name => status, :size => delay.to_f/10.0, :type => 3)
end
end

},

:iis => Proc.new { |server,line|
_, date, time,serverip, url, referrer, port, size, host, useragent, status = /^([\d-]+) ([\d:]+) ([\d.]+) (.+? .+?) (\S+) (.+?) (\S+) ([\d.]+) (.+?) (\d+) (.*)$/.match(line).to_a

if host
method, url, http_version = url.split(" ")

url, parameters = url.split('?')

server.add_activity(:block => 'sites', :name => server.name, :size => size.to_i/1000000.0) # Size of activity based on size of request
server.add_activity(:block => 'urls', :name => url)
server.add_activity(:block => 'users', :name => host, :size => size.to_i/1000000.0)
server.add_activity(:block => 'referrers', :name => referrer) unless (referrer.include?(server.name) || referrer.include?(server.host))
server.add_activity(:block => 'user agents', :name => useragent, :type => 3)

if( url.include?('.gif') || url.include?('.jpg') || url.include?('.png') || url.include?('.ico'))
type = 'image'
elsif url.include?('.css')
type = 'css'
elsif url.include?('.js')
type = 'javascript'
elsif url.include?('.swf')
type = 'flash'
elsif( url.include?('.avi') || url.include?('.ogm') || url.include?('.flv') || url.include?('.mpg') )
type = 'movie'
elsif( url.include?('.mp3') || url.include?('.wav') || url.include?('.fla') || url.include?('.aac') || url.include?('.ogg'))
type = 'music'
else
type = 'page'
end
server.add_activity(:block => 'content', :name => type)
server.add_activity(:block => 'status', :name => status, :type => 3) # don't show a blob

# Events to pop up
server.add_event(:block => 'info', :name => "Logins", :message => "Login...", :update_stats => true, :color => [1.5, 1.0, 0.5, 1.0]) if method == "POST" && url.include?('login')
server.add_event(:block => 'info', :name => "Sales", :message => "$", :update_stats => true, :color => [1.5, 0.0, 0.0, 1.0]) if method == "POST" && url.include?('/checkout')
server.add_event(:block => 'info', :name => "Signups", :message => "New User...", :update_stats => true, :color => [1.0, 1.0, 1.0, 1.0]) if( method == "POST" && (url.include?('/signup') || url.include?('/users/create')))
end
}

}

###
### Configuration end
######################
# Lots of hacks and bad code below. :-)

$BLOBS = { }
$FPS = 50.0
$ASPECT = 0.6

$TOP = 11.0
$RIGHT_COL = 11.0
$LEFT_COL = -20.0
$LINE_SIZE = 0.3
$BLOB_OFFSET = 7.0
$STATS = []


class Item
attr_accessor :message, :size, :color, :type

def initialize(message, size, color, type)
@message = message
@size = size
@color = color
@type = type
end

end

class Activity
attr_accessor :x, :y, :z, :type, :wx, :wy, :wz

def initialize(message, x,y,z, color, size, type=0)
@message = message
@x, @y, @z = x, y, z
# @xi, @yi, @zi = 0.18 + ( (rand(100)/100.0 - 0.5) * 0.02 ), (rand(100)/100.0 - 0.5) * 0.02, 0
@xi, @yi, @zi = 0.18 , 0.03, 0

if @x >= 0.0
@xi = -@xi
end

@xi = (rand(100)/100.0 * 0.02) - 0.01 if type == 2

@color = color
@size = size
@type = type
end

def render

if @type == 5
dy = @wy - @y
if dy.abs < y =" @wy" dx =" @wx" x =" @wx" x ="="" x =" 20.0" y =" -$TOP" yi =" -@yi" x =" 30.0" type ="="" type ="="" type ="="" list =" GL.GenLists(1)" type ="="" list =" GL.GenLists(1)" type ="="" list =" GL.GenLists(1)" type =" 0," right =" false," start_position =" -$TOP)" name =" name" right =" right" x =" (right" y =" start_position" z =" 0" wy =" start_position" color =" color" size =" 0.01" queue =" []" pending =" []" activities =" []" messages =" 0" rate =" 0" total =" 0" sum =" 0" average =" 0.0" last_time =" 0" step =" 0," updates =" 0" active =" false" type =" type" type ="="" average =" @sum" rate ="="" rate =" 1.0" messages =" 0" rate ="="" rate =" 1.0" messages =" 0" active =" true"> 0
@updates += 1
@rate = (@rate.to_f * 59 + @messages) / 60
@messages = 0
if @pending.size > 0
if @pending.size == 1
@step = rand(1000)
else
@step = 1.0 / (@queue.size + @pending.size) * 1000
end
@queue = @queue + @pending
@pending = []
else
@step = 0
end
@last_time = GLUT.Get(GLUT::ELAPSED_TIME)
@last_time -= @step unless @queue.size == 1
end

def render(options = { })
@x = (@right ? $RIGHT_COL : $LEFT_COL)

d = @wy - @y
if d.abs < y =" @wy"> 0 ? [10.0, 1.0, 1.0, 1.0] : @color ))
GL.Translate(@x, @y, @z)
GL.RasterPos(0.0, 0.0)

if @type == 0
if @rate < txt = " r/m " txt = "#{sprintf(" type ="="" total ="="" txt = " total " txt = "#{sprintf(" type ="="" average ="="" txt = " avg " txt = "#{sprintf(" list =" GL.GenLists(1)" list =" GL.GenLists(1)" t =" GLUT.Get(GLUT::ELAPSED_TIME)"> 0 && @last_time + @step < last_time =" t" item =" @queue.pop" url =" item.message" color =" item.color" size =" item.size" type =" item.type" size =" $MIN_BLOB_SIZE"> $MAX_BLOB_SIZE
size = $MAX_BLOB_SIZE
end

if type == 2
@activities.push Activity.new(url, 0.0 - (0.043 * url.length), $TOP, 0.0, color, size, type)
elsif type == 5
a = Activity.new(url, 0.0, $TOP, 0.0, color, size, type)
a.wx = @x
a.wy = @y + 0.05
@activities.push a
elsif type != 4
if @x >= 0
@activities.push Activity.new(url, @x, @y, @z, color, size, type)
else
@activities.push Activity.new(url, @x + $BLOB_OFFSET, @y, @z, color, size, type)
end
end
end

@activities.each do |a|
if a.x > 18.0 || a.x < -18.0 @activities.delete a else a.wy = @y + 0.05 if a.type == 5 a.render $STATS[1] += 1 end end end end class Block attr_reader :name, :position, :order, :bottom_position def initialize(options) @name = options[:name] @position = options[:position] || :left @size = options[:size] || 10 @clean = options[:auto_clean] || true @order = options[:order] || 100 @color = options[:color] @show = case options[:show] when :rate: 0 when :total: 1 when :average: 2 else 0 end @header = Element.new(@name.upcase , [1.0, 1.0, 1.0, 1.0], @show, @position == :right) @elements = { } @bottom_position = -$TOP end def render(num) return num if @elements.size == 0 @header.wy = $TOP - (num * $LINE_SIZE) @header.render num += 1 sorted = case @show when 0: @elements.values.sort { |k,v| v.rate <=> k.rate}[0..@size-1]
when 1: @elements.values.sort { |k,v| v.total <=> k.total}[0..@size-1]
when 2: @elements.values.sort { |k,v| v.average <=> k.average}[0..@size-1]
end

sorted.each do |e|
e.wy = $TOP - (num * $LINE_SIZE)
e.render
$STATS[0] += 1
if e.rate <= 0.0001 && e.active && e.updates > 4
@elements.delete(e.name)
end
num += 1
end
(@elements.values - sorted).each do |e|
$STATS[0] += 1
e.activities.each do |a|
a.render
if a.x > 18.0 || a.x < -18.0 e.activities.delete a end end if e.activities.size == 0 && @clean && e.updates > 4
@elements.delete(e.name)
end
end
@elements.delete_if { |k,v| (!sorted.include? v) && v.active && v.activities.size == 0} if @clean
@bottom_position = $TOP - ((sorted.size > 0 ? (num-1) : num) * $LINE_SIZE)
num + 1
end

def add_activity(options = { })
@elements[options[:name]] ||= Element.new(options[:name], @color || options[:color], @show, @position == :right, @bottom_position)
@elements[options[:name]].add_activity(options[:message], options[:size] || 0.01, options[:type] || 0 )
end

def add_event(options = { })
@elements[options[:name]] ||= Element.new(options[:name], options[:color], @show, @position == :right)
@elements[options[:name]].add_event(options[:message], options[:update_stats] || false)
end

def update
@elements.each_value do |e|
e.update
end
end
end

class Server
attr_reader :name, :host, :color, :parser

def initialize(options)
@name = options[:name] || options[:host]
@host = options[:host]
@color = options[:color] || [1.0, 1.0, 1.0, 1.0]
@parser = $PARSERS[options[:parser]] || $PARSERS[:apache]
@blocks = options[:blocks]
end

#block, message, size
def add_activity(options = { })
block = @blocks[options[:block]].add_activity( { :name => @name, :color => @color, :size => 0.03 }.update(options) )
end

#block, message
def add_event(options = { })
block = @blocks[options[:block]].add_event( { :name => @name, :color => @color, :size => 0.03}.update(options) )
end

end

class GlTail

def draw
GL.Clear(GL::COLOR_BUFFER_BIT);
# GL.Clear(GL::COLOR_BUFFER_BIT | GL::DEPTH_BUFFER_BIT);

GL.PushMatrix()

positions = Hash.new

$STATS = [0,0]

@blocks.values.sort { |k,v| k.order <=> v.order}.each do |block|
positions[block.position] = block.render( positions[block.position] || 0 )
end

GL.PopMatrix()
GLUT.SwapBuffers()

@frames = 0 if not defined? @frames
@t0 = 0 if not defined? @t0

@frames += 1
t = GLUT.Get(GLUT::ELAPSED_TIME)
if t - @t0 >= 5000
seconds = (t - @t0) / 1000.0
$FPS = @frames / seconds
printf("%d frames in %6.3f seconds = %6.3f FPS\n",
@frames, seconds, $FPS)
@t0, @frames = t, 0
puts "Elements[#{$STATS[0]}], Activities[#{$STATS[1]}]"
end
end

def idle
GLUT.PostRedisplay()
do_process
end

# Change view angle, exit upon ESC
def key(k, x, y)
case k
when 27 # Escape
exit
end
GLUT.PostRedisplay()
end

# Change view angle
def special(k, x, y)
GLUT.PostRedisplay()
end

# New window size or exposure
def reshape(width, height)
$ASPECT = height.to_f / width.to_f

puts "Reshape: #{width}x#{height} = #{$ASPECT}"

GL.Viewport(0, 0, width, height)
GL.MatrixMode(GL::PROJECTION)
GL.LoadIdentity()

GL.Frustum(-2.0, 2.0, -$ASPECT*2, $ASPECT*2, 5.0, 60.0)

$TOP = 19.0 * $ASPECT
$LINE_SIZE = 0.5 * (1122/height.to_f) * $ASPECT
$BLOB_OFFSET = 11.6 * (1122/height.to_f) * $ASPECT
$RIGHT_COL = 18.3 * $ASPECT

GL.MatrixMode(GL::MODELVIEW)
GL.LoadIdentity()
GL.Translate(0.0, 0.0, -50.0)
end

def init
GL.Lightfv(GL::LIGHT0, GL::POSITION, [5.0, 5.0, 10.0, 0.0])
GL.Disable(GL::CULL_FACE)
GL.Enable(GL::LIGHTING)
GL.Enable(GL::LIGHT0)

GL.Disable(GL::DEPTH_TEST)
GL.Disable(GL::NORMALIZE)

@channels = Array.new
@sessions = Array.new
@servers = Hash.new
@blocks = Hash.new
@mode = 0

$BLOCKS.each do |b|
@blocks[b[:name]] = Block.new b
end

$SERVERS.each do |s|
puts "Connecting to #{s[:host]}..."
session_options = { }
session_options[:port] = s[:port] if s[:port]
# session_options[:verbose] = :debug

if s[:password]
session = Net::SSH.start(s[:host], s[:user], s[:password], session_options)
else
session = Net::SSH.start(s[:host], s[:user], session_options)
end
do_tail session, s[:name], s[:color], s[:files].join(" "), s[:command]
session.connection.process
@sessions.push session
@servers[s[:name]] ||= Server.new(:name => s[:name] || s[:host], :host => s[:host], :color => s[:color], :parser => s[:parser], :blocks => @blocks )
end

@since = GLUT.Get(GLUT::ELAPSED_TIME)
end

def visible(vis)
GLUT.IdleFunc((vis == GLUT::VISIBLE ? method(:idle).to_proc : nil))
end

def mouse(button, state, x, y)
@mouse = state
@x0, @y0 = x, y
end

def motion(x, y)
if @mouse == GLUT::DOWN then
end
@x0, @y0 = x, y
end

def initialize
GLUT.Init()
GLUT.InitDisplayMode(GLUT::RGB | GLUT::DOUBLE)
GLUT.InitDisplayMode(GLUT::RGB | GLUT::DEPTH | GLUT::DOUBLE)

GLUT.InitWindowPosition(0, 0)
GLUT.InitWindowSize($WINDOW_WIDTH, $WINDOW_HEIGHT)
GLUT.CreateWindow('glTail')
init()

GLUT.DisplayFunc(method(:draw).to_proc)
GLUT.ReshapeFunc(method(:reshape).to_proc)
GLUT.KeyboardFunc(method(:key).to_proc)
GLUT.SpecialFunc(method(:special).to_proc)
GLUT.VisibilityFunc(method(:visible).to_proc)
GLUT.MouseFunc(method(:mouse).to_proc)
GLUT.MotionFunc(method(:motion).to_proc)
end

def start
GLUT.MainLoop()
end

def parse_line( ch, data )
ch[:buffer].gsub(/\r\n/,"\n").gsub(/\n/, "\n\n").each("") do |line|

unless line.include? "\n\n"
ch[:buffer] = "#{line}"
next
end

line.gsub!(/\n\n/, "\n")
line.gsub!(/\n\n/, "\n")

server = @servers.values.find { |v| (v.host == ch[:host]) && (v.name == ch[:name]) }
server.parser.call(server, line)
end
ch[:buffer] = "" if ch[:buffer].include? "\n"
end

def do_tail( session, name, color, file, command )
session.open_channel do |channel|
puts "Channel opened on #{session.host}...\n"
channel[:host] = session.host
channel[:name] = name
channel[:color] = color
channel[:buffer] = ""
channel.request_pty :want_reply => true

channel.on_data do |ch, data|
ch[:buffer] << active =" 0" active ="="">= 1000
@since = GLUT.Get(GLUT::ELAPSED_TIME)
@channels.each { |ch| ch.connection.ping! }

@blocks.each_value do |b|
b.update
end
end
self
end

end

GlTail.new.start

tim's shared items

Blog Archive

Add to Google Reader or Homepage