PlanetMySQL Voting: Vote UP / Vote DOWN
Archive for the ‘facebook’ Category
Retrieve time period like facebook fashion
Июль 13th, 2010PlanetMySQL Voting: Vote UP / Vote DOWN
User’s Demographic Data From Facebook
Май 14th, 2010Sometimes we may need to collect facebook user’s basic data for our website or application. Then we’ve to call graph api or legacy api or fql query to collect some specific data. This is a basic requirements for most of the fbconnect base website or facebook application. To simplify this task here I published some code so that you could easily use this code and can integrate in your site. Read Full Article

PlanetMySQL Voting: Vote UP / Vote DOWN
User’s Demographic Data from Facebook
Май 14th, 2010
Sometimes you may need to collect facebook user’s basic data for your website or application. Then you’ve to call graph api or legacy api or fql query to collect some specific data. This is a basic requirements for most of the fbconnect base website or facebook application.
For this reason, here I’m sharing the code, how could I collect those basic data and store them in database.
Before proceeding check the demo.
If you’re automatically logged in the site, then first logout and relogin and approve all the permissions. Now I’m showing the database table schema first

MySql code of this schema is:
CREATE TABLE IF NOT EXISTS `demographic` ( `uid` BIGINT UNSIGNED NOT NULL , `first_name` VARCHAR(50) NULL , `last_name` VARCHAR(50) NULL , `email` VARCHAR(200) NULL , `link` VARCHAR(255) NULL , `affiliations` VARCHAR(255) NULL , `birthday` VARCHAR(50) NULL , `current_location` VARCHAR(200) NULL , `education_history` VARCHAR(500) NULL , `work` MEDIUMTEXT NULL , `hometown_location` VARCHAR(400) NULL , `interests` VARCHAR(200) NULL , `locale` VARCHAR(50) NULL , `movies` VARCHAR(500) NULL , `music` VARCHAR(500) NULL , `political` VARCHAR(200) NULL , `relationship_status` VARCHAR(100) NULL , `sex` VARCHAR(10) NULL , `tv` VARCHAR(200) NULL , `status` TINYINT NULL , `created` DATETIME NULL , `updated` DATETIME NULL , PRIMARY KEY (`uid`) ) ENGINE = InnoDB
This code collects data from facebook
if ($fbme){
//collect some data using legacy api
$param = array(
'method' => 'users.getinfo',
'uids' => $fbme['id'],
'fields' => 'birthday_date, interests, locale, political, relationship_status, affiliations',
'callback' => ''
);
try{
$info = $facebook->api($param);
}
catch(Exception $o){
error_log("Legacy Api Calling Error!");
}
//using graph api
//array data
$workInfo = getWorkInfoAsString($fbme);
$education = getEducationAsString($fbme);
$moviesArr = $facebook->api("/me/movies");
$musicArr = $facebook->api("/me/music");
$televisionArr = $facebook->api("/me/television");
//format some api data
$movies = getArrayDataAsString($moviesArr['data']);
$music = getArrayDataAsString($musicArr['data']);
$television = getArrayDataAsString($televisionArr['data']);
//data from legacy api
$networks = '';
if (!empty($info[0]['affiliations'])){
$flag = true;
foreach ($info[0]['affiliations'] as $item){
if (!$flag) $networks.= ' # ';
$networks .= $item['name'];
$flag = false;
}
}
$now = date("Y-m-d G:i:s");
$insData = array(
'uid' => $fbme['id'],
'first_name' => $fbme['first_name'],
'last_name' => $fbme['last_name'],
'email' => $fbme['email'],
'link' => $fbme['link'],
'affiliations' => $networks,
'birthday' => $info[0]['birthday_date'],
'current_location' => $fbme['location']['name'],
'education_history' => $education,
'work' => $workInfo,
'hometown_location' => $fbme['hometown']['name'],
'interests' => $info[0]['interests'],
'locale' => $info[0]['locale'],
'movies' => $movies,
'music' => $music,
'political' => $info[0]['political'],
'relationship_status' => $info[0]['relationship_status'],
'sex' => $fbme['gender'],
'tv' => $television,
'status' => '0',
'created' => $now,
'updated' => $now,
);
//$this->db->insert('demographic', $insData);
}
function getWorkInfoAsString($fbme, $delim = '#', $partDelim = ' | '){
$info = "";
$flag = false;
foreach($fbme['work'] as $item){
if ($flag)
$info .= $partDelim;
$flag = true;
$info .= $item['employer']['name'] . $delim . $item['location']['name'] . $delim . $item['position']['name'] . $delim . $item['start_date'] . $delim . $item['end_date'];
}
return $info;
}
function getEducationAsString($fbme, $delim = '#', $partDelim = ' | '){
$info = "";
$flag = false;
foreach($fbme['education'] as $item){
if ($flag)
$info .= $partDelim;
$flag = true;
$info .= $item['school']['name'] . $delim . $item['year']['name'];
}
return $info;
}
function getArrayDataAsString($data, $delim = '#', $partDelim = ' | '){
$info = "";
$flag = false;
foreach($data as $item){
if ($flag)
$info .= $partDelim;
$flag = true;
$info .= $item['name'];
}
return $info;
}
Look $insData contains all the values. So you just need to insert $insData in your database table. In this example I used mainly graph api, and for some small information I call legacy api. Regarding data storing format, if I found any data as array like education_history then I store that data like below format
[education_history] => International Islamic University Chittagong#2008 | Govt. Shah Sultan College, Bogra#2003
first # for part of a single data like (education institute and year), and finally | that separates array item. If your profile has well filled data then by visiting this demo you will see the data example.
So if you store education_history and next time you need to break them as array then you could write code like
$arrEdu = explode('|', $education_history); // break string to array items
$education = array();
$i = 0;
foreach($arrEdu as $item){
$brk = explode('#', $item);
$education[$i]['institute'] = $brk[0];
$education[$i]['year'] = $brk[1];
++$i;
}
echo '<pre>';
print_r($education);
echo '</pre>';
This will output
Array
(
[0] => Array
(
[institute] => International Islamic University Chittagong
[year] => 2008
)
[1] => Array
(
[institute] => Govt. Shah Sultan College, Bogra
[year] => 2003
)
)
If you read the code you’ll see its very easy to understand.
Full Source Code
<?php
include_once "fbmain.php";
$config['baseurl'] = "http://thinkdiff.net/demo/newfbconnect1/demographicdata/index.php";
//if user is logged in and session is valid.
if ($fbme){
//collect some data using legacy api
$param = array(
'method' => 'users.getinfo',
'uids' => $fbme['id'],
'fields' => 'birthday_date, interests, locale, political, relationship_status, affiliations',
'callback' => ''
);
try{
$info = $facebook->api($param);
}
catch(Exception $o){
error_log("Legacy Api Calling Error!");
}
//using graph api
//array data
$workInfo = getWorkInfoAsString($fbme);
$education = getEducationAsString($fbme);
$moviesArr = $facebook->api("/me/movies");
$musicArr = $facebook->api("/me/music");
$televisionArr = $facebook->api("/me/television");
//format some api data
$movies = getArrayDataAsString($moviesArr['data']);
$music = getArrayDataAsString($musicArr['data']);
$television = getArrayDataAsString($televisionArr['data']);
//data from legacy api
$networks = '';
if (!empty($info[0]['affiliations'])){
$flag = true;
foreach ($info[0]['affiliations'] as $item){
if (!$flag) $networks.= ' # ';
$networks .= $item['name'];
$flag = false;
}
}
$now = date("Y-m-d G:i:s");
$insData = array(
'uid' => $fbme['id'],
'first_name' => $fbme['first_name'],
'last_name' => $fbme['last_name'],
'email' => $fbme['email'],
'link' => $fbme['link'],
'affiliations' => $networks,
'birthday' => $info[0]['birthday_date'],
'current_location' => $fbme['location']['name'],
'education_history' => $education,
'work' => $workInfo,
'hometown_location' => $fbme['hometown']['name'],
'interests' => $info[0]['interests'],
'locale' => $info[0]['locale'],
'movies' => $movies,
'music' => $music,
'political' => $info[0]['political'],
'relationship_status' => $info[0]['relationship_status'],
'sex' => $fbme['gender'],
'tv' => $television,
'status' => '0',
'created' => $now,
'updated' => $now,
);
//$this->db->insert('demographic', $insData);
}
function getWorkInfoAsString($fbme, $delim = '#', $partDelim = ' | '){
$info = "";
$flag = false;
foreach($fbme['work'] as $item){
if ($flag)
$info .= $partDelim;
$flag = true;
$info .= $item['employer']['name'] . $delim . $item['location']['name'] . $delim . $item['position']['name'] . $delim . $item['start_date'] . $delim . $item['end_date'];
}
return $info;
}
function getEducationAsString($fbme, $delim = '#', $partDelim = ' | '){
$info = "";
$flag = false;
foreach($fbme['education'] as $item){
if ($flag)
$info .= $partDelim;
$flag = true;
$info .= $item['school']['name'] . $delim . $item['year']['name'];
}
return $info;
}
function getArrayDataAsString($data, $delim = '#', $partDelim = ' | '){
$info = "";
$flag = false;
foreach($data as $item){
if ($flag)
$info .= $partDelim;
$flag = true;
$info .= $item['name'];
}
return $info;
}
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Facebook User's Demographic Data Collection | Thinkdiff.net</title>
</head>
<body>
<div id="fb-root"></div>
<script type="text/javascript">
window.fbAsyncInit = function() {
FB.init({appId: '<?=$fbconfig['appid' ]?>', status: true, cookie: true, xfbml: true});
/* All the events registered */
FB.Event.subscribe('auth.login', function(response) {
// do something with response
login();
});
FB.Event.subscribe('auth.logout', function(response) {
// do something with response
logout();
});
};
(function() {
var e = document.createElement('script');
e.type = 'text/javascript';
e.src = document.location.protocol +
'//connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);
}());
function login(){
document.location.href = "<?=$config['baseurl']?>";
}
function logout(){
document.location.href = "<?=$config['baseurl']?>";
}
</script>
<h3>Facebook User's Demographic Data Collection | Thinkdiff.net</h3>
<?php if (!$fbme) { ?>
You've to login using FB Login Button to see your demographic data
<?php } ?>
<p>
<fb:login-button autologoutlink="true" perms="email,publish_stream,offline_access,user_birthday,user_location,user_work_history,user_religion_politics,user_relationships"></fb:login-button>
</p>
<!-- all time check if user session is valid or not -->
<?php
if ($fbme){
echo '<pre>';
print_r($insData);
echo '</pre>';
}
?>
</body>
</html>
Hope this code will help you to quickly integrate in your project. This data collection code will work in both canvas application and fbconnect base application. You can modify the code easily to get customize data. But fyi this code doesn’t collect all the information of facebook user rather some basic and essential information
And don’t forget extended permission list. I provided this list of permissions as I needed to collect above data.
<fb:login-button autologoutlink="true" perms="email,publish_stream,offline_access,user_birthday,user_location,user_work_history,user_religion_politics,user_relationships"></fb:login-button>
PlanetMySQL Voting: Vote UP / Vote DOWN
On hot backups
Май 9th, 2010Few years ago I was looking at crash recovery code, and realized that InnoDB has removed all the comments from the code, related to replay of transaction log. Judging by high quality of comments in the remaining codebase, I realized that it was all done to obscure any efforts to build another InnoDB hot backup solution – competitor to first Innobase standalone offering.
I was enjoying the moment when Percona launched their own implementation of the tool. Since the inception, it became more and more robust and feature rich.
We have used xtrabackup in our environment a lot – just… not for backup – the major use case right now is for cloning server instances – either for building new replicas, shadow servers, or replacing masters – and allows us to do that without interrupting any operation.
Now what makes the whole situation way more interesting – Oracle/MySQL announced at the conference, that InnoDB Hot Backup will be part of the Enterprise offering – which makes it way more available to MySQL customer community, than when it required quite expensive per-server licenses.
Of course, open source xtrabackup is way easier to tweak for our environment (O_DIRECT support, posix_fadvise(), flashcache hints, etc – was all added after release) – and it is interesting, how Oracle-provided tool will evolve. Right now xtrabackup already supports streaming operation, which makes it much more usable in large-database-on-small-hardware (read: sharded) environments, and provides flexibility to the users. Oracle of course owns much more of in-house expertise of both current internals operation, as well as all the future changes that will happen, so we may see leadership in the field coming from their side too.
One of our reasons for not using physical backup solution is simply that it is not space efficient. There may be multiple ways to approach that – from robust incremental backups, to partial backups, that wouldn’t include secondary indexes or have limited set of tables taken.
Some changes may actually require extended MySQL/InnoDB support – on multiple-terabyte instances one may not want to rescan the dataset for each incremental backup run – as resulting diff would be just a hundred gigabytes or less. This would require support for always-running backup agent that would aggregate information about block changes and allow for more efficient backup operation.
Discarding secondary indexes is way more attractive option with 5.1/Plugin ability to do fast independent index builds, that don’t require one row at a time B-Tree builds for all indexes at once (and of course, hit severe memory penalties on large tables or in parallel workloads).
Having always ready backups is important not only for ability to rebuild a box (and we have replicas for machine failures) – the real value is when backups can be used for massive-scale thousands of machines subset of table rows extraction. For that one cannot just ship full instance data around from backup storage – so recovery tools will have to be way flexible.
Probably core feature for that kind of operation would be ability to import tables directly from hot backup to online instances – unfortunately, restarting database instance is still costly (though we’re doing quite some work in that direction too).
I’m extremely happy that InnoDB started fixing operational issues like crash recovery performance, but there’s still a wide area of problems not touched properly yet – extremely in disaster recovery space, and I’m eager to see developments in this field – both from Oracle, and community members.
PlanetMySQL Voting: Vote UP / Vote DOWN
My MySQL keynote slides and video
Апрель 16th, 2010Been asked a few times in the last few days about where my slides are from my MySQL keynote from *last* year.
Ooops.
Um, yeah. Sorry about that. Here’s a link to ‘The SmugMug Tale’ slides, and you can watch the video below:
Sorry for the extreme lag. I suck.
The important highlights go something like this:
- Use transactional replication. Without it, you’re dead in the water. You have no idea where a crashed slave was.
- Use a filesystem that lets you do snapshots. Easily the best way to do backups, spin up new slaves, etc. I love ZFS. You’ll need transactional replication to really make this painless.
- Use SSDs if you can. We can’t afford to be fully deployed on SSDs (terabytes are expensive), but putting them in the write path to lower latency is awesome. The read path might help, too, depending on how much caching you’re already doing. Love hybrid storage pools.
- Use Fishworks (aka Open Storage) if you can. The analytics are unbeatable, plus you get SSDs, snapshots, ZFS, and tons of other goodies.
- Use transactional replication. This is so important I’m repeating it. Patch it into MySQL (Google, Facebook, and Percona have patches) or use XtraDB if you use replication. We use the Percona patch.
Holler in the comments if something in the presentation isn’t clear, I’ll answer. Apologies again.
Shameless plug - we’re hiring. And it’s a blast.

PlanetMySQL Voting: Vote UP / Vote DOWN
Kontrollsoft is on Facebook – become a fan
Январь 3rd, 2010PlanetMySQL Voting: Vote UP / Vote DOWN
Kontrollsoft is on Facebook – become a fan
Январь 3rd, 2010PlanetMySQL Voting: Vote UP / Vote DOWN
How I stopped worrying and learned to love Twitter
Июль 20th, 2009I was warned by my brother a while ago that should I start tweeting, he would stage an intervention. I had already confessed to accounts with facebook, multiply, myspace, and several others (disclaimer/explanation: all of those sites are customers of my longtime employer). Twitter, to the uninitiated, looks like the crack cocaine of social networking that turns the weekend photo-poster into a hardcore jittering lifecaster. Nobody wants to see their family member come to that, right? But follow along, twitter has purpose. Or just skip to the bottom.
I was never an active friendster user. The first site I used regularly was the more inward-facing multiply.com - and then mostly because it was an easy way to foist photos of my daughter on my extended family. Multiply is more of a community-based, relationship-savvy site than a place to find online friends. If I am cousin-of-John, it makes the assumption (with my consent) that I am interested in content by wife-of-John, brother-of-John, etc. Combined with who I have directly connected to, Multiply can quickly become a nice "walled garden" of family and friends content and connections. Easy media uploading, a slider I can set to "show me what the people close to me are up to", and that's really about all I needed.
But then, like everyone else with a facebook account, sometime in the last 18 months a bizarre game of "this is your life" began. Invitations to connect came in from grade school friends, distant family, former co-workers, babysitters and fellow inmates. Scratch that last one.
I'm in (facebook-only, mostly) contact with literally dozens of people that I hadn't talked to in 5-25 years, that I seriously doubt I would have ever heard from or about. Its really interesting, and I enjoy seeing the 2-3 things a week they note about their lives, the occasional photo or link to what they're doing. Unlike Multiply, facebook defaults to "everyone is an acquaintance" and gives you one firehose of updates sorted by when they were posted. Its fun to gaze over when I have a few minutes online and see who is up to what.
Tweets then started to bleed in to the status update page. I knew of, and had zero interest in, this "text the world" service called Twitter. Why would I even use an online outlet to send a message to a friend of mine? I have an email address, cell phone number and at least one IM handle for most of my friends and families... can't I connect with them easily enough? So why on earth are there facebook updates like "hanging out with @tomjefferson in #philly #consitition #usa"? What's with all the @ signs and hashes?
Well, it was low-effort enough (no "friending", much less relationship definition, required for most posts) to review the updates for an individual person on twitter. Good friends who lived far away, co-workers involved in a crucial event, things like that (the celebs like Lance came later). To streamline the process of viewing those, I got an account.
Twitter is the most stalker-friendly social networking site. Twitter by default does not even ask if you know or like anyone, only if you want to "follow" them. Seems kinda creepy for those unfamiliar with the Information Age. And it really is like a big water cooler on the internet. It's hard to resist joining in after a bit.
The photos of the kids still go to multiply, and I still watch facebook to keep up with a more extended group. But the most inane of updates and commentary are best put out to twitter, and here is why. My frustrated tweet when a desktop social networking client crashed on me:
pantoniades: #gwibber unstable on fedora 11. Need a new desktop Twitter client.
9:42 AM Jul 13th from Twitterrific
Inane, right? On multiply I'd confuse more people than inform. I promise you most of my family doesn't understand the context for half of the words above. On facebook, that's just clutter. But on twitter, here's what happens next:
pauljakma: @pantoniades grab #gwibber 1.2.0 (e.g. from #Fedora rawhide) - works great
4:55 AM Jul 14th from Gwibber in reply to pantoniades
I don't know Paul Jakma. I'm guessing he's a gwibber developer or enthusiast. But more importantly, he's right. Yes, I could likely have found that tip in an IRC channel, bugzilla note or through some google search, but I was really not invested in this client. I got the fix, he kept somebody on his project, and neither one of us invested much effort (presumably he has a tickler on "#gwibber"
.
I haven't found any long-lost friends on twitter, and I'm not putting the photos of my kids goofing around in the bathtub on facebook. Perhaps there is one uber-site to rule them all, but I'm also quite happy with the three I've got. Provided I can dodge the van my brother sends to take me off to deprogramming.
