Living in LA I'm fascinated by technologies and Internet. I built my own 3D Printer while developing high traffic website such as GameFront.com
7+ years of web technologies (JS, HTML, CSS)
4+ years software development and web development
Involved with full life cycle of application development including:
- Writing technical specifications and documentation
- Development, testing and maintenance
- Server maintenance
- Team management
Autodidact and self-motivated, learn quickly new technologies. Enjoy working in a Team, getting and giving advice.
Always looking for performance and code quality.
Specialties: Technologies: LAMP stack, PHP, Zend Framework, Drupal, Magento, Joomla, CSS, HTML, HTML5, XHTML, JavaScript, Scriptaculous, jQuery, Prototype, JSON, AJAX, Varnish, Graphite, RESTful Api, Facebook API, Twitter API, MySpace API, LinkedIn API, Viadeo API, Google API, Linux (Debian), Windows, Mac, MySQL, MongoDb, Hadoop, Node.JS
- Developed heavily on Magento Enterprise
- Defined coding standard and ran code reviews
- Defined the current architecture with Varnish for HTTP caching
- Increased overall performance
- Worked with Hadoop, Pig Script and Hive to create daily/weekly report
- Designed and developed the second phase of Gamefront.com
- Ran code reviews
- Conducted interview for new Developer and new Director of Engineering
- Assisted new developers
- Currently working with Hadoop, Pig Script on big data analysis
- Did some R&D with Node.Js and MongoDb to create a new storage application to support Gamefront's files and Break's videos upload/download
- Developed and maintained Breakstudios.break.com a custom CMS delivering +130k articles
- Developed and maintained Analytics for Breakstudios which track traffic on Breakstudios articles
- Developed and maintained Gamefront.com which handle 5+ Million page view a month, thousand of uploads every day, hundred of thousand of downloads every day
- Helped develop and maintain Chickipedia which was originally built on top of MediaWiki
- Developed and maintained few Wordpress plugins which include a page view & Facebook likes tracker, a Breakstudios delivery plugin on top of XML/RPC
- Maintain, update and develop 23 shops with Magento and new technologies
- Responsibilities include maintain servers, monitor servers, develop procedural documents of the system and work with High-Traffic application
- Use Magento, Zend Framework, Prototype and Wordpress
http://www.monomachines.com
http://www.monomachines.com/blog
- Designed and developed a new platform for Social Network using scripting languages such as HTML, CSS, Javascript and PHP5
- Used REST API (Twitter, Facebook, MySpace) and JS libraries (Prototype & jQuery)
http://www.betwyx.com
- Designed, developed and deployed an e-commerce application using scripting languages such as PHP5 and Javascript (Prototype, Ajax)
- Configured and maintained servers for High-Traffic services
http://www.pro-outillage.com (Closed in 2010)
- Maintained, updated and developed many website using different application such as SPIP, Wordpress, Joomla, Dot Clear and osCommerce with PHP, MySQL and Javascript
- Searched for new way of development with framework such as Zend Framework and Symfony
- Responsibilities included increase web traffic with the help of the knowledge of internet marketing and ecommerce selling
- Transformed templates from Photoshop to XHTML strict
http://www.ajc-interactive.com
http://www.primeurs-nordeaux.com
http://www.megalots.com
http://www.dam-sport.net
http://www.synergiashop.com
http://www.maison-pratique.fr
- Designed and developed a new BSP (BlueAge Shared Plug-in) for BluAge (Pioneer in Model Driven Architecture)
- Responsibilities included unit testing
- Developed a website with PHP/MySQL
- Used Flash & Javascript
- Managed web hosting
http://www.easy-mutuelle.com
Everybody knows there are two extensions for memcache on PHP:
You can use memcache the PHP extension as a session_handler for PHP like so :
session.save_handler = memcache
session.save_path = "tcp://serv01:11211,tcp://serv02:11211,tcp://serv03:11211"
Or you can use memcached like so:
session.save_handler = memcached
session.save_path = "serv01:11211,serv02:11211,serv03:11211"
But how to set other parameters to memcached such as:
In PHP I will do like so:
$cache = new Memcached();
$cache->addServer('serv01', 11211);
$cache->addServer('serv02', 11211);
$cache->addServer('serv03', 11211);
$cache->setOption(Memcached::OPT_HASH, Memcached::HASH_MD5);
$cache->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
$cache->setOption(Memcached::OPT_CONNECT_TIMEOUT, 150);
$cache->setOption(Memcached::OPT_RETRY_TIMEOUT, 0);
But so far I have not found any documentation or examples of how to set those variables when they are use by the session_handler.
Basically you need Memcache OR Memcached Library that match your PHP Executable. When I say match I'm not speaking of date but of code. The old PHP won't support new Memcache and vice-versa.
You can try to compile a special one just for your version of PHP (I tried once with other libraries it's not fun). Or you can find a version of PHP that would work with a version of Memcache but this new PHP will also need to work with your version of Apache...
After years of playing with that I just gave up and just used a unix system.
PS: Now that I think about it PHP already come with a correct version of Memcache... So your error may be just that you're using "new Memcached();" instead of "new Memcache();"
The title of this question might be confusing but the problem is simple.
I'm using Zend_Cache with memcached as a backend. I have two module called "Last articles" and "Popular articles". Both of this module are on every pages and use a similar query such as :
Select * from table where status = 'published' and category = '' order by dateCreated|/popularity\
My table have 1.5 million rows so far. I have indexes on every field that I'm using in the previous query. I cache the recent articles for 1hour and the popular for 4hours. I have 4 web server (php5/apache2) and 1 database server (mysql). The table engine is innoDB.
The problem some time my cache expire right in the middle of a heavy load, which make my web site unavailable until those modules are cached again. I could had a new MYSQL server.
But is there a way to handle the caching in a smarter way? Like for example the server1 will try to refresh the cache while server 2,3 and 4 will still use the same value out of the cache.
I can write some code to do that, but I was wondering if there is way to do that directly with Zend_Cache? Of if there is a design pattern that i could apply to my problem?
[EDIT] I want something that I could scale up to 100 servers
I actually can add a category via setup script, the thing is for some reason some of the fields doesn't get set properly. Here's is my code
$this->startSetup();
Mage::register('isSecureArea', 1);
$category = Mage::getModel('catalog/category');
$category->setPath('1/2') // set parent to be root category
->setName('Category Name')
->setUrlKey('category-name')
->setIsActive(0)
->setIncludeInMenu(1)
->setInfinitescroll(1)
->setDisplayMode('PAGE')
->setLandingPage($idToCmsBlock)
->setPageLayout('anotherLayoutThanDefault')
->setCustomUseParentSettings(0)
->setCustomLayoutUpdate('<reference name="head"><action method="addCss"><stylesheet>css/somecss.css</stylesheet></action></reference>')
->save();
$this->endSetup();
After running this script, I have a category created with all my value set in the EAVs table. However the Flat table will be missing displayMode, landingPage, pageLayout, customLayoutUpdate even if I re-index the flat table.
The weird thing is that if I go in the admin, I can see all those fields properly set but if I go in my frontend most of those fields are ignored. I will have to go to the admin, unset those value and reset them for each of them to work properly.
Also let say I use setEnabled(1), my category will be "enable" in the admin but not show up in the frontend.
PS: I have Flat Category activated, if I disable it seems to work fine but if I re-index it still not working.
I finally found it, I'm not sure why but those fields are not showing up properly because they were inserted for the default store (storeId=1) because my script is running in an update script. You need to use the storeId 0.
With this information you would think that the solution would be something like :
$this->startSetup();
Mage::register('isSecureArea', 1);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$category = Mage::getModel('catalog/category');
$category->setPath('1/2') // set parent to be root category
->setStoreId(Mage_Core_Model_App::ADMIN_STORE_ID)
->setName('Category Name')
...
->save();
$this->endSetup();
But this code doesn't work either. Indeed after looking into Mage::app() (Mage_Core_Model_App Line 804) I noticed a IF condition that would always return the default store if you're in a setup script.
The trick is to fake that you're not in a setup script, my working solution is:
$this->startSetup();
Mage::register('isSecureArea', 1);
// Force the store to be admin
Mage::app()->setUpdateMode(false);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$category = Mage::getModel('catalog/category');
$category->setPath('1/2') // set parent to be root category
->setStoreId(Mage_Core_Model_App::ADMIN_STORE_ID)
->setName('Category Name')
...
->save();
$this->endSetup();
I've been playing with Hive for few days now but I still have a hard time with partition.
I've been recording Apache logs (Combine format) in Hadoop for few months. They are stored in row text format, partitioned by date (via flume): /logs/yyyy/mm/dd/hh/*
Example:
/logs/2012/02/10/00/Part01xx (02/10/2012 12:00 am)
/logs/2012/02/10/00/Part02xx
/logs/2012/02/10/13/Part0xxx (02/10/2012 01:00 pm)
The date in the combined log file is following this format [10/Feb/2012:00:00:00 -0800]
How can I create a external table with partition in Hive that use my physical partition. I can't find any good documentation on Hive partition. I found related Question such as:
If I load my logs in an external table with Hive, I cannot partition with the time, since it's not the good format (Feb <=> 02). Even if if it was in a good format how do i transform a string "10/02/2012:00:00:00 -0800" into multiple directory "/2012/02/10/00"?
I could eventually use pig script to convert my raw logs into hive tables but at this point I should just be using pig instead of hive to do my reporting.
Previous answers were not clear to me. Basically each hadoop servers (node or namenode) will create a server and listen on the IP associated with its lookup name.
Let say you have 3 box (box1, box2, box3), the /etc/hosts file should look like this:
127.0.0.1 localhost
192.168.10.1 box1
192.168.10.2 box2
192.168.10.3 box3
Instead of :
127.0.0.1 localhost box1
192.168.10.2 box2
192.168.10.3 box3
//(this is incorrect, box one will be listening exclusively on 127.0.0.1)
I've been seeing a bunch of website with something called tile view (I think). The idea is you have multiple element on a html page with different width and height.
And you have a javascript that will organize randomly each element next to each other to maximize the number of element you can see at once.
An example is http://www.clipboard.com/feeds (You may have to select tile view next to the search bar)
Is there a jquery plugin already? or a native javascript that do something similar?
If not what kind of algorithm would you use to do it?
What you tried is what every body think first however it's not really easy to scale... You can always add more servers or use sharding etc... If you have million of users and people who follow lots of people this solution would become really hard to execute.
There is another solution that is basically just doing the aggregation when someone post a status. Facebook use this idea and it might be easier to scale and if someone is following 25000 people, he will see his list of status pretty quickly and your server wont have to "fight" to retrieve the data quickly.
You will have a user collection, each user will have a statuses array. Let say you have user1 and user2, and that user1 follow user2. When user2 push a status, his status will be saved in user1 array of statuses AND in user2 array of statuses. You will use more storage which with mongoDB mean more memory.... At Facebook they are using Hadoop with HBase for the main storage then they have huge arrays of servers with lots of memory.
One inconvenient is if you delete one status you have to delete it everywhere... Major advantage to this solution, each user will have an array of statuses already in order! In the previous solution if you follow 3users, you need to grab all their feeds then sort them, then render them...
[Edit] Like Shekhar point out int the comment, Mongo has a document Limit. You need to create a status collection an save the status twice, once for user2 and once for user1 and need to have a fromId, toId, status, and time
First of all why are you configuring curl twice?
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields2);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
Then when you do the first call to first page with $fields2 (The long XML string), the call should return an XML (like you say) and in this XML response there is a field ItemCount which contain the total number of hotels.
And if you look at the long string of XML you send with $fields2 there is a field call 'FirstItem' where contain 0 for the first call. This field is you offset, you can increment it to skip hotels.
Example:
$fields2 = array(
'ajax'=>'xmlSearchEngineResponder',
'xml' => "%3C%3Fxml%20version%3D%221.0%22%3F%3E%3CSearchRequest%20xmlns%3D%22http%3A%2F%2Fwww.liberologico.com%2Fdbsite%2Fjolly-search%22%20xmlns%3Axsi%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema-instance%22%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5B%2A%5D%5D%3E%3C%2FScope%3E%3CFilters%3E%3CFilters%20xsi%3Atype%3D%22FilterSpecType%22%3E%3CField%3Eaptve_territorio%3C%2FField%3E%3CValue%3E%3CSingleValue%3E%3C%21%5BCDATA%5B%2A%5D%5D%3E%3C%2FSingleValue%3E%3C%2FValue%3E%3CMode%3ETHESAURUS%3C%2FMode%3E%3COperation%3ELIKE%3C%2FOperation%3E%3C%2FFilters%3E%3CFilters%20xsi%3Atype%3D%22FilterSpecType%22%3E%3CField%3Efull_text_search%3C%2FField%3E%3CValue%3E%3CSingleValue%3E%3C%21%5BCDATA%5B%2A%5D%5D%3E%3C%2FSingleValue%3E%3C%2FValue%3E%3CMode%3EFREE_TEXT%3C%2FMode%3E%3COperation%3ELIKE%3C%2FOperation%3E%3C%2FFilters%3E%3CFilters%20xsi%3Atype%3D%22FilterSpecType%22%3E%3CField%3Elang%3C%2FField%3E%3CValue%3E%3CSingleValue%3E%3C%21%5BCDATA%5Bit%5D%5D%3E%3C%2FSingleValue%3E%3C%2FValue%3E%3CMode%3EFREE_TEXT%3C%2FMode%3E%3COperation%3EEQUAL%3C%2FOperation%3E%3C%2FFilters%3E%3C%2FFilters%3E%3CSubSearches%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BEventi%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BArte%20%26%20Cultura%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BMare%20%26%20Natura%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BPiatti%20%26%20Prodotti%20tipici%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BRelax%20%26%20Divertimento%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BDove%20Alloggiare%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BDove%20Mangiare%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BInformazioni%20Utili%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3C%2FSubSearches%3E%3C%2FSearch%3E%3CActiveResultSet%3E%3CTab%3E%3C%21%5BCDATA%5BDove%20Alloggiare%5D%5D%3E%3C%2FTab%3E%3CFirstItem%3E0%3C%2FFirstItem%3E%3CPagerSize%3E10%3C%2FPagerSize%3E%3C%2FActiveResultSet%3E%3C%2FSearchRequest%3E",
'force' => 'false');
Return you the first 10 Results;
$fields2 = array(
'ajax'=>'xmlSearchEngineResponder',
'xml' => "%3C%3Fxml%20version%3D%221.0%22%3F%3E%3CSearchRequest%20xmlns%3D%22http%3A%2F%2Fwww.liberologico.com%2Fdbsite%2Fjolly-search%22%20xmlns%3Axsi%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema-instance%22%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5B%2A%5D%5D%3E%3C%2FScope%3E%3CFilters%3E%3CFilters%20xsi%3Atype%3D%22FilterSpecType%22%3E%3CField%3Eaptve_territorio%3C%2FField%3E%3CValue%3E%3CSingleValue%3E%3C%21%5BCDATA%5B%2A%5D%5D%3E%3C%2FSingleValue%3E%3C%2FValue%3E%3CMode%3ETHESAURUS%3C%2FMode%3E%3COperation%3ELIKE%3C%2FOperation%3E%3C%2FFilters%3E%3CFilters%20xsi%3Atype%3D%22FilterSpecType%22%3E%3CField%3Efull_text_search%3C%2FField%3E%3CValue%3E%3CSingleValue%3E%3C%21%5BCDATA%5B%2A%5D%5D%3E%3C%2FSingleValue%3E%3C%2FValue%3E%3CMode%3EFREE_TEXT%3C%2FMode%3E%3COperation%3ELIKE%3C%2FOperation%3E%3C%2FFilters%3E%3CFilters%20xsi%3Atype%3D%22FilterSpecType%22%3E%3CField%3Elang%3C%2FField%3E%3CValue%3E%3CSingleValue%3E%3C%21%5BCDATA%5Bit%5D%5D%3E%3C%2FSingleValue%3E%3C%2FValue%3E%3CMode%3EFREE_TEXT%3C%2FMode%3E%3COperation%3EEQUAL%3C%2FOperation%3E%3C%2FFilters%3E%3C%2FFilters%3E%3CSubSearches%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BEventi%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BArte%20%26%20Cultura%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BMare%20%26%20Natura%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BPiatti%20%26%20Prodotti%20tipici%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BRelax%20%26%20Divertimento%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BDove%20Alloggiare%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BDove%20Mangiare%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3CSearch%3E%3CScope%3E%3C%21%5BCDATA%5BInformazioni%20Utili%5D%5D%3E%3C%2FScope%3E%3C%2FSearch%3E%3C%2FSubSearches%3E%3C%2FSearch%3E%3CActiveResultSet%3E%3CTab%3E%3C%21%5BCDATA%5BDove%20Alloggiare%5D%5D%3E%3C%2FTab%3E%3CFirstItem%3E10%3C%2FFirstItem%3E%3CPagerSize%3E10%3C%2FPagerSize%3E%3C%2FActiveResultSet%3E%3C%2FSearchRequest%3E",
'force' => 'false');
Will return you the next 10 results. Also there is a field call PagerSize thant can allow you to retrieve more result at once.
So i would do the first call to get the total number of hotel, and the loop to get all the other pages.
//do first curl call
//then
$totalHotel = 5214; // To retrieve in the first call
$increment = 10; // the number of hotel to treat at once
$nbOfHotelimported = $increment;
while($totalHotel-$increment){
// do another curl call
// with FirstItem set to $nbOfHotelimported
// and pageSizer set to $increment
$nbOfHotelimported += $increment;
}
I did the same, transfer workspace from Zend Studios 8 to Zend Studio 9. It worked fine on Ubuntu but it did not work Windows 7...
Anyway I highly recommend to start with a fresh workspace, to not bring over old settings from Zend Studios 8.
Your code doesn't work because $("a[href=value]") doesn't exist.
You wan to use $("a[href='"+value+"']") instead, where value will be "replace" by the value of the variable value.
Here a fix:
var arr = ["#2", "#5", "#6"];
$.each(arr, function(index, value) {
$("a[href='"+value+"']").addClass('hilite');
});
Its addValidatorS (multiple validators):
$this->addElement('text', 'firstname', array(
'label' => 'Your first name:',
'required' => true,
'validators' => array(
array('regex', false, array(
'pattern' => '/[^<>]/i',
'messages' => 'Your first name cannot contain those characters : < >'))
)
));
You cannot add a click event only on a portion of a background image in your input field.
However you could use the click event on the input text field and calculate based on the position of the mouse when the click happen, if the click is indeed on the good portion of the background image but that is quite complicate and the position of the mouse compared to the input text will vary in different browser.
PS: What I would do is design the input field with an image next. For instance look at this input field for the search: http://www.gamefront.com/
[EDIT] Here a sample, tested just with Mozilla. As I said before you need to play with the pixel (distanceFromTop,distanceFromLeft,inputWidth,inputHeight,pictureWitdh) to find the good spot: http://pastebin.com/00rWTadz
<script type="text/javascript">
var tempX = 0;
var tempY = 0;
document.onmousemove = getMouseXY;
function getMouseXY(e) {
tempX = e.pageX;
tempY = e.pageY;
// catch possible negative values in NS4
if (tempX < 0){tempX = 0}
if (tempY < 0){tempY = 0}
// show the position values in the form named Show
// in the text fields named MouseX and MouseY
document.getElementById('MouseX').value = tempX;
document.getElementById('MouseY').value = tempY;
return true;
}
function search(){
// position of input field
var distanceFromTop = 60;
var distanceFromLeft = 8;
// size of input field
var inputWidth = 204;
var inputHeight = 20;
// size of picture
var pictureWitdh = 20;
// dont need to check mouse position on axis y
// because onclick event already is on input field
// check mouse position on axis x
if(tempX > (distanceFromLeft+inputWidth-pictureWitdh)){
alert('Did click on the right');
}
}
</script>
<input type="text" id="MouseX" value="0" size="4"> X<br>
<input type="text" id="MouseY" value="0" size="4"> Y<br>
<input type="text" id="search" onclick="search(this)" />
For #1 "list ALL employees, but only show a check next to the ones that are currently on the project". (That work only if you show only one project at the time)
SELECT * from employee as e
LEFT JOIN EMPLOYEE_PROJECT as ep on ep.employee_id = e.id
WHERE ep.project_id = <project id>
in php :
if("employee_id" IS NOT NULL/empty){
echo "check";
}
For #2, usually my middle table project_employee has nothing else than two id (employeeId, projectId). So i generally just delete every employee for this projectId and re-add them. If you have other data in the same table, this might not work. And you will have to compare old data store to new data to be stored.
After looking trough the source code of both PECL extension and libmemcached itself I finally found my answer in the comment of the blog of the author of the memcached extension.
http://zmievski.org/2009/01/new-memcached-extension
I quote in case his blog disappeared some day:
Andrei said: @Ash, the session save path syntax is not quite the same as the other memcache extension. Try:
session.save_path="127.0.0.1:11211"
Ash Searle said: Is there any documentation for the syntax – i.e. does it handle multiple servers and optional parameters like the earlier memcache implementations? (e.g. save_path="127.0.0.1:11211?persistent=1&timeout=1&retry_interval=15")
Andrei said: @Ash, no, it’s not that advanced. For now, the syntax is the default one that libmemcached parser supports: basically, a comma-separated list of hostname:port entries, where :port is optional.
OR
Rich Choy said: Is there a reference on the Web that explains each connection parameter that appears after host:port? For example what exactly does “timeout=1″ mean?
Andrei said: @Rich, which extension are you using? :) Mine doesn’t support those extra parameters, you must be talking about pecl/memcache one.
AND
Frank Orson said: 1) Does pecl/memcached support UDP on the client? I could not find any info about this. I know that pecl/memcache 3.0.4 supports it.
2) Does pecl/memcached have failover support in the client?
Andrei said: Frank, I’m working on next version (2.0) of the memcached extension. It’ll have UDP support and replication (failover).
If you check the source code of version 2 you can see for example that you can append in the save_path string "PERSISTENT=" and "--SERVER" ((which I don't know how it would be used)
I'm trying to use early flush with php5/apache2 to execute some code, render some json and after that executing another part of the code that take several second but doesn't produce any response. The basic code so far is:
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
echo 'Page loading'; // code to render;
ob_flush();
flush();
sleep(29); // LONG time code to execute
The previous example does not work. I mean it will echo 'Page loading' after 29seconds. If I looked at the http response I have:
(Status-Line) HTTP/1.1 200 OK
Date Mon, 04 Jul 2011 19:49:19 GMT
Server Apache/2.2.11 (Win32) mod_ssl/2.2.11 OpenSSL/0.9.8k PHP/5.3.0
X-Powered-By PHP/5.3.0
Expires Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma no-cache
Keep-Alive timeout=5, max=100
Connection Keep-Alive
Transfer-Encoding chunked
Content-Type text/html
My problem is not really why it doesnt work? but How can I checked where my string get buffered? I know that there is different buffer: - php output_buffer, php zlib.buffer - apache mode_deflate / gzip - browser buffering
All php output buffering are off, apache mode_deflate is activated but as you can see the transfer-encoding is "chunked". I have no idea how to find out where is my problem, I'm using HttpFox to see the header and I try to get the content of the HTTP request, HttpFox say that the content is not ready until the 29seconds are done.
Any advice?
Marc B was right...
I had to make a loop of a 1000, with output_buffering activated
$var = 1000;
while(--$var)
echo 'Page loading'; // code to render;
To be able to see result before the sleep.
I have to to a loop of 100, with output_buffering = off to get the same result.
I finally implemented a class that inherit from Zend_Cache_Backend_Libmemcached I'm overriding the load() method.
Each of my server has there hostname finishing by a set of number such as serv01, serv02, serv03, serv04. The main idea is taht each server will think that the cache expired at different time. For example serv01 will think that the cache is expired 20minutes before it actually expires, serv02 will be 15minutes, serv03 10minutes and serv04 5minutes.
By doing so my cache will never be refresh at the same time on each server, and if one server is down the cache will be refresh by another server.
The Upload process is actually done by a flash "uploadify/uploader.swf" some flash uploader came with a debug mode so you can see the response from PHP.
Worst case you can tell PHP to write some debug line into a external log file with put_file_contents
[EDIT:] According this page http://www.uploadify.com/forums/discussion/2085/built-in-debug/p1 Uploadify doesn't come with a debug mode. So you are better writing in a log file with file_put_contents Also this flash works like a normal HTML form (except that flash can retrieve a percentage of uploading), so you can create a simple HTML form thant send a file through your PHP such as:
<html>
<head>
<title>Upload file</title>
</head>
<body>
<form id="form" method="post" enctype="multipart/form-data" action="yourFile.php">
<input type="file" name="Filedata" />
<input type="submit" value="Upload" />
</form>
</body>
</html>
If you need to use utf8_encode() it's meaning that the data in your database is not encoded in UTF8. When you say that your database is encoded in "utf8_unicode_ci" it doesn't actually mean that your data is encoded in UTF8.
To verify that set encoding is working with Zend Framework by using any of the code you show, it's quite easy. With firefox just right click on the page and click on "View page info" if it's say "Encoding: UTF8" it means that your page is correctly encoded but that your data is not.
If you was using utf8_decode(), then it would mean that Zend is failing to set the encoding.
I'm using cocos2d for Javascript: http://www.cocos2d-javascript.org
And there is even a tutorial for a brick game: http://www.cocos2d-javascript.org/tutorials/breakout-clone-tutorial-part-2
But it's not about jQuery...
jQuery $.ajax() will automatically transform you JSON "file" into a javascript object if your request come back with a JSON header.
However you can override this by using dataType of $.ajax:
$.ajax({
url: "test.html",
dataType: "text",
success: function(data){
alert(data);
}
});
The previous script will alert you JSON file like you want.
[Update] You can try to use eval():
$.ajax({
url: "test.html",
dataType: "text",
success: function(data){
var options = eval(data);
}
});
In this case your data need to be executable by javascript.
[Update 2] JsonP style, your json file need to looks like that:
var options = {
"zoom": 4, "minZoom" : 4,
"scrollWheel" : false,
"center": new google.maps.LatLng(39.828175, -94.5795),
"mapTypeId": google.maps.MapTypeId.ROADMAP
};
Notice the "var options ="
Your ajax request need to look like that:
$.ajax({
url: "test.html",
dataType: "text",
success: function(data){
alert(data);// will show your data as text
eval(data); this will execute your "JSON file"
//after eval you can now use options as a variable
alert(options);
}
});
You can try:
resources.router.routes.resolution.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.resolution.route = '/resolution/(.*)'
resources.router.routes.resolution.defaults.module = default
resources.router.routes.resolution.defaults.controller = resolution
resources.router.routes.resolution.defaults.action = index
resources.router.routes.resolution.map.1 = "res"
[Updated]
I don't think there is a way to do that because Zend_form is dissociated from the controller. You could register in the registry your pos/get variables but thats dirty. You could also access directly $_GET/$_POST...
Or in your controller you can do:
$form = new Zend_form();
$form->populate($this->_getAllParams());
Which will populate your form with all values from $_POST/$_GET
No you cannot do that. I invite you to read a POST definition: http://en.wikipedia.org/wiki/POST_%28HTTP%29
or this page: http://en.wikipedia.org/wiki/GET_%28HTTP%29#Request_methods
Look for:
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
; date.timezone = America/Los_Angeles
and Uncomment this line:
date.timezone = America/Los_Angeles
And choose your time zone...
Actually it's easy you have an error in you Frontend options, 'cache_with_XXX_variables' need to be in an array with the key 'default_options':
$frontendOptions = array(
'lifetime' => 120,
'automatic_serialization' => true,
'default_options' => array(
'cache' => true,
'cache_with_get_variables' => true,
'cache_with_post_variables' => true,
'cache_with_session_variables' => true,
'cache_with_files_variables' => true,
'cache_with_cookie_variables' => true,
)
);
First you are missing the tag in your HTML code but that should not be an issue.
Secondly your header is incorrect, you have that:
$headers = "From Ahmad \r\n";
//$headers .= "Reply-To: ". strip_tags($_POST['req-email']) . "\r\n";
//$headers .= "CC: susan@example.com\r\n";
$headers .= 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-Type: text/html; charset=ISO-8859-1' . "\r\n";
$subject = 'Email report';
instead of:
//$headers .= "Reply-To: ". strip_tags($_POST['req-email']) . "\r\n";
//$headers .= "CC: susan@example.com\r\n";
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-Type: text/html; charset=ISO-8859-1' . "\r\n";
$headers .= "From: Ahmad <email@email.com>\r\n";
$subject = 'Email report';
Basically I think you header should start by "Mime-Version".
Check this code: http://us.php.net/manual/en/function.mail.php#example-2877
If the rest of your DB is not in UTF8 and just this table is in UTF8 you can either change the charset in the head of your HTML or use utf8_decode() to decode the utf8 string.
That's interesting! I will look into that.
Be careful there is TWO memcache libraries one called "memcache" and one called "memcached" the later is "more" recent. "php_memcache.dll" is for memcache and "php_memcached.dll" is for memcached. Which would explain your last error.
Yes I could use Magento SOAP API but I prefer not.
So far I think I was able to found out that it was related to flat tables. If i Disable them my categories would be working properly.
I tried that as well, and I have that same effect. Actually i even copy/paste the logic from the Admin Controller that save categories and it still doesn't work.
This is to add a custom attribute in a category
Actually my problem is pretty easy... I have to add my partition one by one... Which I tried and failed until I understood the correct syntax: ALTER TABLE raw_datastore ADD PARTITION (year = '2011', month='05', day='05', hour='14') LOCATION '/logs/2011/05/05/14'; If I do that now I can do select count(*) and it works. So I'm going to appprove your answer but it would be cool if you can edit your answer to add the fact that you need to add the partition yourself.
Olaf I tried your solution pastebin.com/TkLCzWdv the table is created correctly however if I query Select count(*) from raw_datastore where year = '2012' and month = '02'; It launch a map/reduce job but there are no result.
I'll have to test that I'll get back to you as soon as I can
So I would the creation of the table look like? and I would I do a query to use those partition?
Thats the thing you cannot do that. Those files are needed to "setup" the project in Zend Studios
You cannot copy a project like that, there are hidden files in the workspace it self that manages other settings for the workspace.
Inside jquery there is native javascript YES but it use the jquery library... If I want to use prototype for example, it would be great not to have to load jquery on the side just for that.
You can use var_dump($_SESSION['DBCONNECTION']) to see what the session contain.
Yes indeed its because my example was from Facebook which use HBase, for MongoDb you can create a status collection, when user2 push the status you save it twice, once for user2 and a second time for user1, your status document will contain a fromId, a toId, time and the status itself...
Following my previous post on setting up Graphite for Ubuntu here another tutorial on how to install statsd, a NodeJS application that can listen for UDP stream and foward it to Graphite.
apt-get install node npm git
cd /opt/
git clone git://github.com/etsy/statsd.git
cd statsd/
cp exampleConfig.js localConfig.js
Edit “/opt/statsd/localConfig.js”, change graphiteHost to “127.0.0.1”.
Edit “/opt/graphite/conf/storage-schemas.conf” and add at the beginning:
[stats]
priority = 110
pattern = ^stats.*
retentions = 10s:6h,1m:7d,10m:1y
Edit “/opt/graphite/conf/storage-aggregation.conf” and replace everything by:
[min]
pattern = \.lower$
xFilesFactor = 0.1
aggregationMethod = min
[max]
pattern = \.upper$
xFilesFactor = 0.1
aggregationMethod = max
[sum]
pattern = \.sum$
xFilesFactor = 0
aggregationMethod = sum
[count]
pattern = \.count$
xFilesFactor = 0
aggregationMethod = sum
[count_legacy]
pattern = ^stats_counts.*
xFilesFactor = 0
aggregationMethod = sum
[default_average]
pattern = .*
xFilesFactor = 0.3
aggregationMethod = average
PS: You will need to restart carbon (/etc/init.d/carbon restart)
We’re going to use upstart and monit for using statsd as a service while being able to monitor it if it crash for any reason.
First we need to make sure that we have upstart and monit
apt-get install upstart monit
Create this file “/etc/init/statsd.conf” and add:
#!upstart
description "Statsd node.js server"
author "Nicolas"
start on startup
stop on shutdown
script
export HOME="/root"
echo $$ > /var/run/statsd.pid
exec sudo -u www-data /usr/bin/nodejs /opt/statsd/stats.js /opt/statsd/localConfig.js >> /var/log/statsd.log 2> /var/log/statsd.error.log
end script
pre-start script
# Date format same as (new Date()).toISOString() for consistency
echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Starting" >> /var/log/statsd.log
end script
pre-stop script
rm /var/run/statsd.pid
echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Stopping" >> /var/log/statsd.log
end script
You can now start/stop your statsd server with those commands
start statsd
stop statsd
We now need to setup monit, for this create this file “/etc/monit/conf.d/statsd” and add
#!monit
set logfile /var/log/monit.log
check process nodejs with pidfile "/var/run/statsd.pid"
start program = "/sbin/start statsd"
stop program = "/sbin/stop statsd"
And then you can restart monit “/etc/init.d/monit restart”
You can now ping statsd via UDP on the port 8125 which will forward it to Graphite.
In the next post I will show you how to use statsd and Graphite.
Source
Graphite is an amazing tool for visualizing all kind of data. I would advise you to read this post from Etsy (codeascraft.etsy.com/2011/02/15/measure-anything-measure-everything) if you want to know what can you do with graphite.
This tutorial shows you how I installed Graphite on an Ubuntu Server 12.10.
First of all Graphite is built in Python on top of the framework Django and the application itself has 3 main parts:
Moreover you will need a Webserver like apache to run the web app, you could be using anyserver you want, then if your application is node made in Python you will need a bridge-app that will relay any data from your application into Carbon, for this I used statsd (a simple nodeJs application).
I would switch to a root user (sudo su) from now, or you can put sudo infront each command.
apt-get update
apt-get install --assume-yes apache2 apache2-mpm-worker libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libapache2-mod-wsgi libaprutil1-ldap memcached python-cairo python-cairo-dev python-django python-ldap python-memcache python-pysqlite2 sqlite3 ssh libapache2-mod-python python-setuptools build-essential python-dev
easy_install zope.interface
easy_install twisted
easy_install txamqp
easy_install django-tagging
cd /root/
wget http://launchpad.net/graphite/0.9/0.9.10/+download/graphite-web-0.9.10.tar.gz
wget http://launchpad.net/graphite/0.9/0.9.10/+download/carbon-0.9.10.tar.gz
wget http://launchpad.net/graphite/0.9/0.9.10/+download/whisper-0.9.10.tar.gz
tar -zxvf graphite-web-0.9.10.tar.gz
tar -zxvf carbon-0.9.10.tar.gz
tar -zxvf whisper-0.9.10.tar.gz
rm carbon-0.9.10.tar.gz
rm graphite-web-0.9.10.tar.gz
rm whisper-0.9.10.tar.gz
cd /root/whisper-0.9.10/
python setup.py install
cd /root/carbon-0.9.10/
python setup.py install
cd /opt/graphite/conf
cp carbon.conf.example carbon.conf
cp storage-schemas.conf.example storage-schemas.conf
cp storage-aggregation.conf.example storage-aggregation.conf
This part will install graphite-web
cd /root/graphite-web-0.9.10/
// make sure dependencies are met
python check-dependencies.py
python setup.py install
// Copy wsgi script for apache
cp /opt/graphite/conf/graphite.wsgi.example /opt/graphite/conf/graphite.wsgi
cd /opt/graphite/webapp/graphite/
cp local_settings.py.example local_settings.py
Then edit “/opt/graphite/webapp/graphite/local_settings.py”, i did:
Now we can initialize the DB:
cd /opt/graphite/webapp/graphite/
python manage.py syncdb
// create a user
// set a password
If this last step went through without any error, that mean you deserve a snack.
cd /opt/graphite/examples/
cp example-graphite-vhost.conf /etc/apache2/sites-available/graphite
cd /etc/apache2/sites-enabled/
ln -s ../sites-available/graphite graphite
I would edit “/etc/apache2/sites-available/graphite”, and change the following:
ErrorLog /var/log/apache2/graphite.error.log CustomLog /var/log/apache2/graphite.access.log common
You now need to change permission on the storage or you web server won’t work you can do:
chown -R www-data:www-data /opt/graphite/storage/
// Restart apache
service apache2 restart
Carbon need to be started in order to save data into it, you can start carbon in command line like this:
cd /opt/graphite
sudo ./bin/carbon-cache.py start
However this is not efficient, since if you reboot you server you will have to start carbon manually. To fix this we can create a service script.
Create a new file “/etc/init.d/carbon” and add the following into it:
#! /bin/sh
# /etc/init.d/carbon
# Some things that run always
touch /var/lock/carbon
GRAPHITE_HOME=/opt/graphite
CARBON_USER=www-data
# Carry out specific functions when asked to by the system
case "$1" in
start)
echo "Starting script carbon "
su $CARBON_USER -c "cd $GRAPHITE_HOME"; su $CARBON_USR -c "$GRAPHITE_HOME/bin/carbon-cache.py start"
;;
stop)
echo "Stopping script carbon"
su $CARBON_USER -c "cd $GRAPHITE_HOME"; su $CARBON_USR -c "$GRAPHITE_HOME/bin/carbon-cache.py stop"
;;
*)
echo "Usage: /etc/init.d/carbon {start|stop}"
exit 1
;;
esac
exit 0
Then change it’s permission to executable (“chmod 777 /etc/init.d/carbon”) and also register this script with Ubuntu “update-rc.d carbon defaults”. Now you can start carbon with this command line “/etc/init.d/carbon start” and if you server reboot, Carbon will be started automatically.
Finally you should be able to access Graphite Dashboard at the following address “http://yourServerName/” where you should be able to access the basic Graph that Carbon generate for itself.
You can also run this command “python /opt/graphite/examples/example-client.py” which will send some data to Graphite about your system.
In my next post I will show you how to install Statsd and how to use it with your web application.
Source
I was bored during a weekend and decided to consume Synology’s API in PHP.
Synology is a company that offers NAS solution for Personal use or for Large business. I love their products, I have a two bay NAS where I store most of my important files. It’s also a perfect Media Storage. Their software (DiskStation) is the best I’ve used so far, you can control anything on your NAS, download other Apps and even have direct shell access via SSH.
In their latest version of DiskStation they offer a Web REST API that allow you to connect to the NAS and do all sort of things including managing other “apps”. I was really interested into managing Download Station and here we go, I created a simple Library that do just that. You can find this library on Github here: https://github.com/zzarbi/synology
Yes I know you are really happy with your “persistent” Key Value store. But did anybody notice hstore that comes along Postgresql. I find Postgresql to be a really great RDBMS that has been ignored all the time. It even has some great publisher/subscriber system as well (or LISTEN/NOTIFY in…
I’ve been playing with Hadoop for few weeks now. Hadoop is an open source Apache product inspired by Google MapReduce and Google File System. It allows your application to work with thousand of nodes and petabytes of data. It’s written in Java and run on commodity hardware. I’m not going to write a tutorial but I will tell you how did I start.
Here a list of the few tutorial that I used:
Basically I followed the tutorial of Michael G. Noll but I use the Cloudera packages for debian/ubuntu. Few thing you need to know:
The main problem I ran into was to add some redundancy to the namenode. On small cluster, the namenode is running on the same server than the secondary namenode and the first datanode. Also the namenode and secondary namenode consume a lot of resources, especially memory.
The namenode distribute data accross your cluster, he also take care of redundancy of the data. If one datanode goes down and that you have a redundancy set to 2. The namenode will replicate the data lost from datanodes (where the data is not lost) to a datanode available to keep that redundancy. The namenode does that by keeping record of every action in two files, called fsImage and edits. fsImage is the current file namespace and edits contain every modification to the current file namespace. For performance optimization the namenode will merge those two files only when it starts. Which mean that if you never restart you namenode, the edits file will grow large and at the next restart it will take some time to merge those two files. That’s why the secondary namenode exist, it will contact the namenode every 1 hour (this is configurable), retrieve those two files, merge them and return them back to the namenode. Merging those two files are resource extensive on large cluster, that’s why you should run this services on a different server than the namenode. The secondary namenode doesn’t backup anything, also it will note replace the namenode if the namenode fail.
You can you can tell the namenode to save those two files to different location (another disk or a remote disk), by defining “dfs.name.dir” in hdsf-site.xml like so:
<property> <name>dfs.name.dir</name> <value>/data/dfs/name/,/disk2/backup/name,/mnt/nfs/backup/name</value> </property>
In my case I configured my secondary namenode on a server with the same specification of the namenode and in its hdfs-site.xml I defined “dfs.name.dir” to use the remote backup and I configured the master/slaves files. If the namenode goes down, I still have to manually turn on the secondary namenode into a namenode but in this case everything is ready (Caution: You will need to transfer the IP of the namenode to the secondary namenode).
Finally as a quick band-aid by reading the documentation I found out that you can download those two files from the namenode via its webservice, you can get fsImage with “http://NAMENODE:50070/getimage?getimage=1” and edits with “http://NAMENODE:50070/getimage?getedit=1”. I wrote a bash script to retrieve those files and back them up on each datanode at different time of the day, at least you wont loose everything.
I hope this will help you start to setup your Hadoop cluster, one last thing you could do is to read the Hadoop documentation.
From all the online streaming services Netflix is the one I use the most, in the same time it’s the one that frustrate me the most. Here my list of feature that they should add asap:
A real search engine:
Indeed right now you can do a basic search that return movies but it doesn’t return real results… What do I mean? well if you search “robots” it will return a list of movies with “robots” in the title and if each of those movie are not available it will give you two similar titles that have little to nothing to do with what you search. There is no way to search by tags, by categories or by date. Also no way to order by ratings. Search by date is really important when I want to search for new content.
Watch preview/trailer:
Actually I had to browse around until I found one title that actually had a trailer. Since they store every movie why don’t they store a tiny piece of each? Or just a YouTube link to the actual movie trailer… Or why not partnered with IMDB? I mean right now it’s what I manually do anyway.
Order comments:
Lets say I found a movie or a documentary. Netflix have lots of comments, you can rate the movie and rate the comments but there is no way to order them by ratings or by comment helpfulness. Amazon is doing a great job with that!
New arrival ?:
On my home page there is two new list “Recently Added” and “New Released”. As a developer I can see that both are redirected to the same script called “newReleases” but with different parameters. One page just get a list ordered by date added (I guess) and the second one ordered by released date (I guess, because it doesn’t seems to be the case). Both of those lists have nothing to do with what normal people consider new content, at least if they are supposed to be new content, those list are bugging. In “Recently added” I have a movie from 1993 and in “New released” I have movie from 2009.
Those are not big features from a UI standpoint, a product standpoint or a development standpoint. The search could use a solr index with a cache layer. The trailer part could be easily plug with IMDB. Ordering comments can however be quite complicated depending on how they implemented. The last feature is the easiest to implement since I think they are just ordering out of a wrong field.
I’ve spent few weeks looking at performance between Apache/PHP vs Node.JS and Mysql vs MongoDB.
All test were run on my local computer with ApacheBench :
- Intel Core 2 Duo E8500 @ 3.16GHz
- 8Gb of Ram
- Ubuntu 11.10 Desktop 64bits
- Apache 2.2.20
- PHP 5.3.6
- Node.JS 0.6.6
- Mongodb 1.8.2
- Mysql 5.1.58
The first graph comparing PHP and Node.JS is based on a simple return “Hello world” application. You can see that Node.Js perform a bit better than Apache/PHP which event fail to give any result in high concurrency test (PS: There is actually a lots of good request but too much of them failed to get any accurate reading). This test is just a brute force representation on the capability of Node.js.
The second graph represent the performance between PHP/Mysql vs PHP/Mongodb vs Node.Js/Mysql vs Node.js/Mongodb. This is a basic application which just retrieve 1 random row out of the database of 100,000 rows and return “Good” on success. You can quickly notice that the degradation of the performance of Node.js when you have to connect to a database at each server request but if we keep the connection open, Node.Js will perform better. I will have to to the same test with PHP and a persistent connection.
Obviously those test for Mongo vs Mysql were made to test a specific use case. I didn’t test performance when retrieving more than one row, or ordering a set of rows or querying a field without index or even looking through a 100Million rows.
I did test writing in MonogB compare to writing in MySQL. For example writing 10,000 rows in MongoDB took 0.6 second where the same code with MySQL took 7 minutes (I was inserting one row at the time). MongoDB end-up being faster here because it’s actually not writing to the disk right away.
Those technologies should be use accordingly, MongoDB is really fast in writing, so you could use it for storing user activity on a social network or login page views. Node.JS is really fast to handle a request, some people even use Node.JS as a load balancer.
Source code:
First of all I’m going to go quickly through all the current solution:
Cable:
Well everybody know that you pay $100 for maybe 5 channels that you would like to watch and they package it with lots of garbage that you would never watch.
Digital TV:
Yes you can still plug an antenna in recent TVs and get a digital signal. I leave in Hollywood and I have only 2 working channel. I don’t how how to explain that but it’s pretty bad.
Netflix:
I use it when I don’t know watch to watch but I’m in the mood to watch something. I just turn it on, browse until I find something. Sometimes if I know watch I want, I’ll check to see if it’s available but most of the time it’s not available at least not in streaming mode.
Hulu:
This one is a pretty good joke. You can either watch TV show for free with lots of advertising, right after they are broadcast on TV or you can pay a monthly fee and watch the same TV show with the same amount of advertising, only difference this time you can use your TV instead of your computer screen.
DVDs:
If you don’t care about quality, this is still a pretty good way to watch a movie. You need a DVD player which you can get for really cheap nowadays.
Bluray:
You need an updated Bluray player, which is pretty hard to get if you didn’t buy a PS3 (PS: Just buy a PS3). I had a player for 3 days until I couldn’t update it to watch a new movie, so I returned it. Also I could use my computer which has an HDMI output with a Full HD cable (whatever that means…) and my Full HD TV. In theory it should work, in practice it’s a nightmare. I end up buying a software that remove protection on the Bluray so I can actually watch it on my TV.
Theaters:
The best choice according to me but I won’t pay $12 for any kind of movie, also you always end-up spending over $25.
iTunes:
Fairly cheap TV show and movies but stuck with DRM and Apple codec, which mean if I buy a media on iTunes, I can’t watch it on my TV except if I have a Apple TV or I’m willing to plug my computer to my TV.
Amazon:
Same thing that iTunes, you need a device that can connect to it.
Ultraviolet:
UV is supposed to be the answer to the crisis, I think the idea is pretty good. It’s really close to what I’m thinking about. First of all it’s limited to newly acquired media and there is not a lot of device than can work with it (Actually just the Flixter app).
Illegal downloads/Streamings:
The Antichrist of Hollywood. There was a survey not so long ago saying that every body under 25 most likely downloaded at least one illegal movie, mp3 or TV show.
But let’s be honest, this is the most convenient way to consume media. It’s on demand, fairly cheap (Still have to pay for Internet), large directory. I’m not saying you should download, I’m just saying it exist and it’s pretty hard to ignore it as a “solution”. Personally I hate streaming, it don’t even know how people consider that as viable solution.
The problem is that all legal solutions are really inconvenient. We are supposed to be in the digital age, everything is supposed to be connected but for some reason Hollywood doesn’t want to grow up. Today under my TV there is only one box, it’s a Western Digital player which has access to Hulu, Netflix, my local network and even Youtube.
This box however doesn’t read DVD or Bluray, so all my collection of DVDs/Bluray is pretty useless and right now I have to rip/encode those DVDs one by one so I can watch them on my TV, but this is still illegal. Indeed in US and most developed countries, it is illegal to bypass a security system such as the one installed on DVDs and Bluray. The thing I don’t understand is at the beginning of the age of Digital Music, it wasn’t illegal to rip a CD, actually even software like iTunes were doing it. Why does it need to be different with videos? You can even rip of your olds records but it’s illegal to do so with a DVD.
I dream of a day where I can just type/scan the bar-code of my DVD collection and make them available for download or streaming to any device that I have. I literally want iCloud for videos! iCloud is a new service from Apple that allow you to sync your local music library to Apple cloud storage. You can then access all your music from Apple device (*only inconvenient). Amazon and Google have a similar product.
In the same time Hollywood need a new way to survey its viewers. There should be a website where I can go and officially vote for a TV Show or why not use some donation system like flattr.com or use the good old text messaging system to vote. Anything would be better than just surveying 300people per city.
I’m sure that you all know how Facebook improve its product:
Facebook is using this “process” since the beginning, we all know about it because they either change their design, or some privacy control, or totally change one part of the product (Message) or not so long ago change the chat and you hated it. This process allow quick implementation of potential great idea but Facebook is so big and still growing that they can afford to loose few people, who will probably come back anyway since Facebook is/was a unique product.
So in some sense you can say that they care more about the product than their users. In some sense because the original point of this shortcut to production is to add value to the product.
The Facebook effect is when you have an user user say something like “Wow this new feature/design is really bad, please bring back the old one” and a week to a few days to an hour later the same user will totally forgot why he wasn’t happy. I’m not quite sure if this is because the change was actually a genius idea, luck or just the user getting tired of complaining… This is not the point, the point is Facebook did it for a long time and got away with it.
The problem is now a other companies are envious. They think they can do the same thing without doing any test, or checking if it’s a useful feature, or checking statistics, or even listening to their user after deployment. They think that they can copy Facebook process and that the user will definitely react but get over it after (This is actually an argument that I heard). There is a saying like “You don’t have to create what the user want, you have to create something that the user doesn’t know he wants”. This is quite dangerous when you actually already have a business, just look at Digg (Reddit on Digg) or the new design of Gizmondo (Lost 15%).
Yes there is a possibility that this could work but there is more example of it failing. Facebook is an exception, it’s what help them grown bigger than MySpace but now that there is new competitors like Google+, they cannot afford it except for tiny tweaks. Moreover I’m not sure that Facbook decide on those features without actually having at least some number backing them up. Their latest feature called Timeline was in beta-test for months and now that it’s out you actually have to opt-in.
Anyway there is different way of improving your products without alienating users such as A/B testing and statistics, you don’t have to bet your company each time you want to improve something.
Few month ago after a trip in France, I wrote US lags in broadband services. I explain how the French government stimulated the market by poking competition with a stick or a carrot (which ever picture your prefer).
I talk about free.fr one of the top 3 French ISPs and how they remodeled the industry in 2002, also that they were working on they own Phone Network which should launch at the beginning of 2012.
Well this day was today Tuesday 10th, Free unveiled there new offer to the rest of the world. Actually just to France, since I didn’t see this news on any other tech blog who are probably busy with CES 2012.
I watched the press conference (in French) where funder Xavier Niel explain why they had to create a new phone operator and how his competitor were abusing their position. He listed a few points against them such as:
A plan with Unlimited call nation wide, Unlimited Text message (extra cost for media message), 1Gb of limited internet cost in France today between 49.99Euros and 85Euros.
Solutions of Free to the previous problem are:
And this for only 19.99Euros ($28) twice cheaper than the cheapest competitor and 4 times as cheap as the two major competitor. If you already have Free as an Internet Provider the price of the plan drop to 15.99Euros ($22).
Few month ago the French government decided that there was a need for a cheap plan for the lower class, because they saw the phone as a necessity. After talking to the 3 operator they came out with a 50minutes, and 50 text message for 10euros ($14) per month. Well Free decided that this was “bullshit” (literally) and offer now 1 hour and 60 text message for 2Euros ($2.8) per month.
The only inconvenience with the Free offer according to the first critics is that they do not subvention phones. You will have to buy the phone you want the full price which for an iPhone 4S is around 629euros. However you have the possibilities to pay in 12, 24 or 36 months. Even with this Free is still way cheaper than its competitor.
Right after this event competitors rushed over Twitter and other social network to announce that they will have new plans really soon but this time the customer will be the one to decide what the market price should really be.
I really wish that the US wakes up to shake its own market.
I recently traveled to France for two week, and while there I also made a visit to my hometown in Reunion Island, which is located 6000 miles from Paris in the middle of the Indian Ocean.
I remembered when I was a teenager back in 1998, I had a monthly 10-hour limit on the dial-up Internet. Once you account for the fact that the modem was a US Robotics 33.6K modem you’ll quickly understand how little 10 hours a month is. This was an era where you could find Free AOL and CompuServe CDs for “free internet”, which wasn’t actually free for me as I still had to pay a phone fee to access those server from where I was. Back then we paid 35euros (around $43 at the time) for the 10 hours of Internet (The price was actually in Francs). However since I generally went over my plan we ended up paying anywhere from $20 to $40 more each month. My family was poor but my parents understood somehow the importance of the Internet. Even Christmas I used to ask to give me additional Internet hours instead of a normal gift.
I remember using WinMX to download “stuff” (this was the beginning of MP3s/DivX) and I was so envious of those Americans with T1 and T5 lines that were all over in WinMx!
Few years later a couple new technologies were introduced, namely ISDN and DSL. These new technologies offered to provide more bandwidth, but naturally since I lived on an island in the middle of nowhere, bandwidth still had to be rationed as with modems. At the time Reunion was connected to the World Wide Web by satellite and we had one unique Internet Provider Wanadoo (old name of Orange and France Telecom). The price for the 128K of DSL was 56euros ($62) and we still had time and bandwidth limits, ISDN was as expansive.
In 2002, Reunion Island was finally connected to the SAFE (South Africa Far East cable) which is an optical fiber submarine communications cable linking Melkbosstrand, South Africa to Penang, Malaysia. I now had 35 hours of 128K DSL Internet and I paid something around 65 euros ($85).
Sometime in 2004, I think, I finally had 512K of unlimited Internet for the same price as the 128K DSL. In 2004 I left Reunion to go to Bordeaux, France and when I arrived I was blown away by the Internet market, which was booming!
In France there were many more Internet providers such as Numericable, Orange, Free, Neuf Cegetel to name a few, who all offered different technologies such as Satellite, Cable and ADSL.
At that time in 2004, Free.fr. another Internet provider, was a new competitor with really aggressive prices! To begin with they offered free dial-up Internet to anyone. Free.fr then started offering unlimited ADSL in addition to unlimited phone time (to landlines) for 29.99 euros ($40), which compared to other providers was a lot cheaper. Other competitors started to follow them and a law was introduced against Orange. It should be noted, for a short period, Orange was forbidden to compete, as they pretty much had a monopoly on the market, so the French government wanted to motivate other competitors to jump into the race. I was livid that this law had passed because as a Orange customer I knew I wouldn’t see my monthly bill be reduced, and thus I was eventually forced to switch to another provider, Free.
Today in France, you can get Unlimited Internet with ADSL 28Mbits, unlimited free phone to more than 200 destinations (landlines only, mobile are however cheap), 128 TV channel, personal Internet box that allow you to record TV and offer games other services such as personal cloud storage, etc, all for only 29.99euros ($45). I should note the law cited above regarding Orange has now finally – and I might add thankfully – been repealed.
There are now only 3 major competitors in the market but there is also multiple number of smaller providers that rent networks from the from bigger providers.
Going back to my homeland, Reunion Island, I cannot understate how impressed I was with the telecommunication market and the plethora of services they now provide! There are multiple providers (at least 5) who are offering the same services as the companies in France for almost the same price (tax are higher in Reunion Island) and all that in only 5 years… There is even free Wifi, which covers part of the island.
In 2008 I moved to San Francisco and couldn’t believe how far behind the US lagged in telecommunications. I had AT&T DSL which is the worse Internet line I have ever used, and the speed wasn’t anything special.
Today I live in Los Angeles, the capital of the media and I even work for a leading company which creates, publishes, and distributes media, Break Media. At home I have Time Warner Internet Cable with Power Boost (20Mbps) for $57, which only covers Internet. I don’t get phone, TV or other anything else for that matter. On top of that, my choices as far as Internet providers is very limited, I can choose AT&T with U-Verse for $75 (24Mbps, still no Phone or TV included and no tax) or Time Warner.
Additionally, even if you want to compare the mobile (cellphone) markets, France and Reunion Island come out ahead. I can get customized plan which are fitted just for my particular needs. For example I don’t call anyone so I don’t need 500 minutes per month but I use the Internet and text a lot. There is no plan for this in the US today (Virgin Mobile does this but not on every phone). The cheapest plan I found is with T-mobile was $70 (for 500 minutes, unlimited Text, unlimited Internet and tax included), which throttles the bandwidth once you’ve reach a threshold.
With Verizon or AT&T you can get 450 Minutes, unlimited Text, 2GB of Internet for $90 (no tax included).
In France, with Orange, I can get unlimited Text, unlimited Internet and 60 to 300 minutes for 25 euros to 56 euros ($36 to $80 tax included) respectively. What’s more, most plans even include mobile TV. Other provider have even better offers, as Orange is generally more expansive. As I stated earlier there are only 3 major providers (Orange, SFR, Bouygues) and many MVNO(Mobile virtual network operator) but Free.fr is also going to begin providing mobile services next year and is expected to undercut the market just as they did with internet services.
So now, sitting in Los Angeles, I’m truly envious of France – and I’m even envious of my Island… It’s really sad that knowing I did so much to escape it, now has better telecommunication services at a better price than the US.
What happen here? Why did the US miss the boom?
I personally have no idea, I wasn’t here during the past 7 years, maybe the country is too big? Infrastructure too old?
But why did my Island succeed where America did not? There are practically no high-tech jobs over there in Reunion Island – which is one of the main reasons why I left (the major sectors are Tourism and Sugar). GDP per capita of my island in 2007 was $23,501 and GDP per capita of US in 2007 $43,170. There is less of a need for Internet in Reunion Island then there is here in the United States.
France doesn’t offer high speed Internet everywhere though as there are still some area with 1024k of ADSL but they are actively working on it. The French government is pushing providers to fix any coverage gaps by providing help in the form of investments or get fined if they do not comply.
I’m not saying the US government should do something like the French government, after all that is against free markets. I’m actually looking at investors and entrepreneurs, as there are a lot of investors who fund new 2.0 companies (Color, Path) but I’m thinking, maybe they should first help lay down a new network infrastructure so they are on par with their Europeans. It may be harder to deploy a new network infrastructure in the US, but the benefits are clearly worth it. Consumer choice with regards to telecommunication services, helps with the market by continually having to innovate while at the same time it benefits consumers who can choose which providers meet their needs more efficiently. It’s a win-win for everyone involved.
When iMessage was announced, I immediately thought it was brilliant. Not only for getting away from the ancient SMS protocol, but as a method of delivery of messages across multiple devices. Now that plenty of people had both an iPhone and an iPad, how great would it be if I could message…
Gearman is designed to distribute tasks to multiple servers. The first example coming to my mind is a online video encoder. There will be two server a web server and an encoder. The user will upload a video to the web server which will send en encoding task to the other server. The task will be run asynchronously and the web server will be able to retrieve information about this task.
In this post I will show you how to install Gearman on windows with cygwin, there is multiple tutorial on how to use Gearman.
I’ve spent few days trying to compile unsuccessfully Gearman latest version 0.24. However the version 0.14 works like a charm.
First you need to install Cygwin, while doing that you will be prompt to add packages, you need to add those packages: (A tutorial on how to use Cygwin)
Gearman require libevent an event notification library which you cannot get with Cygwin, you will need to compile it.
First you need to download the latest libevent release here (2.0.14 for me)
Unpacked the package somewhere.
Open cygwing shell and cd to the unpacked library.
Run the following command:
First download the Gearman package 0.14 that you can find here https://launchpad.net/gearmand/+download
Unpacked it somewhere
Cd to the unpacked directory with Cygwin
Run the following command:
Now Gearman should be ready to use! You can do gearman.exe —help for a list of command.
Please note that there is no PECL extension for gearman on windows, so you might want to use the pear extension instead (pear install Net_Gearman-alpha).
PS: This is obviously not made for production server
Two weeks ago I was reading Techcrunch (like every single day) and I got to this article http://techcrunch.com/2011/09/01/syma-s107-review.
It’s a review of a toy, except that it’s an advanced toy. I run over to Amazon an bought a bunch of them.
I’ve been playing with it since last week and right now there is two other waiting for me at the front office of my job.
Those tiny helicopter have only 3 degree of control instead of the normal 4 (and 5 in certain case). Which made them extremely easy to fly!!! It’s really stable, the quality is amazing for just $20 but only for indoor purpose which is cool because I’m having a lot of fun flying around my living room.
In the same time I found another brand JXD who sell the Drift King around the same price who has 4 degree of control. I cannot wait to test it, I’ll update the post as soon as I receive it.
If you’re like me an love anything that fly with a remote go get one of these right now!
I got TouchPad since the Fire Sale of HP. I also have an iPad 2.
I’ve been using neither really… I mean I’ve used the iPad 2 to play some game or browse the Internet or even watch some video via a NAS but I don’t really use it. I think I’ll be using it when I’ll go in vacation which I hope happen soon.
I’ve also been playing with XCode and iOS and so used the iPad to test my code. I had to pay the $99 licensing fee of Apple to be able to test my code on my iPad with my computer. No need to say that this part is really annoying, long and expensive especially when you don’t have a Mac.
Since I’m not using my newly acquired TouchPad and that my girlfriend is most of the time with my iPad. I figure that I should get a look at the development on TouchPad.
One word: “Awesome”
It couldn’t be easier! Install the SDK/PDK which come with a real emulator using Virtual Box instead of a simulator like iOS, Install eclipse, Install WebOs Plugin and that’s it, you’re ready to develop. No need of generating a certificate! (At least at this point). No need to compile! It’s blazing fast to deploy your application.
Follow some tutorial like this one and you will be able to develop your first application.
The framework seems to be a bit bulky but I think there is way around that so you should be able to use any Javascript framework like jQuery Mobile.
A week ago HP decided to kill their tablet the “HP TouchPad” and WebOs.
At that time nobody cared about the product, I even never read a test or review. Few day after to get rid off their stock, HP told to all their sellers to sell the 16Gb tablet for $99 and the 32Gb for $149.
Suddenly the touchpad became a best seller overnight. It ran out of stock everywhere and still today people try to buy them.
After the fire sale HP decided that it will finally keep webOs around. The majority of people who bought the touchPad, did it with the hope of installing Android on it.
However the second reason (The first being the price) why I never bought an Android tablet was because it actually run Android. Indeed I tested the Zoom for 3 days and I just didn’t see the appeal of it, poor UI, poor application. The fact that the Zoom was a poor product didn’t help. Since I’ve seen the Galaxy Tab in action and it looks amazing!
Last Friday CyanogenMod (well known in the Android community) were able to install their mod on a touchPad. Getting Android a step closer to be fully operational.
However I’m in a state where I don’t know if I really want Android on my touchPad. I really wish HP decide to open source webOs. The UI is way better than Android while being quite different from iOS. I think this is the real hope for the touchpad community.
One other option would maybe installing MeeGo…
I’ve spent few weeks on Google+ and I think I have a good idea of the product.
First I though Google+ could be a really good competitor to Facebook. A lot of feature of Google+ are better than Facebook. At least the features I care about, for instance Pictures and Circles.
Google Pictures derived from Picasa which is an amazing product.
Circles is really easy to use if you don’t try to create 50 circles. If you have more than 10 Circles that mean you should work harder. Personally I have only 6 Circles which are Family, Friends, Acquaintances, Following, Coworkers and Blocked.
On the meantime I hate two things about Google+:
Indeed I think I sound stupid when I speak with my friends and say literally something like “Check this out on Google Plus”. I think Google is going to have a hard time attracting more people with this name. Every social network I use/used have only two syllables Facebook, Twitter, Foursquare, LinkedIn, MySpace with some exception like Instagram. I’m not saying that they should have only two syllables and I know that “sounds bad” is like “looks bad”, it’s depends of each person.
For the +1 button the problem is different. At the beginning I didn’t mind of it. Now that each time I +1 something on Google+ I get “You +1’d this” This sound really really stupid. Either Google need to find a new “name” for it either they have to stop trying to use it as a verb.
I was amazed by the simplicity of Google+ to manage the privacy of your profile. Such as relation ship status, place you’ve lived, … Indeed each property (not all of them) can be shared to one or multiple circles. You can do the same on Facebook but it’s not on the same page. On Facebook you can edit your profile, and in another page you can edit who can see what using Facebook lists.
Different appraoch for the same problem but I do prefer Google+ on this one.
However Google+ circles doesn’t fix everything for me. The “default” sahring setting of Google+ is “Extended Circles” which according to Google mean “Everyone in your circles, plus all the people in their circles.”
In my case I need a default circles which would include family and friends, but exclude people in their circles. Right now you can do that, if you share something just with some selected circles, however you have to each circles. (Google+ does remember what you used last.)
To understand my point of view you have to know how I’m using
Twitter, Facebook and LinkedIn.
I used those application like Rocky Agrawal (TechCrunch: When Google Circles Collide) each networks is used for a specific audience.
I would share a “LOL Cat” picture via Facebook and/or Twitter but not to LinkedIn, I would share an TechCrunch article to Twitter and LinkedIn but I would not
bored my friends with it. I would share family picture only on Facebook.
So what we need is the ability to create “master circles”, I know that would complexity to the application, but if Google was able to fix the original problem of making list, they should be able to fix this new problem.
A master circles could contain one or multiple circles and it could be exclusive or inclusive. Meaning that I want to be able to share to everyone in your circles, plus all the people in their circles or not.
I spent quite some time to figure out how to make PHP flush its output earlier than expected! Today I finally figure it out.
First of all, what is early flush? Well basically when you do in PHP “echo ‘test’;” PHP will put this echo in its buffer, and write the buffer to the output only when PHP collected enough data.
The main value that manage the buffer size is output_buffering in php.ini, it takes an integer or the string ‘Off’ to be turned off.
PHP also offer multiple way to manage its buffer with flush and other methods such as:
flush() will attempt to flush the buffer forcing PHP to send the current output all the way to the browser. As said in PHP documentation, it’s better used with ob_flush().
Also as said in PHP documentation “flush() may not be able to override the buffering scheme of your web server and it has no effect on any client-side buffering in the browser.”. Which mean that there is at least two other buffers, one in your web server and one in your browser itself.
Indeed Apache has its own buffer, and some browser such as IE will not show anything until it received 256 bytes of output.
With the version 1.1 of the HTTP protocol, there is a new transfer encoding called “Chunked transfer encoding” that allow a webserver to send partial data, and to process it while waiting for some other part of data. This can be really usefull for AJAX call. Actually some website such as Yahoo! will use such behavior to load part of there HTML really really fast while waiting for the rest of the page.
This mod of transfer is however not compatible with every module of Apache, like mod_gzip, it’s however compatible with the later version mod_deflate.
To disable mod_gzip you can do so:
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
With output_buffering set to Off in php.ini
<?php ob_implicit_flush(true); // activate implicit flush (not needed if activated in php.ini)
// disable gziping/compression
@apache_setenv('no-gzip', 1); @ini_set('zlib.output_compression', 0);
// start capturing echo statement ob_start(); $var = 100; while(--$var) // loop echo 'Page loading'; // code to render; ob_flush(); flush(); sleep(10); // LONG time code to execute exit;
You will see ‘Page Loading’ a 100 times in your browser really fast, and you can see that after that your page is still loading/waiting for 10seconds. With this type of behavior you could send the HTML header first, containing CSS and Javascript while the rest of the page get loaded.
With output_buffering set to Off in php.ini
<?php class IndexController extends Zend_Controller_Action {
public function testAction(){
// You need to activate implicit flush because Zend Framework deactivate it before getting to the controller
ob_implicit_flush(true); // activate implicit flush
// disable gziping/compression
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
// start capturing echo statement
ob_start();
$var = 100;
while(--$var) // loop
echo 'Page loading'; // code to render;
ob_flush();
flush();
sleep(10); // LONG time code to execute
exit;
}
}
PS: This code was not tested on IIS or apache/php on windows
PS2: Why do you loop with 100? You can choose lower value such as 50 but it didn’t work with me because the browser has also a buffer and if there is not enough data the browser won’t show anything.