function fulfill_order($our_orderid)
{
    $our = fetch_order_info($our_orderid);
    if ($our->status != 'OPEN') {
        return;
    }
    if ($our->processed) {
        throw new Error('Unprocessed', "Shouldn't be here for {$our_orderid}");
    }
    // Dividing two bignum(20) values only gives us 4 decimal places in the result
    // this can cause us to process the matching orders out of sequence unless we arrange
    // for the quotient to be greater than 1 by putting the bigger value on top.
    //
    // With BTC at around 10 GBP each, I just saw the previous version of this query
    // process 2 orders out of sequence because the values of initial_want_amount / initial_amount
    // for the two orders were 0.09348 and 0.09346, which compare equal to 4 decimal places
    if ($our->initial_amount > $our->initial_want_amount) {
        $order_by = "initial_want_amount / initial_amount ASC";
    } else {
        $order_by = "initial_amount / initial_want_amount DESC";
    }
    $query = "\n        SELECT orderid, uid\n        FROM orderbook\n        WHERE\n            status='OPEN'\n            AND processed=TRUE\n            AND type='{$our->want_type}'\n            AND want_type='{$our->type}'\n            AND initial_amount * '{$our->initial_amount}' >= initial_want_amount * '{$our->initial_want_amount}'\n            AND uid!='{$our->uid}'\n        ORDER BY {$order_by}, timest ASC;\n    ";
    wait_for_lock($our->uid);
    $result = b_query($query);
    while ($row = mysql_fetch_array($result)) {
        echo "Found matching ", $row['orderid'], " from user ", $row['uid'], ".\n";
        wait_for_lock($row['uid']);
        // lock their account
        $them = fetch_order_info($row['orderid']);
        // re-fetch their order now that they're locked
        if ($them->status != 'OPEN') {
            echo "order {$them->orderid} was cancelled on us\n";
            release_lock($them->uid);
            continue;
        }
        printf("old order: has %s; wants %s\n", internal_to_numstr($them->amount), internal_to_numstr($them->want_amount));
        if ($them->type != $our->want_type || $our->type != $them->want_type) {
            throw Error('Problem', 'Urgent problem. Contact the site owner IMMEDIATELY.');
        }
        // echo "  them: orderid {$them->orderid}, uid {$them->uid}, have {$them->amount} {$them->type}, want {$them->want_amount}\n";
        // echo "  us: orderid {$our->orderid}, uid {$our->uid }, have: {$our->amount} {$our->type}, want {$our->want_amount}\n";
        // echo "  them->initial_amount = {$them->initial_amount}, them->initial_want_amount = {$them->initial_want_amount}\n";
        $left = gmp_mul($our->amount, $them->initial_amount);
        $right = gmp_mul($them->amount, $them->initial_want_amount);
        if (gmp_cmp($left, $right) >= 0) {
            // We need to calculate how much of our stuff they can afford at their price
            // we ignore the remainder - it's totally insignificant.
            list($them->new_want, $remainder) = gmp_div_qr($right, $them->initial_amount);
            if (gmp_cmp($remainder, 0) != 0) {
                $them->new_want = gmp_add($them->new_want, 1);
            }
            $them->new_want = gmp_strval($them->new_want);
            echo "    we swallow them; they can afford {$them->new_want} from us\n";
            pacman($them->orderid, $them->uid, $them->amount, $them->type, $them->commission, $our->orderid, $our->uid, $them->new_want, $our->type, $our->commission, $our->amount, $our->initial_amount, $our->initial_want_amount);
            release_lock($them->uid);
            // re-update as still haven't finished...
            // info needed for any further transactions
            $our = fetch_order_info($our->orderid);
            // order was closed and our job is done.
            if ($our->status != 'OPEN') {
                break;
            }
        } else {
            // We need to calculate how much of their stuff we can afford at their price
            // we ignore the remainder - it's totally insignificant.
            list($our->new_want, $remainder) = gmp_div_qr($left, $them->initial_want_amount);
            if (gmp_cmp($remainder, 0) != 0) {
                $our->new_want = gmp_add($our->new_want, 1);
            }
            $our->new_want = gmp_strval($our->new_want);
            echo "    they swallow us; we can afford {$our->new_want} from them\n";
            pacman($our->orderid, $our->uid, $our->amount, $our->type, $our->commission, $them->orderid, $them->uid, $our->new_want, $our->want_type, $them->commission, $them->amount, $them->initial_amount, $them->initial_want_amount);
            release_lock($them->uid);
            break;
        }
    }
    release_lock($our->uid);
}
Example #2
0
			<ul>
				<li><a href="http://code.google.com/p/googlechartphplib/">Project home on Google Code</a></li>
				<li><a href="http://code.google.com/p/googlechartphplib/issues/list">Issue Tracker</a></li>
				<li><code>remi at cloudconnected dot fr</code></li>
			</ul>

		</div>
		<div class="clear"></div>
	</div>
	
	<div id="footer">
		<h3>About</h3>
		<p>I'm RĂ©mi Lanvin, and you can contact me by email at <code>remi at cloudconnected dot fr</code></p>
		<p>Sometimes I have enough free time to write an article <a href="http://cloudconnected.fr">on my dev blog</a>, or something <a href="http://twitter.com/rlanvin">on my Twitter account</a>.</p>
		<p id="pacman"><img src="<?php 
echo pacman();
?>
" alt="Tribute to Pacman with a Pie Chart" title="Tribute to Pacman with a Pie Chart"></p>
	</div>
</div>

<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-11912505-4']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();